From a9365a1fa6644853eb2a76af1b2bcf2d88046a82 Mon Sep 17 00:00:00 2001 From: zzyyyl Date: Sun, 2 Oct 2022 17:38:14 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E4=B8=80=E4=BA=9B=20tasks.json?= =?UTF-8?q?=20=E7=9A=84=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resource/tasks.json | 6 +- .../InfrastOperImageAnalyzer.cpp | 2 +- src/MeoAssistant/TaskData.cpp | 254 ++++++++++++------ src/MeoAssistant/TaskData.h | 57 +++- 4 files changed, 236 insertions(+), 83 deletions(-) diff --git a/resource/tasks.json b/resource/tasks.json index bc20d2fa2b..5f8d50005d 100644 --- a/resource/tasks.json +++ b/resource/tasks.json @@ -4780,9 +4780,10 @@ }, "InfrastOperMoodProgressBar": { "template": "empty.png", + "templThreshold_Doc": "这里的templThreshold,作为进度条最小灰度阈值使用", "templThreshold": 160, + "specialThreshold_Doc": "这里的specialThreshold作为进度条相邻点最大变化阈值使用", "specialThreshold": 20, - "Doc": "这里的templThreshold,作为进度条最小灰度阈值使用;specialThreshold作为进度条相邻点最大变化阈值使用。懒得重新弄个字段了", "rectMove_Doc": "基于笑脸的位置移动", "rectMove": [ 21, @@ -6396,7 +6397,7 @@ }, "BattleCancelSelection": { "algorithm": "JustReturn", - "action": "ClickSelf", + "action": "ClickRect", "specificRect": [ 150, 0, @@ -7589,7 +7590,6 @@ ] }, "Roguelike1RecruitWithoutButton": { - "template": "RecruitSkipWithoutButton.png", "algorithm": "JustReturn", "action": "ClickRect", "specificRect": [ diff --git a/src/MeoAssistant/ImageAnalyzer/InfrastOperImageAnalyzer.cpp b/src/MeoAssistant/ImageAnalyzer/InfrastOperImageAnalyzer.cpp index 5b1e67fb4c..fba18e7288 100644 --- a/src/MeoAssistant/ImageAnalyzer/InfrastOperImageAnalyzer.cpp +++ b/src/MeoAssistant/ImageAnalyzer/InfrastOperImageAnalyzer.cpp @@ -86,7 +86,7 @@ void asst::InfrastOperImageAnalyzer::oper_detect() const Rect skill_rect_move = Task.get("InfrastSkills")->rect_move; const Rect name_rect_move = Task.get("InfrastOperNameOcr")->rect_move; const Rect facility_rect_move = Task.get("InfrastOperFacilityOcr")->rect_move; - const Rect prg_rect_move = Task.get("InfrastOperMoodProgressBar")->roi; + const Rect prg_rect_move = Task.get("InfrastOperMoodProgressBar")->rect_move; const std::vector all_rect_move = { skill_rect_move, name_rect_move, facility_rect_move, prg_rect_move }; InfrastSmileyImageAnalyzer smiley_analyzer(m_image); diff --git a/src/MeoAssistant/TaskData.cpp b/src/MeoAssistant/TaskData.cpp index 6187ee17c3..4f7b615b24 100644 --- a/src/MeoAssistant/TaskData.cpp +++ b/src/MeoAssistant/TaskData.cpp @@ -14,42 +14,6 @@ const std::unordered_set& asst::TaskData::get_templ_required() cons return m_templ_required; } -#ifdef ASST_DEBUG -// 为了解决类似 beddc7c828126c678391e0b4da288db6d2c2d58a 导致的问题,加载的时候做一个语法检查 -// 主要是处理是否包含未知键值的问题 -bool asst::TaskData::syntax_check(std::string_view task_name, const json::value& json) -{ - static const std::unordered_set allowed_key = { - "algorithm", "template", - "text", "action", - "sub", "subErrorIgnored", - "next", "maxTimes", - "exceededNext", "onErrorNext", - "preDelay", "rearDelay", - "roi", "cache", - "rectMove", "reduceOtherTimes", - "specificRect", "templThreshold", - "maskRange", "fullMatch", - "ocrReplace", - - "hash", "specialThreshold", - "threshold", - }; - auto is_doc = [&](std::string_view key) { - return key.find("Doc") != std::string_view::npos || key.find("doc") != std::string_view::npos; - }; - bool validity = true; - // TODO: 之后也许还要对 key-value 联合检查,task_json 先留着 - for (const auto& [name, task_json] : json.as_object()) { - if (!allowed_key.contains(name) && !is_doc(name)) { - Log.error(task_name, "has unknown key:", name); - validity = false; - } - } - return validity; -} -#endif - bool asst::TaskData::parse(const json::value& json) { LogTraceFunction; @@ -67,20 +31,8 @@ bool asst::TaskData::parse(const json::value& json) for (const auto& [name, task_json] : json.as_object()) { std::string algorithm_str = task_json.get("algorithm", "matchtemplate"); ranges::transform(algorithm_str, algorithm_str.begin(), to_lower); - auto algorithm = AlgorithmType::Invalid; - if (algorithm_str == "matchtemplate") { - algorithm = AlgorithmType::MatchTemplate; - } - else if (algorithm_str == "justreturn") { - algorithm = AlgorithmType::JustReturn; - } - else if (algorithm_str == "ocrdetect") { - algorithm = AlgorithmType::OcrDetect; - } - else if (algorithm_str == "hash") { - algorithm = AlgorithmType::Hash; - } - else { + auto algorithm = get_algorithm_type(algorithm_str); + if (algorithm == AlgorithmType::Invalid) [[unlikely]] { Log.error("Unknown algorithm", algorithm_str); return false; } @@ -140,34 +92,8 @@ bool asst::TaskData::parse(const json::value& json) task_info_ptr->name = name; std::string action = task_json.get("action", "donothing"); ranges::transform(action, action.begin(), to_lower); - if (action == "clickself") { - task_info_ptr->action = ProcessTaskAction::ClickSelf; - } - else if (action == "clickrand") { - task_info_ptr->action = ProcessTaskAction::ClickRand; - } - else if (action == "donothing" || action.empty()) { - task_info_ptr->action = ProcessTaskAction::DoNothing; - } - else if (action == "stop") { - task_info_ptr->action = ProcessTaskAction::Stop; - } - else if (action == "clickrect") { - task_info_ptr->action = ProcessTaskAction::ClickRect; - } - else if (action == "swipetotheleft") { - task_info_ptr->action = ProcessTaskAction::SwipeToTheLeft; - } - else if (action == "swipetotheright") { - task_info_ptr->action = ProcessTaskAction::SwipeToTheRight; - } - else if (action == "slowlyswipetotheleft") { - task_info_ptr->action = ProcessTaskAction::SlowlySwipeToTheLeft; - } - else if (action == "slowlyswipetotheright") { - task_info_ptr->action = ProcessTaskAction::SlowlySwipeToTheRight; - } - else { + task_info_ptr->action = get_action_type(action); + if (task_info_ptr->action == ProcessTaskAction::Invalid) [[unlikely]] { Log.error("Unknown action:", action, ", Task:", name); return false; } @@ -253,3 +179,175 @@ bool asst::TaskData::parse(const json::value& json) #endif return true; } + +#ifdef ASST_DEBUG +// 为了解决类似 beddc7c828126c678391e0b4da288db6d2c2d58a 导致的问题,加载的时候做一个语法检查 +// 主要是处理是否包含未知键值的问题 +bool asst::TaskData::syntax_check(std::string_view task_name, const json::value& task_json) +{ + static const std::unordered_map> allowed_key_under_algorithm = { + { AlgorithmType::Invalid, + { + "algorithm", + "template", + "text", + "action", + "sub", + "subErrorIgnored", + "next", + "maxTimes", + "exceededNext", + "onErrorNext", + "preDelay", + "rearDelay", + "roi", + "cache", + "rectMove", + "reduceOtherTimes", + "templThreshold", + "maskRange", + "fullMatch", + "ocrReplace", + "hash", + "specialThreshold", + "threshold", + } }, + { AlgorithmType::MatchTemplate, + { + "algorithm", + "template", + "action", + "sub", + "subErrorIgnored", + "next", + "maxTimes", + "exceededNext", + "onErrorNext", + "preDelay", + "rearDelay", + "roi", + "cache", + "rectMove", + "reduceOtherTimes", + + "templThreshold", + "maskRange", + } }, + { AlgorithmType::OcrDetect, + { + "algorithm", + "text", + "action", + "sub", + "subErrorIgnored", + "next", + "maxTimes", + "exceededNext", + "onErrorNext", + "preDelay", + "rearDelay", + "roi", + "cache", + "rectMove", + "reduceOtherTimes", + + "fullMatch", + "ocrReplace", + } }, + { AlgorithmType::JustReturn, + { + "algorithm", + "action", + "sub", + "subErrorIgnored", + "next", + "maxTimes", + "exceededNext", + "onErrorNext", + "preDelay", + "rearDelay", + "reduceOtherTimes", + + "roi", "rectMove", + } }, + { AlgorithmType::Hash, + { + "algorithm", + "action", + "sub", + "subErrorIgnored", + "next", + "maxTimes", + "exceededNext", + "onErrorNext", + "preDelay", + "rearDelay", + "roi", + "cache", + "rectMove", + "reduceOtherTimes", + + "hash", + "maskRange", + "specialThreshold", + "threshold", + } }, + }; + + static const std::unordered_map> allowed_key_under_action = { + { ProcessTaskAction::ClickRect, + { + "specificRect", + } }, + }; + + auto is_doc = [&](std::string_view key) { + return key.find("Doc") != std::string_view::npos || key.find("doc") != std::string_view::npos; + }; + + // 兜底策略,如果某个 key ("xxx") 不符合规范(可能是代码中使用到的参数,而不是任务流程) + // 需要加一个注释 ("xxx_Doc") 就能过 syntax_check. + auto has_doc = [&](const std::string& key) -> bool { + return task_json.find(key + "_Doc") || task_json.find(key + "_doc"); + }; + + bool validity = true; + + // 获取 algorithm + std::string algorithm_str = task_json.get("algorithm", "matchtemplate"); + auto to_lower = [](char c) -> char { return static_cast(std::tolower(c)); }; + ranges::transform(algorithm_str, algorithm_str.begin(), to_lower); + auto algorithm = get_algorithm_type(algorithm_str); + if (algorithm == AlgorithmType::Invalid) [[unlikely]] { + Log.error(task_name, "has unknown algorithm:", algorithm_str); + validity = false; + } + + std::string action_str = task_json.get("action", "donothing"); + ranges::transform(action_str, action_str.begin(), to_lower); + auto action = get_action_type(action_str); + if (action == ProcessTaskAction::Invalid) [[unlikely]] { + Log.error(task_name, "has unknown action:", algorithm_str); + validity = false; + } + + std::unordered_set allowed_key {}; + if (allowed_key_under_algorithm.contains(algorithm)) { + decltype(allowed_key) tmp = allowed_key_under_algorithm.at(algorithm); + allowed_key.merge(tmp); + } + if (allowed_key_under_action.contains(action)) { + decltype(allowed_key) tmp = allowed_key_under_action.at(action); + allowed_key.merge(tmp); + } + + // TODO: 之后也许还要对 key-value 联合检查,json 先留着 + for (const auto& [name, json] : task_json.as_object()) { + if (!allowed_key.contains(name) && !is_doc(name) && !has_doc(name)) { + Log.error(task_name, "has unknown key:", name); + validity = false; + } + } + return validity; +} +#endif diff --git a/src/MeoAssistant/TaskData.h b/src/MeoAssistant/TaskData.h index 72016275e7..a329722da4 100644 --- a/src/MeoAssistant/TaskData.h +++ b/src/MeoAssistant/TaskData.h @@ -6,6 +6,8 @@ #include #include +#include "Utils/AsstTypes.h" + namespace asst { struct TaskInfo; @@ -43,9 +45,62 @@ namespace asst protected: virtual bool parse(const json::value& json) override; + + private: + static AlgorithmType get_algorithm_type(std::string_view algorithm_str) + { + if (algorithm_str == "matchtemplate") { + return AlgorithmType::MatchTemplate; + } + else if (algorithm_str == "justreturn") { + return AlgorithmType::JustReturn; + } + else if (algorithm_str == "ocrdetect") { + return AlgorithmType::OcrDetect; + } + else if (algorithm_str == "hash") { + return AlgorithmType::Hash; + } + return AlgorithmType::Invalid; + } + + static ProcessTaskAction get_action_type(std::string_view action_str) + { + if (action_str == "clickself") { + return ProcessTaskAction::ClickSelf; + } + else if (action_str == "clickrand") { + return ProcessTaskAction::ClickRand; + } + else if (action_str == "donothing" || action_str.empty()) { + return ProcessTaskAction::DoNothing; + } + else if (action_str == "stop") { + return ProcessTaskAction::Stop; + } + else if (action_str == "clickrect") { + return ProcessTaskAction::ClickRect; + } + else if (action_str == "swipetotheleft") { + return ProcessTaskAction::SwipeToTheLeft; + } + else if (action_str == "swipetotheright") { + return ProcessTaskAction::SwipeToTheRight; + } + else if (action_str == "slowlyswipetotheleft") { + return ProcessTaskAction::SlowlySwipeToTheLeft; + } + else if (action_str == "slowlyswipetotheright") { + return ProcessTaskAction::SlowlySwipeToTheRight; + } + return ProcessTaskAction::Invalid; + } + #ifdef ASST_DEBUG - bool syntax_check(std::string_view task_name, const json::value& json); + bool syntax_check(std::string_view task_name, const json::value& task_json); #endif + + protected: std::unordered_map> m_all_tasks_info; std::unordered_set m_templ_required; };