Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: 更新用户手册&开发文档 #281

Merged
merged 11 commits into from
Dec 19, 2024
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
目前已有的功能:

- 启动/关闭游戏
- 切换账号
- 收取荒原、魔精收取生产物品
- 每日心相(意志解析)
- 刷体力、最优材料关卡、活动关卡、吃糖选项
Expand Down
77 changes: 45 additions & 32 deletions docs/zh_cn/develop/Bug 排查.md
Original file line number Diff line number Diff line change
@@ -1,52 +1,53 @@
# Bug 排查

修 bug 也是开发中重要的一环,如何快速准确地定位、分析、解决 bug 是有技巧的。本文将介绍一些常见的 bug 排查方法。
修 bug 也是开发中重要的一环。
如何快速准确地定位、分析、解决 bug 是有技巧的。
本文将简单介绍排查 bug 的一般流程。

> [!NOTE]
>
> 以下内容仅供参考,注意时效性。

## 前置准备

与 bug 发现者沟通,尽可能的获取 bug 相关的信息,如:
与 bug 提出者沟通,尽可能的获取 bug 相关的信息,如:

- 资源版本
- 系统版本
- 问题的细节(发生的时间、场景等)
- 配置文件、日志、截图等
- 问题的细节描述(发生的时间、场景等)
- 配置文件、日志、截图等必要信息

## 定位问题
## 定位关键 log

### 确认资源版本以及运行方式
1. 确认资源版本以及运行方式

对于 M9A 来说,有两种运行方式:1. MaaPiCli 2. MFAWPF
对于 M9A 来说,有两种运行方式:1. MaaPiCli 2. MFAWPF

根据观察,MaaPiCli运行时有行log为
根据观察,MaaPiCli运行时有行log为

```plaintext
[2024-11-28 19:46:32.571][INF][Px14600][Tx16498][Parser.cpp][L56][MaaNS::ProjectInterfaceNS::Parser::parse_interface] Interface Version: [data.version=v2.4.11]
```
```plaintext
[2024-11-28 19:46:32.571][INF][Px14600][Tx16498][Parser.cpp][L56][MaaNS::ProjectInterfaceNS::Parser::parse_interface] Interface Version: [data.version=v2.4.11]
```

既能看出资源版本,又能看出是以 MaaPiCli 方式运行。
而 MFAWPF 运行时有log为

```plaintext
[2024-11-30 01:46:56.490][INF][Px20060][Tx33876][Parser.cpp][L56][MaaNS::ProjectInterfaceNS::Parser::parse_interface] Interface Version: [data.version=]
```
```plaintext
MFAWPF Version: [mfa.version=v1.2.2.0] Interface Version: [data.version=v2.5.5]
```

当 `version` 为空时,MaaPiCli log 为以上样式。
由 data.version 可以确定资源版本。以此判断当前问题发生的版本是否已修复当前 bug。
同时确认运行方式。因为不同运行方式,可能影响问题的复刻。

确认资源版本可以了解是否为已修复bug版本,确认运行方式则是因为不同运行方式,config文件不同,同时可能生成的bug也不同。
2. 定位问题所在的 log 位置

### 确定问题 log 范围
分两种情况:
- 任务提前结束
- 任务陷入无限循环

- 根据问题描述发生的时间缩小范围
- 根据问题发生的任务缩小范围
- 根据[ERR]确定错误相关原因
- 根据bug相关的[ERR]处反向查找 `Task Hit` ,以确定出错任务
前者全局搜素 **[ERR]** ,查看报错是与什么有关。
后者全局搜索 **Task Hit** ,查找不正常的匹配情况(如持续匹配一个本不该一直匹配的 node)。

## 分析问题

在这里我将问题大致分为三类:资源加载问题、连接问题以及 pipeline 问题(timeout)
在这里我将问题大致分为三类:资源加载问题、连接问题以及 pipeline 问题。

### 资源加载问题

