{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "title": "maa task config",
    "patternProperties": {
        "^(?!\\$)": {
            "type": "object",
            "oneOf": [
                {
                    "$ref": "#/definitions/JustReturnTask"
                },
                {
                    "$ref": "#/definitions/MatchTemplateTask"
                },
                {
                    "$ref": "#/definitions/OcrDetectTask"
                },
                {
                    "$ref": "#/definitions/FeatureMatchTask"
                }
            ]
        }
    },
    "definitions": {
        "Rectangle": {
            "type": "array",
            "maxItems": 4,
            "minItems": 4,
            "items": {
                "type": "number"
            }
        },
        "ParamsArray": {
            "type": "array",
            "items": {
                "type": "integer"
            }
        },
        "TaskNameList": {
            "type": "array",
            "items": {
                "type": "string",
                "description": "要执行的任务"
            }
        },
        "BaseTask": {
            "properties": {
                "baseTask": {
                    "type": "string",
                    "description": "可选项,以其他任务为模板生成任务"
                },
                "algorithm": {
                    "type": "string",
                    "pattern": "JustReturn|MatchTemplate|OcrDetect|FeatureMatch",
                    "default": "MatchTemplate",
                    "description": "可选项,表示识别算法的类型, 默认为 MatchTemplate"
                },
                "action": {
                    "type": "string",
                    "pattern": "ClickSelf|ClickRand|DoNothing|Stop|ClickRect|Swipe|Input",
                    "default": "DoNothing",
                    "description": "可选项,表示识别到后的动作\n不填写时默认为 DoNothing"
                },
                "inputText": {
                    "type": "string",
                    "default": "",
                    "description": "可选项,当 action 为 Input 时有效,表示要输入的文本"
                },
                "sub": {
                    "$ref": "#/definitions/TaskNameList",
                    "description": "可选项,子任务。会在执行完当前任务后,依次执行每一个子任务\n可以套娃,子任务再套子任务。但要注意不要写出了死循环"
                },
                "subErrorIgnored": {
                    "type": "boolean",
                    "default": false,
                    "description": "可选项,是否忽略子任务的错误。默认为 false\n为 false 时,若某个子任务出错,则不继续执行后续任务(相当于本任务出错了)\n为 true 时,子任务是否出错没有影响"
                },
                "next": {
                    "$ref": "#/definitions/TaskNameList",
                    "description": "可选项,表示执行完当前任务后,下一个要执行的任务\n会从前往后依次去识别,去执行第一个匹配上的\n不填写默认执行完当前任务直接停止"
                },
                "maxTimes": {
                    "type": "number",
                    "description": "可选项,表示该任务最大执行次数\n不填写时默认无穷大\n达到最大次数后,若存在 exceededNext 字段,则执行 exceededNext;否则直接任务停止"
                },
                "exceededNext": {
                    "$ref": "#/definitions/TaskNameList",
                    "description": "可选项,表示达到了最大执行次数后要执行的任务\n不填写时,达到了最大执行次数则停止;填写后就执行这里的,而不是 next 里的"
                },
                "onErrorNext": {
                    "$ref": "#/definitions/TaskNameList",
                    "description": "可选项,表示执行出错时,后续要执行的任务"
                },
                "preDelay": {
                    "type": "number",
                    "description": "可选项,表示识别到后延迟多久才执行 action,单位毫秒;不填写时默认 0"
                },
                "postDelay": {
                    "type": "number",
                    "description": "可选项,表示 action 执行完后延迟多久才去识别 next, 单位毫秒;不填写时默认 0"
                },
                "roi": {
                    "$ref": "#/definitions/Rectangle",
                    "description": "可选项,表示识别的范围,格式为 [ x, y, width, height ]\n以 1280 * 720 为基准自动缩放;不填写时默认 [ 0, 0, 1280, 720 ]\n尽量填写,减小识别范围可以减少性能消耗,加快识别速度"
                },
                "cache": {
                    "type": "boolean",
                    "default": true,
                    "description": "可选项,表示该任务是否使用缓存,默认为 true;\n第一次识别到后,以后永远只在第一次识别到的位置进行识别,开启可大幅节省性能\n但仅适用于待识别目标位置完全不会变的任务,若待识别目标位置会变请设为 false"
                },
                "rectMove": {
                    "$ref": "#/definitions/Rectangle",
                    "description": "可选项,识别后的目标移动,不建议使用该选项。以 1280 * 720 为基准自动缩放\n例如识别到了 A 图标,但实际要点击的是 A 图标旁边的某个位置,则进行移动后再点击。可以的话尽量直接识别要点击的位置,不建议使用该选项\n当 action 为 Swipe 时表示滑动终点"
                },
                "reduceOtherTimes": {
                    "type": "array",
                    "items": {
                        "type": "string",
                        "description": "要执行的任务"
                    },
                    "description": "可选项,执行后减少其他任务的执行计数。"
                },
                "specificRect": {
                    "$ref": "#/definitions/Rectangle",
                    "description": "当 action 为 ClickRect 时有效且必选,表示指定的点击位置(范围内随机一点),以 1280 * 720 为基准自动缩放\n当 action 为 Swipe 时有效且必选,表示滑动起点"
                },
                "specialParams": {
                    "$ref": "#/definitions/ParamsArray",
                    "description": "某些任务使用的特殊参数(大部分是手写阈值给插件用的)(std::vector<int>)"
                },
                "highResolutionSwipeFix": {
                    "type": "boolean",
                    "default": false,
                    "description": "可选项,是否启用高分辨率滑动修复,现阶段应该只有关卡导航未使用 unity 滑动方式所以需要开启,默认为 false"
                }
            },
            "allOf": [
                {
                    "if": {
                        "required": ["action"],
                        "properties": {
                            "action": {
                                "enum": ["ClickRect"]
                            }
                        }
                    },
                    "then": {
                        "required": ["specificRect"]
                    }
                },
                {
                    "if": {
                        "required": ["action"],
                        "properties": {
                            "action": {
                                "enum": ["Swipe"]
                            }
                        }
                    },
                    "then": {
                        "required": ["specificRect", "rectMove"]
                    }
                },
                {
                    "if": {
                        "required": ["algorithm", "action"],
                        "properties": {
                            "algorithm": {
                                "const": "JustReturn"
                            },
                            "action": {
                                "const": "Input"
                            }
                        }
                    },
                    "then": {
                        "required": ["inputText"]
                    }
                }
            ]
        },
        "JustReturnTask": {
            "allOf": [
                {
                    "$ref": "#/definitions/BaseTask"
                },
                {
                    "properties": {
                        "algorithm": {
                            "type": "string",
                            "pattern": "JustReturn"
                        }
                    },
                    "required": ["algorithm"]
                }
            ],
            "description": "不进行识别,直接执行 action"
        },
        "MatchTemplateTask": {
            "allOf": [
                {
                    "$ref": "#/definitions/BaseTask"
                },
                {
                    "properties": {
                        "algorithm": {
                            "type": "string",
                            "pattern": "MatchTemplate"
                        }
                    }
                }
            ],
            "properties": {
                "template": {
                    "type": ["array", "string"],
                    "items": {
                        "type": "string"
                    },
                    "description": "可选项,要匹配的图片文件名\n不填时写默认 \"任务名.png\""
                },
                "templThreshold": {
                    "type": ["array", "number"],
                    "items": {
                        "type": "number"
                    },
                    "default": 0.8,
                    "description": "可选项,图片模板匹配得分的阈值,超过阈值才认为识别到了。\n默认 0.8, 可根据日志查看实际得分是多少\n多模板时,阈值数量需与模板数量一致"
                },
                "maskRange": {
                    "type": "array",
                    "maxItems": 2,
                    "minItems": 2,
                    "items": {
                        "type": "integer"
                    },
                    "default": [1, 255],
                    "description": "可选项,灰度掩码范围。例如将图片不需要识别的部分涂成黑色(灰度值为 0),然后设置 [ 1, 255 ], 匹配的时候即刻忽略涂黑的部分"
                },
                "colorScales": {
                    "type": "array",
                    "description": "当 method 为 HSVCount 或 RGBCount 时有效且必选,数色掩码范围。",
                    "items": {
                        "type": "array",
                        "minItems": 2,
                        "maxItems": 2
                    }
                },
                "colorWithClose": {
                    "type": "boolean",
                    "default": true,
                    "description": "可选项,当 method 为 HSVCount 或 RGBCount 时有效,默认为 true\n数色时是否先用闭运算处理掩码范围\n闭运算可以填补小黑点,一般会提高数色匹配效果,但若图片中包含文字建议设为 false"
                },
                "pureColor": {
                    "type": "boolean",
                    "default": false,
                    "description": "可选项,当 method 为 HSVCount 或 RGBCount 时有效,默认为 false\n是否只使用数色匹配而不使用模板匹配\n适用于颜色特征明显但模板匹配效果不佳的场景\n使用此选项时建议相应提高 templThreshold 阈值"
                },
                "method": {
                    "oneOf": [
                        {
                            "type": "string",
                            "enum": ["Ccoeff", "RGBCount", "HSVCount"]
                        },
                        {
                            "type": "array",
                            "items": {
                                "type": "string",
                                "enum": ["Ccoeff", "RGBCount", "HSVCount"]
                            }
                        }
                    ],
                    "default": "Ccoeff",
                    "description": "可选项,模板匹配算法,可以是列表\n不填写时默认为 Ccoeff\n - Ccoeff: 对颜色不敏感的模板匹配算法,对应 cv::TM_CCOEFF_NORMED\n - RGBCount: 对颜色敏感的模板匹配算法,先将待匹配区域和模板图片依据 colorScales 二值化,以 F1-score 为指标计算 RGB 颜色空间内的相似度,再将结果与 Ccoeff 的结果点积\n - HSVCount: 类似 RGBCount,颜色空间换为 HSV"
                }
            },
            "description": "匹配图片"
        },
        "OcrDetectTask": {
            "allOf": [
                {
                    "$ref": "#/definitions/BaseTask"
                },
                {
                    "properties": {
                        "algorithm": {
                            "type": "string",
                            "pattern": "OcrDetect"
                        }
                    }
                }
            ],
            "properties": {
                "text": {
                    "type": "array",
                    "items": {
                        "type": "string"
                    },
                    "description": "必选项,要识别的文字内容,只要任一匹配上了即认为识别到了"
                },
                "fullMatch": {
                    "type": "boolean",
                    "default": false,
                    "description": "可选项,文字识别是否需要全字匹配(不能多字),默认为 false\nfalse 时只要是子串即可:例如 text: [ \"开始\"],实际识别到了 \"开始行动\",也算识别成功;\ntrue 时则必须识别到了 \"开始\",多一个字都不行"
                },
                "isAscii": {
                    "type": "boolean",
                    "default": false,
                    "description": "可选项,要识别的文字内容是否为 ASCII 码字符\n不填写默认 false"
                },
                "ocrReplace": {
                    "type": "array",
                    "items": {
                        "type": "array",
                        "minItems": 2,
                        "maxItems": 2,
                        "items": {
                            "type": "string"
                        }
                    },
                    "description": "可选项,针对常见识别错的文字进行替换(支持正则)"
                },
                "withoutDet": {
                    "type": "boolean",
                    "default": false,
                    "description": "可选项,是否不使用检测模型\n不填写默认 false"
                },
                "useRaw": {
                    "type": "boolean",
                    "default": true,
                    "description": "可选项,是否使用原图匹配\n不填写默认 true,false 时为灰度匹配\n仅当 algorithm 为 OcrDetect 且 withoutDet 为 false 时生效。"
                },
                "binThreshold": {
                    "type": "array",
                    "maxItems": 2,
                    "minItems": 2,
                    "items": {
                        "type": "integer"
                    },
                    "default": [140, 255],
                    "description": "可选项,二值化灰度阈值(默认 [140, 255])\n灰度值不处于范围内的像素将被视为背景,排除在文字区域之外\n仅当 algorithm 为 OcrDetect 且 withoutDet 为 false 时生效。"
                }
            },
            "required": ["algorithm", "text"],
            "description": "文字识别"
        },
        "FeatureMatchTask": {
            "allOf": [
                {
                    "$ref": "#/definitions/BaseTask"
                },
                {
                    "properties": {
                        "algorithm": {
                            "type": "string",
                            "pattern": "FeatureMatch"
                        }
                    },
                    "required": ["algorithm"]
                }
            ],
            "properties": {
                "template": {
                    "type": "string",
                    "description": "可选项,要匹配的图片文件名\n不填时默认为 \"任务名.png\""
                },
                "count": {
                    "type": "integer",
                    "minimum": 1,
                    "default": 4,
                    "description": "匹配的特征点数量要求(阈值)。默认值为 4。"
                },
                "ratio": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 1.0,
                    "default": 0.6,
                    "description": "KNN 匹配的距离比值,[0 - 1.0] 越大越宽松。默认值为 0.6。"
                },
                "detector": {
                    "type": "string",
                    "enum": ["SIFT", "ORB", "BRISK", "KAZE", "AKAZE", "SURF"],
                    "default": "SIFT",
                    "description": "特征点检测器。默认值为 SIFT。可选:SIFT, ORB, BRISK, KAZE, AKAZE, SURF"
                }
            },
            "description": "使用特征点算法进行图像匹配"
        }
    }
}