From 11d7515121dd0f4bcbc9a703d8c1ea22823c7b43 Mon Sep 17 00:00:00 2001 From: MistEO Date: Wed, 29 Sep 2021 11:30:09 +0800 Subject: [PATCH] =?UTF-8?q?style.=E7=BB=9F=E4=B8=80=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E7=BC=A9=E8=BF=9B=E3=80=81=E6=8B=AC=E5=8F=B7=E6=8D=A2=E8=A1=8C?= =?UTF-8?q?=EF=BC=8C=E6=89=80=E6=9C=89=E4=BB=A3=E7=A0=81=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/AsstCaller.h | 36 +- resource/infrast.json | 78 +- resource/tasks.json | 2 +- src/MeoAssistance/AbstractConfiger.cpp | 50 +- src/MeoAssistance/AbstractConfiger.h | 28 +- src/MeoAssistance/AbstractTask.cpp | 108 +- src/MeoAssistance/AbstractTask.h | 64 +- src/MeoAssistance/Assistance.cpp | 993 +++++++++--------- src/MeoAssistance/Assistance.h | 122 +-- src/MeoAssistance/AsstAux.h | 222 ++-- src/MeoAssistance/AsstCaller.cpp | 156 +-- src/MeoAssistance/AsstDef.h | 394 +++---- src/MeoAssistance/AsstMsg.h | 167 ++- src/MeoAssistance/Configer.cpp | 88 +- src/MeoAssistance/Configer.h | 52 +- src/MeoAssistance/CreditShoppingTask.cpp | 188 ++-- src/MeoAssistance/CreditShoppingTask.h | 1 - src/MeoAssistance/Identify.cpp | 657 ++++++------ src/MeoAssistance/Identify.h | 108 +- src/MeoAssistance/IdentifyOperTask.cpp | 251 +++-- src/MeoAssistance/IdentifyOperTask.h | 26 +- src/MeoAssistance/InfrastAbstractTask.cpp | 536 +++++----- src/MeoAssistance/InfrastAbstractTask.h | 70 +- src/MeoAssistance/InfrastConfiger.cpp | 77 +- src/MeoAssistance/InfrastConfiger.h | 46 +- src/MeoAssistance/InfrastDormTask.cpp | 582 +++++----- src/MeoAssistance/InfrastDormTask.h | 70 +- src/MeoAssistance/InfrastOfficeTask.cpp | 100 +- src/MeoAssistance/InfrastOfficeTask.h | 24 +- src/MeoAssistance/InfrastPowerTask.cpp | 178 ++-- src/MeoAssistance/InfrastPowerTask.h | 30 +- src/MeoAssistance/InfrastProductionTask.cpp | 465 ++++---- src/MeoAssistance/InfrastProductionTask.h | 48 +- src/MeoAssistance/Logger.hpp | 232 ++-- src/MeoAssistance/OcrAbstractTask.cpp | 38 +- src/MeoAssistance/OcrAbstractTask.h | 156 +-- src/MeoAssistance/OpenRecruitTask.cpp | 382 +++---- src/MeoAssistance/OpenRecruitTask.h | 22 +- src/MeoAssistance/ProcessTask.cpp | 566 +++++----- src/MeoAssistance/ProcessTask.h | 34 +- src/MeoAssistance/RecruitConfiger.cpp | 56 +- src/MeoAssistance/RecruitConfiger.h | 40 +- src/MeoAssistance/ScreenCaptureTask.cpp | 16 +- src/MeoAssistance/TaskConfiger.cpp | 316 +++--- src/MeoAssistance/TaskConfiger.h | 1 - src/MeoAssistance/UserConfiger.cpp | 38 +- src/MeoAssistance/UserConfiger.h | 1 - src/MeoAssistance/Version.h | 2 +- src/MeoAssistance/WinMacro.cpp | 704 ++++++------- src/MeoAssistance/WinMacro.h | 104 +- src/MeoAsstGui/App.xaml | 8 +- src/MeoAsstGui/App.xaml.cs | 6 +- src/MeoAsstGui/Helper/AsstProxy.cs | 5 +- src/MeoAsstGui/Helper/ViewStatusStorage.cs | 9 +- src/MeoAsstGui/Properties/AssemblyInfo.cs | 12 +- src/MeoAsstGui/Resources/Icon.xaml | 2 +- src/MeoAsstGui/Resources/Styles.xaml | 4 +- .../SanityParamSettingUserControl.xaml | 1 - .../ViewModels/MainFunctionViewModel.cs | 14 +- src/MeoAsstGui/ViewModels/RootViewModel.cs | 6 +- .../ViewModels/VersionUpdateViewModel.cs | 16 +- src/MeoAsstGui/Views/MainFunctionView.xaml | 4 +- tools/TestCaller/main.cpp | 52 +- 63 files changed, 4444 insertions(+), 4420 deletions(-) diff --git a/include/AsstCaller.h b/include/AsstCaller.h index 2460175686..4ecc59743a 100644 --- a/include/AsstCaller.h +++ b/include/AsstCaller.h @@ -5,29 +5,29 @@ #ifdef __cplusplus extern "C" { #endif - typedef void (MEO_CALL* AsstCallback)(int msg, const char* detail_json, void* custom_arg); + typedef void (MEO_CALL* AsstCallback)(int msg, const char* detail_json, void* custom_arg); - MEOAPI_PORT void* MEO_CALL AsstCreate(); - MEOAPI_PORT void* MEO_CALL AsstCreateEx(AsstCallback callback, void* custom_arg); - void MEOAPI AsstDestory(void* p_asst); + MEOAPI_PORT void* MEO_CALL AsstCreate(); + MEOAPI_PORT void* MEO_CALL AsstCreateEx(AsstCallback callback, void* custom_arg); + void MEOAPI AsstDestory(void* p_asst); - bool MEOAPI AsstCatchDefault(void* p_asst); - bool MEOAPI AsstCatchEmulator(void* p_asst); - bool MEOAPI AsstCatchUSB(void* p_asst); - bool MEOAPI AsstCatchRemote(void* p_asst, const char* address); + bool MEOAPI AsstCatchDefault(void* p_asst); + bool MEOAPI AsstCatchEmulator(void* p_asst); + bool MEOAPI AsstCatchUSB(void* p_asst); + bool MEOAPI AsstCatchRemote(void* p_asst, const char* address); - bool MEOAPI AsstStartSanity(void* p_asst); - bool MEOAPI AsstStartVisit(void* p_asst, bool with_shopping); - bool MEOAPI AsstStartProcessTask(void* p_asst, const char* task); - bool MEOAPI AsstStartOpenRecruit(void* p_asst, const int required_level[], int required_len, bool set_time); - bool MEOAPI AsstStartIndertifyOpers(void* p_asst); - bool MEOAPI AsstStartInfrast(void* p_asst); - bool MEOAPI AsstStartDebugTask(void* p_asst); + bool MEOAPI AsstStartSanity(void* p_asst); + bool MEOAPI AsstStartVisit(void* p_asst, bool with_shopping); + bool MEOAPI AsstStartProcessTask(void* p_asst, const char* task); + bool MEOAPI AsstStartOpenRecruit(void* p_asst, const int required_level[], int required_len, bool set_time); + bool MEOAPI AsstStartIndertifyOpers(void* p_asst); + bool MEOAPI AsstStartInfrast(void* p_asst); + bool MEOAPI AsstStartDebugTask(void* p_asst); - void MEOAPI AsstStop(void* p_asst); - bool MEOAPI AsstSetParam(void* p_asst, const char* type, const char* param, const char* value); + void MEOAPI AsstStop(void* p_asst); + bool MEOAPI AsstSetParam(void* p_asst, const char* type, const char* param, const char* value); - MEOAPI_PORT const char* MEO_CALL AsstGetVersion(); + MEOAPI_PORT const char* MEO_CALL AsstGetVersion(); #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/resource/infrast.json b/resource/infrast.json index d90cfd3e40..9fe281afc8 100644 --- a/resource/infrast.json +++ b/resource/infrast.json @@ -572,7 +572,6 @@ "efficiency": 10 } ], - "endFlag": [ "安洁莉娜", "嵯峨", @@ -840,21 +839,72 @@ ], "featureKey_Doc": "特征检测的关键字,如果OCR识别到了左边的内容,但是却没有右边的内容,则进行特征检测进一步确认", "featureKey": [ - [ "森", "森蚺" ], - [ "白面", "白面鸮" ], - [ "灰", "灰烬" ], - [ "早", "早露" ], - [ "石", "燧石" ], - [ "深", "深靛" ], - [ "影", "傀影" ], - [ "峨", "嵯峨" ], - [ "利安", "卡涅利安" ], - [ "星", "陨星" ], - [ "冬", "凛冬" ], - [ "狮", "狮蝎" ] + [ + "森", + "森蚺" + ], + [ + "白面", + "白面鸮" + ], + [ + "灰", + "灰烬" + ], + [ + "早", + "早露" + ], + [ + "石", + "燧石" + ], + [ + "深", + "深靛" + ], + [ + "影", + "傀影" + ], + [ + "峨", + "嵯峨" + ], + [ + "利安", + "卡涅利安" + ], + [ + "星", + "陨星" + ], + [ + "冬", + "凛冬" + ], + [ + "狮", + "狮蝎" + ] ], "featureWhatever_Doc": "这里面的无论如何都进行特征检测", - "featureWhatever": [ "砾", "煌", "山", "黑", "W", "夕", "红", "芬", "梅", "宴", "孑", "吽", "空", "阿" ], + "featureWhatever": [ + "砾", + "煌", + "山", + "黑", + "W", + "夕", + "红", + "芬", + "梅", + "宴", + "孑", + "吽", + "空", + "阿" + ], "allNames": [ "桃金娘", "食铁兽", diff --git a/resource/tasks.json b/resource/tasks.json index 4125d2915d..f64fc1e3c6 100644 --- a/resource/tasks.json +++ b/resource/tasks.json @@ -218,7 +218,7 @@ "StartButton1", "StartButton2", "Loading" - ], + ], "next": [ "StartToWakeUp", "OfflineConfirm" diff --git a/src/MeoAssistance/AbstractConfiger.cpp b/src/MeoAssistance/AbstractConfiger.cpp index b9dba503fe..9dc8be4d2b 100644 --- a/src/MeoAssistance/AbstractConfiger.cpp +++ b/src/MeoAssistance/AbstractConfiger.cpp @@ -10,34 +10,34 @@ bool asst::AbstractConfiger::load(const std::string& filename) { - DebugTraceFunction; - DebugTrace("Configer::load | ", filename); + DebugTraceFunction; + DebugTrace("Configer::load | ", filename); - std::ifstream ifs(filename, std::ios::in); - if (!ifs.is_open()) { - return false; - } - std::stringstream iss; - iss << ifs.rdbuf(); - ifs.close(); - std::string content(iss.str()); + std::ifstream ifs(filename, std::ios::in); + if (!ifs.is_open()) { + return false; + } + std::stringstream iss; + iss << ifs.rdbuf(); + ifs.close(); + std::string content(iss.str()); - auto&& ret = json::parser::parse(content); - if (!ret) { - DebugTrace("parse error", content); - return false; - } + auto&& ret = json::parser::parse(content); + if (!ret) { + DebugTrace("parse error", content); + return false; + } - json::value root = std::move(ret.value()); + json::value root = std::move(ret.value()); - try { - parse(root); - } - catch (json::exception& e) { - DebugTraceError("Load config json error!", e.what()); - return false; - } + try { + parse(root); + } + catch (json::exception& e) { + DebugTraceError("Load config json error!", e.what()); + return false; + } - DebugTrace("Load config succeed"); - return true; + DebugTrace("Load config succeed"); + return true; } \ No newline at end of file diff --git a/src/MeoAssistance/AbstractConfiger.h b/src/MeoAssistance/AbstractConfiger.h index a1a71313a9..9df0f2e8ce 100644 --- a/src/MeoAssistance/AbstractConfiger.h +++ b/src/MeoAssistance/AbstractConfiger.h @@ -7,24 +7,24 @@ #include "AsstDef.h" namespace json { - class value; + class value; } namespace asst { - class AbstractConfiger - { - public: - virtual ~AbstractConfiger() = default; - virtual bool load(const std::string& filename); + class AbstractConfiger + { + public: + virtual ~AbstractConfiger() = default; + virtual bool load(const std::string& filename); - protected: - AbstractConfiger() = default; - AbstractConfiger(const AbstractConfiger& rhs) = default; - AbstractConfiger(AbstractConfiger&& rhs) noexcept = default; + protected: + AbstractConfiger() = default; + AbstractConfiger(const AbstractConfiger& rhs) = default; + AbstractConfiger(AbstractConfiger&& rhs) noexcept = default; - AbstractConfiger& operator=(const AbstractConfiger& rhs) = default; - AbstractConfiger& operator=(AbstractConfiger&& rhs) noexcept = default; + AbstractConfiger& operator=(const AbstractConfiger& rhs) = default; + AbstractConfiger& operator=(AbstractConfiger&& rhs) noexcept = default; - virtual bool parse(const json::value& json) = 0; - }; + virtual bool parse(const json::value& json) = 0; + }; } diff --git a/src/MeoAssistance/AbstractTask.cpp b/src/MeoAssistance/AbstractTask.cpp index 69bf975cf4..441ea91c2b 100644 --- a/src/MeoAssistance/AbstractTask.cpp +++ b/src/MeoAssistance/AbstractTask.cpp @@ -15,95 +15,95 @@ using namespace asst; AbstractTask::AbstractTask(AsstCallback callback, void* callback_arg) - :m_callback(callback), - m_callback_arg(callback_arg) + : m_callback(callback), + m_callback_arg(callback_arg) { - ; + ; } void AbstractTask::set_ptr( - std::shared_ptr controller_ptr, - std::shared_ptr identify_ptr) + std::shared_ptr controller_ptr, + std::shared_ptr identify_ptr) { - m_controller_ptr = controller_ptr; - m_identify_ptr = identify_ptr; + m_controller_ptr = controller_ptr; + m_identify_ptr = identify_ptr; } void AbstractTask::set_exit_flag(bool* exit_flag) { - m_exit_flag = exit_flag; + m_exit_flag = exit_flag; } bool AbstractTask::sleep(unsigned millisecond) { - if (need_exit()) { - return false; - } - if (millisecond == 0) { - return true; - } - auto start = std::chrono::system_clock::now(); - unsigned duration = 0; + if (need_exit()) { + return false; + } + if (millisecond == 0) { + return true; + } + auto start = std::chrono::system_clock::now(); + unsigned duration = 0; - json::value callback_json; - callback_json["time"] = millisecond; - m_callback(AsstMsg::ReadyToSleep, callback_json, m_callback_arg); + json::value callback_json; + callback_json["time"] = millisecond; + m_callback(AsstMsg::ReadyToSleep, callback_json, m_callback_arg); - while (!need_exit() && duration < millisecond) { - duration = std::chrono::duration_cast( - std::chrono::system_clock::now() - start).count(); - std::this_thread::yield(); - } - m_callback(AsstMsg::EndOfSleep, callback_json, m_callback_arg); + while (!need_exit() && duration < millisecond) { + duration = std::chrono::duration_cast( + std::chrono::system_clock::now() - start).count(); + std::this_thread::yield(); + } + m_callback(AsstMsg::EndOfSleep, callback_json, m_callback_arg); - return !need_exit(); + return !need_exit(); } bool AbstractTask::print_window(const std::string& dir, bool raw) { - //const cv::Mat& image = m_controller_ptr->get_image(true); - //if (image.empty()) { - // return false; - //} - // 现在用adb直接截图了,不用裁剪了 - //// 保存的截图额外再裁剪掉一圈,不然企鹅物流识别不出来 - //int offset = Configer::get_instance().m_options.print_window_crop_offset; - //cv::Rect rect(offset, offset, image.cols - offset * 2, image.rows - offset * 2); + //const cv::Mat& image = m_controller_ptr->get_image(true); + //if (image.empty()) { + // return false; + //} + // 现在用adb直接截图了,不用裁剪了 + //// 保存的截图额外再裁剪掉一圈,不然企鹅物流识别不出来 + //int offset = Configer::get_instance().m_options.print_window_crop_offset; + //cv::Rect rect(offset, offset, image.cols - offset * 2, image.rows - offset * 2); - std::filesystem::create_directory(dir); - const std::string time_str = StringReplaceAll(StringReplaceAll(GetFormatTimeString(), " ", "_"), ":", "-"); - const std::string filename = dir + time_str + ".png"; + std::filesystem::create_directory(dir); + const std::string time_str = StringReplaceAll(StringReplaceAll(GetFormatTimeString(), " ", "_"), ":", "-"); + const std::string filename = dir + time_str + ".png"; - bool ret = cv::imwrite(filename, m_controller_ptr->get_image(raw)); + bool ret = cv::imwrite(filename, m_controller_ptr->get_image(raw)); - json::value callback_json; - callback_json["filename"] = filename; - callback_json["ret"] = ret; - callback_json["offset"] = 0; - m_callback(AsstMsg::PrintWindow, callback_json, m_callback_arg); + json::value callback_json; + callback_json["filename"] = filename; + callback_json["ret"] = ret; + callback_json["offset"] = 0; + m_callback(AsstMsg::PrintWindow, callback_json, m_callback_arg); - return true; + return true; } bool asst::AbstractTask::need_exit() const noexcept { - return m_exit_flag != NULL && *m_exit_flag == true; + return m_exit_flag != NULL && *m_exit_flag == true; } bool asst::AbstractTask::is_ptr_inited() const noexcept { - if (m_controller_ptr == NULL - || m_identify_ptr == NULL) - { - return false; - } - return true; + if (m_controller_ptr == NULL + || m_identify_ptr == NULL) + { + return false; + } + return true; } bool asst::AbstractTask::click_return_button() { - DebugTraceFunction; + DebugTraceFunction; - const static Rect ConfirmButtonRect(20, 20, 135, 35); - return m_controller_ptr->click(ConfirmButtonRect); + const static Rect ConfirmButtonRect(20, 20, 135, 35); + return m_controller_ptr->click(ConfirmButtonRect); } \ No newline at end of file diff --git a/src/MeoAssistance/AbstractTask.h b/src/MeoAssistance/AbstractTask.h index abf73bfe1c..79f897f31d 100644 --- a/src/MeoAssistance/AbstractTask.h +++ b/src/MeoAssistance/AbstractTask.h @@ -6,45 +6,45 @@ namespace cv { - class Mat; + class Mat; } namespace asst { - class WinMacro; - class Identify; + class WinMacro; + class Identify; - class AbstractTask - { - public: - AbstractTask(AsstCallback callback, void* callback_arg); - virtual ~AbstractTask() = default; - AbstractTask(const AbstractTask&) = default; - AbstractTask(AbstractTask&&) = default; + class AbstractTask + { + public: + AbstractTask(AsstCallback callback, void* callback_arg); + virtual ~AbstractTask() = default; + AbstractTask(const AbstractTask&) = default; + AbstractTask(AbstractTask&&) = default; - virtual void set_ptr(std::shared_ptr controller_ptr, std::shared_ptr identify_ptr); - virtual bool run() = 0; + virtual void set_ptr(std::shared_ptr controller_ptr, std::shared_ptr identify_ptr); + virtual bool run() = 0; - virtual void set_exit_flag(bool* exit_flag); - virtual void set_retry_times(int times) { m_retry_times = times; } - virtual int get_retry_times() { return m_retry_times; } - virtual void set_task_chain(std::string name) { m_task_chain = std::move(name); } - virtual const std::string& get_task_chain() { return m_task_chain; } - virtual void on_run_fails(int retry_times) { ; } - protected: - virtual bool sleep(unsigned millisecond); - virtual bool print_window(const std::string& dir, bool raw = true); - virtual bool need_exit() const noexcept; - virtual bool is_ptr_inited() const noexcept; + virtual void set_exit_flag(bool* exit_flag); + virtual void set_retry_times(int times) { m_retry_times = times; } + virtual int get_retry_times() { return m_retry_times; } + virtual void set_task_chain(std::string name) { m_task_chain = std::move(name); } + virtual const std::string& get_task_chain() { return m_task_chain; } + virtual void on_run_fails(int retry_times) { ; } + protected: + virtual bool sleep(unsigned millisecond); + virtual bool print_window(const std::string& dir, bool raw = true); + virtual bool need_exit() const noexcept; + virtual bool is_ptr_inited() const noexcept; - virtual bool click_return_button(); + virtual bool click_return_button(); - std::shared_ptr m_controller_ptr = nullptr; - std::shared_ptr m_identify_ptr = nullptr; + std::shared_ptr m_controller_ptr = nullptr; + std::shared_ptr m_identify_ptr = nullptr; - AsstCallback m_callback; - void* m_callback_arg = NULL; - bool* m_exit_flag = NULL; - std::string m_task_chain; - int m_retry_times = INT_MAX; - }; + AsstCallback m_callback; + void* m_callback_arg = NULL; + bool* m_exit_flag = NULL; + std::string m_task_chain; + int m_retry_times = INT_MAX; + }; } \ No newline at end of file diff --git a/src/MeoAssistance/Assistance.cpp b/src/MeoAssistance/Assistance.cpp index 31ecbe070b..f86d3b34e5 100644 --- a/src/MeoAssistance/Assistance.cpp +++ b/src/MeoAssistance/Assistance.cpp @@ -20,692 +20,671 @@ using namespace asst; Assistance::Assistance(AsstCallback callback, void* callback_arg) - : m_callback(callback), m_callback_arg(callback_arg) + : m_callback(callback), m_callback_arg(callback_arg) { - DebugTraceFunction; + DebugTraceFunction; - // 检查返回值,若为false则回调错误 - auto callback_error = [&](const std::string& filename = std::string()) { - DebugTraceError("Resource error", filename); - if (m_callback == nullptr) { - return; - } - json::value callback_json; - callback_json["filename"] = filename; - callback_json["what"] = "Resource"; - m_callback(AsstMsg::InitFaild, callback_json, m_callback_arg); - }; + // 检查返回值,若为false则回调错误 + auto callback_error = [&](const std::string& filename = std::string()) { + DebugTraceError("Resource error", filename); + if (m_callback == nullptr) { + return; + } + json::value callback_json; + callback_json["filename"] = filename; + callback_json["what"] = "Resource"; + m_callback(AsstMsg::InitFaild, callback_json, m_callback_arg); + }; - bool ret = Configer::get_instance().load(GetResourceDir() + "config.json"); - if (!ret) { - callback_error("config.json"); - return; - } - ret = TaskConfiger::get_instance().load(GetResourceDir() + "tasks.json"); - if (!ret) { - callback_error("tasks.json"); - return; - } - ret = RecruitConfiger::get_instance().load(GetResourceDir() + "recruit.json"); - if (!ret) { - callback_error("recruit.json"); - return; - } - ret = InfrastConfiger::get_instance().load(GetResourceDir() + "infrast.json"); - if (!ret) { - callback_error("infrast.json"); - return; - } + bool ret = Configer::get_instance().load(GetResourceDir() + "config.json"); + if (!ret) { + callback_error("config.json"); + return; + } + ret = TaskConfiger::get_instance().load(GetResourceDir() + "tasks.json"); + if (!ret) { + callback_error("tasks.json"); + return; + } + ret = RecruitConfiger::get_instance().load(GetResourceDir() + "recruit.json"); + if (!ret) { + callback_error("recruit.json"); + return; + } + ret = InfrastConfiger::get_instance().load(GetResourceDir() + "infrast.json"); + if (!ret) { + callback_error("infrast.json"); + return; + } - m_identify_ptr = std::make_shared(); - for (const auto& [name, info] : TaskConfiger::get_instance().m_all_tasks_info) - { - if (info->algorithm != AlgorithmType::MatchTemplate) - { - continue; - } - std::string filename = std::dynamic_pointer_cast(info)->template_filename; - ret = m_identify_ptr->add_image(name, GetResourceDir() + "template\\" + filename); - if (!ret) { - callback_error(filename); - return; - } - } - for (auto& p : std::filesystem::directory_iterator(GetResourceDir() + "template\\special\\")) { - if (p.path().extension() == ".png") { - std::string filename = p.path().filename().u8string(); - std::string without_extension = filename.substr(0, filename.size() - 4); - ret = m_identify_ptr->add_image(without_extension, p.path().u8string()); - } - } + m_identify_ptr = std::make_shared(); + for (const auto& [name, info] : TaskConfiger::get_instance().m_all_tasks_info) { + if (info->algorithm != AlgorithmType::MatchTemplate) { + continue; + } + std::string filename = std::dynamic_pointer_cast(info)->template_filename; + ret = m_identify_ptr->add_image(name, GetResourceDir() + "template\\" + filename); + if (!ret) { + callback_error(filename); + return; + } + } + for (auto& p : std::filesystem::directory_iterator(GetResourceDir() + "template\\special\\")) { + if (p.path().extension() == ".png") { + std::string filename = p.path().filename().u8string(); + std::string without_extension = filename.substr(0, filename.size() - 4); + ret = m_identify_ptr->add_image(without_extension, p.path().u8string()); + } + } - m_identify_ptr->set_ocr_param(Configer::get_instance().m_options.ocr_gpu_index, Configer::get_instance().m_options.ocr_thread_number); - ret = m_identify_ptr->ocr_init_models(GetResourceDir() + "OcrLiteOnnx\\models\\"); - if (!ret) { - callback_error("OcrLiteOnnx\\models\\"); - return; - } + m_identify_ptr->set_ocr_param(Configer::get_instance().m_options.ocr_gpu_index, Configer::get_instance().m_options.ocr_thread_number); + ret = m_identify_ptr->ocr_init_models(GetResourceDir() + "OcrLiteOnnx\\models\\"); + if (!ret) { + callback_error("OcrLiteOnnx\\models\\"); + return; + } - for (const auto& [key, name] : InfrastConfiger::get_instance().m_oper_name_feat) { - ret = m_identify_ptr->add_text_image(name, GetResourceDir() + "operators\\" + Utf8ToGbk(name) + ".png"); - if (!ret) { - callback_error(name); - return; - } - } - for (const auto& name : InfrastConfiger::get_instance().m_oper_name_feat_whatever) { - ret = m_identify_ptr->add_text_image(name, GetResourceDir() + "operators\\" + Utf8ToGbk(name) + ".png"); - if (!ret) { - callback_error(name); - return; - } - } - ret = UserConfiger::get_instance().load(GetCurrentDir() + "user.json"); - if (!ret) { - callback_error("user.json"); - return; - } + for (const auto& [key, name] : InfrastConfiger::get_instance().m_oper_name_feat) { + ret = m_identify_ptr->add_text_image(name, GetResourceDir() + "operators\\" + Utf8ToGbk(name) + ".png"); + if (!ret) { + callback_error(name); + return; + } + } + for (const auto& name : InfrastConfiger::get_instance().m_oper_name_feat_whatever) { + ret = m_identify_ptr->add_text_image(name, GetResourceDir() + "operators\\" + Utf8ToGbk(name) + ".png"); + if (!ret) { + callback_error(name); + return; + } + } + ret = UserConfiger::get_instance().load(GetCurrentDir() + "user.json"); + if (!ret) { + callback_error("user.json"); + return; + } - m_controller_ptr = std::make_shared(); - - m_working_thread = std::thread(std::bind(&Assistance::working_proc, this)); - m_msg_thread = std::thread(std::bind(&Assistance::msg_proc, this)); + m_controller_ptr = std::make_shared(); + + m_working_thread = std::thread(std::bind(&Assistance::working_proc, this)); + m_msg_thread = std::thread(std::bind(&Assistance::msg_proc, this)); } Assistance::~Assistance() { - DebugTraceFunction; + DebugTraceFunction; - //if (m_controller_ptr != nullptr) { - // m_controller_ptr->show_window(); - //} + //if (m_controller_ptr != nullptr) { + // m_controller_ptr->show_window(); + //} - m_thread_exit = true; - m_thread_idle = true; - m_condvar.notify_all(); - m_msg_condvar.notify_all(); + m_thread_exit = true; + m_thread_idle = true; + m_condvar.notify_all(); + m_msg_condvar.notify_all(); - if (m_working_thread.joinable()) { - m_working_thread.join(); - } - if (m_msg_thread.joinable()) { - m_msg_thread.join(); - } + if (m_working_thread.joinable()) { + m_working_thread.join(); + } + if (m_msg_thread.joinable()) { + m_msg_thread.join(); + } } bool asst::Assistance::catch_default() { - DebugTraceFunction; + DebugTraceFunction; - switch (Configer::get_instance().m_options.connect_type) - { - case ConnectType::Emulator: - return catch_emulator(); - case ConnectType::USB: - return catch_usb(); - case ConnectType::Remote: - return catch_remote(Configer::get_instance().m_options.connect_remote_address); - default: - return false; - } + switch (Configer::get_instance().m_options.connect_type) { + case ConnectType::Emulator: + return catch_emulator(); + case ConnectType::USB: + return catch_usb(); + case ConnectType::Remote: + return catch_remote(Configer::get_instance().m_options.connect_remote_address); + default: + return false; + } } bool Assistance::catch_emulator(const std::string& emulator_name) { - DebugTraceFunction; + DebugTraceFunction; - stop(); + stop(); - bool ret = false; - //std::string cor_name = emulator_name; + bool ret = false; + //std::string cor_name = emulator_name; - std::unique_lock lock(m_mutex); + std::unique_lock lock(m_mutex); - // 自动匹配模拟器,逐个找 - if (emulator_name.empty()) { - for (const auto& [name, info] : Configer::get_instance().m_handles) { - ret = m_controller_ptr->try_capture(info); - if (ret) { - //cor_name = name; - break; - } - } - } - else { // 指定的模拟器 - ret = m_controller_ptr->try_capture(Configer::get_instance().m_handles[emulator_name]); - } + // 自动匹配模拟器,逐个找 + if (emulator_name.empty()) { + for (const auto& [name, info] : Configer::get_instance().m_handles) { + ret = m_controller_ptr->try_capture(info); + if (ret) { + //cor_name = name; + break; + } + } + } + else { // 指定的模拟器 + ret = m_controller_ptr->try_capture(Configer::get_instance().m_handles[emulator_name]); + } - m_inited = ret; - return ret; + m_inited = ret; + return ret; } bool asst::Assistance::catch_usb() { - DebugTraceFunction; + DebugTraceFunction; - stop(); + stop(); - bool ret = false; + bool ret = false; - std::unique_lock lock(m_mutex); + std::unique_lock lock(m_mutex); - EmulatorInfo remote_info = Configer::get_instance().m_handles["USB"]; + EmulatorInfo remote_info = Configer::get_instance().m_handles["USB"]; - ret = m_controller_ptr->try_capture(remote_info, true); + ret = m_controller_ptr->try_capture(remote_info, true); - m_inited = ret; - return ret; + m_inited = ret; + return ret; } bool asst::Assistance::catch_remote(const std::string& address) { - DebugTraceFunction; + DebugTraceFunction; - stop(); + stop(); - bool ret = false; + bool ret = false; - std::unique_lock lock(m_mutex); + std::unique_lock lock(m_mutex); - EmulatorInfo remote_info = Configer::get_instance().m_handles["Remote"]; - remote_info.adb.connect = StringReplaceAll(remote_info.adb.connect, "[Address]", address); - remote_info.adb.click = StringReplaceAll(remote_info.adb.click, "[Address]", address); - remote_info.adb.swipe = StringReplaceAll(remote_info.adb.swipe, "[Address]", address); - remote_info.adb.display = StringReplaceAll(remote_info.adb.display, "[Address]", address); - remote_info.adb.screencap = StringReplaceAll(remote_info.adb.screencap, "[Address]", address); + EmulatorInfo remote_info = Configer::get_instance().m_handles["Remote"]; + remote_info.adb.connect = StringReplaceAll(remote_info.adb.connect, "[Address]", address); + remote_info.adb.click = StringReplaceAll(remote_info.adb.click, "[Address]", address); + remote_info.adb.swipe = StringReplaceAll(remote_info.adb.swipe, "[Address]", address); + remote_info.adb.display = StringReplaceAll(remote_info.adb.display, "[Address]", address); + remote_info.adb.screencap = StringReplaceAll(remote_info.adb.screencap, "[Address]", address); - ret = m_controller_ptr->try_capture(remote_info, true); + ret = m_controller_ptr->try_capture(remote_info, true); - m_inited = ret; - return ret; + m_inited = ret; + return ret; } bool asst::Assistance::start_sanity() { - return start_process_task("SanityBegin", ProcessTaskRetryTimesDefault); + return start_process_task("SanityBegin", ProcessTaskRetryTimesDefault); } bool asst::Assistance::start_visit(bool with_shopping) { - DebugTraceFunction; - if (!m_thread_idle || !m_inited) { - return false; - } + DebugTraceFunction; + if (!m_thread_idle || !m_inited) { + return false; + } - std::unique_lock lock(m_mutex); - m_identify_ptr->clear_cache(); + std::unique_lock lock(m_mutex); + m_identify_ptr->clear_cache(); - append_match_task("VisitBegin", { "VisitBegin" }, ProcessTaskRetryTimesDefault); + append_match_task("VisitBegin", { "VisitBegin" }, ProcessTaskRetryTimesDefault); - if (with_shopping) { - auto shopping_task_ptr = std::make_shared(task_callback, (void*)this); - shopping_task_ptr->set_task_chain("VisitBegin"); - m_tasks_deque.emplace_back(shopping_task_ptr); - } + if (with_shopping) { + auto shopping_task_ptr = std::make_shared(task_callback, (void*)this); + shopping_task_ptr->set_task_chain("VisitBegin"); + m_tasks_deque.emplace_back(shopping_task_ptr); + } - m_thread_idle = false; - m_condvar.notify_one(); + m_thread_idle = false; + m_condvar.notify_one(); - return true; + return true; } bool Assistance::start_process_task(const std::string& task, int retry_times, bool block) { - DebugTraceFunction; - DebugTrace("Start |", task, block ? "block" : "non block"); - if (!m_thread_idle || !m_inited) - { - return false; - } + DebugTraceFunction; + DebugTrace("Start |", task, block ? "block" : "non block"); + if (!m_thread_idle || !m_inited) { + return false; + } - std::unique_lock lock; - if (block) - { - lock = std::unique_lock(m_mutex); - //clear_exec_times(); - m_identify_ptr->clear_cache(); - } + std::unique_lock lock; + if (block) { + lock = std::unique_lock(m_mutex); + //clear_exec_times(); + m_identify_ptr->clear_cache(); + } - append_match_task(task, { task }, retry_times); + append_match_task(task, { task }, retry_times); - m_thread_idle = false; - m_condvar.notify_one(); + m_thread_idle = false; + m_condvar.notify_one(); - return true; + return true; } #ifdef LOG_TRACE bool Assistance::start_debug_task() { - DebugTraceFunction; - if (!m_thread_idle || !m_inited) - { - return false; - } + DebugTraceFunction; + if (!m_thread_idle || !m_inited) { + return false; + } - std::unique_lock lock(m_mutex); + std::unique_lock lock(m_mutex); - //{ - // append_match_task("Debug", {"UavAssist-MFG"}); - //} - //{ - // constexpr static const char* InfrastTaskCahin = "Debug"; - // auto shift_task_ptr = std::make_shared(task_callback, (void*)this); + //{ + // append_match_task("Debug", {"UavAssist-MFG"}); + //} + //{ + // constexpr static const char* InfrastTaskCahin = "Debug"; + // auto shift_task_ptr = std::make_shared(task_callback, (void*)this); - // auto ret = get_opers_idtf_result(); - // if (!ret) { - // DebugTraceInfo("Get opers info error"); - // //return false; - // } - // else { - // shift_task_ptr->set_all_opers_info(std::move(ret.value())); - // } - // shift_task_ptr->set_task_chain(InfrastTaskCahin); - // m_tasks_deque.emplace_back(shift_task_ptr); - //} - { - constexpr static const char* DebugTaskChain = "Debug"; - auto shift_task_ptr = std::make_shared(task_callback, (void*)this); - shift_task_ptr->set_task_chain(DebugTaskChain); - m_tasks_deque.emplace_back(shift_task_ptr); - } + // auto ret = get_opers_idtf_result(); + // if (!ret) { + // DebugTraceInfo("Get opers info error"); + // //return false; + // } + // else { + // shift_task_ptr->set_all_opers_info(std::move(ret.value())); + // } + // shift_task_ptr->set_task_chain(InfrastTaskCahin); + // m_tasks_deque.emplace_back(shift_task_ptr); + //} + { + constexpr static const char* DebugTaskChain = "Debug"; + auto shift_task_ptr = std::make_shared(task_callback, (void*)this); + shift_task_ptr->set_task_chain(DebugTaskChain); + m_tasks_deque.emplace_back(shift_task_ptr); + } - m_thread_idle = false; - m_condvar.notify_one(); + m_thread_idle = false; + m_condvar.notify_one(); - return true; + return true; } #endif bool Assistance::start_open_recruit(const std::vector& required_level, bool set_time) { - DebugTraceFunction; - if (!m_thread_idle || !m_inited) - { - return false; - } + DebugTraceFunction; + if (!m_thread_idle || !m_inited) { + return false; + } - std::unique_lock lock(m_mutex); + std::unique_lock lock(m_mutex); - auto task_ptr = std::make_shared(task_callback, (void*)this); - task_ptr->set_param(required_level, set_time); - task_ptr->set_retry_times(OpenRecruitTaskRetyrTimesDefault); - task_ptr->set_task_chain("OpenRecruit"); - m_tasks_deque.emplace_back(task_ptr); + auto task_ptr = std::make_shared(task_callback, (void*)this); + task_ptr->set_param(required_level, set_time); + task_ptr->set_retry_times(OpenRecruitTaskRetyrTimesDefault); + task_ptr->set_task_chain("OpenRecruit"); + m_tasks_deque.emplace_back(task_ptr); - m_thread_idle = false; - m_condvar.notify_one(); + m_thread_idle = false; + m_condvar.notify_one(); - return true; + return true; } bool asst::Assistance::start_to_identify_opers() { - DebugTraceFunction; - if (!m_thread_idle || !m_inited) - { - return false; - } + DebugTraceFunction; + if (!m_thread_idle || !m_inited) { + return false; + } - std::unique_lock lock(m_mutex); + std::unique_lock lock(m_mutex); - append_match_task("IdentifyOpers", { "OperatorBegin" }); + append_match_task("IdentifyOpers", { "OperatorBegin" }); - auto task_ptr = std::make_shared(task_callback, (void*)this); - task_ptr->set_task_chain("IdentifyOpers"); - m_tasks_deque.emplace_back(task_ptr); + auto task_ptr = std::make_shared(task_callback, (void*)this); + task_ptr->set_task_chain("IdentifyOpers"); + m_tasks_deque.emplace_back(task_ptr); - m_thread_idle = false; - m_condvar.notify_one(); + m_thread_idle = false; + m_condvar.notify_one(); - return true; + return true; } bool asst::Assistance::start_infrast() { - DebugTraceFunction; - if (!m_thread_idle || !m_inited) - { - return false; - } + DebugTraceFunction; + if (!m_thread_idle || !m_inited) { + return false; + } - std::unique_lock lock(m_mutex); - auto ret = get_opers_idtf_result(); - if (!ret) { - DebugTraceInfo("Get opers info error"); - return false; - } - constexpr static const char* InfrastTaskCahin = "Infrast"; - // 换班任务,依次遍历基建设施列表里的最多5个设施,识别并选择最优解干员组合 - auto shift_task_ptr = std::make_shared(task_callback, (void*)this); - shift_task_ptr->set_task_chain(InfrastTaskCahin); - shift_task_ptr->set_all_opers_info(std::move(ret.value())); + std::unique_lock lock(m_mutex); + auto ret = get_opers_idtf_result(); + if (!ret) { + DebugTraceInfo("Get opers info error"); + return false; + } + constexpr static const char* InfrastTaskCahin = "Infrast"; + // 换班任务,依次遍历基建设施列表里的最多5个设施,识别并选择最优解干员组合 + auto shift_task_ptr = std::make_shared(task_callback, (void*)this); + shift_task_ptr->set_task_chain(InfrastTaskCahin); + shift_task_ptr->set_all_opers_info(std::move(ret.value())); - /* 基建任务整体流程: - 1. 从任意界面进入基建,使用ProcessTask - 2. 一键收获贸易站、制造站、干员信赖,使用ProcessTask - 1) 如果收获了,使用基建全缩放到最小的模板匹配 - 2) 如果没收获,使用基建默认大小的模板匹配 - 3. 进入宿舍,把心情低于阈值的、心情没满但不在工作的,都换下去,使用InfrastDormTask - 4. 根据用户设置,按顺序进入制造站or贸易站,使用ProcessTask - 5. 对制造站or贸易站进行换班,使用InfrastStationTask - 6. 根据用户设置,使用无人机加速制造or贸易,使用ProcessTask - 7. 会客室线索处理、发电站换班、控制中枢、办公室换班,同样需要根据用户设置决定顺序,TODO - 8. 再次进入宿舍,把基建中可能换下来的干员(心情不低的)加入宿舍 - */ + /* 基建任务整体流程: + 1. 从任意界面进入基建,使用ProcessTask + 2. 一键收获贸易站、制造站、干员信赖,使用ProcessTask + 1) 如果收获了,使用基建全缩放到最小的模板匹配 + 2) 如果没收获,使用基建默认大小的模板匹配 + 3. 进入宿舍,把心情低于阈值的、心情没满但不在工作的,都换下去,使用InfrastDormTask + 4. 根据用户设置,按顺序进入制造站or贸易站,使用ProcessTask + 5. 对制造站or贸易站进行换班,使用InfrastStationTask + 6. 根据用户设置,使用无人机加速制造or贸易,使用ProcessTask + 7. 会客室线索处理、发电站换班、控制中枢、办公室换班,同样需要根据用户设置决定顺序,TODO + 8. 再次进入宿舍,把基建中可能换下来的干员(心情不低的)加入宿舍 + */ - // 1. 从任意界面进入基建,使用ProcessTask - // 2. 一键收获贸易站、制造站、干员信赖,使用ProcessTask - // 这个任务结束后,是在进入基建后的主界面 - append_match_task(InfrastTaskCahin, { "InfrastBegin" }); + // 1. 从任意界面进入基建,使用ProcessTask + // 2. 一键收获贸易站、制造站、干员信赖,使用ProcessTask + // 这个任务结束后,是在进入基建后的主界面 + append_match_task(InfrastTaskCahin, { "InfrastBegin" }); - // 3. 进入宿舍,把心情低于阈值的、心情没满但不在工作的,都换下去 - auto dorm_task_ptr = std::make_shared(task_callback, (void*)this); - dorm_task_ptr->set_task_chain(InfrastTaskCahin); - m_tasks_deque.emplace_back(dorm_task_ptr); + // 3. 进入宿舍,把心情低于阈值的、心情没满但不在工作的,都换下去 + auto dorm_task_ptr = std::make_shared(task_callback, (void*)this); + dorm_task_ptr->set_task_chain(InfrastTaskCahin); + m_tasks_deque.emplace_back(dorm_task_ptr); - // 返回基建的主界面 - append_match_task(InfrastTaskCahin, { "InfrastBegin" }); + // 返回基建的主界面 + append_match_task(InfrastTaskCahin, { "InfrastBegin" }); - // 5. 对制造站or贸易站进行换班,使用InfrastStationTask + // 5. 对制造站or贸易站进行换班,使用InfrastStationTask - // TODO,这里需要根据用户设置,是先制造站还是先贸易站,或者是别的设施 - // 从进入制造站,到设施列表的界面 - append_match_task(InfrastTaskCahin, { "ManufacturingMini", "Manufacturing" }); + // TODO,这里需要根据用户设置,是先制造站还是先贸易站,或者是别的设施 + // 从进入制造站,到设施列表的界面 + append_match_task(InfrastTaskCahin, { "ManufacturingMini", "Manufacturing" }); - // 制造站换班 - m_tasks_deque.emplace_back(shift_task_ptr); + // 制造站换班 + m_tasks_deque.emplace_back(shift_task_ptr); - // 返回基建的主界面 - append_match_task(InfrastTaskCahin, { "InfrastBegin" }); + // 返回基建的主界面 + append_match_task(InfrastTaskCahin, { "InfrastBegin" }); - // TODO,这里需要根据用户设置,是先制造站还是先贸易站,或者是别的设施 - // 从进入贸易站,到设施列表的界面 - append_match_task(InfrastTaskCahin, { "Trade", "TradeMini" }); + // TODO,这里需要根据用户设置,是先制造站还是先贸易站,或者是别的设施 + // 从进入贸易站,到设施列表的界面 + append_match_task(InfrastTaskCahin, { "Trade", "TradeMini" }); - // 贸易站换班 - m_tasks_deque.emplace_back(shift_task_ptr); + // 贸易站换班 + m_tasks_deque.emplace_back(shift_task_ptr); - // 6. 根据用户设置,使用无人机加速制造or贸易,使用ProcessTask - // 对贸易站使用无人机加速 - append_match_task(InfrastTaskCahin, { "UavAssist-Trade" }); + // 6. 根据用户设置,使用无人机加速制造or贸易,使用ProcessTask + // 对贸易站使用无人机加速 + append_match_task(InfrastTaskCahin, { "UavAssist-Trade" }); - // 返回基建的主界面 - append_match_task(InfrastTaskCahin, { "InfrastBegin" }); + // 返回基建的主界面 + append_match_task(InfrastTaskCahin, { "InfrastBegin" }); - // 7. 会客室线索处理、发电站换班、控制中枢、办公室换班,同样需要根据用户设置决定顺序,TODO - // 发电站换班 - auto power_task_ptr = std::make_shared(task_callback, (void*)this); - power_task_ptr->set_task_chain(InfrastTaskCahin); - m_tasks_deque.emplace_back(std::move(power_task_ptr)); + // 7. 会客室线索处理、发电站换班、控制中枢、办公室换班,同样需要根据用户设置决定顺序,TODO + // 发电站换班 + auto power_task_ptr = std::make_shared(task_callback, (void*)this); + power_task_ptr->set_task_chain(InfrastTaskCahin); + m_tasks_deque.emplace_back(std::move(power_task_ptr)); - // 返回基建的主界面 - append_match_task(InfrastTaskCahin, { "InfrastBegin" }); + // 返回基建的主界面 + append_match_task(InfrastTaskCahin, { "InfrastBegin" }); - auto office_task_ptr = std::make_shared(task_callback, (void*)this); - office_task_ptr->set_task_chain(InfrastTaskCahin); - m_tasks_deque.emplace_back(std::move(office_task_ptr)); + auto office_task_ptr = std::make_shared(task_callback, (void*)this); + office_task_ptr->set_task_chain(InfrastTaskCahin); + m_tasks_deque.emplace_back(std::move(office_task_ptr)); - // 返回基建的主界面 - append_match_task(InfrastTaskCahin, { "InfrastBegin" }); + // 返回基建的主界面 + append_match_task(InfrastTaskCahin, { "InfrastBegin" }); - // 8. 再次进入宿舍,把基建中可能换下来的干员(心情不低的)加入宿舍 - m_tasks_deque.emplace_back(dorm_task_ptr); + // 8. 再次进入宿舍,把基建中可能换下来的干员(心情不低的)加入宿舍 + m_tasks_deque.emplace_back(dorm_task_ptr); - // 全操作完之后,再返回基建的主界面 - append_match_task(InfrastTaskCahin, { "InfrastBegin" }); + // 全操作完之后,再返回基建的主界面 + append_match_task(InfrastTaskCahin, { "InfrastBegin" }); - m_thread_idle = false; - m_condvar.notify_one(); + m_thread_idle = false; + m_condvar.notify_one(); - return true; + return true; } void Assistance::stop(bool block) { - DebugTraceFunction; - DebugTrace("Stop |", block ? "block" : "non block"); + DebugTraceFunction; + DebugTrace("Stop |", block ? "block" : "non block"); - m_thread_idle = true; + m_thread_idle = true; - std::unique_lock lock; - if (block) - { // 外部调用 - lock = std::unique_lock(m_mutex); - } - decltype(m_tasks_deque) empty; - m_tasks_deque.swap(empty); - clear_exec_times(); - m_identify_ptr->clear_cache(); + std::unique_lock lock; + if (block) { // 外部调用 + lock = std::unique_lock(m_mutex); + } + decltype(m_tasks_deque) empty; + m_tasks_deque.swap(empty); + clear_exec_times(); + m_identify_ptr->clear_cache(); } bool Assistance::set_param(const std::string& type, const std::string& param, const std::string& value) { - DebugTraceFunction; - DebugTrace("SetParam |", type, param, value); + DebugTraceFunction; + DebugTrace("SetParam |", type, param, value); - return TaskConfiger::get_instance().set_param(type, param, value); + return TaskConfiger::get_instance().set_param(type, param, value); } void Assistance::working_proc() { - DebugTraceFunction; - auto p_this = this; + DebugTraceFunction; + auto p_this = this; - int retry_times = 0; - while (!m_thread_exit) { - //DebugTraceScope("Assistance::working_proc Loop"); - std::unique_lock lock(m_mutex); + int retry_times = 0; + while (!m_thread_exit) { + //DebugTraceScope("Assistance::working_proc Loop"); + std::unique_lock lock(m_mutex); - if (!m_thread_idle && !m_tasks_deque.empty()) { - //m_controller_ptr->set_idle(false); + if (!m_thread_idle && !m_tasks_deque.empty()) { + //m_controller_ptr->set_idle(false); - auto start_time = std::chrono::system_clock::now(); - std::shared_ptr task_ptr = m_tasks_deque.front(); - // 先pop出来,如果执行失败再还原回去 - m_tasks_deque.pop_front(); + auto start_time = std::chrono::system_clock::now(); + std::shared_ptr task_ptr = m_tasks_deque.front(); + // 先pop出来,如果执行失败再还原回去 + m_tasks_deque.pop_front(); - task_ptr->set_ptr(m_controller_ptr, m_identify_ptr); - task_ptr->set_exit_flag(&m_thread_idle); - bool ret = task_ptr->run(); - if (ret) { - retry_times = 0; - if (m_tasks_deque.empty()) { - json::value task_all_completed_json; - task_all_completed_json["task_chain"] = task_ptr->get_task_chain(); - task_callback(AsstMsg::TaskChainCompleted, task_all_completed_json, p_this); - } - } - else { - // 失败了累加失败次数,超限了再pop - if (retry_times >= task_ptr->get_retry_times()) { - json::value task_error_json; - task_error_json["retry_limit"] = task_ptr->get_retry_times(); - task_error_json["retry_times"] = retry_times; - task_error_json["task_chain"] = task_ptr->get_task_chain(); - task_callback(AsstMsg::TaskError, task_error_json, p_this); + task_ptr->set_ptr(m_controller_ptr, m_identify_ptr); + task_ptr->set_exit_flag(&m_thread_idle); + bool ret = task_ptr->run(); + if (ret) { + retry_times = 0; + if (m_tasks_deque.empty()) { + json::value task_all_completed_json; + task_all_completed_json["task_chain"] = task_ptr->get_task_chain(); + task_callback(AsstMsg::TaskChainCompleted, task_all_completed_json, p_this); + } + } + else { + // 失败了累加失败次数,超限了再pop + if (retry_times >= task_ptr->get_retry_times()) { + json::value task_error_json; + task_error_json["retry_limit"] = task_ptr->get_retry_times(); + task_error_json["retry_times"] = retry_times; + task_error_json["task_chain"] = task_ptr->get_task_chain(); + task_callback(AsstMsg::TaskError, task_error_json, p_this); - retry_times = 0; - } - else { - ++retry_times; - // 执行失败再还原回去 - m_tasks_deque.emplace_front(task_ptr); - task_ptr->on_run_fails(retry_times); - } - } + retry_times = 0; + } + else { + ++retry_times; + // 执行失败再还原回去 + m_tasks_deque.emplace_front(task_ptr); + task_ptr->on_run_fails(retry_times); + } + } - int& delay = Configer::get_instance().m_options.task_delay; - m_condvar.wait_until(lock, start_time + std::chrono::milliseconds(delay), - [&]() -> bool { return m_thread_idle; }); - } - else { - m_thread_idle = true; - //m_controller_ptr->set_idle(true); - m_condvar.wait(lock); - } - } + int& delay = Configer::get_instance().m_options.task_delay; + m_condvar.wait_until(lock, start_time + std::chrono::milliseconds(delay), + [&]() -> bool { return m_thread_idle; }); + } + else { + m_thread_idle = true; + //m_controller_ptr->set_idle(true); + m_condvar.wait(lock); + } + } } void Assistance::msg_proc() { - DebugTraceFunction; + DebugTraceFunction; - while (!m_thread_exit) - { - //DebugTraceScope("Assistance::msg_proc Loop"); - std::unique_lock lock(m_msg_mutex); - if (!m_msg_queue.empty()) - { - // 结构化绑定只能是引用,后续的pop会使引用失效,所以需要重新构造一份,这里采用了move的方式 - auto&& [temp_msg, temp_detail] = m_msg_queue.front(); - AsstMsg msg = std::move(temp_msg); - json::value detail = std::move(temp_detail); - m_msg_queue.pop(); - lock.unlock(); + while (!m_thread_exit) { + //DebugTraceScope("Assistance::msg_proc Loop"); + std::unique_lock lock(m_msg_mutex); + if (!m_msg_queue.empty()) { + // 结构化绑定只能是引用,后续的pop会使引用失效,所以需要重新构造一份,这里采用了move的方式 + auto&& [temp_msg, temp_detail] = m_msg_queue.front(); + AsstMsg msg = std::move(temp_msg); + json::value detail = std::move(temp_detail); + m_msg_queue.pop(); + lock.unlock(); - if (m_callback) - { - m_callback(msg, detail, m_callback_arg); - } - } - else - { - m_msg_condvar.wait(lock); - } - } + if (m_callback) { + m_callback(msg, detail, m_callback_arg); + } + } + else { + m_msg_condvar.wait(lock); + } + } } void Assistance::task_callback(AsstMsg msg, const json::value& detail, void* custom_arg) { - DebugTrace("Assistance::task_callback |", msg, detail.to_string()); + DebugTrace("Assistance::task_callback |", msg, detail.to_string()); - Assistance* p_this = (Assistance*)custom_arg; - json::value more_detail = detail; - switch (msg) - { - case AsstMsg::PtrIsNull: - case AsstMsg::ImageIsEmpty: - p_this->stop(false); - break; - //case AsstMsg::WindowMinimized: - // p_this->m_controller_ptr->show_window(); - // break; - case AsstMsg::AppendProcessTask: - more_detail["type"] = "ProcessTask"; - [[fallthrough]]; - case AsstMsg::AppendTask: - p_this->append_task(more_detail, true); - return; // 这俩消息Assistance会新增任务,外部不需要处理,直接拦掉 - break; - case AsstMsg::OpersIdtfResult: - set_opers_idtf_result(more_detail); // 保存到文件 - break; - default: - break; - } + Assistance* p_this = (Assistance*)custom_arg; + json::value more_detail = detail; + switch (msg) { + case AsstMsg::PtrIsNull: + case AsstMsg::ImageIsEmpty: + p_this->stop(false); + break; + //case AsstMsg::WindowMinimized: + // p_this->m_controller_ptr->show_window(); + // break; + case AsstMsg::AppendProcessTask: + more_detail["type"] = "ProcessTask"; + [[fallthrough]]; + case AsstMsg::AppendTask: + p_this->append_task(more_detail, true); + return; // 这俩消息Assistance会新增任务,外部不需要处理,直接拦掉 + break; + case AsstMsg::OpersIdtfResult: + set_opers_idtf_result(more_detail); // 保存到文件 + break; + default: + break; + } - // Todo: 有些不需要回调给外部的消息,得在这里给拦截掉 - // 加入回调消息队列,由回调消息线程外抛给外部 - p_this->append_callback(msg, std::move(more_detail)); + // Todo: 有些不需要回调给外部的消息,得在这里给拦截掉 + // 加入回调消息队列,由回调消息线程外抛给外部 + p_this->append_callback(msg, std::move(more_detail)); } void asst::Assistance::append_match_task( - const std::string& task_chain, const std::vector& tasks, int retry_times, bool front) + const std::string& task_chain, const std::vector& tasks, int retry_times, bool front) { - auto task_ptr = std::make_shared(task_callback, (void*)this); - task_ptr->set_task_chain(task_chain); - task_ptr->set_tasks(tasks); - task_ptr->set_retry_times(retry_times); - if (front) { - m_tasks_deque.emplace_front(task_ptr); - } - else { - m_tasks_deque.emplace_back(task_ptr); - } + auto task_ptr = std::make_shared(task_callback, (void*)this); + task_ptr->set_task_chain(task_chain); + task_ptr->set_tasks(tasks); + task_ptr->set_retry_times(retry_times); + if (front) { + m_tasks_deque.emplace_front(task_ptr); + } + else { + m_tasks_deque.emplace_back(task_ptr); + } } void asst::Assistance::append_task(const json::value& detail, bool front) { - std::string task_type = detail.at("type").as_string(); - std::string task_chain = detail.get("task_chain", ""); - int retry_times = detail.get("retry_times", INT_MAX); + std::string task_type = detail.at("type").as_string(); + std::string task_chain = detail.get("task_chain", ""); + int retry_times = detail.get("retry_times", INT_MAX); - if (task_type == "ProcessTask") - { - std::vector next_vec; - if (detail.exist("tasks")) - { - json::array next_arr = detail.at("tasks").as_array(); - for (const json::value& next_json : next_arr) - { - next_vec.emplace_back(next_json.as_string()); - } - } - else if (detail.exist("task")) - { - next_vec.emplace_back(detail.at("task").as_string()); - } - append_match_task(task_chain, next_vec, retry_times, front); - } - // else if // TODO + if (task_type == "ProcessTask") { + std::vector next_vec; + if (detail.exist("tasks")) { + json::array next_arr = detail.at("tasks").as_array(); + for (const json::value& next_json : next_arr) { + next_vec.emplace_back(next_json.as_string()); + } + } + else if (detail.exist("task")) { + next_vec.emplace_back(detail.at("task").as_string()); + } + append_match_task(task_chain, next_vec, retry_times, front); + } + // else if // TODO } void asst::Assistance::append_callback(AsstMsg msg, json::value detail) { - std::unique_lock lock(m_msg_mutex); - m_msg_queue.emplace(msg, std::move(detail)); - m_msg_condvar.notify_one(); + std::unique_lock lock(m_msg_mutex); + m_msg_queue.emplace(msg, std::move(detail)); + m_msg_condvar.notify_one(); } void Assistance::clear_exec_times() { - for (auto&& pair : TaskConfiger::get_instance().m_all_tasks_info) - { - pair.second->exec_times = 0; - } + for (auto&& pair : TaskConfiger::get_instance().m_all_tasks_info) { + pair.second->exec_times = 0; + } } void asst::Assistance::set_opers_idtf_result(const json::value& detail) { - constexpr static const char* Filename = "operators.json"; - std::ofstream ofs(GetCurrentDir() + Filename, std::ios::out); - ofs << detail.format() << std::endl; - ofs.close(); + constexpr static const char* Filename = "operators.json"; + std::ofstream ofs(GetCurrentDir() + Filename, std::ios::out); + ofs << detail.format() << std::endl; + ofs.close(); } std::optional> Assistance::get_opers_idtf_result() { - constexpr static const char* Filename = "operators.json"; - std::ifstream ifs(GetCurrentDir() + Filename, std::ios::in); - if (!ifs.is_open()) { - return std::nullopt; - } - std::stringstream iss; - iss << ifs.rdbuf(); - ifs.close(); - std::string content(iss.str()); + constexpr static const char* Filename = "operators.json"; + std::ifstream ifs(GetCurrentDir() + Filename, std::ios::in); + if (!ifs.is_open()) { + return std::nullopt; + } + std::stringstream iss; + iss << ifs.rdbuf(); + ifs.close(); + std::string content(iss.str()); - auto&& parse_ret = json::parse(content); - if (!parse_ret) { - DebugTraceError(__FUNCTION__, "json parsing error!"); - return std::nullopt; - } - json::value root = std::move(parse_ret.value()); - std::unordered_map opers_info; - try { - for (const json::value& info_json : root["all"].as_array()) - { - OperInfrastInfo info; - info.name = info_json.at("name").as_string(); - info.elite = info_json.at("elite").as_integer(); - info.level = info_json.get("level", 0); - opers_info.emplace(info.name, std::move(info)); - } - } - catch (json::exception& exp) { - DebugTraceError(__FUNCTION__, "json parsing error!", exp.what()); - return std::nullopt; - } - return opers_info; + auto&& parse_ret = json::parse(content); + if (!parse_ret) { + DebugTraceError(__FUNCTION__, "json parsing error!"); + return std::nullopt; + } + json::value root = std::move(parse_ret.value()); + std::unordered_map opers_info; + try { + for (const json::value& info_json : root["all"].as_array()) { + OperInfrastInfo info; + info.name = info_json.at("name").as_string(); + info.elite = info_json.at("elite").as_integer(); + info.level = info_json.get("level", 0); + opers_info.emplace(info.name, std::move(info)); + } + } + catch (json::exception& exp) { + DebugTraceError(__FUNCTION__, "json parsing error!", exp.what()); + return std::nullopt; + } + return opers_info; } \ No newline at end of file diff --git a/src/MeoAssistance/Assistance.h b/src/MeoAssistance/Assistance.h index 3ed66bbc0b..64c91fd35d 100644 --- a/src/MeoAssistance/Assistance.h +++ b/src/MeoAssistance/Assistance.h @@ -13,84 +13,84 @@ #include "Task.h" namespace cv { - class Mat; + class Mat; } namespace asst { - class WinMacro; - class Identify; + class WinMacro; + class Identify; - class Assistance - { - public: - Assistance(AsstCallback callback = nullptr, void* callback_arg = nullptr); - ~Assistance(); + class Assistance + { + public: + Assistance(AsstCallback callback = nullptr, void* callback_arg = nullptr); + ~Assistance(); - // 根据配置文件,决定捕获模拟器、USB 还是远程设备 - bool catch_default(); - // 捕获模拟器 - bool catch_emulator(const std::string& emulator_name = std::string()); - // 捕获usb设备 - bool catch_usb(); - // 捕获远程地址(安卓手机) - bool catch_remote(const std::string& address); + // 根据配置文件,决定捕获模拟器、USB 还是远程设备 + bool catch_default(); + // 捕获模拟器 + bool catch_emulator(const std::string& emulator_name = std::string()); + // 捕获usb设备 + bool catch_usb(); + // 捕获远程地址(安卓手机) + bool catch_remote(const std::string& address); - // 开始刷理智 - bool start_sanity(); - // 开始访问好友基建 - bool start_visit(bool with_shopping = false); + // 开始刷理智 + bool start_sanity(); + // 开始访问好友基建 + bool start_visit(bool with_shopping = false); - // 开始公开招募操作 - bool start_open_recruit(const std::vector& required_level, bool set_time = true); - // 开始干员识别任务 - bool start_to_identify_opers(); - // 开始全自动基建任务 - bool start_infrast(); + // 开始公开招募操作 + bool start_open_recruit(const std::vector& required_level, bool set_time = true); + // 开始干员识别任务 + bool start_to_identify_opers(); + // 开始全自动基建任务 + bool start_infrast(); - // 开始流程任务,应该是private的,调试用临时放到public - bool start_process_task(const std::string& task, int retry_times = ProcessTaskRetryTimesDefault, bool block = true); + // 开始流程任务,应该是private的,调试用临时放到public + bool start_process_task(const std::string& task, int retry_times = ProcessTaskRetryTimesDefault, bool block = true); #ifdef LOG_TRACE - // 调试用 - bool start_debug_task(); + // 调试用 + bool start_debug_task(); #endif - void stop(bool block = true); + void stop(bool block = true); - bool set_param(const std::string& type, const std::string& param, const std::string& value); + bool set_param(const std::string& type, const std::string& param, const std::string& value); - static constexpr int ProcessTaskRetryTimesDefault = 20; - static constexpr int OpenRecruitTaskRetyrTimesDefault = 5; + static constexpr int ProcessTaskRetryTimesDefault = 20; + static constexpr int OpenRecruitTaskRetyrTimesDefault = 5; - private: - void working_proc(); - void msg_proc(); - static void task_callback(AsstMsg msg, const json::value& detail, void* custom_arg); + private: + void working_proc(); + void msg_proc(); + static void task_callback(AsstMsg msg, const json::value& detail, void* custom_arg); - void append_match_task(const std::string& task_chain, const std::vector& tasks, int retry_times = ProcessTaskRetryTimesDefault, bool front = false); - void append_task(const json::value& detail, bool front = false); - void append_callback(AsstMsg msg, json::value detail); - void clear_exec_times(); - static void set_opers_idtf_result(const json::value& detail); // 保存干员识别结果 - static std::optional> - get_opers_idtf_result(); // 读取干员识别结果 + void append_match_task(const std::string& task_chain, const std::vector& tasks, int retry_times = ProcessTaskRetryTimesDefault, bool front = false); + void append_task(const json::value& detail, bool front = false); + void append_callback(AsstMsg msg, json::value detail); + void clear_exec_times(); + static void set_opers_idtf_result(const json::value& detail); // 保存干员识别结果 + static std::optional> + get_opers_idtf_result(); // 读取干员识别结果 - std::shared_ptr m_controller_ptr = nullptr; - std::shared_ptr m_identify_ptr = nullptr; - bool m_inited = false; + std::shared_ptr m_controller_ptr = nullptr; + std::shared_ptr m_identify_ptr = nullptr; + bool m_inited = false; - bool m_thread_exit = false; - std::deque> m_tasks_deque; - AsstCallback m_callback = nullptr; - void* m_callback_arg = nullptr; + bool m_thread_exit = false; + std::deque> m_tasks_deque; + AsstCallback m_callback = nullptr; + void* m_callback_arg = nullptr; - bool m_thread_idle = true; - std::thread m_working_thread; - std::mutex m_mutex; - std::condition_variable m_condvar; + bool m_thread_idle = true; + std::thread m_working_thread; + std::mutex m_mutex; + std::condition_variable m_condvar; - std::thread m_msg_thread; - std::queue> m_msg_queue; - std::mutex m_msg_mutex; - std::condition_variable m_msg_condvar; - }; + std::thread m_msg_thread; + std::queue> m_msg_queue; + std::mutex m_msg_mutex; + std::condition_variable m_msg_condvar; + }; } \ No newline at end of file diff --git a/src/MeoAssistance/AsstAux.h b/src/MeoAssistance/AsstAux.h index 3b7c792752..c7100c9bb8 100644 --- a/src/MeoAssistance/AsstAux.h +++ b/src/MeoAssistance/AsstAux.h @@ -4,125 +4,125 @@ #include namespace asst { - static std::string GetCurrentDir() - { - static std::string cur_dir; - if (cur_dir.empty()) { - char exepath_buff[_MAX_PATH] = { 0 }; - ::GetModuleFileNameA(NULL, exepath_buff, _MAX_PATH); - std::string exepath(exepath_buff); - cur_dir = exepath.substr(0, exepath.find_last_of('\\') + 1); - } - return cur_dir; - } + static std::string GetCurrentDir() + { + static std::string cur_dir; + if (cur_dir.empty()) { + char exepath_buff[_MAX_PATH] = { 0 }; + ::GetModuleFileNameA(NULL, exepath_buff, _MAX_PATH); + std::string exepath(exepath_buff); + cur_dir = exepath.substr(0, exepath.find_last_of('\\') + 1); + } + return cur_dir; + } - static std::string GetResourceDir() - { - static std::string res_dir = GetCurrentDir() + "resource\\"; - return res_dir; - } + static std::string GetResourceDir() + { + static std::string res_dir = GetCurrentDir() + "resource\\"; + return res_dir; + } - static std::string StringReplaceAll(const std::string& src, const std::string& old_value, const std::string& new_value) - { - std::string str = src; - for (std::string::size_type pos(0); pos != std::string::npos; pos += new_value.length()) { - if ((pos = str.find(old_value, pos)) != std::string::npos) - str.replace(pos, old_value.length(), new_value); - else - break; - } - return str; - } + static std::string StringReplaceAll(const std::string& src, const std::string& old_value, const std::string& new_value) + { + std::string str = src; + for (std::string::size_type pos(0); pos != std::string::npos; pos += new_value.length()) { + if ((pos = str.find(old_value, pos)) != std::string::npos) + str.replace(pos, old_value.length(), new_value); + else + break; + } + return str; + } - static std::string GetFormatTimeString() - { - SYSTEMTIME curtime; - GetLocalTime(&curtime); - char buff[64] = { 0 }; - sprintf_s(buff, "%04d-%02d-%02d %02d:%02d:%02d.%03d", - curtime.wYear, curtime.wMonth, curtime.wDay, - curtime.wHour, curtime.wMinute, curtime.wSecond, curtime.wMilliseconds); - return buff; - } + static std::string GetFormatTimeString() + { + SYSTEMTIME curtime; + GetLocalTime(&curtime); + char buff[64] = { 0 }; + sprintf_s(buff, "%04d-%02d-%02d %02d:%02d:%02d.%03d", + curtime.wYear, curtime.wMonth, curtime.wDay, + curtime.wHour, curtime.wMinute, curtime.wSecond, curtime.wMilliseconds); + return buff; + } - static std::string GbkToUtf8(const std::string& gbk_str) - { - const char* src_str = gbk_str.c_str(); - int len = MultiByteToWideChar(CP_ACP, 0, src_str, -1, NULL, 0); - wchar_t* wstr = new wchar_t[len + 1]; - memset(wstr, 0, len + 1); - MultiByteToWideChar(CP_ACP, 0, src_str, -1, wstr, len); - len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL); - char* str = new char[len + 1]; - memset(str, 0, len + 1); - WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL); - std::string strTemp = str; - if (wstr) delete[] wstr; - if (str) delete[] str; - return strTemp; - } + static std::string GbkToUtf8(const std::string& gbk_str) + { + const char* src_str = gbk_str.c_str(); + int len = MultiByteToWideChar(CP_ACP, 0, src_str, -1, NULL, 0); + wchar_t* wstr = new wchar_t[len + 1]; + memset(wstr, 0, len + 1); + MultiByteToWideChar(CP_ACP, 0, src_str, -1, wstr, len); + len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL); + char* str = new char[len + 1]; + memset(str, 0, len + 1); + WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL); + std::string strTemp = str; + if (wstr) delete[] wstr; + if (str) delete[] str; + return strTemp; + } - static std::string Utf8ToGbk(const std::string& utf8_str) - { - const char* src_str = utf8_str.c_str(); - int len = MultiByteToWideChar(CP_UTF8, 0, src_str, -1, NULL, 0); - wchar_t* wszGBK = new wchar_t[len + 1]; - memset(wszGBK, 0, len * 2 + 2); - MultiByteToWideChar(CP_UTF8, 0, src_str, -1, wszGBK, len); - len = WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, NULL, 0, NULL, NULL); - char* szGBK = new char[len + 1]; - memset(szGBK, 0, len + 1); - WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, szGBK, len, NULL, NULL); - std::string strTemp(szGBK); - if (wszGBK) delete[] wszGBK; - if (szGBK) delete[] szGBK; - return strTemp; - } + static std::string Utf8ToGbk(const std::string& utf8_str) + { + const char* src_str = utf8_str.c_str(); + int len = MultiByteToWideChar(CP_UTF8, 0, src_str, -1, NULL, 0); + wchar_t* wszGBK = new wchar_t[len + 1]; + memset(wszGBK, 0, len * 2 + 2); + MultiByteToWideChar(CP_UTF8, 0, src_str, -1, wszGBK, len); + len = WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, NULL, 0, NULL, NULL); + char* szGBK = new char[len + 1]; + memset(szGBK, 0, len + 1); + WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, szGBK, len, NULL, NULL); + std::string strTemp(szGBK); + if (wszGBK) delete[] wszGBK; + if (szGBK) delete[] szGBK; + return strTemp; + } - template - constexpr inline RetTy make_rect(const ArgType& rect) - { - return RetTy{ rect.x, rect.y, rect.width, rect.height }; - } + template + constexpr inline RetTy make_rect(const ArgType& rect) + { + return RetTy{ rect.x, rect.y, rect.width, rect.height }; + } - //template::value>::type> - // std::string VectorToString(const std::vector& vector, bool to_gbk = false) { - // if (vector.empty()) { - // return std::string(); - // } - // static const std::string inter = ", "; - // std::string str; - // for (const T& ele : vector) { - // if (to_gbk) { - // str += Utf8ToGbk(ele) + inter; - // } - // else { - // str += ele + inter; - // } - // } + //template::value>::type> + // std::string VectorToString(const std::vector& vector, bool to_gbk = false) { + // if (vector.empty()) { + // return std::string(); + // } + // static const std::string inter = ", "; + // std::string str; + // for (const T& ele : vector) { + // if (to_gbk) { + // str += Utf8ToGbk(ele) + inter; + // } + // else { + // str += ele + inter; + // } + // } - // if (!str.empty()) { - // str.erase(str.size() - inter.size(), inter.size()); - // } - // return str; - //} + // if (!str.empty()) { + // str.erase(str.size() - inter.size(), inter.size()); + // } + // return str; + //} - //template::value>::type> - // std::string VectorToString(const std::vector& vector) { - // if (vector.empty()) { - // return std::string(); - // } - // static const std::string inter = ", "; - // std::string str; - // for (const T& ele : vector) { - // str += std::to_string(ele) + inter; - // } + //template::value>::type> + // std::string VectorToString(const std::vector& vector) { + // if (vector.empty()) { + // return std::string(); + // } + // static const std::string inter = ", "; + // std::string str; + // for (const T& ele : vector) { + // str += std::to_string(ele) + inter; + // } - // if (!str.empty()) { - // str.erase(str.size() - inter.size(), inter.size()); - // } - // return str; - //} + // if (!str.empty()) { + // str.erase(str.size() - inter.size(), inter.size()); + // } + // return str; + //} } \ No newline at end of file diff --git a/src/MeoAssistance/AsstCaller.cpp b/src/MeoAssistance/AsstCaller.cpp index c3c34c3eb2..49b8d7d488 100644 --- a/src/MeoAssistance/AsstCaller.cpp +++ b/src/MeoAssistance/AsstCaller.cpp @@ -12,19 +12,19 @@ #if _MSC_VER // Win32平台下Dll的入口 BOOL APIENTRY DllMain(HANDLE hModule, - DWORD ul_reason_for_call, - LPVOID lpReserved + DWORD ul_reason_for_call, + LPVOID lpReserved ) { - UNREFERENCED_PARAMETER(hModule); - UNREFERENCED_PARAMETER(lpReserved); - switch (ul_reason_for_call) { - case DLL_PROCESS_ATTACH: - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - case DLL_PROCESS_DETACH: - break; - } - return TRUE; + UNREFERENCED_PARAMETER(hModule); + UNREFERENCED_PARAMETER(lpReserved); + switch (ul_reason_for_call) { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; } #elif VA_GNUC @@ -35,151 +35,151 @@ AsstCallback _callback = nullptr; void CallbackTrans(asst::AsstMsg msg, const json::value& json, void* custom_arg) { - _callback(static_cast(msg), asst::Utf8ToGbk(json.to_string()).c_str(), custom_arg); + _callback(static_cast(msg), asst::Utf8ToGbk(json.to_string()).c_str(), custom_arg); } void* AsstCreate() { - return new asst::Assistance(); + return new asst::Assistance(); } void* AsstCreateEx(AsstCallback callback, void* custom_arg) { - // 创建多实例回调会有问题,有空再慢慢整 - _callback = callback; - return new asst::Assistance(CallbackTrans, custom_arg); + // 创建多实例回调会有问题,有空再慢慢整 + _callback = callback; + return new asst::Assistance(CallbackTrans, custom_arg); } void AsstDestory(void* p_asst) { - if (p_asst == nullptr) { - return; - } + if (p_asst == nullptr) { + return; + } - delete p_asst; - p_asst = nullptr; + delete p_asst; + p_asst = nullptr; } bool AsstCatchDefault(void* p_asst) { - if (p_asst == nullptr) { - return false; - } + if (p_asst == nullptr) { + return false; + } - return ((asst::Assistance*)p_asst)->catch_default(); + return ((asst::Assistance*)p_asst)->catch_default(); } bool AsstCatchEmulator(void* p_asst) { - if (p_asst == nullptr) { - return false; - } + if (p_asst == nullptr) { + return false; + } - return ((asst::Assistance*)p_asst)->catch_emulator(); + return ((asst::Assistance*)p_asst)->catch_emulator(); } bool AsstCatchUSB(void* p_asst) { - if (p_asst == nullptr) { - return false; - } + if (p_asst == nullptr) { + return false; + } - return ((asst::Assistance*)p_asst)->catch_usb(); + return ((asst::Assistance*)p_asst)->catch_usb(); } bool AsstCatchRemote(void* p_asst, const char* address) { - if (p_asst == nullptr) { - return false; - } + if (p_asst == nullptr) { + return false; + } - return ((asst::Assistance*)p_asst)->catch_remote(address); + return ((asst::Assistance*)p_asst)->catch_remote(address); } bool AsstStartSanity(void* p_asst) { - if (p_asst == nullptr) { - return false; - } + if (p_asst == nullptr) { + return false; + } - return ((asst::Assistance*)p_asst)->start_sanity(); + return ((asst::Assistance*)p_asst)->start_sanity(); } bool AsstStartVisit(void* p_asst, bool with_shopping) { - if (p_asst == nullptr) { - return false; - } + if (p_asst == nullptr) { + return false; + } - return ((asst::Assistance*)p_asst)->start_visit(with_shopping); + return ((asst::Assistance*)p_asst)->start_visit(with_shopping); } bool AsstStartProcessTask(void* p_asst, const char* task) { - if (p_asst == nullptr) { - return false; - } + if (p_asst == nullptr) { + return false; + } - return ((asst::Assistance*)p_asst)->start_process_task(task, asst::Assistance::ProcessTaskRetryTimesDefault); + return ((asst::Assistance*)p_asst)->start_process_task(task, asst::Assistance::ProcessTaskRetryTimesDefault); } void AsstStop(void* p_asst) { - if (p_asst == nullptr) { - return; - } + if (p_asst == nullptr) { + return; + } - ((asst::Assistance*)p_asst)->stop(); + ((asst::Assistance*)p_asst)->stop(); } bool AsstSetParam(void* p_asst, const char* type, const char* param, const char* value) { - if (p_asst == nullptr) { - return false; - } + if (p_asst == nullptr) { + return false; + } - return ((asst::Assistance*)p_asst)->set_param(type, param, value); + return ((asst::Assistance*)p_asst)->set_param(type, param, value); } const char* AsstGetVersion() { - return asst::Version; + return asst::Version; } bool AsstStartOpenRecruit(void* p_asst, const int required_level[], int required_len, bool set_time) { - if (p_asst == nullptr) { - return false; - } - std::vector level_vector; - level_vector.assign(required_level, required_level + required_len); - return ((asst::Assistance*)p_asst)->start_open_recruit(level_vector, set_time); + if (p_asst == nullptr) { + return false; + } + std::vector level_vector; + level_vector.assign(required_level, required_level + required_len); + return ((asst::Assistance*)p_asst)->start_open_recruit(level_vector, set_time); } bool AsstStartIndertifyOpers(void* p_asst) { - if (p_asst == nullptr) { - return false; - } - return ((asst::Assistance*)p_asst)->start_to_identify_opers(); + if (p_asst == nullptr) { + return false; + } + return ((asst::Assistance*)p_asst)->start_to_identify_opers(); } bool AsstStartInfrast(void* p_asst) { - if (p_asst == nullptr) { - return false; - } - return ((asst::Assistance*)p_asst)->start_infrast(); + if (p_asst == nullptr) { + return false; + } + return ((asst::Assistance*)p_asst)->start_infrast(); } bool AsstStartDebugTask(void* p_asst) { - if (p_asst == nullptr) { - return false; - } + if (p_asst == nullptr) { + return false; + } #if LOG_TRACE - return ((asst::Assistance*)p_asst)->start_debug_task(); + return ((asst::Assistance*)p_asst)->start_debug_task(); #else - return false; + return false; #endif // LOG_TRACE } \ No newline at end of file diff --git a/src/MeoAssistance/AsstDef.h b/src/MeoAssistance/AsstDef.h index 84324023b8..62cdeed666 100644 --- a/src/MeoAssistance/AsstDef.h +++ b/src/MeoAssistance/AsstDef.h @@ -9,226 +9,226 @@ namespace json { - class value; + class value; } namespace asst { - enum class ProcessTaskAction { - Invalid = 0, - BasicClick = 0x100, - ClickSelf = BasicClick | 1, // 点击自身位置 - ClickRect = BasicClick | 2, // 点击指定区域 - ClickRand = BasicClick | 4, // 点击随机区域 - DoNothing = 0x200, // 什么都不做 - Stop = 0x400, // 停止当前Task - PrintWindow = 0x800, // 截图 - BasicSwipe = 0x1000, - SwipeToTheLeft = BasicSwipe | 1, // 往左划一下 - SwipeToTheRight = BasicSwipe | 2, // 往右划一下 - }; + enum class ProcessTaskAction { + Invalid = 0, + BasicClick = 0x100, + ClickSelf = BasicClick | 1, // 点击自身位置 + ClickRect = BasicClick | 2, // 点击指定区域 + ClickRand = BasicClick | 4, // 点击随机区域 + DoNothing = 0x200, // 什么都不做 + Stop = 0x400, // 停止当前Task + PrintWindow = 0x800, // 截图 + BasicSwipe = 0x1000, + SwipeToTheLeft = BasicSwipe | 1, // 往左划一下 + SwipeToTheRight = BasicSwipe | 2, // 往右划一下 + }; - enum class AlgorithmType { - Invaild = -1, - JustReturn, - MatchTemplate, - CompareHist, - OcrDetect - }; + enum class AlgorithmType { + Invaild = -1, + JustReturn, + MatchTemplate, + CompareHist, + OcrDetect + }; - struct Point - { - Point() = default; - Point(const Point&) noexcept = default; - Point(Point&&) noexcept = default; - Point(int x, int y) : x(x), y(y) {} - Point& operator=(const Point&) noexcept = default; - Point& operator=(Point&&) noexcept = default; - int x = 0; - int y = 0; - }; + struct Point + { + Point() = default; + Point(const Point&) noexcept = default; + Point(Point&&) noexcept = default; + Point(int x, int y) : x(x), y(y) {} + Point& operator=(const Point&) noexcept = default; + Point& operator=(Point&&) noexcept = default; + int x = 0; + int y = 0; + }; - struct Rect - { - Rect() = default; - Rect(const Rect&) noexcept = default; - Rect(Rect&&) noexcept = default; - Rect(int x, int y, int width, int height) - : x(x), y(y), width(width), height(height) {} - Rect operator*(double rhs) const - { - return { x, y, static_cast(width * rhs), static_cast(height * rhs) }; - } - Rect center_zoom(double scale, int max_width = INT_MAX, int max_height = INT_MAX) const - { - int half_width_scale = static_cast(width * (1 - scale) / 2); - int half_hight_scale = static_cast(height * (1 - scale) / 2); - Rect dst(x + half_width_scale, y + half_hight_scale, - static_cast(width * scale), static_cast(height * scale)); - if (dst.x < 0) { dst.x = 0; } - if (dst.y < 0) { dst.y = 0; } - if (dst.width + dst.x >= max_width) { dst.width = max_width - dst.x; } - if (dst.height + dst.y >= max_height) { dst.height = max_height - dst.y; } - return dst; - } - Rect& operator=(const Rect&) noexcept = default; - Rect& operator=(Rect&&) noexcept = default; + struct Rect + { + Rect() = default; + Rect(const Rect&) noexcept = default; + Rect(Rect&&) noexcept = default; + Rect(int x, int y, int width, int height) + : x(x), y(y), width(width), height(height) {} + Rect operator*(double rhs) const + { + return { x, y, static_cast(width * rhs), static_cast(height * rhs) }; + } + Rect center_zoom(double scale, int max_width = INT_MAX, int max_height = INT_MAX) const + { + int half_width_scale = static_cast(width * (1 - scale) / 2); + int half_hight_scale = static_cast(height * (1 - scale) / 2); + Rect dst(x + half_width_scale, y + half_hight_scale, + static_cast(width * scale), static_cast(height * scale)); + if (dst.x < 0) { dst.x = 0; } + if (dst.y < 0) { dst.y = 0; } + if (dst.width + dst.x >= max_width) { dst.width = max_width - dst.x; } + if (dst.height + dst.y >= max_height) { dst.height = max_height - dst.y; } + return dst; + } + Rect& operator=(const Rect&) noexcept = default; + Rect& operator=(Rect&&) noexcept = default; - int x = 0; - int y = 0; - int width = 0; - int height = 0; - }; + int x = 0; + int y = 0; + int width = 0; + int height = 0; + }; - struct TextArea { - TextArea() = default; - TextArea(const TextArea&) = default; - TextArea(TextArea&&) noexcept = default; - template - TextArea(std::string text, RectArgs &&... rect_args) - : text(std::move(text)), - rect(std::forward(rect_args)...) { - static_assert(std::is_constructible::value, - "Parameter can't be used to construct a asst::Rect"); - } - operator std::string() const { return text; } - TextArea& operator=(const TextArea&) = default; - TextArea& operator=(TextArea&&) noexcept = default; + struct TextArea { + TextArea() = default; + TextArea(const TextArea&) = default; + TextArea(TextArea&&) noexcept = default; + template + TextArea(std::string text, RectArgs &&... rect_args) + : text(std::move(text)), + rect(std::forward(rect_args)...) { + static_assert(std::is_constructible::value, + "Parameter can't be used to construct a asst::Rect"); + } + operator std::string() const { return text; } + TextArea& operator=(const TextArea&) = default; + TextArea& operator=(TextArea&&) noexcept = default; - std::string text; - Rect rect; - }; + std::string text; + Rect rect; + }; - struct HandleInfo { - std::string class_name; - std::string window_name; - }; + struct HandleInfo { + std::string class_name; + std::string window_name; + }; - struct AdbCmd { - std::string path; - std::string connect; - std::string click; - std::string swipe; - std::string display; - std::string display_regex; - std::string screencap; - //std::string pullscreen; - int display_width = 0; - int display_height = 0; - }; + struct AdbCmd { + std::string path; + std::string connect; + std::string click; + std::string swipe; + std::string display; + std::string display_regex; + std::string screencap; + //std::string pullscreen; + int display_width = 0; + int display_height = 0; + }; - struct EmulatorInfo { - std::string name; - HandleInfo handle; - AdbCmd adb; - std::string path; - }; + struct EmulatorInfo { + std::string name; + HandleInfo handle; + AdbCmd adb; + std::string path; + }; - // 任务信息 - struct TaskInfo { - virtual ~TaskInfo() = default; - std::string name; // 任务名 - AlgorithmType algorithm = // 图像算法类型 - AlgorithmType::Invaild; - ProcessTaskAction action = // 要进行的操作 - ProcessTaskAction::Invalid; - std::vector next; // 下一个可能的任务(列表) - int exec_times = 0; // 任务已执行了多少次 - int max_times = INT_MAX; // 任务最多执行多少次 - std::vector exceeded_next; // 达到最多次数了之后,下一个可能的任务(列表) - std::vector reduce_other_times; // 执行了该任务后,需要减少别的任务的执行次数。例如执行了吃理智药,则说明上一次点击蓝色开始行动按钮没生效,所以蓝色开始行动要-1 - asst::Rect specific_area; // 指定区域,目前仅针对ClickRect任务有用,会点这个区域 - int pre_delay = 0; // 执行该任务前的延时 - int rear_delay = 0; // 执行该任务后的延时 - int retry_times = INT_MAX; // 未找到图像时的重试次数 - Rect identify_area; // 要识别的区域,若为0则全图识别 - }; + // 任务信息 + struct TaskInfo { + virtual ~TaskInfo() = default; + std::string name; // 任务名 + AlgorithmType algorithm = // 图像算法类型 + AlgorithmType::Invaild; + ProcessTaskAction action = // 要进行的操作 + ProcessTaskAction::Invalid; + std::vector next; // 下一个可能的任务(列表) + int exec_times = 0; // 任务已执行了多少次 + int max_times = INT_MAX; // 任务最多执行多少次 + std::vector exceeded_next; // 达到最多次数了之后,下一个可能的任务(列表) + std::vector reduce_other_times; // 执行了该任务后,需要减少别的任务的执行次数。例如执行了吃理智药,则说明上一次点击蓝色开始行动按钮没生效,所以蓝色开始行动要-1 + asst::Rect specific_area; // 指定区域,目前仅针对ClickRect任务有用,会点这个区域 + int pre_delay = 0; // 执行该任务前的延时 + int rear_delay = 0; // 执行该任务后的延时 + int retry_times = INT_MAX; // 未找到图像时的重试次数 + Rect identify_area; // 要识别的区域,若为0则全图识别 + }; - // 文字识别任务的信息 - struct OcrTaskInfo : public TaskInfo { - virtual ~OcrTaskInfo() = default; - std::vector text; // 文字的容器,匹配到这里面任一个,就算匹配上了 - bool need_match = false; // 是否需要全匹配,否则搜索到子串就算匹配上了 - std::unordered_map - replace_map; // 部分文字容易识别错,字符串强制replace之后,再进行匹配 - bool cache = false; // 是否使用缓存区域:上次处理该任务时,在一些rect里识别到过text,这次优先在这些rect里识别,省点性能 - std::vector cache_area; // 识别缓存区域 - }; + // 文字识别任务的信息 + struct OcrTaskInfo : public TaskInfo { + virtual ~OcrTaskInfo() = default; + std::vector text; // 文字的容器,匹配到这里面任一个,就算匹配上了 + bool need_match = false; // 是否需要全匹配,否则搜索到子串就算匹配上了 + std::unordered_map + replace_map; // 部分文字容易识别错,字符串强制replace之后,再进行匹配 + bool cache = false; // 是否使用缓存区域:上次处理该任务时,在一些rect里识别到过text,这次优先在这些rect里识别,省点性能 + std::vector cache_area; // 识别缓存区域 + }; - // 图片匹配任务的信息 - struct MatchTaskInfo : public TaskInfo { - virtual ~MatchTaskInfo() = default; - std::string template_filename; // 匹配模板图片文件名 - double templ_threshold = 0; // 模板匹配阈值 - double hist_threshold = 0; // 直方图比较阈值 - bool cache = false; // 是否使用缓存(直方图),false时就一直用模板匹配。默认为true - }; + // 图片匹配任务的信息 + struct MatchTaskInfo : public TaskInfo { + virtual ~MatchTaskInfo() = default; + std::string template_filename; // 匹配模板图片文件名 + double templ_threshold = 0; // 模板匹配阈值 + double hist_threshold = 0; // 直方图比较阈值 + bool cache = false; // 是否使用缓存(直方图),false时就一直用模板匹配。默认为true + }; - enum class ConnectType { - Emulator, - USB, - Remote - }; + enum class ConnectType { + Emulator, + USB, + Remote + }; - struct Options { - ConnectType connect_type; // 连接类型 - std::string connect_remote_address; // 连接局域网中的安卓设备的地址,仅在connectType为Remote时生效 - int task_delay = 0; // 任务间延时:越快操作越快,但会增加CPU消耗 - int control_delay_lower = 0; // 点击随机延时下限:每次点击操作会进行随机延时 - int control_delay_upper = 0; // 点击随机延时上限:每次点击操作会进行随机延时 - bool print_window = false; // 截图功能:开启后每次结算界面会截图到screenshot目录下 - int print_window_delay = 0; // 截图延时:每次到结算界面,掉落物品不是一次性出来的,有个动画,所以需要等一会再截图 - int ocr_gpu_index = -1; // OcrLite使用GPU编号,-1(使用CPU)/0(使用GPU0)/1(使用GPU1)/... - int ocr_thread_number = 0; // OcrLite线程数量 - }; + struct Options { + ConnectType connect_type; // 连接类型 + std::string connect_remote_address; // 连接局域网中的安卓设备的地址,仅在connectType为Remote时生效 + int task_delay = 0; // 任务间延时:越快操作越快,但会增加CPU消耗 + int control_delay_lower = 0; // 点击随机延时下限:每次点击操作会进行随机延时 + int control_delay_upper = 0; // 点击随机延时上限:每次点击操作会进行随机延时 + bool print_window = false; // 截图功能:开启后每次结算界面会截图到screenshot目录下 + int print_window_delay = 0; // 截图延时:每次到结算界面,掉落物品不是一次性出来的,有个动画,所以需要等一会再截图 + int ocr_gpu_index = -1; // OcrLite使用GPU编号,-1(使用CPU)/0(使用GPU0)/1(使用GPU1)/... + int ocr_thread_number = 0; // OcrLite线程数量 + }; - struct InfrastOptions { // 基建的选项 - double dorm_threshold = 0; // 宿舍心情百分比阈值,心情百分比小于该值的干员会被放进宿舍 - }; + struct InfrastOptions { // 基建的选项 + double dorm_threshold = 0; // 宿舍心情百分比阈值,心情百分比小于该值的干员会被放进宿舍 + }; - // 干员信息,公开招募相关 - struct OperRecruitInfo { - std::string name; - std::string type; - int level = 0; - std::string sex; - std::unordered_set tags; - bool hidden = false; - std::string name_en; - }; + // 干员信息,公开招募相关 + struct OperRecruitInfo { + std::string name; + std::string type; + int level = 0; + std::string sex; + std::unordered_set tags; + bool hidden = false; + std::string name_en; + }; - // 公开招募的干员组合 - struct OperRecruitCombs { - std::vector opers; - int max_level = 0; - int min_level = 0; - double avg_level = 0; - }; + // 公开招募的干员组合 + struct OperRecruitCombs { + std::vector opers; + int max_level = 0; + int min_level = 0; + double avg_level = 0; + }; - // 干员信息,基建相关 - struct OperInfrastInfo { - std::string name; - int elite = 0; // 精英化等级 - int level = 0; // 等级 - bool operator==(const OperInfrastInfo& rhs) const { - return name == rhs.name; - } - }; - // 基建干员组合 - struct OperInfrastComb { - std::vector comb; - int efficiency = 0; // 组合的效率 - }; + // 干员信息,基建相关 + struct OperInfrastInfo { + std::string name; + int elite = 0; // 精英化等级 + int level = 0; // 等级 + bool operator==(const OperInfrastInfo& rhs) const { + return name == rhs.name; + } + }; + // 基建干员组合 + struct OperInfrastComb { + std::vector comb; + int efficiency = 0; // 组合的效率 + }; - constexpr double DoubleDiff = 1e-12; + constexpr double DoubleDiff = 1e-12; } namespace std { - template<> - class hash { - public: - size_t operator()(const asst::OperInfrastInfo& info) const - { - return std::hash()(info.name); - } - }; + template<> + class hash { + public: + size_t operator()(const asst::OperInfrastInfo& info) const + { + return std::hash()(info.name); + } + }; } diff --git a/src/MeoAssistance/AsstMsg.h b/src/MeoAssistance/AsstMsg.h index 5c41e7643e..03fc664c2b 100644 --- a/src/MeoAssistance/AsstMsg.h +++ b/src/MeoAssistance/AsstMsg.h @@ -8,90 +8,89 @@ #include namespace asst { - enum class AsstMsg { - /* Error Msg */ - PtrIsNull, // 指针为空 - ImageIsEmpty, // 图像为空 - WindowMinimized, // [已弃用] 窗口被最小化了 - InitFaild, // 初始化失败 - TaskError, // 任务错误(任务一直出错,retry次数达到上限) - OcrResultError, // Ocr识别结果错误 - /* Info Msg: about Task */ - TaskStart = 1000, // 任务开始 - TaskMatched, // 任务匹配成功 - ReachedLimit, // 单个原子任务达到次数上限 - ReadyToSleep, // 准备开始睡眠 - EndOfSleep, // 睡眠结束 - AppendProcessTask, // 新增流程任务,Assistance内部消息,外部不需要处理 - AppendTask, // 新增任务,Assistance内部消息,外部不需要处理 - TaskCompleted, // 单个原子任务完成 - PrintWindow, // 截图消息 - ProcessTaskStopAction, // 流程任务执行到了Stop的动作 - TaskChainCompleted, // 任务链完成 - ProcessTaskNotMatched, // 流程任务识别错误 - /* Info Msg: about Identify */ - TextDetected = 2000, // 识别到文字 - ImageFindResult, // 查找图像的结果 - ImageMatched, // 图像匹配成功 - /* Open Recruit Msg */ - RecruitTagsDetected = 3000, // 公招识别到了Tags - RecruitSpecialTag, // 公招识别到了特殊的Tag - RecruitResult, // 公开招募结果 - /* Infrast Msg */ - OpersDetected = 4000, // 识别到了干员s - OpersIdtfResult, // 干员识别结果(总的) - InfrastComb, // 当前房间的最优干员组合 - EnterStation, // 进入某个房间 - StationInfo, // 当前房间信息 - ReadyToShift, // 准备换班 - ShiftCompleted, // 换班完成(单个房间) - NoNeedToShift // 无需换班(单个房间) + enum class AsstMsg { + /* Error Msg */ + PtrIsNull, // 指针为空 + ImageIsEmpty, // 图像为空 + WindowMinimized, // [已弃用] 窗口被最小化了 + InitFaild, // 初始化失败 + TaskError, // 任务错误(任务一直出错,retry次数达到上限) + OcrResultError, // Ocr识别结果错误 + /* Info Msg: about Task */ + TaskStart = 1000, // 任务开始 + TaskMatched, // 任务匹配成功 + ReachedLimit, // 单个原子任务达到次数上限 + ReadyToSleep, // 准备开始睡眠 + EndOfSleep, // 睡眠结束 + AppendProcessTask, // 新增流程任务,Assistance内部消息,外部不需要处理 + AppendTask, // 新增任务,Assistance内部消息,外部不需要处理 + TaskCompleted, // 单个原子任务完成 + PrintWindow, // 截图消息 + ProcessTaskStopAction, // 流程任务执行到了Stop的动作 + TaskChainCompleted, // 任务链完成 + ProcessTaskNotMatched, // 流程任务识别错误 + /* Info Msg: about Identify */ + TextDetected = 2000, // 识别到文字 + ImageFindResult, // 查找图像的结果 + ImageMatched, // 图像匹配成功 + /* Open Recruit Msg */ + RecruitTagsDetected = 3000, // 公招识别到了Tags + RecruitSpecialTag, // 公招识别到了特殊的Tag + RecruitResult, // 公开招募结果 + /* Infrast Msg */ + OpersDetected = 4000, // 识别到了干员s + OpersIdtfResult, // 干员识别结果(总的) + InfrastComb, // 当前房间的最优干员组合 + EnterStation, // 进入某个房间 + StationInfo, // 当前房间信息 + ReadyToShift, // 准备换班 + ShiftCompleted, // 换班完成(单个房间) + NoNeedToShift // 无需换班(单个房间) + }; - }; + static std::ostream& operator<<(std::ostream& os, const AsstMsg& type) + { + static const std::unordered_map _type_name = { + {AsstMsg::PtrIsNull, "PtrIsNull"}, + {AsstMsg::ImageIsEmpty, "ImageIsEmpty"}, + {AsstMsg::WindowMinimized, "WindowMinimized"}, + {AsstMsg::InitFaild, "InitFaild"}, + {AsstMsg::TaskStart, "TaskStart"}, + {AsstMsg::ImageFindResult, "ImageFindResult"}, + {AsstMsg::ImageMatched, "ImageMatched"}, + {AsstMsg::TaskMatched, "TaskMatched"}, + {AsstMsg::ReachedLimit, "ReachedLimit"}, + {AsstMsg::ReadyToSleep, "ReadyToSleep"}, + {AsstMsg::EndOfSleep, "EndOfSleep"}, + {AsstMsg::AppendProcessTask, "AppendProcessTask"}, + {AsstMsg::TaskCompleted, "TaskCompleted"}, + {AsstMsg::TaskChainCompleted, "TaskChainCompleted"}, + {AsstMsg::PrintWindow, "PrintWindow"}, + {AsstMsg::TaskError, "TaskError"}, + {AsstMsg::ProcessTaskNotMatched, "ProcessTaskNotMatched"}, + {AsstMsg::ProcessTaskStopAction, "ProcessTaskStopAction"}, + {AsstMsg::TextDetected, "TextDetected"}, + {AsstMsg::RecruitTagsDetected, "RecruitTagsDetected"}, + {AsstMsg::OcrResultError, "OcrResultError"}, + {AsstMsg::RecruitSpecialTag, "RecruitSpecialTag"}, + {AsstMsg::RecruitResult, "RecruitResult"}, + {AsstMsg::AppendTask, "AppendTask"}, + {AsstMsg::OpersDetected, "OpersDetected"}, + {AsstMsg::OpersIdtfResult, "OpersIdtfResult"}, + {AsstMsg::InfrastComb, "InfrastComb"}, + {AsstMsg::EnterStation, "EnterStation"}, + {AsstMsg::StationInfo, "StationInfo"}, + {AsstMsg::ReadyToShift, "ReadyToShift"}, + {AsstMsg::ShiftCompleted, "ShiftCompleted"}, + {AsstMsg::NoNeedToShift, "NoNeedToShift"} + }; + return os << _type_name.at(type); + } - static std::ostream& operator<<(std::ostream& os, const AsstMsg& type) - { - static const std::unordered_map _type_name = { - {AsstMsg::PtrIsNull, "PtrIsNull"}, - {AsstMsg::ImageIsEmpty, "ImageIsEmpty"}, - {AsstMsg::WindowMinimized, "WindowMinimized"}, - {AsstMsg::InitFaild, "InitFaild"}, - {AsstMsg::TaskStart, "TaskStart"}, - {AsstMsg::ImageFindResult, "ImageFindResult"}, - {AsstMsg::ImageMatched, "ImageMatched"}, - {AsstMsg::TaskMatched, "TaskMatched"}, - {AsstMsg::ReachedLimit, "ReachedLimit"}, - {AsstMsg::ReadyToSleep, "ReadyToSleep"}, - {AsstMsg::EndOfSleep, "EndOfSleep"}, - {AsstMsg::AppendProcessTask, "AppendProcessTask"}, - {AsstMsg::TaskCompleted, "TaskCompleted"}, - {AsstMsg::TaskChainCompleted, "TaskChainCompleted"}, - {AsstMsg::PrintWindow, "PrintWindow"}, - {AsstMsg::TaskError, "TaskError"}, - {AsstMsg::ProcessTaskNotMatched, "ProcessTaskNotMatched"}, - {AsstMsg::ProcessTaskStopAction, "ProcessTaskStopAction"}, - {AsstMsg::TextDetected, "TextDetected"}, - {AsstMsg::RecruitTagsDetected, "RecruitTagsDetected"}, - {AsstMsg::OcrResultError, "OcrResultError"}, - {AsstMsg::RecruitSpecialTag, "RecruitSpecialTag"}, - {AsstMsg::RecruitResult, "RecruitResult"}, - {AsstMsg::AppendTask, "AppendTask"}, - {AsstMsg::OpersDetected, "OpersDetected"}, - {AsstMsg::OpersIdtfResult, "OpersIdtfResult"}, - {AsstMsg::InfrastComb, "InfrastComb"}, - {AsstMsg::EnterStation, "EnterStation"}, - {AsstMsg::StationInfo, "StationInfo"}, - {AsstMsg::ReadyToShift, "ReadyToShift"}, - {AsstMsg::ShiftCompleted, "ShiftCompleted"}, - {AsstMsg::NoNeedToShift, "NoNeedToShift"} - }; - return os << _type_name.at(type); - } - - // AsstCallback 消息回调函数 - // 参数: - // AsstMsg 消息类型 - // const json::value& 消息详情json,每种消息不同,Todo,需要补充个协议文档啥的 - // void* 外部调用者自定义参数,每次回调会带出去,建议传个(void*)this指针进来 - using AsstCallback = std::function; + // AsstCallback 消息回调函数 + // 参数: + // AsstMsg 消息类型 + // const json::value& 消息详情json,每种消息不同,Todo,需要补充个协议文档啥的 + // void* 外部调用者自定义参数,每次回调会带出去,建议传个(void*)this指针进来 + using AsstCallback = std::function; } \ No newline at end of file diff --git a/src/MeoAssistance/Configer.cpp b/src/MeoAssistance/Configer.cpp index 73e62c61a0..ab3d9e924f 100644 --- a/src/MeoAssistance/Configer.cpp +++ b/src/MeoAssistance/Configer.cpp @@ -12,57 +12,57 @@ using namespace asst; bool asst::Configer::parse(const json::value& json) { - m_version = json.at("version").as_string(); + m_version = json.at("version").as_string(); - const json::value& options_json = json.at("options"); - { - m_options.connect_type = static_cast(options_json.at("connectType").as_integer()); - m_options.connect_remote_address = options_json.at("connectRemoteAddress").as_string(); - m_options.task_delay = options_json.at("taskDelay").as_integer(); - //m_options.identify_cache = options_json.at("identifyCache").as_boolean(); - m_options.control_delay_lower = options_json.at("controlDelayRange")[0].as_integer(); - m_options.control_delay_upper = options_json.at("controlDelayRange")[1].as_integer(); - m_options.print_window = options_json.at("printWindow").as_boolean(); - m_options.print_window_delay = options_json.at("printWindowDelay").as_integer(); - m_options.ocr_thread_number = options_json.at("ocrThreadNumber").as_integer(); - } - DebugTrace("Options", options_json.to_string()); + const json::value& options_json = json.at("options"); + { + m_options.connect_type = static_cast(options_json.at("connectType").as_integer()); + m_options.connect_remote_address = options_json.at("connectRemoteAddress").as_string(); + m_options.task_delay = options_json.at("taskDelay").as_integer(); + //m_options.identify_cache = options_json.at("identifyCache").as_boolean(); + m_options.control_delay_lower = options_json.at("controlDelayRange")[0].as_integer(); + m_options.control_delay_upper = options_json.at("controlDelayRange")[1].as_integer(); + m_options.print_window = options_json.at("printWindow").as_boolean(); + m_options.print_window_delay = options_json.at("printWindowDelay").as_integer(); + m_options.ocr_thread_number = options_json.at("ocrThreadNumber").as_integer(); + } + DebugTrace("Options", options_json.to_string()); - const json::value& infrast_options_json = json.at("infrastOptions"); - { - m_infrast_options.dorm_threshold = infrast_options_json.get("dormThreshold", 0.3); - } - DebugTrace("InfrastOptions", infrast_options_json.to_string()); + const json::value& infrast_options_json = json.at("infrastOptions"); + { + m_infrast_options.dorm_threshold = infrast_options_json.get("dormThreshold", 0.3); + } + DebugTrace("InfrastOptions", infrast_options_json.to_string()); - for (const auto& [name, emulator_json] : json.at("emulator").as_object()) { - EmulatorInfo emulator_info; - emulator_info.name = name; + for (const auto& [name, emulator_json] : json.at("emulator").as_object()) { + EmulatorInfo emulator_info; + emulator_info.name = name; - const json::object& handle_json = emulator_json.at("handle").as_object(); - emulator_info.handle.class_name = handle_json.at("class").as_string(); - emulator_info.handle.window_name = handle_json.at("window").as_string(); + const json::object& handle_json = emulator_json.at("handle").as_object(); + emulator_info.handle.class_name = handle_json.at("class").as_string(); + emulator_info.handle.window_name = handle_json.at("window").as_string(); - const json::object& adb_json = emulator_json.at("adb").as_object(); - emulator_info.adb.path = adb_json.at("path").as_string(); - emulator_info.adb.connect = adb_json.at("connect").as_string(); - emulator_info.adb.click = adb_json.at("click").as_string(); - emulator_info.adb.swipe = adb_json.at("swipe").as_string(); - emulator_info.adb.display = adb_json.at("display").as_string(); - emulator_info.adb.display_regex = adb_json.at("displayRegex").as_string(); - emulator_info.adb.screencap = adb_json.at("screencap").as_string(); - //emulator_info.adb.pullscreen = adb_json.at("pullscreen").as_string(); + const json::object& adb_json = emulator_json.at("adb").as_object(); + emulator_info.adb.path = adb_json.at("path").as_string(); + emulator_info.adb.connect = adb_json.at("connect").as_string(); + emulator_info.adb.click = adb_json.at("click").as_string(); + emulator_info.adb.swipe = adb_json.at("swipe").as_string(); + emulator_info.adb.display = adb_json.at("display").as_string(); + emulator_info.adb.display_regex = adb_json.at("displayRegex").as_string(); + emulator_info.adb.screencap = adb_json.at("screencap").as_string(); + //emulator_info.adb.pullscreen = adb_json.at("pullscreen").as_string(); - emulator_info.path = emulator_json.get("path", std::string()); + emulator_info.path = emulator_json.get("path", std::string()); - m_handles.emplace(name, std::move(emulator_info)); - } + m_handles.emplace(name, std::move(emulator_info)); + } - for (const json::value& rep : json.at("infrastOcrReplace").as_array()) { - m_infrast_ocr_replace.emplace(rep.as_array()[0].as_string(), rep.as_array()[1].as_string()); - } - for (const json::value& rep : json.at("recruitOcrReplace").as_array()) { - m_recruit_ocr_replace.emplace(rep.as_array()[0].as_string(), rep.as_array()[1].as_string()); - } + for (const json::value& rep : json.at("infrastOcrReplace").as_array()) { + m_infrast_ocr_replace.emplace(rep.as_array()[0].as_string(), rep.as_array()[1].as_string()); + } + for (const json::value& rep : json.at("recruitOcrReplace").as_array()) { + m_recruit_ocr_replace.emplace(rep.as_array()[0].as_string(), rep.as_array()[1].as_string()); + } - return true; + return true; } \ No newline at end of file diff --git a/src/MeoAssistance/Configer.h b/src/MeoAssistance/Configer.h index 136ce349fa..f3cca09ff5 100644 --- a/src/MeoAssistance/Configer.h +++ b/src/MeoAssistance/Configer.h @@ -9,37 +9,37 @@ #include "AsstDef.h" namespace asst { - class Configer : public AbstractConfiger - { - public: - virtual ~Configer() = default; + class Configer : public AbstractConfiger + { + public: + virtual ~Configer() = default; - static Configer& get_instance() { - static Configer unique_instance; - return unique_instance; - } + static Configer& get_instance() { + static Configer unique_instance; + return unique_instance; + } - constexpr static int WindowWidthDefault = 1280; - constexpr static int WindowHeightDefault = 720; - constexpr static double TemplThresholdDefault = 0.9; - constexpr static double HistThresholdDefault = 0.9; + constexpr static int WindowWidthDefault = 1280; + constexpr static int WindowHeightDefault = 720; + constexpr static double TemplThresholdDefault = 0.9; + constexpr static double HistThresholdDefault = 0.9; - std::string m_version; - Options m_options; - std::unordered_map m_handles; - std::unordered_map m_recruit_ocr_replace; - std::unordered_map m_infrast_ocr_replace; + std::string m_version; + Options m_options; + std::unordered_map m_handles; + std::unordered_map m_recruit_ocr_replace; + std::unordered_map m_infrast_ocr_replace; - InfrastOptions m_infrast_options; + InfrastOptions m_infrast_options; - protected: - Configer() = default; - Configer(const Configer& rhs) = default; - Configer(Configer&& rhs) noexcept = default; + protected: + Configer() = default; + Configer(const Configer& rhs) = default; + Configer(Configer&& rhs) noexcept = default; - Configer& operator=(const Configer& rhs) = default; - Configer& operator=(Configer&& rhs) noexcept = default; + Configer& operator=(const Configer& rhs) = default; + Configer& operator=(Configer&& rhs) noexcept = default; - virtual bool parse(const json::value& json) override; - }; + virtual bool parse(const json::value& json) override; + }; } diff --git a/src/MeoAssistance/CreditShoppingTask.cpp b/src/MeoAssistance/CreditShoppingTask.cpp index 9cca31c063..ba645de6d7 100644 --- a/src/MeoAssistance/CreditShoppingTask.cpp +++ b/src/MeoAssistance/CreditShoppingTask.cpp @@ -11,111 +11,111 @@ bool asst::CreditShoppingTask::run() { - if (m_controller_ptr == nullptr - || m_identify_ptr == nullptr) - { - m_callback(AsstMsg::PtrIsNull, json::value(), m_callback_arg); - return false; - } + if (m_controller_ptr == nullptr + || m_identify_ptr == nullptr) + { + m_callback(AsstMsg::PtrIsNull, json::value(), m_callback_arg); + return false; + } - cv::Mat image = m_controller_ptr->get_image(); + cv::Mat image = m_controller_ptr->get_image(); - // 识别信用点的图标 - auto find_res_vec = m_identify_ptr->find_all_images(image, "CreditPoint", Configer::TemplThresholdDefault, false); + // 识别信用点的图标 + auto find_res_vec = m_identify_ptr->find_all_images(image, "CreditPoint", Configer::TemplThresholdDefault, false); - // 按位置排个序 - std::sort(find_res_vec.begin(), find_res_vec.end(), []( - const auto& lhs, const auto& rhs) -> bool { - if (std::abs(lhs.rect.y - rhs.rect.y) < 5) { // y差距较小则理解为是同一排的,按x排序 - return lhs.rect.x < rhs.rect.x; - } - else { - return lhs.rect.y < rhs.rect.y; - } - }); + // 按位置排个序 + std::sort(find_res_vec.begin(), find_res_vec.end(), []( + const auto& lhs, const auto& rhs) -> bool { + if (std::abs(lhs.rect.y - rhs.rect.y) < 5) { // y差距较小则理解为是同一排的,按x排序 + return lhs.rect.x < rhs.rect.x; + } + else { + return lhs.rect.y < rhs.rect.y; + } + }); - // 计算哪些商品是需要买的 - std::vector need_to_buy; - for (const auto& res : find_res_vec) { - cv::Rect name_rect; - name_rect.x = res.rect.x - 80; - name_rect.y = res.rect.y - 210; - name_rect.width = 230; - name_rect.height = 70; - if (name_rect.x < 0) { - name_rect.x = 0; - } - // 过滤掉不买的 - // TODO,哪些要买哪些不买,提供个接口出去 - static const std::vector not_to_buy_names = { "碳", "家具" }; - const auto& ocr_res = m_identify_ptr->ocr_detect(image(name_rect)); - auto find_iter = std::find_first_of(ocr_res.cbegin(), ocr_res.cend(), not_to_buy_names.cbegin(), not_to_buy_names.cend(), - [](const auto& lhs, const std::string& rhs) -> bool { - return lhs.text.find(rhs) != std::string::npos; - }); - if (find_iter != ocr_res.cend()) { + // 计算哪些商品是需要买的 + std::vector need_to_buy; + for (const auto& res : find_res_vec) { + cv::Rect name_rect; + name_rect.x = res.rect.x - 80; + name_rect.y = res.rect.y - 210; + name_rect.width = 230; + name_rect.height = 70; + if (name_rect.x < 0) { + name_rect.x = 0; + } + // 过滤掉不买的 + // TODO,哪些要买哪些不买,提供个接口出去 + static const std::vector not_to_buy_names = { "碳", "家具" }; + const auto& ocr_res = m_identify_ptr->ocr_detect(image(name_rect)); + auto find_iter = std::find_first_of(ocr_res.cbegin(), ocr_res.cend(), not_to_buy_names.cbegin(), not_to_buy_names.cend(), + [](const auto& lhs, const std::string& rhs) -> bool { + return lhs.text.find(rhs) != std::string::npos; + }); + if (find_iter != ocr_res.cend()) { #ifdef LOG_TRACE - cv::putText(image, "Not to buy", cv::Point(res.rect.x, res.rect.y), 1, 2, cv::Scalar(255, 0, 0)); + cv::putText(image, "Not to buy", cv::Point(res.rect.x, res.rect.y), 1, 2, cv::Scalar(255, 0, 0)); #endif // LOG_TRACE - continue; - } - Rect commodity_rect(res.rect.x - 60, res.rect.y - 180, 220, 220); - // 识别“售罄” - auto sold_out_res = m_identify_ptr->find_image(image(make_rect(commodity_rect)), "SoldOut"); + continue; + } + Rect commodity_rect(res.rect.x - 60, res.rect.y - 180, 220, 220); + // 识别“售罄” + auto sold_out_res = m_identify_ptr->find_image(image(make_rect(commodity_rect)), "SoldOut"); #ifdef LOG_TRACE - cv::rectangle(image, make_rect(commodity_rect), cv::Scalar(0, 0, 255)); - if (sold_out_res.score >= Configer::TemplThresholdDefault) { - cv::putText(image, "Sold Out", cv::Point(commodity_rect.x, commodity_rect.y), 1, 2, cv::Scalar(255, 0, 0)); - } + cv::rectangle(image, make_rect(commodity_rect), cv::Scalar(0, 0, 255)); + if (sold_out_res.score >= Configer::TemplThresholdDefault) { + cv::putText(image, "Sold Out", cv::Point(commodity_rect.x, commodity_rect.y), 1, 2, cv::Scalar(255, 0, 0)); + } #endif // LOG_TRACE - if (sold_out_res.score >= Configer::TemplThresholdDefault) { - continue; - } - need_to_buy.emplace_back(commodity_rect.center_zoom(0.8)); - } + if (sold_out_res.score >= Configer::TemplThresholdDefault) { + continue; + } + need_to_buy.emplace_back(commodity_rect.center_zoom(0.8)); + } - for (const Rect& commodity_rect : need_to_buy) { - if (need_exit()) { - return false; - } - m_controller_ptr->click(commodity_rect); - sleep(1000); - image = m_controller_ptr->get_image(); + for (const Rect& commodity_rect : need_to_buy) { + if (need_exit()) { + return false; + } + m_controller_ptr->click(commodity_rect); + sleep(1000); + image = m_controller_ptr->get_image(); - // “购买商品”按钮 - static Rect buy_it_rect; - if (buy_it_rect.width == 0) { - auto buy_it_res = m_identify_ptr->find_image(image, "BuyIt", Configer::TemplThresholdDefault); - if (buy_it_res.score < Configer::TemplThresholdDefault) { - // 没事别到“购买商品”按钮,不应该出现这种情况,TODO 报错 - return false; - } - buy_it_rect = buy_it_res.rect; - } - if (need_exit()) { - return false; - } - m_controller_ptr->click(buy_it_rect); - sleep(1000); - // 识别是否信用不足无法购买 - image = m_controller_ptr->get_image(); - static const std::vector shopping_finished = { "信用不足", "无法购买" }; - const auto& ocr_res = ocr_detect(image(cv::Rect(940, 60, 339, 110))); - auto find_iter = std::find_first_of(ocr_res.cbegin(), ocr_res.cend(), shopping_finished.cbegin(), shopping_finished.cend(), - [](const auto& lhs, const std::string& rhs) -> bool { - return lhs.text.find(rhs) != std::string::npos; - }); - if (find_iter != ocr_res.cend()) { - click_return_button(); - return true; - } + // “购买商品”按钮 + static Rect buy_it_rect; + if (buy_it_rect.width == 0) { + auto buy_it_res = m_identify_ptr->find_image(image, "BuyIt", Configer::TemplThresholdDefault); + if (buy_it_res.score < Configer::TemplThresholdDefault) { + // 没事别到“购买商品”按钮,不应该出现这种情况,TODO 报错 + return false; + } + buy_it_rect = buy_it_res.rect; + } + if (need_exit()) { + return false; + } + m_controller_ptr->click(buy_it_rect); + sleep(1000); + // 识别是否信用不足无法购买 + image = m_controller_ptr->get_image(); + static const std::vector shopping_finished = { "信用不足", "无法购买" }; + const auto& ocr_res = ocr_detect(image(cv::Rect(940, 60, 339, 110))); + auto find_iter = std::find_first_of(ocr_res.cbegin(), ocr_res.cend(), shopping_finished.cbegin(), shopping_finished.cend(), + [](const auto& lhs, const std::string& rhs) -> bool { + return lhs.text.find(rhs) != std::string::npos; + }); + if (find_iter != ocr_res.cend()) { + click_return_button(); + return true; + } + + // 这里随便点一下都行,把购买完弹出来物品的界面取消掉 + m_controller_ptr->click(buy_it_rect); + sleep(1000); + } - // 这里随便点一下都行,把购买完弹出来物品的界面取消掉 - m_controller_ptr->click(buy_it_rect); - sleep(1000); - } - return true; -} +} \ No newline at end of file diff --git a/src/MeoAssistance/CreditShoppingTask.h b/src/MeoAssistance/CreditShoppingTask.h index f7c7f9ab90..2a9331fe1b 100644 --- a/src/MeoAssistance/CreditShoppingTask.h +++ b/src/MeoAssistance/CreditShoppingTask.h @@ -14,5 +14,4 @@ namespace asst { virtual bool run() override; private: }; - } \ No newline at end of file diff --git a/src/MeoAssistance/Identify.cpp b/src/MeoAssistance/Identify.cpp index 1eabec0d08..6c9364db7d 100644 --- a/src/MeoAssistance/Identify.cpp +++ b/src/MeoAssistance/Identify.cpp @@ -17,454 +17,453 @@ using namespace cv::xfeatures2d; bool Identify::add_image(const std::string& name, const std::string& path) { - Mat image = imread(path); - if (image.empty()) { - return false; - } - m_mat_map.emplace(name, image); - return true; + Mat image = imread(path); + if (image.empty()) { + return false; + } + m_mat_map.emplace(name, image); + return true; } bool asst::Identify::add_text_image(const std::string& text, const std::string& path) { - Mat image = imread(path); - if (image.empty()) { - return false; - } + Mat image = imread(path); + if (image.empty()) { + return false; + } - m_feature_map.emplace(text, surf_detect(image)); + m_feature_map.emplace(text, surf_detect(image)); - return true; + return true; } Mat Identify::image_2_hist(const cv::Mat& src) { - Mat src_hsv; - cvtColor(src, src_hsv, COLOR_BGR2HSV); + Mat src_hsv; + cvtColor(src, src_hsv, COLOR_BGR2HSV); - int histSize[] = { 50, 60 }; - float h_ranges[] = { 0, 180 }; - float s_ranges[] = { 0, 256 }; - const float* ranges[] = { h_ranges, s_ranges }; - int channels[] = { 0, 1 }; + int histSize[] = { 50, 60 }; + float h_ranges[] = { 0, 180 }; + float s_ranges[] = { 0, 256 }; + const float* ranges[] = { h_ranges, s_ranges }; + int channels[] = { 0, 1 }; - MatND src_hist; + MatND src_hist; - calcHist(&src_hsv, 1, channels, Mat(), src_hist, 2, histSize, ranges); - normalize(src_hist, src_hist, 0, 1, NORM_MINMAX); + calcHist(&src_hsv, 1, channels, Mat(), src_hist, 2, histSize, ranges); + normalize(src_hist, src_hist, 0, 1, NORM_MINMAX); - return src_hist; + return src_hist; } double Identify::image_hist_comp(const cv::Mat& src, const cv::MatND& hist) { - // keep the interface return value unchanged - return 1 - compareHist(image_2_hist(src), hist, CV_COMP_BHATTACHARYYA); + // keep the interface return value unchanged + return 1 - compareHist(image_2_hist(src), hist, CV_COMP_BHATTACHARYYA); } std::pair, cv::Mat> asst::Identify::surf_detect(const cv::Mat& image) { - // 灰度图转换 - cv::Mat mat_gray; - cv::cvtColor(image, mat_gray, cv::COLOR_RGB2GRAY); + // 灰度图转换 + cv::Mat mat_gray; + cv::cvtColor(image, mat_gray, cv::COLOR_RGB2GRAY); - constexpr int min_hessian = 400; - // SURF特征点检测 - static cv::Ptr detector = SURF::create(min_hessian); - std::vector keypoints; - cv::Mat mat_vector; - // 找到特征点并计算特征描述子(向量) - detector->detectAndCompute(mat_gray, Mat(), keypoints, mat_vector); + constexpr int min_hessian = 400; + // SURF特征点检测 + static cv::Ptr detector = SURF::create(min_hessian); + std::vector keypoints; + cv::Mat mat_vector; + // 找到特征点并计算特征描述子(向量) + detector->detectAndCompute(mat_gray, Mat(), keypoints, mat_vector); - return std::make_pair(std::move(keypoints), std::move(mat_vector)); + return std::make_pair(std::move(keypoints), std::move(mat_vector)); } std::optional asst::Identify::feature_match( - const std::vector& query_keypoints, const cv::Mat& query_mat_vector, - const std::vector& train_keypoints, const cv::Mat& train_mat_vector + const std::vector& query_keypoints, const cv::Mat& query_mat_vector, + const std::vector& train_keypoints, const cv::Mat& train_mat_vector #ifdef LOG_TRACE - , const cv::Mat query_mat, const cv::Mat train_mat + , const cv::Mat query_mat, const cv::Mat train_mat #endif ) { - if (query_mat_vector.empty() || train_mat_vector.empty()) { - DebugTraceError("feature_match | image empty"); - return std::nullopt; - } - std::vector matches; - static FlannBasedMatcher matcher; - matcher.match(query_mat_vector, train_mat_vector, matches); + if (query_mat_vector.empty() || train_mat_vector.empty()) { + DebugTraceError("feature_match | image empty"); + return std::nullopt; + } + std::vector matches; + static FlannBasedMatcher matcher; + matcher.match(query_mat_vector, train_mat_vector, matches); #ifdef LOG_TRACE - //std::cout << matches.size() << " / " << query_keypoints.size() << std::endl; - cv::Mat allmatch_mat; - cv::drawMatches(query_mat, query_keypoints, train_mat, train_keypoints, matches, allmatch_mat); + //std::cout << matches.size() << " / " << query_keypoints.size() << std::endl; + cv::Mat allmatch_mat; + cv::drawMatches(query_mat, query_keypoints, train_mat, train_keypoints, matches, allmatch_mat); #endif - // 最大的距离 - auto max_iter = std::max_element(matches.cbegin(), matches.cend(), - [](const cv::DMatch& lhs, const cv::DMatch& rhs) ->bool { - return lhs.distance < rhs.distance; - }); // 描述符欧式距离(knn) - if (max_iter == matches.cend()) { - return std::nullopt;; - } - float maxdist = max_iter->distance; + // 最大的距离 + auto max_iter = std::max_element(matches.cbegin(), matches.cend(), + [](const cv::DMatch& lhs, const cv::DMatch& rhs) ->bool { + return lhs.distance < rhs.distance; + }); // 描述符欧式距离(knn) + if (max_iter == matches.cend()) { + return std::nullopt;; + } + float maxdist = max_iter->distance; - std::vector approach_matches; - std::vector train_approach_keypoints; - std::vector query_approach_keypoints; - std::vector train_approach_points; - std::vector query_approach_points; - // 利用距离进行一次逼近 - constexpr static const double MatchRatio = 0.4; - int approach_index = 0; - for (const cv::DMatch dmatch : matches) { - if (dmatch.distance < maxdist * MatchRatio) { - // 按理说不会越界,以防万一还是检查一下 - if (dmatch.queryIdx >= 0 && dmatch.queryIdx < query_keypoints.size() - && dmatch.trainIdx >= 0 && dmatch.trainIdx < train_keypoints.size()) { - approach_matches.emplace_back(dmatch); - train_approach_points.emplace_back(train_keypoints.at(dmatch.trainIdx).pt); - query_approach_points.emplace_back(query_keypoints.at(dmatch.queryIdx).pt); - train_approach_keypoints.emplace_back(train_keypoints.at(dmatch.trainIdx)); - query_approach_keypoints.emplace_back(query_keypoints.at(dmatch.queryIdx)); - } - } - } + std::vector approach_matches; + std::vector train_approach_keypoints; + std::vector query_approach_keypoints; + std::vector train_approach_points; + std::vector query_approach_points; + // 利用距离进行一次逼近 + constexpr static const double MatchRatio = 0.4; + int approach_index = 0; + for (const cv::DMatch dmatch : matches) { + if (dmatch.distance < maxdist * MatchRatio) { + // 按理说不会越界,以防万一还是检查一下 + if (dmatch.queryIdx >= 0 && dmatch.queryIdx < query_keypoints.size() + && dmatch.trainIdx >= 0 && dmatch.trainIdx < train_keypoints.size()) { + approach_matches.emplace_back(dmatch); + train_approach_points.emplace_back(train_keypoints.at(dmatch.trainIdx).pt); + query_approach_points.emplace_back(query_keypoints.at(dmatch.queryIdx).pt); + train_approach_keypoints.emplace_back(train_keypoints.at(dmatch.trainIdx)); + query_approach_keypoints.emplace_back(query_keypoints.at(dmatch.queryIdx)); + } + } + } #ifdef LOG_TRACE - cv::Mat approach_mat; - cv::drawMatches(query_mat, query_keypoints, train_mat, train_keypoints, approach_matches, approach_mat); + cv::Mat approach_mat; + cv::drawMatches(query_mat, query_keypoints, train_mat, train_keypoints, approach_matches, approach_mat); #endif - if (query_approach_points.empty()) - { - return std::nullopt; - } + if (query_approach_points.empty()) { + return std::nullopt; + } - // 使用RANSAC剔除异常值 - std::vector ransac_status; - cv::Mat fundametal = cv::findFundamentalMat(query_approach_points, train_approach_points, ransac_status, cv::FM_RANSAC); + // 使用RANSAC剔除异常值 + std::vector ransac_status; + cv::Mat fundametal = cv::findFundamentalMat(query_approach_points, train_approach_points, ransac_status, cv::FM_RANSAC); - std::vector ransac_matchs; - std::vector train_ransac_keypoints; - std::vector query_ransac_keypoints; - int index = 0; - for (size_t i = 0; i != ransac_status.size(); ++i) { - if (ransac_status.at(i) != 0) { - train_ransac_keypoints.emplace_back(train_approach_keypoints.at(i)); - query_ransac_keypoints.emplace_back(query_approach_keypoints.at(i)); - cv::DMatch dmatch = approach_matches.at(i); - ransac_matchs.emplace_back(std::move(dmatch)); - ++index; - } - } + std::vector ransac_matchs; + std::vector train_ransac_keypoints; + std::vector query_ransac_keypoints; + int index = 0; + for (size_t i = 0; i != ransac_status.size(); ++i) { + if (ransac_status.at(i) != 0) { + train_ransac_keypoints.emplace_back(train_approach_keypoints.at(i)); + query_ransac_keypoints.emplace_back(query_approach_keypoints.at(i)); + cv::DMatch dmatch = approach_matches.at(i); + ransac_matchs.emplace_back(std::move(dmatch)); + ++index; + } + } - // 做一次算数均值滤波,过滤异常的点。这个算法有点蠢,TODO可以看下怎么改 - size_t point_size = train_ransac_keypoints.size(); - if (point_size == 0) { - return std::nullopt; - } - cv::Point sum_point = std::accumulate( - train_ransac_keypoints.cbegin(), train_ransac_keypoints.cend(), cv::Point(), - [](cv::Point sum, const cv::KeyPoint& rhs) -> cv::Point { - return cv::Point(sum.x + rhs.pt.x, sum.y + rhs.pt.y); - }); - cv::Point avg_point(sum_point.x / point_size, sum_point.y / point_size); - std::vector good_matchs; - std::vector good_points; - // TODO,这个阈值需要根据分辨率进行缩放,而且最好写到配置文件里 - constexpr static int DistanceThreshold = 100; - for (size_t i = 0; i != train_ransac_keypoints.size(); ++i) { - // 没必要算距离,x y各算一下就行了,省点CPU时间 - //int distance = std::sqrt(std::pow(avg_point.x - cur_x, 2) + std::pow(avg_point.y - cur_y, 2)); - cv::Point2f& pt = train_ransac_keypoints.at(i).pt; - int x_distance = std::abs(avg_point.x - pt.x); - int y_distance = std::abs(avg_point.y - pt.y); - if (x_distance < DistanceThreshold && y_distance < DistanceThreshold) { - good_matchs.emplace_back(ransac_matchs.at(i)); - good_points.emplace_back(pt); - } - } + // 做一次算数均值滤波,过滤异常的点。这个算法有点蠢,TODO可以看下怎么改 + size_t point_size = train_ransac_keypoints.size(); + if (point_size == 0) { + return std::nullopt; + } + cv::Point sum_point = std::accumulate( + train_ransac_keypoints.cbegin(), train_ransac_keypoints.cend(), cv::Point(), + [](cv::Point sum, const cv::KeyPoint& rhs) -> cv::Point { + return cv::Point(sum.x + rhs.pt.x, sum.y + rhs.pt.y); + }); + cv::Point avg_point(sum_point.x / point_size, sum_point.y / point_size); + std::vector good_matchs; + std::vector good_points; + // TODO,这个阈值需要根据分辨率进行缩放,而且最好写到配置文件里 + constexpr static int DistanceThreshold = 100; + for (size_t i = 0; i != train_ransac_keypoints.size(); ++i) { + // 没必要算距离,x y各算一下就行了,省点CPU时间 + //int distance = std::sqrt(std::pow(avg_point.x - cur_x, 2) + std::pow(avg_point.y - cur_y, 2)); + cv::Point2f& pt = train_ransac_keypoints.at(i).pt; + int x_distance = std::abs(avg_point.x - pt.x); + int y_distance = std::abs(avg_point.y - pt.y); + if (x_distance < DistanceThreshold && y_distance < DistanceThreshold) { + good_matchs.emplace_back(ransac_matchs.at(i)); + good_points.emplace_back(pt); + } + } #ifdef LOG_TRACE - cv::Mat ransac_mat; - cv::drawMatches(query_mat, query_keypoints, train_mat, train_keypoints, ransac_matchs, ransac_mat); + cv::Mat ransac_mat; + cv::drawMatches(query_mat, query_keypoints, train_mat, train_keypoints, ransac_matchs, ransac_mat); - cv::Mat good_mat; - cv::drawMatches(query_mat, query_keypoints, train_mat, train_keypoints, good_matchs, good_mat); + cv::Mat good_mat; + cv::drawMatches(query_mat, query_keypoints, train_mat, train_keypoints, good_matchs, good_mat); #endif - constexpr static const double MatchSizeRatioThreshold = 0.1; - if (good_points.size() >= query_keypoints.size() * MatchSizeRatioThreshold) { - Rect dst; - int left = 0, right = 0, top = 0, bottom = 0; - for (const cv::Point& pt : good_points) { - if (pt.x < left || left == 0) { - left = pt.x; - } - if (pt.x > right || right == 0) { - right = pt.x; - } - if (pt.y < top || top == 0) { - top = pt.y; - } - if (pt.y > bottom || bottom == 0) { - bottom = pt.y; - } - } - dst = { left, top, right - left, bottom - top }; - return dst; - } - return std::nullopt; + constexpr static const double MatchSizeRatioThreshold = 0.1; + if (good_points.size() >= query_keypoints.size() * MatchSizeRatioThreshold) { + Rect dst; + int left = 0, right = 0, top = 0, bottom = 0; + for (const cv::Point& pt : good_points) { + if (pt.x < left || left == 0) { + left = pt.x; + } + if (pt.x > right || right == 0) { + right = pt.x; + } + if (pt.y < top || top == 0) { + top = pt.y; + } + if (pt.y > bottom || bottom == 0) { + bottom = pt.y; + } + } + dst = { left, top, right - left, bottom - top }; + return dst; + } + return std::nullopt; } std::vector