Expand All @@ -64,19 +65,31 @@
[2024-11-24 23:44:05.539][ERR][Px26056][Tx55883][ControlUnitMgr.cpp][L55][MaaNS::CtrlUnitNs::ControlUnitMgr::connect] failed to connect [adb_path_=D:/MuMu Player 12/shell/adb.exe] [adb_serial_=127.0.0.1:16384]
```

### pipeline 问题
### Pipeline 问题

这类是 M9A 主要需要关注的问题,需要了解原 pipeline 流程以及 log 展示的执行情况,加以分析。

1. 非 pipeline 流程类问题

这种问题本身 pipeline 流程逻辑上没有问题。

根据出问题的 node 分为两种:

第一种是 非 无条件匹配/inverse node。
常见原因是截图截太快了,匹配到 `next` 中 node,但当前画面尚未未稳定。
解决方案是为当前 node 添加合适的 `post_wait_freezes`,等待画面稳定再做判断。

一般来说,是pipeline逻辑有漏洞导致的,需要进一步分析。
第二种是 无条件匹配/inverse node。
这种可能是进到非预期界面,导致判断失误。
解决方案是按需修改。

常用的解决方法有:
2. pipeline 流程类问题

- 增加 `flag` 任务
- 增加 `pre/post_wait_freezes` (注意默认 `target` 是否是你想要的)
- 更改实现逻辑(如更换识别方式以及动作逻辑)
这种是任务流程本身完备性不足,需在分析后修改。

## 解决问题

前两种参考[常见问题](../manual/常见问题.md)解决,pipeline 问题需要进一步分析
前两种参考[常见问题](../manual/常见问题.md)解决,pipeline 问题根据分析结果修改

## 验证修复

Expand Down
114 changes: 87 additions & 27 deletions docs/zh_cn/develop/Pipeline 编写.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,50 +9,106 @@
#### 资源命名

- 对于图片等文件,采用大驼峰命名法,所有单词的首字母都大写。
- 对于 `pipeline.json` 文件,一般来说,采用蛇形命名法,单词之间用下划线分隔,所有字母小写,
特别地,专有名词的活动采取大驼峰命名法,一般在 `activity`
- 对于 `image` 下文件夹,每个文件夹对应一个 `pipeline.json` 文件,文件夹名采用大驼峰命名法,
特别地,`activity` 内 `pipeline.json` 对应的 `image` 放到 `Combat/Activity` 处。
- 对于 `pipeline` 文件夹下的 json 文件名,一般采用蛇形命名法,单词之间用下划线分隔,所有字母小写,
特别地,专有名词的活动采取大驼峰命名法,一般在 `activity` 文件夹内
- 对于 `image` 下文件夹,每个文件夹对应一个 `pipeline` 文件夹下的 json 文件,文件夹名采用大驼峰命名法,
特别地,`activity` 内 json 文件对应的 `image` 放到 `Combat/Activity` 处。

#### Task 命名
#### Node 命名

大多数采用大驼峰命名法,特别地,部分情况下用 `_` 连接前、后缀。
node 的定义为符合任务流水线(Pipeline)协议的一个完整的 `JsonObject`,大多数采用大驼峰命名法,特别地,部分情况下用 `_` 连接前、后缀。

前缀一般为 `Sub` 或 当前活动缩写(如 `SOD` 黄昏的音序、`EITM` 山麓的回音)等,其他情况建议不要前缀。
前缀一般为 `Sub` 或 当前活动缩写(如 `SOD` 黄昏的音序、`EITM` 山麓的回音)等。(其他情况建议不要前缀)

后缀一般为 `数字` 或 `状态` 等,表示该任务的具体阶段或状态。(建议新写的任务不加后缀
后缀一般为 `数字` 或 `状态` 等,表示该 node 的具体阶段或状态。(建议新写的 node 不加后缀

### Task 编写
### Node 编写

参考[Pipeline 协议详细说明](https://github.com/MaaXYZ/MaaFramework/blob/main/docs/zh_cn/3.1-%E4%BB%BB%E5%8A%A1%E6%B5%81%E6%B0%B4%E7%BA%BF%E5%8D%8F%E8%AE%AE.md)
具体内容参见[Pipeline 协议详细说明](https://github.com/MaaXYZ/MaaFramework/blob/main/docs/zh_cn/3.1-%E4%BB%BB%E5%8A%A1%E6%B5%81%E6%B0%B4%E7%BA%BF%E5%8D%8F%E8%AE%AE.md)

> [!NOTE]
>
> - 一般 `next` 放置当前任务的出口任务,`interrupt` 放置当前任务的中断任务。
> - 建议多写些 `Flag` 任务进行判断,以保证任务的稳定性。
> - 部分情况下,可在 `next` 加入自身,以提高任务的稳定性。(存在程序未正确接受动作的情况)
> - `next` 放置当前 node 的出口 node,`interrupt` 放置当前 node 的中断 node。
> - 多将具有 Flag 性质的 node 设为出口 node,作为当前 node 完成的标志。
> - 降低 node 之间的耦合。
> 如 `BackButton` 一般不设置 `next`,而是作为一个“异常处理”放入 `interrupt`,以便保证任务流程的清晰,并方便 interrupt node 被其它任务复用。
> - 部分情况下,可将 node 加入自身 `next` 。(存在动作未被游戏正确接受/尚未在游戏内生效的情况)
> - 在涉及切换页面的 node 中加入 `post_wait_freezes` ,并使用 `object` 作为值,设置合适的 `time` 和 `target`。
> - 涉及滑动的操作时,在后面加个点击操作,以便确保画面稳定。

> [!WARNING]
>
> - 慎用 `inverse` 字段,这可能会导致任务的不可预测。
> 如必须使用,请保证其有带 `post_wait_freezes` 的前置 node,以保证匹配该 node 时处于预期状态。
> - 慎用“无条件匹配” node。
> node 的 `recognition` 字段默认为 `DirectHit`。 `recognition` 字段为 `DirectHit` 的 node 即为“无条件匹配” node。
> 使用“无条件匹配” node,可能导致任务运行到非预期状态时,程序未能正常报错,而是循环匹配该 node,造成任务卡死。
> 如非必要,请选择其它实现逻辑完成任务。

#### Node 连接

Node 间主要通过 `next` 或 `interrupt` 字段连接。

`next`完成 node 间的串联,`interrupt`实现执行以当前 interrupt node为 entry 的新任务链,并在该任务链完成后返回当前 node。

简单表示如下:

```mermaid
graph LR
A(Task Entry<br>Node A) --> |next| B(Node B)
A --> |interrupt| C(Node C)
C --> |return| A
```

将 interrupt node 变复杂点:

```mermaid
graph LR
A(Task Entry<br>Node A) --> |next| B(Node B)
A --> |interrupt| C(Node C)
C --> |next| D(Node D)
C --> |interrupt| E(Node E)
D --> |return| A
E --> |return| C
```

为保证任务链有一个较好的结构,请按以下原则进行 node 连接:

1. 标志完成阶段性任务的 node 应放在 `next` 中。
2. 为达到匹配 `next` 中 node 而处理其他状况的 node 应放在 `interrupt` 中。

如 活动刷取任务、位于活动主界面、进入活动主界面 三者关系如下:

```mermaid
graph LR
A(活动刷取任务) --> |next| B(位于活动主界面)
A --> |interrupt| C(进入活动主界面)
C --> |return| A
```

这里“进入活动主界面”就不会放在 `next` ,而是放入 `interrupt` 。

### next & interrupt 任务顺序
#### Next & Interrupt Node 排序

总体上,`interrupt` 第一个任务 比 `next` 最后一个任务低一优先级
总体上,`interrupt` 第一个 node 比 `next` 最后一个 node 低一优先级

在 `next` 或 `interrupt` 内部,统一先按照优先级由高到低顺序排列,不能出现优先级倒挂的情况。举例:

```plaintext
现有判断一个小弹窗的任务B,和判断跳出弹窗前界面的任务A
如果弹窗出现时依旧能匹配到任务A,则任务B的优先级应该高于任务A,否则会出现无法处理B而卡死于A的情况
现有判断一个小弹窗的 node B,和判断跳出弹窗前界面的 node A
如果弹窗出现时依旧能匹配到A,则B的优先级应该高于A,否则会出现无法处理B而卡死于A的情况
```

同一优先级内的任务,可按照匹配频率由高到低顺序排列,以便提高命中率,降低资源消耗。
同一优先级内的 node,可按照匹配频率由高到低顺序排列,以便提高 node 命中率,降低资源消耗。

### 注释规范
#### 注释规范

`pipeline.json` 文件中,注释共两种属性字段:

1. `.*_doc$|^doc$`: 以 _doc 结尾的字符串或者正好是 doc 的字符串。
2. `.*_code$|^code$`:以 _code 结尾的字符串或者正好是 code 的字符串。

前者为对当前 task(或某字段)的说明,后者为对必填字段的占位。举例:
前者为对当前 node(或某字段)的说明,后者为对必填字段的占位。举例:

```json
{
Expand All @@ -67,16 +123,20 @@
183
],
"action": "Click",
"post_wait_freezes": 300,
"next": [
"ActivityMainFlag",
"EnterTheActivityMain"
]
"post_wait_freezes": {
"time": 500,
"target": [
0,
179,
190,
541
]
}
}
}
```

`doc` 为当前 task 说明。
`doc` 为当前 node 说明。

`template_code` 为必填字段占位,
原因是 `recognition` 为 `TemplateMatch` 时, "template" 字段必填,但我们想在 `interface.json` 中修改,故用 `template_code` 占位。
原因是 `recognition` 为 `TemplateMatch` 时, "template" 字段必填,但我们想在 `interface.json` 中修改,而不是该 json 文件中。故用 `template_code` 占位。
48 changes: 31 additions & 17 deletions docs/zh_cn/develop/interface.json 编写.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# interface.json 编写

[参考资料——interface.schema.json](https://github.com/MaaXYZ/MaaFramework/blob/main/tools/interface.schema.json)
> [!TIP]
>
> 参考资料:
> [interface.schema.json](https://github.com/MaaXYZ/MaaFramework/blob/main/tools/interface.schema.json)
> [ProjectInterface协议.md](https://github.com/MaaXYZ/MaaFramework/blob/main/docs/zh_cn/3.2-ProjectInterface%E5%8D%8F%E8%AE%AE.md)
`interface.json` 旨在提供菜单配置。

Expand Down Expand Up @@ -36,7 +40,7 @@

任务列表。任务列表包含多个任务,而每个任务又有任务名 `name`、任务入口 `entry`、任务参数 `pipeline_override`、以及任务选项 `option`,其中 `name` `entry` 必填。

`pipeline_override` 中应为 pipeline task,并带有覆写参数,例如:
`pipeline_override` 中应为 pipeline node,并带有覆写参数,例如:

```json
{
Expand All @@ -51,31 +55,35 @@
}
```

这里原task为
这里原 node 为

```json
{
"EnterTheActivityMain": {
"doc": "进入当期活动主界面",
"template_code": "在interface.json中修改template",
"recognition": "TemplateMatch",
"template_code": "在interface.json中修改template",
"roi": [
885,
123,
340,
183
],
"action": "Click",
"post_wait_freezes": 300,
"next": [
"ActivityMainFlag",
"EnterTheActivityMain"
]
"post_wait_freezes": {
"time": 500,
"target": [
0,
179,
190,
541
]
}
}
}
```

经过覆写,该 task 在执行“轶事派遣(角色故事请自行阅读)”任务时,实际执行效果等同于:
经过覆写,该 node 在执行“轶事派遣(角色故事请自行阅读)”任务时,实际执行效果等同于:

```json
{
Expand All @@ -89,18 +97,22 @@
183
],
"action": "Click",
"post_wait_freezes": 300,
"next": [
"ActivityMainFlag",
"EnterTheActivityMain"
]
"post_wait_freezes": {
"time": 500,
"target": [
0,
179,
190,
541
]
}
}
}
```

执行“轶事派遣(角色故事请自行阅读)”任务后,task 便会恢复原状。
执行“轶事派遣(角色故事请自行阅读)”任务后,node 便会恢复原状。

`option` 则是根据你下面的具体设置来决定如何覆写 pipeline task
`option` 则是根据你下面的具体设置来决定如何覆写 pipeline node

## option

Expand Down Expand Up @@ -147,6 +159,8 @@
}
```

`defaul_case` 为默认选项,从 `cases` 中选择一个。

## version

版本。不必填写,ci install 时会自动生成。
Expand Down
Loading