diff --git a/include/AsstCaller.h b/include/AsstCaller.h index 7bec692b44..9da5496e50 100644 --- a/include/AsstCaller.h +++ b/include/AsstCaller.h @@ -36,8 +36,7 @@ extern "C" { bool ASSTAPI AsstStart(AsstHandle handle); bool ASSTAPI AsstStop(AsstHandle handle); - bool ASSTAPI AsstSetPenguinId(AsstHandle handle, const char* id); - // bool ASSTAPI AsstSetParam(AsstHandle handle, const char* type, const char* param, const char* value); + bool ASSTAPI AsstSetParam(AsstHandle handle, const char* param_id, const char* param_value); unsigned long long ASSTAPI AsstGetImage(AsstHandle handle, void* buff, unsigned long long buff_size); bool ASSTAPI AsstCtrlerClick(AsstHandle handle, int x, int y, bool block); diff --git a/include/AsstDef.h b/include/AsstDef.h new file mode 100644 index 0000000000..a09d9ec94c --- /dev/null +++ b/include/AsstDef.h @@ -0,0 +1,4 @@ +#pragma once + +#define AsstParamIdPenguinId "penguin_id" +#define AsstParamIdOcrText "ocr_text" diff --git a/src/MeoAssistant/AbstractImageAnalyzer.cpp b/src/MeoAssistant/AbstractImageAnalyzer.cpp index a43a86762d..22b39bb820 100644 --- a/src/MeoAssistant/AbstractImageAnalyzer.cpp +++ b/src/MeoAssistant/AbstractImageAnalyzer.cpp @@ -11,6 +11,15 @@ asst::AbstractImageAnalyzer::AbstractImageAnalyzer(const cv::Mat image) #endif {} +asst::AbstractImageAnalyzer::AbstractImageAnalyzer(const cv::Mat image, std::shared_ptr task_data) + : m_image(image), m_roi(empty_rect_to_full(Rect(), image)), + m_task_data(task_data) +#ifdef ASST_DEBUG + , + m_image_draw(image.clone()) +#endif +{} + asst::AbstractImageAnalyzer::AbstractImageAnalyzer(const cv::Mat image, const Rect& roi) : m_image(image), m_roi(empty_rect_to_full(roi, image)) @@ -41,6 +50,11 @@ void asst::AbstractImageAnalyzer::set_roi(const Rect& roi) noexcept m_roi = empty_rect_to_full(roi, m_image); } +void asst::AbstractImageAnalyzer::set_task_data(std::shared_ptr task_data) +{ + m_task_data = task_data; +} + asst::Rect asst::AbstractImageAnalyzer::empty_rect_to_full(const Rect& rect, const cv::Mat image) noexcept { return rect.empty() ? Rect(0, 0, image.cols, image.rows) : rect; diff --git a/src/MeoAssistant/AbstractImageAnalyzer.h b/src/MeoAssistant/AbstractImageAnalyzer.h index db187e6577..2a6401f956 100644 --- a/src/MeoAssistant/AbstractImageAnalyzer.h +++ b/src/MeoAssistant/AbstractImageAnalyzer.h @@ -2,15 +2,17 @@ #include -#include "AsstDef.h" +#include "AsstTypes.h" namespace asst { + class TaskData; class AbstractImageAnalyzer { public: AbstractImageAnalyzer() = default; AbstractImageAnalyzer(const cv::Mat image); + AbstractImageAnalyzer(const cv::Mat image, std::shared_ptr task_data); AbstractImageAnalyzer(const cv::Mat image, const Rect& roi); AbstractImageAnalyzer(const AbstractImageAnalyzer&) = delete; AbstractImageAnalyzer(AbstractImageAnalyzer&&) = delete; @@ -18,6 +20,7 @@ namespace asst virtual void set_image(const cv::Mat image, const Rect& roi = Rect()); virtual void set_roi(const Rect& roi) noexcept; + void set_task_data(std::shared_ptr task_data); virtual bool analyze() = 0; @@ -30,6 +33,7 @@ namespace asst cv::Mat m_image; Rect m_roi; + std::shared_ptr m_task_data = nullptr; #ifdef ASST_DEBUG cv::Mat m_image_draw; diff --git a/src/MeoAssistant/AbstractTask.cpp b/src/MeoAssistant/AbstractTask.cpp index 8d109b3360..65137e682c 100644 --- a/src/MeoAssistant/AbstractTask.cpp +++ b/src/MeoAssistant/AbstractTask.cpp @@ -70,6 +70,12 @@ AbstractTask& asst::AbstractTask::set_status(std::shared_ptr stat return *this; } +AbstractTask& asst::AbstractTask::set_task_data(std::shared_ptr task_data) noexcept +{ + m_task_data = task_data; + return *this; +} + void asst::AbstractTask::clear_plugin() noexcept { m_plugins.clear(); @@ -155,6 +161,8 @@ void asst::AbstractTask::callback(AsstMsg msg, const json::value& detail) for (TaskPluginPtr plugin : m_plugins) { plugin->set_exit_flag(m_exit_flag); plugin->set_ctrler(m_ctrler); + plugin->set_status(m_status); + plugin->set_task_data(m_task_data); plugin->set_task_ptr(this); if (!plugin->verify(msg, detail)) { @@ -173,7 +181,7 @@ void asst::AbstractTask::callback(AsstMsg msg, const json::value& detail) void asst::AbstractTask::click_return_button() { LogTraceFunction; - const auto return_task_ptr = Task.get("Return"); + const auto return_task_ptr = m_task_data->get("Return"); Rect ReturnButtonRect = return_task_ptr->specific_rect; diff --git a/src/MeoAssistant/AbstractTask.h b/src/MeoAssistant/AbstractTask.h index 602f01c9db..e02feb8f5e 100644 --- a/src/MeoAssistant/AbstractTask.h +++ b/src/MeoAssistant/AbstractTask.h @@ -19,6 +19,7 @@ namespace asst class Controller; class RuntimeStatus; + class TaskData; class AbstractTask { @@ -34,6 +35,7 @@ namespace asst AbstractTask& set_retry_times(int times) noexcept; AbstractTask& set_ctrler(std::shared_ptr ctrler) noexcept; AbstractTask& set_status(std::shared_ptr status) noexcept; + AbstractTask& set_task_data(std::shared_ptr task_data) noexcept; template std::shared_ptr regiseter_plugin() @@ -73,5 +75,6 @@ namespace asst std::set m_plugins; std::shared_ptr m_ctrler = nullptr; std::shared_ptr m_status = nullptr; + std::shared_ptr m_task_data = nullptr; }; } diff --git a/src/MeoAssistant/AipOcr.h b/src/MeoAssistant/AipOcr.h index f22fbda1d1..506f24f73f 100644 --- a/src/MeoAssistant/AipOcr.h +++ b/src/MeoAssistant/AipOcr.h @@ -2,7 +2,7 @@ #include -#include "AsstDef.h" +#include "AsstTypes.h" namespace cv { diff --git a/src/MeoAssistant/Assistant.cpp b/src/MeoAssistant/Assistant.cpp index 0ede6531b0..1e78747067 100644 --- a/src/MeoAssistant/Assistant.cpp +++ b/src/MeoAssistant/Assistant.cpp @@ -27,6 +27,7 @@ #include "RuntimeStatus.h" #include "StageDropsTaskPlugin.h" #include "DronesForShamareTaskPlugin.h" +#include "AsstDef.h" using namespace asst; @@ -37,6 +38,7 @@ Assistant::Assistant(AsstApiCallback callback, void* callback_arg) LogTraceFunction; m_status = std::make_shared(); + m_task_data = std::make_shared(); m_ctrler = std::make_shared(task_callback, (void*)this); m_working_thread = std::thread(&Assistant::working_proc, this); @@ -401,17 +403,6 @@ bool asst::Assistant::append_infrast(infrast::WorkMode work_mode, const std::vec return true; } -void asst::Assistant::set_penguin_id(const std::string& id) -{ - auto& opt = Resrc.cfg().get_options(); - if (id.empty()) { - opt.penguin_report.extra_param.clear(); - } - else { - opt.penguin_report.extra_param = "-H \"authorization: PenguinID " + id + "\""; - } -} - std::vector asst::Assistant::get_image() const { if (!m_inited) { @@ -429,6 +420,27 @@ bool asst::Assistant::ctrler_click(int x, int y, bool block) return true; } +bool asst::Assistant::set_param(const std::string& param_id, const std::string& param_value) +{ + Log.info(__FUNCTION__, param_id, param_value); + + using SetParamFuncType = std::function; + + static const std::unordered_map ParamsMapping = { + {AsstParamIdPenguinId, std::bind(&Assistant::set_penguid_id, this, std::placeholders::_1)}, + {AsstParamIdOcrText, std::bind(&Assistant::set_ocr_text, this, std::placeholders::_1)}, + }; + + if (const auto iter = ParamsMapping.find(param_id); + iter != ParamsMapping.cend()) { + return iter->second(param_value); + } + else { + Log.error("Invaild Param Id", param_id); + return false; + } +} + bool asst::Assistant::start(bool block) { LogTraceFunction; @@ -492,7 +504,8 @@ void Assistant::working_proc() task_ptr->set_exit_flag(&m_thread_idle) .set_ctrler(m_ctrler) - .set_status(m_status); + .set_status(m_status) + .set_task_data(m_task_data); bool ret = task_ptr->run(); @@ -581,3 +594,40 @@ void Assistant::clear_cache() m_status->clear_data(); //Task.clear_cache(); } + +bool asst::Assistant::set_penguid_id(const std::string& param_value) +{ + auto& opt = Resrc.cfg().get_options(); + if (param_value.empty()) { + opt.penguin_report.extra_param.clear(); + } + else { + opt.penguin_report.extra_param = "-H \"authorization: PenguinID " + param_value + "\""; + } + return true; +} + +bool asst::Assistant::set_ocr_text(const std::string& param_value) +{ + const auto json_opt = json::parse(param_value); + if (!json_opt) { + return false; + } + const auto& root = json_opt.value(); + + for (auto&& [key, text] : root.as_object()) { + if (!text.is_array()) { + return false; + } + std::vector text_vec; + for (auto&& text : text.as_array()) { + if (!text.is_string()) { + return false; + } + text_vec.emplace_back(text.as_string()); + } + m_task_data->set_ocr_text(key, std::move(text_vec)); + } + + return true; +} diff --git a/src/MeoAssistant/Assistant.h b/src/MeoAssistant/Assistant.h index 78017542f2..06b05c17e3 100644 --- a/src/MeoAssistant/Assistant.h +++ b/src/MeoAssistant/Assistant.h @@ -9,7 +9,7 @@ #include #include "AbstractTask.h" -#include "AsstDef.h" +#include "AsstTypes.h" #include "AsstMsg.h" #include "AsstInfrastDef.h" @@ -25,6 +25,7 @@ namespace asst class Controller; class Identify; class Controller; + class TaskData; class Assistant { @@ -77,13 +78,10 @@ namespace asst // 停止任务队列并清空 bool stop(bool block = true); - // 设置企鹅数据汇报个人ID - void set_penguin_id(const std::string& id); - std::vector get_image() const; bool ctrler_click(int x, int y, bool block = true); - [[deprecated]] bool set_param(const std::string& type, const std::string& param, const std::string& value); + bool set_param(const std::string& param_id, const std::string& param_value); static constexpr int ProcessTaskRetryTimesDefault = AbstractTask::RetryTimesDefault; static constexpr int OpenRecruitTaskRetryTimesDefault = 5; @@ -98,11 +96,16 @@ namespace asst void append_callback(AsstMsg msg, json::value detail); void clear_cache(); + /* set params */ + bool set_penguid_id(const std::string& param_value); + bool set_ocr_text(const std::string& param_value); + bool m_inited = false; std::string m_uuid; std::shared_ptr m_ctrler = nullptr; std::shared_ptr m_status = nullptr; + std::shared_ptr m_task_data = nullptr; bool m_thread_exit = false; std::queue> m_tasks_queue; diff --git a/src/MeoAssistant/AsstCaller.cpp b/src/MeoAssistant/AsstCaller.cpp index c43855f13e..16467c93a0 100644 --- a/src/MeoAssistant/AsstCaller.cpp +++ b/src/MeoAssistant/AsstCaller.cpp @@ -6,7 +6,7 @@ #include #include "Assistant.h" -#include "AsstDef.h" +#include "AsstTypes.h" #include "Version.h" #include "Logger.hpp" #include "Resource.h" @@ -79,7 +79,7 @@ bool AsstConnect(AsstHandle handle, const char* adb_path, const char* address, c return handle->connect(adb_path, address, config ? config : std::string()); } -bool ASSTAPI AsstAppendStartUp(AsstHandle handle) +bool AsstAppendStartUp(AsstHandle handle) { if (!inited || handle == nullptr) { return false; @@ -197,14 +197,13 @@ bool AsstStop(AsstHandle handle) return handle->stop(); } -bool AsstSetPenguinId(AsstHandle handle, const char* id) +bool AsstSetParam(AsstHandle handle, const char* param_id, const char* param_value) { if (!inited || handle == nullptr) { return false; } - handle->set_penguin_id(id); - return true; + return handle->set_param(param_id, param_value); } unsigned long long AsstGetImage(AsstHandle handle, void* buff, unsigned long long buff_size) diff --git a/src/MeoAssistant/AsstInfrastDef.h b/src/MeoAssistant/AsstInfrastDef.h index 3ae7f2dae1..9ec00ab65c 100644 --- a/src/MeoAssistant/AsstInfrastDef.h +++ b/src/MeoAssistant/AsstInfrastDef.h @@ -1,6 +1,6 @@ #pragma once -#include "AsstDef.h" +#include "AsstTypes.h" namespace asst { diff --git a/src/MeoAssistant/AsstMsg.h b/src/MeoAssistant/AsstMsg.h index bf50639965..cf0fc0e391 100644 --- a/src/MeoAssistant/AsstMsg.h +++ b/src/MeoAssistant/AsstMsg.h @@ -13,7 +13,7 @@ namespace asst /* Global Info */ InternalError = 0, // 内部错误 InitFailed, // 初始化失败 - ConnectionInfo, // 连接相关错误 + ConnectionInfo, // 连接相关错误 AllTasksCompleted, // 全部任务完成 /* TaskChain Info */ TaskChainError = 10000, // 任务链执行/识别错误 diff --git a/src/MeoAssistant/AsstDef.h b/src/MeoAssistant/AsstTypes.h similarity index 100% rename from src/MeoAssistant/AsstDef.h rename to src/MeoAssistant/AsstTypes.h diff --git a/src/MeoAssistant/AutoRecruitTask.cpp b/src/MeoAssistant/AutoRecruitTask.cpp index 46a889e376..84936f5767 100644 --- a/src/MeoAssistant/AutoRecruitTask.cpp +++ b/src/MeoAssistant/AutoRecruitTask.cpp @@ -80,7 +80,7 @@ bool asst::AutoRecruitTask::_run() bool asst::AutoRecruitTask::analyze_start_buttons() { OcrImageAnalyzer start_analyzer; - start_analyzer.set_task_info("StartRecruit"); + start_analyzer.set_task_info(m_task_data->get("StartRecruit")); auto image = m_ctrler->get_image(); start_analyzer.set_image(image); diff --git a/src/MeoAssistant/AutoRecruitTask.h b/src/MeoAssistant/AutoRecruitTask.h index 6ab96df4da..2e8b87bd3c 100644 --- a/src/MeoAssistant/AutoRecruitTask.h +++ b/src/MeoAssistant/AutoRecruitTask.h @@ -1,40 +1,40 @@ #pragma once #include "AbstractTask.h" -#include "AsstDef.h" +#include "AsstTypes.h" namespace asst { - class AutoRecruitTask final : public AbstractTask - { - public: - using AbstractTask::AbstractTask; - virtual ~AutoRecruitTask() = default; + class AutoRecruitTask final : public AbstractTask + { + public: + using AbstractTask::AbstractTask; + virtual ~AutoRecruitTask() = default; - AutoRecruitTask& set_select_level(std::vector select_level) noexcept; - AutoRecruitTask& set_confirm_level(std::vector confirm_level) noexcept; - AutoRecruitTask& set_need_refresh(bool need_refresh) noexcept; - AutoRecruitTask& set_max_times(int max_times) noexcept; - AutoRecruitTask& set_use_expedited(bool use_or_not) noexcept; + AutoRecruitTask& set_select_level(std::vector select_level) noexcept; + AutoRecruitTask& set_confirm_level(std::vector confirm_level) noexcept; + AutoRecruitTask& set_need_refresh(bool need_refresh) noexcept; + AutoRecruitTask& set_max_times(int max_times) noexcept; + AutoRecruitTask& set_use_expedited(bool use_or_not) noexcept; - protected: - virtual bool _run() override; + protected: + virtual bool _run() override; - bool analyze_start_buttons(); - bool recruit_index(size_t index); - bool calc_and_recruit(); - bool check_recruit_home_page(); - bool recruit_now(); - bool confirm(); - bool refresh(); + bool analyze_start_buttons(); + bool recruit_index(size_t index); + bool calc_and_recruit(); + bool check_recruit_home_page(); + bool recruit_now(); + bool confirm(); + bool refresh(); - std::vector m_select_level; - std::vector m_confirm_level; - bool m_need_refresh = false; - bool m_use_expedited = false; - int m_max_times = 0; + std::vector m_select_level; + std::vector m_confirm_level; + bool m_need_refresh = false; + bool m_use_expedited = false; + int m_max_times = 0; - std::vector m_start_buttons; - int m_cur_times = 0; - }; + std::vector m_start_buttons; + int m_cur_times = 0; + }; } diff --git a/src/MeoAssistant/BattleImageAnalyzer.cpp b/src/MeoAssistant/BattleImageAnalyzer.cpp index 90fc1b6c6e..a368ebb4ed 100644 --- a/src/MeoAssistant/BattleImageAnalyzer.cpp +++ b/src/MeoAssistant/BattleImageAnalyzer.cpp @@ -8,6 +8,10 @@ #include "Logger.hpp" #include "TaskData.h" +asst::BattleImageAnalyzer::BattleImageAnalyzer(const cv::Mat image, std::shared_ptr task_data) + : AbstractImageAnalyzer(image, task_data) +{} + bool asst::BattleImageAnalyzer::analyze() { // 生命值和家门,只要识别到了任一个,就可以说明当前是在战斗场景 @@ -46,16 +50,16 @@ bool asst::BattleImageAnalyzer::opers_analyze() LogTraceFunction; MultiMatchImageAnalyzer flags_analyzer(m_image); - flags_analyzer.set_task_info("BattleOpersFlag"); + flags_analyzer.set_task_info(m_task_data->get("BattleOpersFlag")); if (!flags_analyzer.analyze()) { return false; } flags_analyzer.sort_result(); - const auto click_move = Task.get("BattleOperClickRange")->rect_move; - const auto role_move = Task.get("BattleOperRoleRange")->rect_move; - const auto cost_move = Task.get("BattleOperCostRange")->rect_move; - const auto avlb_move = Task.get("BattleOperAvailable")->rect_move; + const auto click_move = m_task_data->get("BattleOperClickRange")->rect_move; + const auto role_move = m_task_data->get("BattleOperRoleRange")->rect_move; + const auto cost_move = m_task_data->get("BattleOperCostRange")->rect_move; + const auto avlb_move = m_task_data->get("BattleOperAvailable")->rect_move; for (const MatchRect& flag_mrect : flags_analyzer.get_result()) { Oper oper; @@ -104,7 +108,7 @@ asst::BattleImageAnalyzer::Role asst::BattleImageAnalyzer::oper_role_analyze(con Role result = Role::Unknown; double max_score = 0; for (auto&& [role, role_name] : RolesName) { - role_analyzer.set_task_info("BattleOperRole" + role_name); + role_analyzer.set_task_info(m_task_data->get("BattleOperRole" + role_name)); role_analyzer.set_roi(roi); if (!role_analyzer.analyze()) { continue; @@ -142,17 +146,17 @@ int asst::BattleImageAnalyzer::oper_cost_analyze(const Rect& roi) static HashImageAnalyzer hash_analyzer; if (!inited) { auto [h_l, h_u] = std::dynamic_pointer_cast( - Task.get("BattleOperCostChannelH"))->mask_range; + m_task_data->get("BattleOperCostChannelH"))->mask_range; auto [s_l, s_u] = std::dynamic_pointer_cast( - Task.get("BattleOperCostChannelS"))->mask_range; + m_task_data->get("BattleOperCostChannelS"))->mask_range; auto [v_l, v_u] = std::dynamic_pointer_cast( - Task.get("BattleOperCostChannelV"))->mask_range; + m_task_data->get("BattleOperCostChannelV"))->mask_range; range_lower = cv::Scalar(h_l, s_l, v_l); range_upper = cv::Scalar(h_u, s_u, v_u); std::unordered_map num_hashs; for (auto&& num : NumName) { auto hashs_vec = std::dynamic_pointer_cast( - Task.get("BattleOperCost" + num))->hashs; + m_task_data->get("BattleOperCost" + num))->hashs; for (size_t i = 0; i != hashs_vec.size(); ++i) { num_hashs.emplace(num + "_" + std::to_string(i), hashs_vec.at(i)); } @@ -195,7 +199,7 @@ bool asst::BattleImageAnalyzer::oper_available_analyze(const Rect& roi) Log.trace("oper available, mean", avg[2]); static int thres = static_cast(std::dynamic_pointer_cast( - Task.get("BattleOperAvailable"))->special_threshold); + m_task_data->get("BattleOperAvailable"))->special_threshold); if (avg[2] < thres) { return false; } @@ -246,7 +250,7 @@ bool asst::BattleImageAnalyzer::home_analyze() bool asst::BattleImageAnalyzer::skill_analyze() { - const auto skill_task_ptr = Task.get("BattleSkillReady"); + const auto skill_task_ptr = m_task_data->get("BattleSkillReady"); const Rect& rect_move = skill_task_ptr->rect_move; MultiMatchImageAnalyzer mm_analyzer(m_image); @@ -263,12 +267,12 @@ bool asst::BattleImageAnalyzer::skill_analyze() bool asst::BattleImageAnalyzer::hp_analyze() { // 识别 HP 的那个蓝白色图标 - auto flag_task_ptr = Task.get("BattleHpFlag"); + auto flag_task_ptr = m_task_data->get("BattleHpFlag"); MatchImageAnalyzer flag_analyzer(m_image); flag_analyzer.set_task_info(flag_task_ptr); if (!flag_analyzer.analyze()) { // 漏怪的时候,那个图标会变成红色的,所以多识别一次 - flag_task_ptr = Task.get("BattleHpFlag2"); + flag_task_ptr = m_task_data->get("BattleHpFlag2"); flag_analyzer.set_task_info(flag_task_ptr); if (!flag_analyzer.analyze()) { return false; @@ -285,17 +289,17 @@ bool asst::BattleImageAnalyzer::hp_analyze() static HashImageAnalyzer hash_analyzer; if (!inited) { auto [h_l, h_u] = std::dynamic_pointer_cast( - Task.get("BattleHpChannelH"))->mask_range; + m_task_data->get("BattleHpChannelH"))->mask_range; auto [s_l, s_u] = std::dynamic_pointer_cast( - Task.get("BattleHpChannelS"))->mask_range; + m_task_data->get("BattleHpChannelS"))->mask_range; auto [v_l, v_u] = std::dynamic_pointer_cast( - Task.get("BattleHpChannelV"))->mask_range; + m_task_data->get("BattleHpChannelV"))->mask_range; range_lower = cv::Scalar(h_l, s_l, v_l); range_upper = cv::Scalar(h_u, s_u, v_u); std::unordered_map num_hashs; for (auto&& num : NumName) { - const auto &hashs_vec = std::dynamic_pointer_cast( - Task.get("BattleHp" + num))->hashs; + const auto& hashs_vec = std::dynamic_pointer_cast( + m_task_data->get("BattleHp" + num))->hashs; for (size_t i = 0; i != hashs_vec.size(); ++i) { num_hashs.emplace(num + "_" + std::to_string(i), hashs_vec.at(i)); } diff --git a/src/MeoAssistant/BattleImageAnalyzer.h b/src/MeoAssistant/BattleImageAnalyzer.h index 6b06c832cc..870b9631d9 100644 --- a/src/MeoAssistant/BattleImageAnalyzer.h +++ b/src/MeoAssistant/BattleImageAnalyzer.h @@ -27,7 +27,7 @@ namespace asst Rect rect; }; public: - using AbstractImageAnalyzer::AbstractImageAnalyzer; + BattleImageAnalyzer(const cv::Mat image, std::shared_ptr task_data); virtual ~BattleImageAnalyzer() = default; virtual bool analyze() override; @@ -51,7 +51,7 @@ namespace asst std::vector m_opers; // 下方干员信息 std::vector m_homes; // 蓝色的家门位置 std::vector m_ready_skills; // 可以释放的技能(Rect实际是干员的位置) - int m_hp; // 剩余生命值 + int m_hp = 0; // 剩余生命值 protected: // 该分析器不支持外部设置ROI diff --git a/src/MeoAssistant/Controller.cpp b/src/MeoAssistant/Controller.cpp index ba30a391c0..9c6c8d6393 100644 --- a/src/MeoAssistant/Controller.cpp +++ b/src/MeoAssistant/Controller.cpp @@ -18,90 +18,90 @@ #include #include -#include "AsstDef.h" +#include "AsstTypes.h" #include "Logger.hpp" #include "Resource.h" asst::Controller::Controller(AsstCallback callback, void* callback_arg) - : m_callback(callback), - m_callback_arg(callback_arg), - m_rand_engine(static_cast(time(nullptr))) + : m_callback(callback), + m_callback_arg(callback_arg), + m_rand_engine(static_cast(time(nullptr))) { - LogTraceFunction; + LogTraceFunction; #ifdef _WIN32 - // 安全属性描述符 - m_pipe_sec_attr.nLength = sizeof SECURITY_ATTRIBUTES; - m_pipe_sec_attr.lpSecurityDescriptor = nullptr; - m_pipe_sec_attr.bInheritHandle = TRUE; + // 安全属性描述符 + m_pipe_sec_attr.nLength = sizeof SECURITY_ATTRIBUTES; + m_pipe_sec_attr.lpSecurityDescriptor = nullptr; + m_pipe_sec_attr.bInheritHandle = TRUE; - // 创建管道,本进程读-子进程写 - BOOL pipe_read_ret = ::CreatePipe(&m_pipe_read, &m_pipe_child_write, &m_pipe_sec_attr, PipeBuffSize); - // 创建管道,本进程写-子进程读 - BOOL pipe_write_ret = ::CreatePipe(&m_pipe_write, &m_pipe_child_read, &m_pipe_sec_attr, PipeBuffSize); + // 创建管道,本进程读-子进程写 + BOOL pipe_read_ret = ::CreatePipe(&m_pipe_read, &m_pipe_child_write, &m_pipe_sec_attr, PipeBuffSize); + // 创建管道,本进程写-子进程读 + BOOL pipe_write_ret = ::CreatePipe(&m_pipe_write, &m_pipe_child_read, &m_pipe_sec_attr, PipeBuffSize); - if (!pipe_read_ret || !pipe_write_ret) { - throw "controller pipe created failed"; - } + if (!pipe_read_ret || !pipe_write_ret) { + throw "controller pipe created failed"; + } - m_child_startup_info.cb = sizeof(STARTUPINFO); - m_child_startup_info.dwFlags = STARTF_USESTDHANDLES; - m_child_startup_info.wShowWindow = SW_HIDE; - // 重定向子进程的读写 - m_child_startup_info.hStdInput = m_pipe_child_read; - m_child_startup_info.hStdOutput = m_pipe_child_write; - m_child_startup_info.hStdError = m_pipe_child_write; + m_child_startup_info.cb = sizeof(STARTUPINFO); + m_child_startup_info.dwFlags = STARTF_USESTDHANDLES; + m_child_startup_info.wShowWindow = SW_HIDE; + // 重定向子进程的读写 + m_child_startup_info.hStdInput = m_pipe_child_read; + m_child_startup_info.hStdOutput = m_pipe_child_write; + m_child_startup_info.hStdError = m_pipe_child_write; #else - int pipe_in_ret = pipe(m_pipe_in); - int pipe_out_ret = pipe(m_pipe_out); - fcntl(m_pipe_out[PIPE_READ], F_SETFL, O_NONBLOCK); + int pipe_in_ret = pipe(m_pipe_in); + int pipe_out_ret = pipe(m_pipe_out); + fcntl(m_pipe_out[PIPE_READ], F_SETFL, O_NONBLOCK); - if (pipe_in_ret < 0 || pipe_out_ret < 0) { - throw "controller pipe created failed"; - } + if (pipe_in_ret < 0 || pipe_out_ret < 0) { + throw "controller pipe created failed"; + } #endif - m_pipe_buffer = std::make_unique(PipeBuffSize); - if (!m_pipe_buffer) { - throw "controller pipe buffer allocated failed"; - } + m_pipe_buffer = std::make_unique(PipeBuffSize); + if (!m_pipe_buffer) { + throw "controller pipe buffer allocated failed"; + } - m_cmd_thread = std::thread(&Controller::pipe_working_proc, this); + m_cmd_thread = std::thread(&Controller::pipe_working_proc, this); } asst::Controller::~Controller() { - LogTraceFunction; + LogTraceFunction; - m_thread_exit = true; - //m_thread_idle = true; - m_cmd_condvar.notify_all(); - m_completed_id = UINT_MAX; // make all WinMacor::wait to exit + m_thread_exit = true; + //m_thread_idle = true; + m_cmd_condvar.notify_all(); + m_completed_id = UINT_MAX; // make all WinMacor::wait to exit - if (m_cmd_thread.joinable()) { - m_cmd_thread.join(); - } + if (m_cmd_thread.joinable()) { + m_cmd_thread.join(); + } #ifndef _WIN32 - if (m_child) { + if (m_child) { #else - if (true) { + if (true) { #endif - call_command(m_adb.release); - } + call_command(m_adb.release); + } #ifdef _WIN32 - ::CloseHandle(m_pipe_read); - ::CloseHandle(m_pipe_write); - ::CloseHandle(m_pipe_child_read); - ::CloseHandle(m_pipe_child_write); + ::CloseHandle(m_pipe_read); + ::CloseHandle(m_pipe_write); + ::CloseHandle(m_pipe_child_read); + ::CloseHandle(m_pipe_child_write); #else - close(m_pipe_in[PIPE_READ]); - close(m_pipe_in[PIPE_WRITE]); - close(m_pipe_out[PIPE_READ]); - close(m_pipe_out[PIPE_WRITE]); + close(m_pipe_in[PIPE_READ]); + close(m_pipe_in[PIPE_WRITE]); + close(m_pipe_out[PIPE_READ]); + close(m_pipe_out[PIPE_WRITE]); #endif -} + } //asst::Rect asst::Controller::shaped_correct(const Rect & rect) const //{ @@ -158,643 +158,643 @@ asst::Controller::~Controller() std::pair asst::Controller::get_scale_size() const noexcept { - return m_scale_size; + return m_scale_size; } void asst::Controller::pipe_working_proc() { - LogTraceFunction; + LogTraceFunction; - while (!m_thread_exit) { - std::unique_lock cmd_queue_lock(m_cmd_queue_mutex); + while (!m_thread_exit) { + std::unique_lock cmd_queue_lock(m_cmd_queue_mutex); - if (!m_cmd_queue.empty()) { // 队列中有任务就执行任务 - std::string cmd = m_cmd_queue.front(); - m_cmd_queue.pop(); - cmd_queue_lock.unlock(); - // todo 判断命令是否执行成功 - call_command(cmd); - ++m_completed_id; - } - //else if (!m_thread_idle) { // 队列中没有任务,又不是闲置的时候,就去截图 - // cmd_queue_lock.unlock(); - // auto start_time = std::chrono::steady_clock::now(); - // screencap(); - // cmd_queue_lock.lock(); - // if (!m_cmd_queue.empty()) { - // continue; - // } - // m_cmd_condvar.wait_until( - // cmd_queue_lock, - // start_time + std::chrono::milliseconds(1000)); // todo 时间写到配置文件里 - //} - else { - //m_cmd_condvar.wait(cmd_queue_lock, [&]() -> bool {return !m_thread_idle; }); - m_cmd_condvar.wait(cmd_queue_lock); - } - } + if (!m_cmd_queue.empty()) { // 队列中有任务就执行任务 + std::string cmd = m_cmd_queue.front(); + m_cmd_queue.pop(); + cmd_queue_lock.unlock(); + // todo 判断命令是否执行成功 + call_command(cmd); + ++m_completed_id; + } + //else if (!m_thread_idle) { // 队列中没有任务,又不是闲置的时候,就去截图 + // cmd_queue_lock.unlock(); + // auto start_time = std::chrono::steady_clock::now(); + // screencap(); + // cmd_queue_lock.lock(); + // if (!m_cmd_queue.empty()) { + // continue; + // } + // m_cmd_condvar.wait_until( + // cmd_queue_lock, + // start_time + std::chrono::milliseconds(1000)); // todo 时间写到配置文件里 + //} + else { + //m_cmd_condvar.wait(cmd_queue_lock, [&]() -> bool {return !m_thread_idle; }); + m_cmd_condvar.wait(cmd_queue_lock); + } + } } std::optional> asst::Controller::call_command(const std::string & cmd) { - LogTraceFunction; + LogTraceFunction; - static std::mutex pipe_mutex; - std::unique_lock pipe_lock(pipe_mutex); + static std::mutex pipe_mutex; + std::unique_lock pipe_lock(pipe_mutex); - std::vector pipe_data; + std::vector pipe_data; #ifdef _WIN32 - PROCESS_INFORMATION process_info = { 0 }; // 进程信息结构体 - BOOL create_ret = ::CreateProcessA(nullptr, const_cast(cmd.c_str()), nullptr, nullptr, TRUE, CREATE_NO_WINDOW, nullptr, nullptr, &m_child_startup_info, &process_info); - if (!create_ret) { - return std::nullopt; - } - DWORD peek_num = 0; - DWORD read_num = 0; - do { - //DWORD write_num = 0; - //WriteFile(parent_write, cmd.c_str(), cmd.size(), &write_num, nullptr); - while (::PeekNamedPipe(m_pipe_read, nullptr, 0, nullptr, &peek_num, nullptr) && peek_num > 0) { - if (::ReadFile(m_pipe_read, m_pipe_buffer.get(), PipeBuffSize, &read_num, nullptr)) { - pipe_data.insert(pipe_data.end(), m_pipe_buffer.get(), m_pipe_buffer.get() + read_num); - } - } - } while (::WaitForSingleObject(process_info.hProcess, 0) == WAIT_TIMEOUT); + PROCESS_INFORMATION process_info = { 0 }; // 进程信息结构体 + BOOL create_ret = ::CreateProcessA(nullptr, const_cast(cmd.c_str()), nullptr, nullptr, TRUE, CREATE_NO_WINDOW, nullptr, nullptr, &m_child_startup_info, &process_info); + if (!create_ret) { + return std::nullopt; + } + DWORD peek_num = 0; + DWORD read_num = 0; + do { + //DWORD write_num = 0; + //WriteFile(parent_write, cmd.c_str(), cmd.size(), &write_num, nullptr); + while (::PeekNamedPipe(m_pipe_read, nullptr, 0, nullptr, &peek_num, nullptr) && peek_num > 0) { + if (::ReadFile(m_pipe_read, m_pipe_buffer.get(), PipeBuffSize, &read_num, nullptr)) { + pipe_data.insert(pipe_data.end(), m_pipe_buffer.get(), m_pipe_buffer.get() + read_num); + } + } + } while (::WaitForSingleObject(process_info.hProcess, 0) == WAIT_TIMEOUT); - DWORD exit_ret = 255; - ::GetExitCodeProcess(process_info.hProcess, &exit_ret); + DWORD exit_ret = 255; + ::GetExitCodeProcess(process_info.hProcess, &exit_ret); - ::CloseHandle(process_info.hProcess); - ::CloseHandle(process_info.hThread); + ::CloseHandle(process_info.hProcess); + ::CloseHandle(process_info.hThread); #else - int exit_ret = 0; - m_child = fork(); - if (m_child == 0) { - // child process - LogTraceScope("Child process: " + cmd); - std::cout << ("Child process: " + cmd) << std::endl; + int exit_ret = 0; + m_child = fork(); + if (m_child == 0) { + // child process + LogTraceScope("Child process: " + cmd); + std::cout << ("Child process: " + cmd) << std::endl; - dup2(m_pipe_in[PIPE_READ], STDIN_FILENO); - dup2(m_pipe_out[PIPE_WRITE], STDOUT_FILENO); - dup2(m_pipe_out[PIPE_WRITE], STDERR_FILENO); + dup2(m_pipe_in[PIPE_READ], STDIN_FILENO); + dup2(m_pipe_out[PIPE_WRITE], STDOUT_FILENO); + dup2(m_pipe_out[PIPE_WRITE], STDERR_FILENO); - // all these are for use by parent only - // close(m_pipe_in[PIPE_READ]); - // close(m_pipe_in[PIPE_WRITE]); - // close(m_pipe_out[PIPE_READ]); - // close(m_pipe_out[PIPE_WRITE]); + // all these are for use by parent only + // close(m_pipe_in[PIPE_READ]); + // close(m_pipe_in[PIPE_WRITE]); + // close(m_pipe_out[PIPE_READ]); + // close(m_pipe_out[PIPE_WRITE]); - exit_ret = execlp("sh", "sh", "-c", cmd.c_str(), nullptr); - exit(exit_ret); - } - else if (m_child > 0) { - // parent process - // LogTraceScope("Parent process: " + cmd); - do { - ssize_t read_num = read(m_pipe_out[PIPE_READ], m_pipe_buffer.get(), PipeBuffSize); + exit_ret = execlp("sh", "sh", "-c", cmd.c_str(), nullptr); + exit(exit_ret); + } + else if (m_child > 0) { + // parent process + // LogTraceScope("Parent process: " + cmd); + do { + ssize_t read_num = read(m_pipe_out[PIPE_READ], m_pipe_buffer.get(), PipeBuffSize); - while (read_num > 0) { - pipe_data.insert(pipe_data.end(), m_pipe_buffer.get(), m_pipe_buffer.get() + read_num); - read_num = read(m_pipe_out[PIPE_READ], m_pipe_buffer.get(), PipeBuffSize); - }; - } while (::waitpid(m_child, &exit_ret, WNOHANG) == 0); - } - else { - // failed to create child process - return std::nullopt; - } + while (read_num > 0) { + pipe_data.insert(pipe_data.end(), m_pipe_buffer.get(), m_pipe_buffer.get() + read_num); + read_num = read(m_pipe_out[PIPE_READ], m_pipe_buffer.get(), PipeBuffSize); + }; + } while (::waitpid(m_child, &exit_ret, WNOHANG) == 0); + } + else { + // failed to create child process + return std::nullopt; + } #endif - Log.trace("Call `", cmd, "` ret", exit_ret, ", output size:", pipe_data.size()); - if (!pipe_data.empty() && pipe_data.size() < 4096) { - Log.trace("output:", std::string(pipe_data.cbegin(), pipe_data.cend())); - } + Log.trace("Call `", cmd, "` ret", exit_ret, ", output size:", pipe_data.size()); + if (!pipe_data.empty() && pipe_data.size() < 4096) { + Log.trace("output:", std::string(pipe_data.cbegin(), pipe_data.cend())); + } - if (!exit_ret) { - return pipe_data; - } - else { - return std::nullopt; - } + if (!exit_ret) { + return pipe_data; + } + else { + return std::nullopt; + } } void asst::Controller::convert_lf(std::vector&data) { - LogTraceFunction; + LogTraceFunction; - if (data.empty() || data.size() < 2) { - return; - } - using Iter = std::vector::iterator; - auto pred = [](const Iter& cur) -> bool { - return *cur == '\r' && *(cur + 1) == '\n'; - }; - // find the first of "\r\n" - Iter first_iter = data.end(); - for (Iter iter = data.begin(); iter != data.end() - 1; ++iter) { - if (pred(iter)) { - first_iter = iter; - break; - } - } - if (first_iter == data.end()) { - return; - } - // move forward all non-crlf elements - Iter end_r1_iter = data.end() - 1; - Iter next_iter = first_iter; - while (++first_iter != end_r1_iter) { - if (!pred(first_iter)) { - *next_iter = std::move(*first_iter); - ++next_iter; - } - } - *next_iter = std::move(*end_r1_iter); - ++next_iter; - data.erase(next_iter, data.end()); + if (data.empty() || data.size() < 2) { + return; + } + using Iter = std::vector::iterator; + auto pred = [](const Iter& cur) -> bool { + return *cur == '\r' && *(cur + 1) == '\n'; + }; + // find the first of "\r\n" + Iter first_iter = data.end(); + for (Iter iter = data.begin(); iter != data.end() - 1; ++iter) { + if (pred(iter)) { + first_iter = iter; + break; + } + } + if (first_iter == data.end()) { + return; + } + // move forward all non-crlf elements + Iter end_r1_iter = data.end() - 1; + Iter next_iter = first_iter; + while (++first_iter != end_r1_iter) { + if (!pred(first_iter)) { + *next_iter = std::move(*first_iter); + ++next_iter; + } + } + *next_iter = std::move(*end_r1_iter); + ++next_iter; + data.erase(next_iter, data.end()); } asst::Point asst::Controller::rand_point_in_rect(const Rect & rect) { - int x = 0, y = 0; - if (rect.width == 0) { - x = rect.x; - } - else { - int x_rand = std::poisson_distribution(rect.width / 2)(m_rand_engine); + int x = 0, y = 0; + if (rect.width == 0) { + x = rect.x; + } + else { + int x_rand = std::poisson_distribution(rect.width / 2)(m_rand_engine); - x = x_rand + rect.x; - } + x = x_rand + rect.x; + } - if (rect.height == 0) { - y = rect.y; - } - else { - int y_rand = std::poisson_distribution(rect.height / 2)(m_rand_engine); - y = y_rand + rect.y; - } + if (rect.height == 0) { + y = rect.y; + } + else { + int y_rand = std::poisson_distribution(rect.height / 2)(m_rand_engine); + y = y_rand + rect.y; + } - return Point(x, y); + return Point(x, y); } void asst::Controller::random_delay() const { - auto& opt = Resrc.cfg().get_options(); - if (opt.control_delay_upper != 0) { - LogTraceFunction; - static std::default_random_engine rand_engine(static_cast(time(nullptr))); - static std::uniform_int_distribution rand_uni( - opt.control_delay_lower, - opt.control_delay_upper); + auto& opt = Resrc.cfg().get_options(); + if (opt.control_delay_upper != 0) { + LogTraceFunction; + static std::default_random_engine rand_engine(static_cast(time(nullptr))); + static std::uniform_int_distribution rand_uni( + opt.control_delay_lower, + opt.control_delay_upper); - unsigned rand_delay = rand_uni(rand_engine); + unsigned rand_delay = rand_uni(rand_engine); - Log.trace("random_delay |", rand_delay, "ms"); - std::this_thread::sleep_for(std::chrono::milliseconds(rand_delay)); - } + Log.trace("random_delay |", rand_delay, "ms"); + std::this_thread::sleep_for(std::chrono::milliseconds(rand_delay)); + } } int asst::Controller::push_cmd(const std::string & cmd) { - random_delay(); + random_delay(); - std::unique_lock lock(m_cmd_queue_mutex); - m_cmd_queue.emplace(cmd); - m_cmd_condvar.notify_one(); - return ++m_push_id; + std::unique_lock lock(m_cmd_queue_mutex); + m_cmd_queue.emplace(cmd); + m_cmd_condvar.notify_one(); + return ++m_push_id; } void asst::Controller::wait(unsigned id) const noexcept { - while (id > m_completed_id) { - std::this_thread::sleep_for(std::chrono::milliseconds(50)); - std::this_thread::yield(); - } + while (id > m_completed_id) { + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + std::this_thread::yield(); + } } bool asst::Controller::screencap() { - LogTraceFunction; + LogTraceFunction; - DecodeFunc decode_raw_with_gzip = [&](const std::vector& data) -> bool { - auto unzip_data = gzip::decompress(data.data(), data.size()); - Log.trace("unzip data size:", unzip_data.size()); - if (unzip_data.empty()) { - return false; - } - size_t std_size = m_width * m_height * 4; - if (unzip_data.size() < std_size) { - return false; - } - size_t header_size = unzip_data.size() - std_size; - Log.trace("header size:", header_size); + DecodeFunc decode_raw_with_gzip = [&](const std::vector& data) -> bool { + auto unzip_data = gzip::decompress(data.data(), data.size()); + Log.trace("unzip data size:", unzip_data.size()); + if (unzip_data.empty()) { + return false; + } + size_t std_size = m_width * m_height * 4; + if (unzip_data.size() < std_size) { + return false; + } + size_t header_size = unzip_data.size() - std_size; + Log.trace("header size:", header_size); - bool is_all_zero = std::all_of(unzip_data.data() + header_size, unzip_data.data() + std_size, - [](uchar uch) -> bool { - return uch == 0; - }); - if (is_all_zero) { - return false; - } - cv::Mat temp(m_height, m_width, CV_8UC4, unzip_data.data() + header_size); - if (temp.empty()) { - return false; - } - cv::cvtColor(temp, temp, cv::COLOR_RGB2BGR); - std::unique_lock image_lock(m_image_mutex); - m_cache_image = temp; - return true; - }; + bool is_all_zero = std::all_of(unzip_data.data() + header_size, unzip_data.data() + std_size, + [](uchar uch) -> bool { + return uch == 0; + }); + if (is_all_zero) { + return false; + } + cv::Mat temp(m_height, m_width, CV_8UC4, unzip_data.data() + header_size); + if (temp.empty()) { + return false; + } + cv::cvtColor(temp, temp, cv::COLOR_RGB2BGR); + std::unique_lock image_lock(m_image_mutex); + m_cache_image = temp; + return true; + }; - DecodeFunc decode_encode = [&](const std::vector& data) -> bool { - cv::Mat temp = cv::imdecode(data, cv::IMREAD_COLOR); - if (temp.empty()) { - return false; - } - std::unique_lock image_lock(m_image_mutex); - m_cache_image = temp; - return true; - }; + DecodeFunc decode_encode = [&](const std::vector& data) -> bool { + cv::Mat temp = cv::imdecode(data, cv::IMREAD_COLOR); + if (temp.empty()) { + return false; + } + std::unique_lock image_lock(m_image_mutex); + m_cache_image = temp; + return true; + }; - switch (m_adb.screencap_method) { - case AdbProperty::ScreencapMethod::UnknownYet: - { - if (screencap(m_adb.screencap_raw_with_gzip, decode_raw_with_gzip)) { - m_adb.screencap_method = AdbProperty::ScreencapMethod::RawWithGzip; - return true; - } - else if (screencap(m_adb.screencap_encode, decode_encode)) { - m_adb.screencap_method = AdbProperty::ScreencapMethod::Encode; - return true; - } - else { - return false; - } - } - case AdbProperty::ScreencapMethod::RawWithGzip: - { - return screencap(m_adb.screencap_raw_with_gzip, decode_raw_with_gzip); - } - break; - case AdbProperty::ScreencapMethod::Encode: - { - return screencap(m_adb.screencap_encode, decode_encode); - } - break; - } + switch (m_adb.screencap_method) { + case AdbProperty::ScreencapMethod::UnknownYet: + { + if (screencap(m_adb.screencap_raw_with_gzip, decode_raw_with_gzip)) { + m_adb.screencap_method = AdbProperty::ScreencapMethod::RawWithGzip; + return true; + } + else if (screencap(m_adb.screencap_encode, decode_encode)) { + m_adb.screencap_method = AdbProperty::ScreencapMethod::Encode; + return true; + } + else { + return false; + } + } + case AdbProperty::ScreencapMethod::RawWithGzip: + { + return screencap(m_adb.screencap_raw_with_gzip, decode_raw_with_gzip); + } + break; + case AdbProperty::ScreencapMethod::Encode: + { + return screencap(m_adb.screencap_encode, decode_encode); + } + break; + } - return false; + return false; } bool asst::Controller::screencap(const std::string & cmd, DecodeFunc decode_func) { - auto ret = call_command(cmd); + auto ret = call_command(cmd); - if (!ret || ret.value().empty()) { - Log.error("data is empty!"); - return false; - } - auto data = std::move(ret).value(); + if (!ret || ret.value().empty()) { + Log.error("data is empty!"); + return false; + } + auto data = std::move(ret).value(); - if (m_adb.screencap_end_of_line == AdbProperty::ScreencapEndOfLine::CRLF) { - convert_lf(data); - } + if (m_adb.screencap_end_of_line == AdbProperty::ScreencapEndOfLine::CRLF) { + convert_lf(data); + } - if (decode_func(data)) { - if (m_adb.screencap_end_of_line == AdbProperty::ScreencapEndOfLine::UnknownYet) { - m_adb.screencap_end_of_line = AdbProperty::ScreencapEndOfLine::LF; - } - return true; - } - else { - Log.info("data is not empty, but image is empty"); + if (decode_func(data)) { + if (m_adb.screencap_end_of_line == AdbProperty::ScreencapEndOfLine::UnknownYet) { + m_adb.screencap_end_of_line = AdbProperty::ScreencapEndOfLine::LF; + } + return true; + } + else { + Log.info("data is not empty, but image is empty"); - if (m_adb.screencap_end_of_line == AdbProperty::ScreencapEndOfLine::UnknownYet) { - Log.info("try to cvt lf"); - convert_lf(data); + if (m_adb.screencap_end_of_line == AdbProperty::ScreencapEndOfLine::UnknownYet) { + Log.info("try to cvt lf"); + convert_lf(data); - if (decode_func(data)) { - m_adb.screencap_end_of_line = AdbProperty::ScreencapEndOfLine::CRLF; - return true; - } - else { - Log.error("convert lf and retry decode falied!"); - } - } - return false; - } + if (decode_func(data)) { + m_adb.screencap_end_of_line = AdbProperty::ScreencapEndOfLine::CRLF; + return true; + } + else { + Log.error("convert lf and retry decode falied!"); + } + } + return false; + } } cv::Mat asst::Controller::get_resized_image() const { - const static cv::Size dsize(m_scale_size.first, m_scale_size.second); + const static cv::Size dsize(m_scale_size.first, m_scale_size.second); - std::shared_lock image_lock(m_image_mutex); - if (m_cache_image.empty()) { - Log.error("image is empty"); - return cv::Mat(dsize, CV_8UC3); - } - cv::Mat resized_mat; - cv::resize(m_cache_image, resized_mat, dsize); - return resized_mat; + std::shared_lock image_lock(m_image_mutex); + if (m_cache_image.empty()) { + Log.error("image is empty"); + return cv::Mat(dsize, CV_8UC3); + } + cv::Mat resized_mat; + cv::resize(m_cache_image, resized_mat, dsize); + return resized_mat; } int asst::Controller::click(const Point & p, bool block) { - int x = static_cast(p.x * m_control_scale); - int y = static_cast(p.y * m_control_scale); - //log.trace("Click, raw:", p.x, p.y, "corr:", x, y); + int x = static_cast(p.x * m_control_scale); + int y = static_cast(p.y * m_control_scale); + //log.trace("Click, raw:", p.x, p.y, "corr:", x, y); - return click_without_scale(Point(x, y), block); + return click_without_scale(Point(x, y), block); } int asst::Controller::click(const Rect & rect, bool block) { - return click(rand_point_in_rect(rect), block); + return click(rand_point_in_rect(rect), block); } int asst::Controller::click_without_scale(const Point & p, bool block) { - if (p.x < 0 || p.x >= m_width || p.y < 0 || p.y >= m_height) { - Log.error("click point out of range"); - } - std::string cur_cmd = utils::string_replace_all(m_adb.click, "[x]", std::to_string(p.x)); - cur_cmd = utils::string_replace_all(cur_cmd, "[y]", std::to_string(p.y)); - int id = push_cmd(cur_cmd); - if (block) { - wait(id); - } - return id; + if (p.x < 0 || p.x >= m_width || p.y < 0 || p.y >= m_height) { + Log.error("click point out of range"); + } + std::string cur_cmd = utils::string_replace_all(m_adb.click, "[x]", std::to_string(p.x)); + cur_cmd = utils::string_replace_all(cur_cmd, "[y]", std::to_string(p.y)); + int id = push_cmd(cur_cmd); + if (block) { + wait(id); + } + return id; } int asst::Controller::click_without_scale(const Rect & rect, bool block) { - return click_without_scale(rand_point_in_rect(rect), block); + return click_without_scale(rand_point_in_rect(rect), block); } int asst::Controller::swipe(const Point & p1, const Point & p2, int duration, bool block, int extra_delay, bool extra_swipe) { - int x1 = static_cast(p1.x * m_control_scale); - int y1 = static_cast(p1.y * m_control_scale); - int x2 = static_cast(p2.x * m_control_scale); - int y2 = static_cast(p2.y * m_control_scale); - //log.trace("Swipe, raw:", p1.x, p1.y, p2.x, p2.y, "corr:", x1, y1, x2, y2); + int x1 = static_cast(p1.x * m_control_scale); + int y1 = static_cast(p1.y * m_control_scale); + int x2 = static_cast(p2.x * m_control_scale); + int y2 = static_cast(p2.y * m_control_scale); + //log.trace("Swipe, raw:", p1.x, p1.y, p2.x, p2.y, "corr:", x1, y1, x2, y2); - return swipe_without_scale(Point(x1, y1), Point(x2, y2), duration, block, extra_delay, extra_swipe); + return swipe_without_scale(Point(x1, y1), Point(x2, y2), duration, block, extra_delay, extra_swipe); } int asst::Controller::swipe(const Rect & r1, const Rect & r2, int duration, bool block, int extra_delay, bool extra_swipe) { - return swipe(rand_point_in_rect(r1), rand_point_in_rect(r2), duration, block, extra_delay, extra_swipe); + return swipe(rand_point_in_rect(r1), rand_point_in_rect(r2), duration, block, extra_delay, extra_swipe); } int asst::Controller::swipe_without_scale(const Point & p1, const Point & p2, int duration, bool block, int extra_delay, bool extra_swipe) { - if (p1.x < 0 || p1.x >= m_width || p1.y < 0 || p1.y >= m_height || p2.x < 0 || p2.x >= m_width || p2.y < 0 || p2.y >= m_height) { - Log.error("swipe point out of range"); - } - std::string cur_cmd = utils::string_replace_all(m_adb.swipe, "[x1]", std::to_string(p1.x)); - cur_cmd = utils::string_replace_all(cur_cmd, "[y1]", std::to_string(p1.y)); - cur_cmd = utils::string_replace_all(cur_cmd, "[x2]", std::to_string(p2.x)); - cur_cmd = utils::string_replace_all(cur_cmd, "[y2]", std::to_string(p2.y)); - if (duration <= 0) { - cur_cmd = utils::string_replace_all(cur_cmd, "[duration]", ""); - } - else { - cur_cmd = utils::string_replace_all(cur_cmd, "[duration]", std::to_string(duration)); - } + if (p1.x < 0 || p1.x >= m_width || p1.y < 0 || p1.y >= m_height || p2.x < 0 || p2.x >= m_width || p2.y < 0 || p2.y >= m_height) { + Log.error("swipe point out of range"); + } + std::string cur_cmd = utils::string_replace_all(m_adb.swipe, "[x1]", std::to_string(p1.x)); + cur_cmd = utils::string_replace_all(cur_cmd, "[y1]", std::to_string(p1.y)); + cur_cmd = utils::string_replace_all(cur_cmd, "[x2]", std::to_string(p2.x)); + cur_cmd = utils::string_replace_all(cur_cmd, "[y2]", std::to_string(p2.y)); + if (duration <= 0) { + cur_cmd = utils::string_replace_all(cur_cmd, "[duration]", ""); + } + else { + cur_cmd = utils::string_replace_all(cur_cmd, "[duration]", std::to_string(duration)); + } - int id = 0; + int id = 0; - int extra_swipe_dist = Resrc.cfg().get_options().adb_extra_swipe_dist /* * m_control_scale*/; - int extra_swipe_duration = Resrc.cfg().get_options().adb_extra_swipe_duration; + int extra_swipe_dist = Resrc.cfg().get_options().adb_extra_swipe_dist /* * m_control_scale*/; + int extra_swipe_duration = Resrc.cfg().get_options().adb_extra_swipe_duration; - // 额外的滑动:adb有bug,同样的参数,偶尔会划得非常远。额外做一个短程滑动,把之前的停下来 - if (extra_swipe && extra_swipe_duration >= 0) { - std::string extra_cmd = utils::string_replace_all(m_adb.swipe, "[x1]", std::to_string(p2.x)); - extra_cmd = utils::string_replace_all(extra_cmd, "[y1]", std::to_string(p2.y)); - int end_x = 0, end_y = 0; - if (p2.x != p1.x) { - double k = (double)(p2.y - p1.y) / (p2.x - p1.x); - double temp = extra_swipe_dist / std::sqrt(1 + k * k); - end_x = p2.x + static_cast((p2.x > p1.x ? -1.0 : 1.0) * temp); - end_y = p2.y + static_cast((p2.y > p1.y ? -1.0 : 1.0) * std::fabs(k) * temp); - } - else { - end_x = p2.x; - end_y = p2.y + (p2.y > p1.y ? -1 : 1) * extra_swipe_dist; - } - extra_cmd = utils::string_replace_all(extra_cmd, "[x2]", std::to_string(end_x)); - extra_cmd = utils::string_replace_all(extra_cmd, "[y2]", std::to_string(end_y)); - extra_cmd = utils::string_replace_all(extra_cmd, "[duration]", std::to_string(extra_swipe_duration)); + // 额外的滑动:adb有bug,同样的参数,偶尔会划得非常远。额外做一个短程滑动,把之前的停下来 + if (extra_swipe && extra_swipe_duration >= 0) { + std::string extra_cmd = utils::string_replace_all(m_adb.swipe, "[x1]", std::to_string(p2.x)); + extra_cmd = utils::string_replace_all(extra_cmd, "[y1]", std::to_string(p2.y)); + int end_x = 0, end_y = 0; + if (p2.x != p1.x) { + double k = (double)(p2.y - p1.y) / (p2.x - p1.x); + double temp = extra_swipe_dist / std::sqrt(1 + k * k); + end_x = p2.x + static_cast((p2.x > p1.x ? -1.0 : 1.0) * temp); + end_y = p2.y + static_cast((p2.y > p1.y ? -1.0 : 1.0) * std::fabs(k) * temp); + } + else { + end_x = p2.x; + end_y = p2.y + (p2.y > p1.y ? -1 : 1) * extra_swipe_dist; + } + extra_cmd = utils::string_replace_all(extra_cmd, "[x2]", std::to_string(end_x)); + extra_cmd = utils::string_replace_all(extra_cmd, "[y2]", std::to_string(end_y)); + extra_cmd = utils::string_replace_all(extra_cmd, "[duration]", std::to_string(extra_swipe_duration)); - push_cmd(cur_cmd); - id = push_cmd(extra_cmd); - } - else { - id = push_cmd(cur_cmd); - } + push_cmd(cur_cmd); + id = push_cmd(extra_cmd); + } + else { + id = push_cmd(cur_cmd); + } - if (block) { - wait(id); - std::this_thread::sleep_for(std::chrono::milliseconds(extra_delay)); - } - return id; + if (block) { + wait(id); + std::this_thread::sleep_for(std::chrono::milliseconds(extra_delay)); + } + return id; } int asst::Controller::swipe_without_scale(const Rect & r1, const Rect & r2, int duration, bool block, int extra_delay, bool extra_swipe) { - return swipe_without_scale(rand_point_in_rect(r1), rand_point_in_rect(r2), duration, block, extra_delay, extra_swipe); + return swipe_without_scale(rand_point_in_rect(r1), rand_point_in_rect(r2), duration, block, extra_delay, extra_swipe); } bool asst::Controller::connect(const std::string & adb_path, const std::string & address, const std::string & config) { - LogTraceFunction; + LogTraceFunction; - auto adb_ret = Resrc.cfg().get_adb_cfg(config); - if (!adb_ret) { - json::value info = json::object{ - {"what", "ConnectFailed"}, - {"why", "ConfigNotFound"}, - {"details", json::object{}} - }; - m_callback(AsstMsg::ConnectionInfo, info, m_callback_arg); - return false; - } + auto adb_ret = Resrc.cfg().get_adb_cfg(config); + if (!adb_ret) { + json::value info = json::object{ + {"what", "ConnectFailed"}, + {"why", "ConfigNotFound"}, + {"details", json::object{}} + }; + m_callback(AsstMsg::ConnectionInfo, info, m_callback_arg); + return false; + } - const auto adb_cfg = std::move(adb_ret.value()); - std::string display_id; + const auto adb_cfg = std::move(adb_ret.value()); + std::string display_id; - auto cmd_replace = [&](const std::string& cfg_cmd) -> std::string { - const std::unordered_map replacements = { - {"[Adb]", adb_path}, - {"[Address]", address}, - {"[DisplayId]", display_id} - }; - std::string formatted = cfg_cmd; - for (const auto& [key, value] : replacements) { - formatted = utils::string_replace_all(formatted, key, value); - } - return formatted; - }; + auto cmd_replace = [&](const std::string& cfg_cmd) -> std::string { + const std::unordered_map replacements = { + {"[Adb]", adb_path}, + {"[Address]", address}, + {"[DisplayId]", display_id} + }; + std::string formatted = cfg_cmd; + for (const auto& [key, value] : replacements) { + formatted = utils::string_replace_all(formatted, key, value); + } + return formatted; + }; - /* connect */ - { - auto connect_ret = call_command(cmd_replace(adb_cfg.connect)); - // 端口即使错误,命令仍然会返回0,TODO 对connect_result进行判断 - if (!connect_ret) { - json::value info = json::object{ - {"what", "ConnectFailed"}, - {"why", "Connection command failed to exec"}, - {"details", json::object{}} - }; - m_callback(AsstMsg::ConnectionInfo, info, m_callback_arg); - return false; - } - else { - json::value info = json::object{ - {"what", "Connected"}, - {"why", ""}, - {"details", json::object{}} - }; - m_callback(AsstMsg::ConnectionInfo, info, m_callback_arg); - } - } + /* connect */ + { + auto connect_ret = call_command(cmd_replace(adb_cfg.connect)); + // 端口即使错误,命令仍然会返回0,TODO 对connect_result进行判断 + if (!connect_ret) { + json::value info = json::object{ + {"what", "ConnectFailed"}, + {"why", "Connection command failed to exec"}, + {"details", json::object{}} + }; + m_callback(AsstMsg::ConnectionInfo, info, m_callback_arg); + return false; + } + else { + json::value info = json::object{ + {"what", "Connected"}, + {"why", ""}, + {"details", json::object{}} + }; + m_callback(AsstMsg::ConnectionInfo, info, m_callback_arg); + } + } - // 按需获取display ID 信息 - if (!adb_cfg.display_id.empty()) { - auto display_id_ret = call_command(cmd_replace(adb_cfg.display_id)); - if (!display_id_ret) { - return false; - } + // 按需获取display ID 信息 + if (!adb_cfg.display_id.empty()) { + auto display_id_ret = call_command(cmd_replace(adb_cfg.display_id)); + if (!display_id_ret) { + return false; + } - auto& display_id_result = display_id_ret.value(); - convert_lf(display_id_result); - std::string display_id_pipe_str( - std::make_move_iterator(display_id_result.begin()), - std::make_move_iterator(display_id_result.end())); - auto last = display_id_pipe_str.rfind(':'); - if (last == std::string::npos) { - return false; - } + auto& display_id_result = display_id_ret.value(); + convert_lf(display_id_result); + std::string display_id_pipe_str( + std::make_move_iterator(display_id_result.begin()), + std::make_move_iterator(display_id_result.end())); + auto last = display_id_pipe_str.rfind(':'); + if (last == std::string::npos) { + return false; + } - display_id = display_id_pipe_str.substr(last + 1); - // 去掉换行 - display_id.pop_back(); - } + display_id = display_id_pipe_str.substr(last + 1); + // 去掉换行 + display_id.pop_back(); + } - /* display */ - { - auto display_ret = call_command(cmd_replace(adb_cfg.display)); - if (!display_ret) { - json::value info = json::object{ - {"what", "ConnectFailed"}, - {"why", "Display command failed to exec"}, - {"details", json::object{}} - }; - m_callback(AsstMsg::ConnectionInfo, info, m_callback_arg); - return false; - } + /* display */ + { + auto display_ret = call_command(cmd_replace(adb_cfg.display)); + if (!display_ret) { + json::value info = json::object{ + {"what", "ConnectFailed"}, + {"why", "Display command failed to exec"}, + {"details", json::object{}} + }; + m_callback(AsstMsg::ConnectionInfo, info, m_callback_arg); + return false; + } - auto& display_result = display_ret.value(); - std::string display_pipe_str( - std::make_move_iterator(display_result.begin()), - std::make_move_iterator(display_result.end())); - int size_value1 = 0; - int size_value2 = 0; + auto& display_result = display_ret.value(); + std::string display_pipe_str( + std::make_move_iterator(display_result.begin()), + std::make_move_iterator(display_result.end())); + int size_value1 = 0; + int size_value2 = 0; #ifdef _MSC_VER - sscanf_s(display_pipe_str.c_str(), adb_cfg.display_format.c_str(), &size_value1, &size_value2); + sscanf_s(display_pipe_str.c_str(), adb_cfg.display_format.c_str(), &size_value1, &size_value2); #else - sscanf(display_pipe_str.c_str(), adb_cfg.display_format.c_str(), &size_value1, &size_value2); + sscanf(display_pipe_str.c_str(), adb_cfg.display_format.c_str(), &size_value1, &size_value2); #endif - // 为了防止抓取句柄的时候手机是竖屏的(还没进游戏),这里取大的值为宽,小的为高 - // 总不能有人竖屏玩明日方舟吧(? - m_width = (std::max)(size_value1, size_value2); - m_height = (std::min)(size_value1, size_value2); - } + // 为了防止抓取句柄的时候手机是竖屏的(还没进游戏),这里取大的值为宽,小的为高 + // 总不能有人竖屏玩明日方舟吧(? + m_width = (std::max)(size_value1, size_value2); + m_height = (std::min)(size_value1, size_value2); + } - /* calc ratio */ - { - constexpr double DefaultRatio = - static_cast(WindowWidthDefault) / static_cast(WindowHeightDefault); - double cur_ratio = static_cast(m_width) / static_cast(m_height); + /* calc ratio */ + { + constexpr double DefaultRatio = + static_cast(WindowWidthDefault) / static_cast(WindowHeightDefault); + double cur_ratio = static_cast(m_width) / static_cast(m_height); - if (cur_ratio >= DefaultRatio // 说明是宽屏或默认16:9,按照高度计算缩放 - || std::fabs(cur_ratio - DefaultRatio) < DoubleDiff) { - int scale_width = static_cast(cur_ratio * WindowHeightDefault); - m_scale_size = std::make_pair(scale_width, WindowHeightDefault); - m_control_scale = static_cast(m_height) / static_cast(WindowHeightDefault); - } - else { // 否则可能是偏正方形的屏幕,按宽度计算 - int scale_height = static_cast(WindowWidthDefault / cur_ratio); - m_scale_size = std::make_pair(WindowWidthDefault, scale_height); - m_control_scale = static_cast(m_width) / static_cast(WindowWidthDefault); - } - } + if (cur_ratio >= DefaultRatio // 说明是宽屏或默认16:9,按照高度计算缩放 + || std::fabs(cur_ratio - DefaultRatio) < DoubleDiff) { + int scale_width = static_cast(cur_ratio * WindowHeightDefault); + m_scale_size = std::make_pair(scale_width, WindowHeightDefault); + m_control_scale = static_cast(m_height) / static_cast(WindowHeightDefault); + } + else { // 否则可能是偏正方形的屏幕,按宽度计算 + int scale_height = static_cast(WindowWidthDefault / cur_ratio); + m_scale_size = std::make_pair(WindowWidthDefault, scale_height); + m_control_scale = static_cast(m_width) / static_cast(WindowWidthDefault); + } + } - /* get uuid (imei) */ - { - auto uuid_ret = call_command(cmd_replace(adb_cfg.uuid)); - if (!uuid_ret) { - json::value info = json::object{ - {"what", "ConnectFailed"}, - {"why", "Uuid command failed to exec"}, - {"details", json::object{}} - }; - m_callback(AsstMsg::ConnectionInfo, info, m_callback_arg); - return false; - } + /* get uuid (imei) */ + { + auto uuid_ret = call_command(cmd_replace(adb_cfg.uuid)); + if (!uuid_ret) { + json::value info = json::object{ + {"what", "ConnectFailed"}, + {"why", "Uuid command failed to exec"}, + {"details", json::object{}} + }; + m_callback(AsstMsg::ConnectionInfo, info, m_callback_arg); + return false; + } - auto& uuid_result = uuid_ret.value(); - std::string uuid_str( - std::make_move_iterator(uuid_result.begin()), - std::make_move_iterator(uuid_result.end())); - uuid_str.erase(std::remove(uuid_str.begin(), uuid_str.end(), ' '), uuid_str.end()); - m_uuid = std::move(uuid_str); + auto& uuid_result = uuid_ret.value(); + std::string uuid_str( + std::make_move_iterator(uuid_result.begin()), + std::make_move_iterator(uuid_result.end())); + uuid_str.erase(std::remove(uuid_str.begin(), uuid_str.end(), ' '), uuid_str.end()); + m_uuid = std::move(uuid_str); - json::value info = json::object{ - {"what", "UuidGetted"}, - {"why", ""}, - {"details", json::object { - { "uuid", m_uuid} - }} - }; - m_callback(AsstMsg::ConnectionInfo, info, m_callback_arg); - } + json::value info = json::object{ + {"what", "UuidGetted"}, + {"why", ""}, + {"details", json::object { + { "uuid", m_uuid} + }} + }; + m_callback(AsstMsg::ConnectionInfo, info, m_callback_arg); + } - m_adb.click = cmd_replace(adb_cfg.click); - m_adb.swipe = cmd_replace(adb_cfg.swipe); - m_adb.screencap_raw_with_gzip = cmd_replace(adb_cfg.screencap_raw_with_gzip); - m_adb.screencap_encode = cmd_replace(adb_cfg.screencap_encode); - m_adb.release = cmd_replace(adb_cfg.release); + m_adb.click = cmd_replace(adb_cfg.click); + m_adb.swipe = cmd_replace(adb_cfg.swipe); + m_adb.screencap_raw_with_gzip = cmd_replace(adb_cfg.screencap_raw_with_gzip); + m_adb.screencap_encode = cmd_replace(adb_cfg.screencap_encode); + m_adb.release = cmd_replace(adb_cfg.release); - return true; + return true; } const std::string& asst::Controller::get_uuid() const { - return m_uuid; + return m_uuid; } cv::Mat asst::Controller::get_image() { - // 有些模拟器adb偶尔会莫名其妙截图失败,多试几次 - for (int i = 0; i != 20; ++i) { - if (screencap()) { - break; - } - } + // 有些模拟器adb偶尔会莫名其妙截图失败,多试几次 + for (int i = 0; i != 20; ++i) { + if (screencap()) { + break; + } + } - return get_resized_image(); + return get_resized_image(); } std::vector asst::Controller::get_image_encode() const { - cv::Mat img = get_resized_image(); - std::vector buf; - cv::imencode(".png", img, buf); + cv::Mat img = get_resized_image(); + std::vector buf; + cv::imencode(".png", img, buf); - return buf; -} + return buf; +} \ No newline at end of file diff --git a/src/MeoAssistant/Controller.h b/src/MeoAssistant/Controller.h index 7ff9590655..4a72689b8e 100644 --- a/src/MeoAssistant/Controller.h +++ b/src/MeoAssistant/Controller.h @@ -17,129 +17,129 @@ #include -#include "AsstDef.h" +#include "AsstTypes.h" #include "AsstMsg.h" namespace asst { - class Controller - { - public: - Controller(AsstCallback callback, void* callback_arg); - Controller(const Controller&) = delete; - Controller(Controller&&) = delete; - ~Controller(); + class Controller + { + public: + Controller(AsstCallback callback, void* callback_arg); + Controller(const Controller&) = delete; + Controller(Controller&&) = delete; + ~Controller(); - bool connect(const std::string& adb_path, const std::string& address, const std::string& config); + bool connect(const std::string& adb_path, const std::string& address, const std::string& config); - const std::string& get_uuid() const; - cv::Mat get_image(); - std::vector get_image_encode() const; + const std::string& get_uuid() const; + cv::Mat get_image(); + std::vector get_image_encode() const; - // 点击和滑动都是异步执行,返回该任务的id - int click(const Point& p, bool block = true); - int click(const Rect& rect, bool block = true); - int click_without_scale(const Point& p, bool block = true); - int click_without_scale(const Rect& rect, bool block = true); + // 点击和滑动都是异步执行,返回该任务的id + int click(const Point& p, bool block = true); + int click(const Rect& rect, bool block = true); + int click_without_scale(const Point& p, bool block = true); + int click_without_scale(const Rect& rect, bool block = true); - constexpr static int SwipeExtraDelayDefault = 1000; - int swipe(const Point& p1, const Point& p2, int duration = 0, bool block = true, int extra_delay = SwipeExtraDelayDefault, bool extra_swipe = false); - int swipe(const Rect& r1, const Rect& r2, int duration = 0, bool block = true, int extra_delay = SwipeExtraDelayDefault, bool extra_swipe = false); - int swipe_without_scale(const Point& p1, const Point& p2, int duration = 0, bool block = true, int extra_delay = SwipeExtraDelayDefault, bool extra_swipe = false); - int swipe_without_scale(const Rect& r1, const Rect& r2, int duration = 0, bool block = true, int extra_delay = SwipeExtraDelayDefault, bool extra_swipe = false); + constexpr static int SwipeExtraDelayDefault = 1000; + int swipe(const Point& p1, const Point& p2, int duration = 0, bool block = true, int extra_delay = SwipeExtraDelayDefault, bool extra_swipe = false); + int swipe(const Rect& r1, const Rect& r2, int duration = 0, bool block = true, int extra_delay = SwipeExtraDelayDefault, bool extra_swipe = false); + int swipe_without_scale(const Point& p1, const Point& p2, int duration = 0, bool block = true, int extra_delay = SwipeExtraDelayDefault, bool extra_swipe = false); + int swipe_without_scale(const Rect& r1, const Rect& r2, int duration = 0, bool block = true, int extra_delay = SwipeExtraDelayDefault, bool extra_swipe = false); - void wait(unsigned id) const noexcept; + void wait(unsigned id) const noexcept; - // 异形屏矫正 - //Rect shaped_correct(const Rect& rect) const; - std::pair get_scale_size() const noexcept; + // 异形屏矫正 + //Rect shaped_correct(const Rect& rect) const; + std::pair get_scale_size() const noexcept; - Controller& operator=(const Controller&) = delete; - Controller& operator=(Controller&&) = delete; + Controller& operator=(const Controller&) = delete; + Controller& operator=(Controller&&) = delete; - private: - void pipe_working_proc(); - std::optional> call_command(const std::string& cmd); - int push_cmd(const std::string& cmd); + private: + void pipe_working_proc(); + std::optional> call_command(const std::string& cmd); + int push_cmd(const std::string& cmd); - using DecodeFunc = std::function&)>; - bool screencap(); - bool screencap(const std::string& cmd, DecodeFunc decode_func); - cv::Mat get_resized_image() const; + using DecodeFunc = std::function&)>; + bool screencap(); + bool screencap(const std::string& cmd, DecodeFunc decode_func); + cv::Mat get_resized_image() const; - Point rand_point_in_rect(const Rect& rect); + Point rand_point_in_rect(const Rect& rect); - void random_delay() const; + void random_delay() const; - // 转换data中所有的crlf为lf:有些模拟器自带的adb,exec-out输出的\n,会被替换成\r\n,导致解码错误,所以这里转一下回来(点名批评mumu) - static void convert_lf(std::vector& data); + // 转换data中所有的crlf为lf:有些模拟器自带的adb,exec-out输出的\n,会被替换成\r\n,导致解码错误,所以这里转一下回来(点名批评mumu) + static void convert_lf(std::vector& data); - AsstCallback m_callback; - void* m_callback_arg = nullptr; + AsstCallback m_callback; + void* m_callback_arg = nullptr; - std::minstd_rand m_rand_engine; + std::minstd_rand m_rand_engine; - constexpr static int PipeBuffSize = 4 * 1024 * 1024; // 管道缓冲区大小 - std::unique_ptr m_pipe_buffer = nullptr; + constexpr static int PipeBuffSize = 4 * 1024 * 1024; // 管道缓冲区大小 + std::unique_ptr m_pipe_buffer = nullptr; #ifdef _WIN32 - HANDLE m_pipe_read = nullptr; // 读管道句柄 - HANDLE m_pipe_write = nullptr; // 写管道句柄 - HANDLE m_pipe_child_read = nullptr; // 子进程的读管道句柄 - HANDLE m_pipe_child_write = nullptr; // 子进程的写管道句柄 - SECURITY_ATTRIBUTES m_pipe_sec_attr = { 0 }; // 管道安全描述符 - STARTUPINFOA m_child_startup_info = { 0 }; // 子进程启动信息 + HANDLE m_pipe_read = nullptr; // 读管道句柄 + HANDLE m_pipe_write = nullptr; // 写管道句柄 + HANDLE m_pipe_child_read = nullptr; // 子进程的读管道句柄 + HANDLE m_pipe_child_write = nullptr; // 子进程的写管道句柄 + SECURITY_ATTRIBUTES m_pipe_sec_attr = { 0 }; // 管道安全描述符 + STARTUPINFOA m_child_startup_info = { 0 }; // 子进程启动信息 #else - constexpr static int PIPE_READ = 0; - constexpr static int PIPE_WRITE = 1; - int m_pipe_in[2] = { 0 }; - int m_pipe_out[2] = { 0 }; - int m_child = 0; + constexpr static int PIPE_READ = 0; + constexpr static int PIPE_WRITE = 1; + int m_pipe_in[2] = { 0 }; + int m_pipe_out[2] = { 0 }; + int m_child = 0; #endif - struct AdbProperty - { - /* command */ - std::string click; - std::string swipe; + struct AdbProperty + { + /* command */ + std::string click; + std::string swipe; - std::string screencap_raw_with_gzip; - std::string screencap_encode; - std::string release; + std::string screencap_raw_with_gzip; + std::string screencap_encode; + std::string release; - /* propertities */ - enum class ScreencapEndOfLine - { - UnknownYet, - CRLF, - LF, - CR - } screencap_end_of_line = ScreencapEndOfLine::UnknownYet; + /* propertities */ + enum class ScreencapEndOfLine + { + UnknownYet, + CRLF, + LF, + CR + } screencap_end_of_line = ScreencapEndOfLine::UnknownYet; - enum class ScreencapMethod - { - UnknownYet, - Default, - RawWithGzip, - Encode - } screencap_method = ScreencapMethod::UnknownYet; - } m_adb; + enum class ScreencapMethod + { + UnknownYet, + Default, + RawWithGzip, + Encode + } screencap_method = ScreencapMethod::UnknownYet; + } m_adb; - std::string m_uuid; - std::pair m_scale_size; - double m_control_scale = 1.0; - int m_width = 0; - int m_height = 0; + std::string m_uuid; + std::pair m_scale_size; + double m_control_scale = 1.0; + int m_width = 0; + int m_height = 0; - mutable std::shared_mutex m_image_mutex; - cv::Mat m_cache_image; + mutable std::shared_mutex m_image_mutex; + cv::Mat m_cache_image; - bool m_thread_exit = false; - //bool m_thread_idle = true; - std::mutex m_cmd_queue_mutex; - std::condition_variable m_cmd_condvar; - std::queue m_cmd_queue; - std::atomic m_completed_id = 0; - unsigned m_push_id = 0; // push_id的自增总是伴随着queue的push,肯定是要上锁的,所以没必要原子 - std::thread m_cmd_thread; - }; + bool m_thread_exit = false; + //bool m_thread_idle = true; + std::mutex m_cmd_queue_mutex; + std::condition_variable m_cmd_condvar; + std::queue m_cmd_queue; + std::atomic m_completed_id = 0; + unsigned m_push_id = 0; // push_id的自增总是伴随着queue的push,肯定是要上锁的,所以没必要原子 + std::thread m_cmd_thread; + }; } diff --git a/src/MeoAssistant/CreditShopImageAnalyzer.cpp b/src/MeoAssistant/CreditShopImageAnalyzer.cpp index 201384488f..d58d192de3 100644 --- a/src/MeoAssistant/CreditShopImageAnalyzer.cpp +++ b/src/MeoAssistant/CreditShopImageAnalyzer.cpp @@ -7,6 +7,10 @@ #include "AsstUtils.hpp" +asst::CreditShopImageAnalyzer::CreditShopImageAnalyzer(const cv::Mat image, std::shared_ptr task_data) + : AbstractImageAnalyzer(image, task_data) +{} + bool asst::CreditShopImageAnalyzer::analyze() { m_commoditys.clear(); @@ -19,7 +23,7 @@ bool asst::CreditShopImageAnalyzer::analyze() bool asst::CreditShopImageAnalyzer::commoditys_analyze() { // 识别信用点的图标 - const auto commodity_task_ptr = Task.get("CreditShop-Commoditys"); + const auto commodity_task_ptr = m_task_data->get("CreditShop-Commoditys"); MultiMatchImageAnalyzer mm_annlyzer(m_image); mm_annlyzer.set_task_info(commodity_task_ptr); @@ -48,7 +52,7 @@ bool asst::CreditShopImageAnalyzer::commoditys_analyze() bool asst::CreditShopImageAnalyzer::whether_to_buy_analyze() { const auto not_to_buy_task_ptr = std::dynamic_pointer_cast( - Task.get("CreditShop-NotToBuy")); + m_task_data->get("CreditShop-NotToBuy")); for (const Rect& commodity : m_commoditys) { // 商品名的区域 @@ -75,7 +79,7 @@ bool asst::CreditShopImageAnalyzer::sold_out_analyze() { // 识别是否售罄 MatchImageAnalyzer sold_out_analyzer(m_image); - sold_out_analyzer.set_task_info("CreditShop-SoldOut"); + sold_out_analyzer.set_task_info(m_task_data->get("CreditShop-SoldOut")); for (const Rect& commodity : m_need_to_buy) { sold_out_analyzer.set_roi(commodity); diff --git a/src/MeoAssistant/CreditShopImageAnalyzer.h b/src/MeoAssistant/CreditShopImageAnalyzer.h index 11727747e5..b3723eaa1d 100644 --- a/src/MeoAssistant/CreditShopImageAnalyzer.h +++ b/src/MeoAssistant/CreditShopImageAnalyzer.h @@ -6,8 +6,7 @@ namespace asst class CreditShopImageAnalyzer final : public AbstractImageAnalyzer { public: - using AbstractImageAnalyzer::AbstractImageAnalyzer; - CreditShopImageAnalyzer(const cv::Mat image, const Rect& roi) = delete; + CreditShopImageAnalyzer(const cv::Mat image, std::shared_ptr task_data); virtual ~CreditShopImageAnalyzer() = default; virtual bool analyze() override; diff --git a/src/MeoAssistant/CreditShoppingTask.cpp b/src/MeoAssistant/CreditShoppingTask.cpp index 702e84a89a..55eb49ea30 100644 --- a/src/MeoAssistant/CreditShoppingTask.cpp +++ b/src/MeoAssistant/CreditShoppingTask.cpp @@ -15,7 +15,7 @@ bool asst::CreditShoppingTask::_run() { const cv::Mat image = m_ctrler->get_image(); - CreditShopImageAnalyzer shop_analyzer(image); + CreditShopImageAnalyzer shop_analyzer(image, m_task_data); if (!shop_analyzer.analyze()) { return false; } @@ -35,7 +35,7 @@ bool asst::CreditShoppingTask::_run() // “购买商品”按钮 static Rect buy_it_rect; if (buy_it_rect.empty()) { - const auto buy_it_task_ptr = Task.get("CreditShop-BuyIt"); + const auto buy_it_task_ptr = m_task_data->get("CreditShop-BuyIt"); const cv::Mat buy_image = m_ctrler->get_image(); MatchImageAnalyzer buy_it_analyzer(buy_image); @@ -59,7 +59,7 @@ bool asst::CreditShoppingTask::_run() const cv::Mat prompt_image = m_ctrler->get_image(); OcrImageAnalyzer prompt_analyzer(prompt_image); - prompt_analyzer.set_task_info("CreditShop-NoMoney"); + prompt_analyzer.set_task_info(m_task_data->get("CreditShop-NoMoney")); if (prompt_analyzer.analyze()) { click_return_button(); return true; diff --git a/src/MeoAssistant/CreditShoppingTask.h b/src/MeoAssistant/CreditShoppingTask.h index 186ccd1850..b74e521b16 100644 --- a/src/MeoAssistant/CreditShoppingTask.h +++ b/src/MeoAssistant/CreditShoppingTask.h @@ -4,7 +4,7 @@ #include -#include "AsstDef.h" +#include "AsstTypes.h" namespace asst { diff --git a/src/MeoAssistant/GeneralConfiger.h b/src/MeoAssistant/GeneralConfiger.h index 86129b4a35..df7f799d32 100644 --- a/src/MeoAssistant/GeneralConfiger.h +++ b/src/MeoAssistant/GeneralConfiger.h @@ -7,95 +7,95 @@ #include #include -#include "AsstDef.h" +#include "AsstTypes.h" namespace asst { - struct AipOcrCfg // 百度 OCR API 的配置 - { - bool enable = false; - bool accurate = false; // 是否使用高精度识别 - std::string client_id; - std::string client_secret; - }; + struct AipOcrCfg // 百度 OCR API 的配置 + { + bool enable = false; + bool accurate = false; // 是否使用高精度识别 + std::string client_id; + std::string client_secret; + }; - struct PenguinReportCfg // 企鹅物流数据汇报 的配置 - { - bool enable = false; - std::string cmd_format; // 命令格式 - std::string extra_param; // 额外参数 - std::string server; // 上传参数中"server"字段,"CN", "US", "JP" and "KR". - }; + struct PenguinReportCfg // 企鹅物流数据汇报 的配置 + { + bool enable = false; + std::string cmd_format; // 命令格式 + std::string extra_param; // 额外参数 + std::string server; // 上传参数中"server"字段,"CN", "US", "JP" and "KR". + }; - struct Options - { - int task_delay = 0; // 任务间延时:越快操作越快,但会增加CPU消耗 - int control_delay_lower = 0; // 点击随机延时下限:每次点击操作会进行随机延时 - int control_delay_upper = 0; // 点击随机延时上限:每次点击操作会进行随机延时 - //bool print_window = false; // 截图功能:开启后每次结算界面会截图到screenshot目录下 - int adb_extra_swipe_dist = 0; // 额外的滑动距离:adb有bug,同样的参数,偶尔会划得非常远。额外做一个短程滑动,把之前的停下来 - int adb_extra_swipe_duration = -1; // 额外的滑动持续时间:adb有bug,同样的参数,偶尔会划得非常远。额外做一个短程滑动,把之前的停下来。若小于0,则关闭额外滑动功能 - PenguinReportCfg penguin_report; // 企鹅数据汇报:每次到结算界面,汇报掉落数据至企鹅数据 https://penguin-stats.cn/ - AipOcrCfg aip_ocr; // 百度 OCR API 的配置 - }; + struct Options + { + int task_delay = 0; // 任务间延时:越快操作越快,但会增加CPU消耗 + int control_delay_lower = 0; // 点击随机延时下限:每次点击操作会进行随机延时 + int control_delay_upper = 0; // 点击随机延时上限:每次点击操作会进行随机延时 + //bool print_window = false; // 截图功能:开启后每次结算界面会截图到screenshot目录下 + int adb_extra_swipe_dist = 0; // 额外的滑动距离:adb有bug,同样的参数,偶尔会划得非常远。额外做一个短程滑动,把之前的停下来 + int adb_extra_swipe_duration = -1; // 额外的滑动持续时间:adb有bug,同样的参数,偶尔会划得非常远。额外做一个短程滑动,把之前的停下来。若小于0,则关闭额外滑动功能 + PenguinReportCfg penguin_report; // 企鹅数据汇报:每次到结算界面,汇报掉落数据至企鹅数据 https://penguin-stats.cn/ + AipOcrCfg aip_ocr; // 百度 OCR API 的配置 + }; - struct AdbCfg - { - /* format */ - std::string address_regex; - std::string display_format; + struct AdbCfg + { + /* format */ + std::string address_regex; + std::string display_format; - /* command */ - std::string devices; - std::string connect; - std::string display_id; - std::string uuid; - std::string click; - std::string swipe; - std::string display; - std::string screencap_raw_with_gzip; - std::string screencap_encode; - std::string release; - }; + /* command */ + std::string devices; + std::string connect; + std::string display_id; + std::string uuid; + std::string click; + std::string swipe; + std::string display; + std::string screencap_raw_with_gzip; + std::string screencap_encode; + std::string release; + }; - class GeneralConfiger : public AbstractConfiger - { - public: - virtual ~GeneralConfiger() = default; + class GeneralConfiger : public AbstractConfiger + { + public: + virtual ~GeneralConfiger() = default; - const std::string& get_version() const noexcept - { - return m_version; - } - const Options& get_options() const noexcept - { - return m_options; - } - Options& get_options() - { - return m_options; - } - std::optional get_adb_cfg(const std::string& name) const - { - if (auto iter = m_adb_cfg.find(name); - iter != m_adb_cfg.cend()) { - return iter->second; - } - else { - return std::nullopt; - } - } + const std::string& get_version() const noexcept + { + return m_version; + } + const Options& get_options() const noexcept + { + return m_options; + } + Options& get_options() + { + return m_options; + } + std::optional get_adb_cfg(const std::string& name) const + { + if (auto iter = m_adb_cfg.find(name); + iter != m_adb_cfg.cend()) { + return iter->second; + } + else { + return std::nullopt; + } + } - void set_options(Options opt) noexcept - { - m_options = std::move(opt); - } + void set_options(Options opt) noexcept + { + m_options = std::move(opt); + } - protected: - virtual bool parse(const json::value& json) override; + protected: + virtual bool parse(const json::value& json) override; - std::string m_version; - Options m_options; - std::unordered_map m_adb_cfg; - }; + std::string m_version; + Options m_options; + std::unordered_map m_adb_cfg; + }; } diff --git a/src/MeoAssistant/InfrastAbstractTask.cpp b/src/MeoAssistant/InfrastAbstractTask.cpp index ff7dffdd60..0d112fa6da 100644 --- a/src/MeoAssistant/InfrastAbstractTask.cpp +++ b/src/MeoAssistant/InfrastAbstractTask.cpp @@ -13,190 +13,190 @@ asst::InfrastAbstractTask& asst::InfrastAbstractTask::set_work_mode(infrast::WorkMode work_mode) noexcept { - m_work_mode = work_mode; - switch (work_mode) { - case infrast::WorkMode::Gentle: - m_work_mode_name = "Gentle"; - break; - case infrast::WorkMode::Aggressive: - m_work_mode_name = "Aggressive"; - break; - case infrast::WorkMode::Extreme: - m_work_mode_name = "Extreme"; - break; - default: - m_work_mode_name.clear(); - break; - } - return *this; + m_work_mode = work_mode; + switch (work_mode) { + case infrast::WorkMode::Gentle: + m_work_mode_name = "Gentle"; + break; + case infrast::WorkMode::Aggressive: + m_work_mode_name = "Aggressive"; + break; + case infrast::WorkMode::Extreme: + m_work_mode_name = "Extreme"; + break; + default: + m_work_mode_name.clear(); + break; + } + return *this; } asst::InfrastAbstractTask& asst::InfrastAbstractTask::set_mood_threshold(double mood_thres) noexcept { - m_mood_threshold = mood_thres; - return *this; + m_mood_threshold = mood_thres; + return *this; } json::value asst::InfrastAbstractTask::basic_info() const { - json::value info = AbstractTask::basic_info(); - auto& details = info["details"]; - details["facility"] = facility_name(); - details["index"] = m_cur_facility_index; - return info; + json::value info = AbstractTask::basic_info(); + auto& details = info["details"]; + details["facility"] = facility_name(); + details["index"] = m_cur_facility_index; + return info; } std::string asst::InfrastAbstractTask::facility_name() const { - if (m_facility_name_cache.empty()) { - std::string class_name = typeid(*this).name(); - // typeid.name() 结果可能和编译器有关,所以这里使用正则尽可能保证结果正确。 - // 但还是不能完全保证,如果不行的话建议 override - std::regex regex("Infrast(.*)Task"); - std::smatch match_obj; - if (std::regex_search(class_name, match_obj, regex)) { - m_facility_name_cache = match_obj[1].str(); - } - else { - m_facility_name_cache = class_name; - } - } - return m_facility_name_cache; + if (m_facility_name_cache.empty()) { + std::string class_name = typeid(*this).name(); + // typeid.name() 结果可能和编译器有关,所以这里使用正则尽可能保证结果正确。 + // 但还是不能完全保证,如果不行的话建议 override + std::regex regex("Infrast(.*)Task"); + std::smatch match_obj; + if (std::regex_search(class_name, match_obj, regex)) { + m_facility_name_cache = match_obj[1].str(); + } + else { + m_facility_name_cache = class_name; + } + } + return m_facility_name_cache; } bool asst::InfrastAbstractTask::on_run_fails() { - LogTraceFunction; + LogTraceFunction; - ProcessTask return_task(*this, { "InfrastBegin" }); - return return_task.run(); + ProcessTask return_task(*this, { "InfrastBegin" }); + return return_task.run(); } bool asst::InfrastAbstractTask::enter_facility(int index) { - const auto image = m_ctrler->get_image(); + const auto image = m_ctrler->get_image(); - InfrastFacilityImageAnalyzer analyzer(image); - analyzer.set_to_be_analyzed({ facility_name() }); - if (!analyzer.analyze()) { - Log.trace("result is empty"); - return false; - } - Rect rect = analyzer.get_rect(facility_name(), index); - if (rect.empty()) { - Log.trace("facility index is out of range"); - return false; - } + InfrastFacilityImageAnalyzer analyzer(image); + analyzer.set_to_be_analyzed({ facility_name() }); + if (!analyzer.analyze()) { + Log.trace("result is empty"); + return false; + } + Rect rect = analyzer.get_rect(facility_name(), index); + if (rect.empty()) { + Log.trace("facility index is out of range"); + return false; + } - m_cur_facility_index = index; - callback(AsstMsg::SubTaskExtraInfo, basic_info_with_what("EnterFacility")); + m_cur_facility_index = index; + callback(AsstMsg::SubTaskExtraInfo, basic_info_with_what("EnterFacility")); - m_ctrler->click(rect); + m_ctrler->click(rect); - const auto enter_task_ptr = Task.get("InfrastEnterFacility"); - sleep(enter_task_ptr->rear_delay); + const auto enter_task_ptr = m_task_data->get("InfrastEnterFacility"); + sleep(enter_task_ptr->rear_delay); - return true; + return true; } bool asst::InfrastAbstractTask::enter_oper_list_page() { - LogTraceFunction; + LogTraceFunction; - ProcessTask task(*this, { "InfrastEnterOperList", "InfrastStationedInfo" }); - return task.run(); + ProcessTask task(*this, { "InfrastEnterOperList", "InfrastStationedInfo" }); + return task.run(); } void asst::InfrastAbstractTask::async_swipe_of_operlist(bool reverse) { - LogTraceFunction; - static Rect begin_rect = Task.get("InfrastOperListSwipeBegin")->specific_rect; - static Rect end_rect = Task.get("InfrastOperListSwipeEnd")->specific_rect; - static int duration = Task.get("InfrastOperListSwipeBegin")->pre_delay; + LogTraceFunction; + static Rect begin_rect = m_task_data->get("InfrastOperListSwipeBegin")->specific_rect; + static Rect end_rect = m_task_data->get("InfrastOperListSwipeEnd")->specific_rect; + static int duration = m_task_data->get("InfrastOperListSwipeBegin")->pre_delay; - if (!reverse) { - m_last_swipe_id = m_ctrler->swipe(begin_rect, end_rect, duration, false, 0, true); - } - else { - m_last_swipe_id = m_ctrler->swipe(end_rect, begin_rect, duration, false, 0, true); - } + if (!reverse) { + m_last_swipe_id = m_ctrler->swipe(begin_rect, end_rect, duration, false, 0, true); + } + else { + m_last_swipe_id = m_ctrler->swipe(end_rect, begin_rect, duration, false, 0, true); + } } void asst::InfrastAbstractTask::await_swipe() { - LogTraceFunction; - static int extra_delay = Task.get("InfrastOperListSwipeBegin")->rear_delay; + LogTraceFunction; + static int extra_delay = m_task_data->get("InfrastOperListSwipeBegin")->rear_delay; - m_ctrler->wait(m_last_swipe_id); - sleep(extra_delay); + m_ctrler->wait(m_last_swipe_id); + sleep(extra_delay); } bool asst::InfrastAbstractTask::click_bottomleft_tab() { - LogTraceFunction; + LogTraceFunction; - ProcessTask task(*this, { "InfrastBottomLeftTab" }); - return task.run(); + ProcessTask task(*this, { "InfrastBottomLeftTab" }); + return task.run(); } bool asst::InfrastAbstractTask::click_clear_button() { - LogTraceFunction; + LogTraceFunction; - ProcessTask task(*this, { "InfrastClearButton" }); - return task.run(); + ProcessTask task(*this, { "InfrastClearButton" }); + return task.run(); } bool asst::InfrastAbstractTask::click_confirm_button() { - LogTraceFunction; + LogTraceFunction; - ProcessTask task(*this, { "InfrastDormConfirmButton" }); - return task.run(); + ProcessTask task(*this, { "InfrastDormConfirmButton" }); + return task.run(); } void asst::InfrastAbstractTask::swipe_of_operlist(bool reverse) { - async_swipe_of_operlist(reverse); - await_swipe(); + async_swipe_of_operlist(reverse); + await_swipe(); } void asst::InfrastAbstractTask::swipe_to_the_left_of_operlist(int loop_times) { - LogTraceFunction; - static Rect begin_rect = Task.get("InfrastOperListSwipeToTheLeftBegin")->specific_rect; - static Rect end_rect = Task.get("InfrastOperListSwipeToTheLeftEnd")->specific_rect; - static int duration = Task.get("InfrastOperListSwipeToTheLeftBegin")->pre_delay; - static int extra_delay = Task.get("InfrastOperListSwipeToTheLeftBegin")->rear_delay; - static int cfg_loop_times = Task.get("InfrastOperListSwipeToTheLeftBegin")->max_times; + LogTraceFunction; + static Rect begin_rect = m_task_data->get("InfrastOperListSwipeToTheLeftBegin")->specific_rect; + static Rect end_rect = m_task_data->get("InfrastOperListSwipeToTheLeftEnd")->specific_rect; + static int duration = m_task_data->get("InfrastOperListSwipeToTheLeftBegin")->pre_delay; + static int extra_delay = m_task_data->get("InfrastOperListSwipeToTheLeftBegin")->rear_delay; + static int cfg_loop_times = m_task_data->get("InfrastOperListSwipeToTheLeftBegin")->max_times; - for (int i = 0; i != cfg_loop_times * loop_times; ++i) { - if (need_exit()) { - return; - } - m_ctrler->swipe(end_rect, begin_rect, duration, true, 0, false); - } - sleep(extra_delay); + for (int i = 0; i != cfg_loop_times * loop_times; ++i) { + if (need_exit()) { + return; + } + m_ctrler->swipe(end_rect, begin_rect, duration, true, 0, false); + } + sleep(extra_delay); } void asst::InfrastAbstractTask::swipe_to_the_left_of_main_ui() { - LogTraceFunction; - static Rect begin_rect = Task.get("InfrastOperListSwipeToTheLeftBegin")->specific_rect; - static Rect end_rect = Task.get("InfrastOperListSwipeToTheLeftEnd")->specific_rect; - static int duration = Task.get("InfrastOperListSwipeToTheLeftBegin")->pre_delay; - static int extra_delay = Task.get("InfrastOperListSwipeToTheLeftBegin")->rear_delay; + LogTraceFunction; + static Rect begin_rect = m_task_data->get("InfrastOperListSwipeToTheLeftBegin")->specific_rect; + static Rect end_rect = m_task_data->get("InfrastOperListSwipeToTheLeftEnd")->specific_rect; + static int duration = m_task_data->get("InfrastOperListSwipeToTheLeftBegin")->pre_delay; + static int extra_delay = m_task_data->get("InfrastOperListSwipeToTheLeftBegin")->rear_delay; - m_ctrler->swipe(end_rect, begin_rect, duration, true, extra_delay, false); + m_ctrler->swipe(end_rect, begin_rect, duration, true, extra_delay, false); } void asst::InfrastAbstractTask::swipe_to_the_right_of_main_ui() { - LogTraceFunction; - static Rect begin_rect = Task.get("InfrastOperListSwipeToTheLeftBegin")->specific_rect; - static Rect end_rect = Task.get("InfrastOperListSwipeToTheLeftEnd")->specific_rect; - static int duration = Task.get("InfrastOperListSwipeToTheLeftBegin")->pre_delay; - static int extra_delay = Task.get("InfrastOperListSwipeToTheLeftBegin")->rear_delay; + LogTraceFunction; + static Rect begin_rect = m_task_data->get("InfrastOperListSwipeToTheLeftBegin")->specific_rect; + static Rect end_rect = m_task_data->get("InfrastOperListSwipeToTheLeftEnd")->specific_rect; + static int duration = m_task_data->get("InfrastOperListSwipeToTheLeftBegin")->pre_delay; + static int extra_delay = m_task_data->get("InfrastOperListSwipeToTheLeftBegin")->rear_delay; - m_ctrler->swipe(begin_rect, end_rect, duration, true, extra_delay, false); -} + m_ctrler->swipe(begin_rect, end_rect, duration, true, extra_delay, false); +} \ No newline at end of file diff --git a/src/MeoAssistant/InfrastAbstractTask.h b/src/MeoAssistant/InfrastAbstractTask.h index dcb06fb130..69920779a1 100644 --- a/src/MeoAssistant/InfrastAbstractTask.h +++ b/src/MeoAssistant/InfrastAbstractTask.h @@ -1,47 +1,47 @@ #pragma once #include "AbstractTask.h" -#include "AsstDef.h" +#include "AsstTypes.h" #include "AsstInfrastDef.h" namespace asst { - class InfrastAbstractTask : public AbstractTask - { - public: - using AbstractTask::AbstractTask; + class InfrastAbstractTask : public AbstractTask + { + public: + using AbstractTask::AbstractTask; - virtual ~InfrastAbstractTask() = default; - InfrastAbstractTask& set_work_mode(infrast::WorkMode work_mode) noexcept; - InfrastAbstractTask& set_mood_threshold(double mood_thres) noexcept; + virtual ~InfrastAbstractTask() = default; + InfrastAbstractTask& set_work_mode(infrast::WorkMode work_mode) noexcept; + InfrastAbstractTask& set_mood_threshold(double mood_thres) noexcept; - virtual json::value basic_info() const override; - virtual std::string facility_name() const; - virtual size_t max_num_of_facilities() const noexcept { return 1ULL; } - virtual size_t max_num_of_opers() const noexcept { return 1ULL; } + virtual json::value basic_info() const override; + virtual std::string facility_name() const; + virtual size_t max_num_of_facilities() const noexcept { return 1ULL; } + virtual size_t max_num_of_opers() const noexcept { return 1ULL; } - constexpr static int OperSelectRetryTimes = 3; - protected: - virtual bool on_run_fails() override; + constexpr static int OperSelectRetryTimes = 3; + protected: + virtual bool on_run_fails() override; - bool enter_facility(int index = 0); - bool enter_oper_list_page(); // 从刚点进设施的界面,到干员列表页 + bool enter_facility(int index = 0); + bool enter_oper_list_page(); // 从刚点进设施的界面,到干员列表页 - void swipe_to_the_left_of_operlist(int loop_times = 1); // 滑动到干员列表的最左侧 - void swipe_to_the_left_of_main_ui(); // 滑动基建的主界面到最左侧 - void swipe_to_the_right_of_main_ui(); // 滑动基建的主界面到最右侧 - void swipe_of_operlist(bool reverse = false); - void async_swipe_of_operlist(bool reverse = false); - void await_swipe(); + void swipe_to_the_left_of_operlist(int loop_times = 1); // 滑动到干员列表的最左侧 + void swipe_to_the_left_of_main_ui(); // 滑动基建的主界面到最左侧 + void swipe_to_the_right_of_main_ui(); // 滑动基建的主界面到最右侧 + void swipe_of_operlist(bool reverse = false); + void async_swipe_of_operlist(bool reverse = false); + void await_swipe(); - virtual bool click_bottomleft_tab(); // 点击进入设施后,左下角的tab(我也不知道这玩意该叫啥) - virtual bool click_clear_button(); // 点击干员选择页面的“清空选择”按钮 - virtual bool click_confirm_button(); // 点击干员选择页面的“确认”按钮 + virtual bool click_bottomleft_tab(); // 点击进入设施后,左下角的tab(我也不知道这玩意该叫啥) + virtual bool click_clear_button(); // 点击干员选择页面的“清空选择”按钮 + virtual bool click_confirm_button(); // 点击干员选择页面的“确认”按钮 - int m_last_swipe_id = 0; - infrast::WorkMode m_work_mode = infrast::WorkMode::Gentle; - std::string m_work_mode_name = "Gentle"; - double m_mood_threshold = 0; - mutable std::string m_facility_name_cache; - int m_cur_facility_index = 0; - }; + int m_last_swipe_id = 0; + infrast::WorkMode m_work_mode = infrast::WorkMode::Gentle; + std::string m_work_mode_name = "Gentle"; + double m_mood_threshold = 0; + mutable std::string m_facility_name_cache; + int m_cur_facility_index = 0; + }; } diff --git a/src/MeoAssistant/InfrastClueImageAnalyzer.cpp b/src/MeoAssistant/InfrastClueImageAnalyzer.cpp index 7976efe719..b76d4cbc20 100644 --- a/src/MeoAssistant/InfrastClueImageAnalyzer.cpp +++ b/src/MeoAssistant/InfrastClueImageAnalyzer.cpp @@ -16,7 +16,7 @@ bool asst::InfrastClueImageAnalyzer::analyze() bool asst::InfrastClueImageAnalyzer::clue_detect() { MultiMatchImageAnalyzer clue_analyzer(m_image); - clue_analyzer.set_task_info("InfrastClue"); + clue_analyzer.set_task_info(StaticTaskData::get_instance().get("InfrastClue")); clue_analyzer.set_roi(m_roi); // 该任务以外部设置的roi为准 if (!clue_analyzer.analyze()) { return false; diff --git a/src/MeoAssistant/InfrastClueVacancyImageAnalyzer.cpp b/src/MeoAssistant/InfrastClueVacancyImageAnalyzer.cpp index 318cacf398..1bc779a834 100644 --- a/src/MeoAssistant/InfrastClueVacancyImageAnalyzer.cpp +++ b/src/MeoAssistant/InfrastClueVacancyImageAnalyzer.cpp @@ -11,7 +11,7 @@ bool asst::InfrastClueVacancyImageAnalyzer::analyze() MatchImageAnalyzer analyzer(m_image); for (const std::string& suffix : m_to_be_analyzed) { - analyzer.set_task_info(clue_vacancy + suffix); + analyzer.set_task_info(StaticTaskData::get_instance().get(clue_vacancy + suffix)); if (!analyzer.analyze()) { Log.trace("no", clue_vacancy, suffix); continue; diff --git a/src/MeoAssistant/InfrastFacilityImageAnalyzer.cpp b/src/MeoAssistant/InfrastFacilityImageAnalyzer.cpp index e477d7fea0..49fd508752 100644 --- a/src/MeoAssistant/InfrastFacilityImageAnalyzer.cpp +++ b/src/MeoAssistant/InfrastFacilityImageAnalyzer.cpp @@ -24,7 +24,7 @@ bool asst::InfrastFacilityImageAnalyzer::analyze() MultiMatchImageAnalyzer mm_analyzer(m_image); auto task_analyze = [&](const std::string& task_name) -> bool { - mm_analyzer.set_task_info(task_name); + mm_analyzer.set_task_info(StaticTaskData::get_instance().get(task_name)); return mm_analyzer.analyze(); }; diff --git a/src/MeoAssistant/InfrastOperImageAnalyzer.cpp b/src/MeoAssistant/InfrastOperImageAnalyzer.cpp index b3525991d6..8bf0b5bb20 100644 --- a/src/MeoAssistant/InfrastOperImageAnalyzer.cpp +++ b/src/MeoAssistant/InfrastOperImageAnalyzer.cpp @@ -8,417 +8,417 @@ bool asst::InfrastOperImageAnalyzer::analyze() { - m_result.clear(); - m_num_of_opers_with_skills = 0; + m_result.clear(); + m_num_of_opers_with_skills = 0; - if (m_to_be_calced & None) { - return true; - } + if (m_to_be_calced & None) { + return true; + } - if (m_to_be_calced & Smiley) { - oper_detect(); - } - if (m_to_be_calced & Mood) { - mood_analyze(); - } - if (m_to_be_calced & NameHash) { - name_hash_analyze(); - } - if (m_to_be_calced & FaceHash) { - face_hash_analyze(); - } - if (m_to_be_calced & Skill) { - skill_analyze(); - } - if (m_to_be_calced & Selected) { - selected_analyze(); - } - if (m_to_be_calced & Doing) { - doing_analyze(); - } + if (m_to_be_calced & Smiley) { + oper_detect(); + } + if (m_to_be_calced & Mood) { + mood_analyze(); + } + if (m_to_be_calced & NameHash) { + name_hash_analyze(); + } + if (m_to_be_calced & FaceHash) { + face_hash_analyze(); + } + if (m_to_be_calced & Skill) { + skill_analyze(); + } + if (m_to_be_calced & Selected) { + selected_analyze(); + } + if (m_to_be_calced & Doing) { + doing_analyze(); + } - return !m_result.empty(); + return !m_result.empty(); } void asst::InfrastOperImageAnalyzer::sort_by_loc() { - LogTraceFunction; + LogTraceFunction; - std::sort( - m_result.begin(), m_result.end(), - [](const infrast::Oper& lhs, const infrast::Oper& rhs) -> bool { - if (std::abs(lhs.rect.x - rhs.rect.x) < 5) { // x差距较小则理解为是同一排的,按y排序 - return lhs.rect.y < rhs.rect.y; - } - else { - return lhs.rect.x < rhs.rect.x; - } - }); + std::sort( + m_result.begin(), m_result.end(), + [](const infrast::Oper& lhs, const infrast::Oper& rhs) -> bool { + if (std::abs(lhs.rect.x - rhs.rect.x) < 5) { // x差距较小则理解为是同一排的,按y排序 + return lhs.rect.y < rhs.rect.y; + } + else { + return lhs.rect.x < rhs.rect.x; + } + }); } void asst::InfrastOperImageAnalyzer::sort_by_mood() { - LogTraceFunction; + LogTraceFunction; - std::sort( - m_result.begin(), m_result.end(), - [](const infrast::Oper& lhs, const infrast::Oper& rhs) -> bool { - // 先按心情排序,心情低的放前面 - if (std::fabs(lhs.mood_ratio - rhs.mood_ratio) > DoubleDiff) { - return lhs.mood_ratio < rhs.mood_ratio; - } - // 心情一样的就按位置排序,左边的放前面 - if (std::abs(lhs.rect.x - rhs.rect.x) > 5) { - return lhs.rect.x < rhs.rect.x; - } - else { - return lhs.rect.y < rhs.rect.y; - } - }); + std::sort( + m_result.begin(), m_result.end(), + [](const infrast::Oper& lhs, const infrast::Oper& rhs) -> bool { + // 先按心情排序,心情低的放前面 + if (std::fabs(lhs.mood_ratio - rhs.mood_ratio) > DoubleDiff) { + return lhs.mood_ratio < rhs.mood_ratio; + } + // 心情一样的就按位置排序,左边的放前面 + if (std::abs(lhs.rect.x - rhs.rect.x) > 5) { + return lhs.rect.x < rhs.rect.x; + } + else { + return lhs.rect.y < rhs.rect.y; + } + }); } void asst::InfrastOperImageAnalyzer::oper_detect() { - LogTraceFunction; + LogTraceFunction; - const Rect upper_roi = Task.get("InfrastSkillsUpper")->roi; - const Rect lower_roi = Task.get("InfrastSkillsLower")->roi; - const std::vector all_roi = { upper_roi, lower_roi }; + const Rect upper_roi = m_task_data->get("InfrastSkillsUpper")->roi; + const Rect lower_roi = m_task_data->get("InfrastSkillsLower")->roi; + const std::vector all_roi = { upper_roi, lower_roi }; - const Rect skill_rect_move = Task.get("InfrastSkills")->rect_move; - const Rect hash_rect_move = Task.get("InfrastOperNameHash")->rect_move; - const Rect prg_rect_move = Task.get("InfrastOperMoodProgressBar")->roi; - const std::vector all_rect_move = { skill_rect_move, hash_rect_move, prg_rect_move }; + const Rect skill_rect_move = m_task_data->get("InfrastSkills")->rect_move; + const Rect hash_rect_move = m_task_data->get("InfrastOperNameHash")->rect_move; + const Rect prg_rect_move = m_task_data->get("InfrastOperMoodProgressBar")->roi; + const std::vector all_rect_move = { skill_rect_move, hash_rect_move, prg_rect_move }; - InfrastSmileyImageAnalyzer smiley_analyzer(m_image); + InfrastSmileyImageAnalyzer smiley_analyzer(m_image); - for (auto&& roi : all_roi) { - smiley_analyzer.set_roi(roi); - if (!smiley_analyzer.analyze()) { - continue; - } - for (const auto& smiley : smiley_analyzer.get_result()) { - auto&& [_type, smiley_rect] = smiley; - bool available = true; + for (auto&& roi : all_roi) { + smiley_analyzer.set_roi(roi); + if (!smiley_analyzer.analyze()) { + continue; + } + for (const auto& smiley : smiley_analyzer.get_result()) { + auto&& [_type, smiley_rect] = smiley; + bool available = true; - for (const Rect& rect_move : all_rect_move) { - Rect cor_rect = rect_move; - cor_rect.x += smiley_rect.x; - cor_rect.y += smiley_rect.y; - // 超过ROI边界了 - if (cor_rect.x + cor_rect.width > roi.x + roi.width || cor_rect.x < roi.x) { - available = false; - break; - } - } - if (!available) { - continue; - } + for (const Rect& rect_move : all_rect_move) { + Rect cor_rect = rect_move; + cor_rect.x += smiley_rect.x; + cor_rect.y += smiley_rect.y; + // 超过ROI边界了 + if (cor_rect.x + cor_rect.width > roi.x + roi.width || cor_rect.x < roi.x) { + available = false; + break; + } + } + if (!available) { + continue; + } #ifdef ASST_DEBUG - cv::rectangle(m_image_draw, utils::make_rect(smiley_rect), cv::Scalar(0, 0, 255), 2); + cv::rectangle(m_image_draw, utils::make_rect(smiley_rect), cv::Scalar(0, 0, 255), 2); #endif // ASST_DEBUG - infrast::Oper oper; - oper.smiley = smiley; - m_result.emplace_back(std::move(oper)); - } - } + infrast::Oper oper; + oper.smiley = smiley; + m_result.emplace_back(std::move(oper)); + } + } } void asst::InfrastOperImageAnalyzer::mood_analyze() { - LogTraceFunction; + LogTraceFunction; - const auto prg_task_ptr = std::dynamic_pointer_cast( - Task.get("InfrastOperMoodProgressBar")); - uint8_t prg_lower_limit = static_cast(prg_task_ptr->templ_threshold); - int prg_diff_thres = static_cast(prg_task_ptr->special_threshold); - Rect rect_move = prg_task_ptr->rect_move; + const auto prg_task_ptr = std::dynamic_pointer_cast( + m_task_data->get("InfrastOperMoodProgressBar")); + uint8_t prg_lower_limit = static_cast(prg_task_ptr->templ_threshold); + int prg_diff_thres = static_cast(prg_task_ptr->special_threshold); + Rect rect_move = prg_task_ptr->rect_move; - for (auto&& oper : m_result) { - bool not_analyze = false; - switch (oper.smiley.type) { - case infrast::SmileyType::Distract: - oper.mood_ratio = 0; - not_analyze = true; - break; - case infrast::SmileyType::Rest: - oper.mood_ratio = 1.0; - not_analyze = true; - break; - case infrast::SmileyType::Work: - not_analyze = false; - break; - default: - // TODO 报错 - break; - } + for (auto&& oper : m_result) { + bool not_analyze = false; + switch (oper.smiley.type) { + case infrast::SmileyType::Distract: + oper.mood_ratio = 0; + not_analyze = true; + break; + case infrast::SmileyType::Rest: + oper.mood_ratio = 1.0; + not_analyze = true; + break; + case infrast::SmileyType::Work: + not_analyze = false; + break; + default: + // TODO 报错 + break; + } - if (not_analyze) { - continue; - } + if (not_analyze) { + continue; + } - Rect roi = rect_move; - roi.x += oper.smiley.rect.x; - roi.y += oper.smiley.rect.y; - cv::Mat prg_image = m_image(utils::make_rect(roi)); - cv::Mat prg_gray; - cv::cvtColor(prg_image, prg_gray, cv::COLOR_BGR2GRAY); + Rect roi = rect_move; + roi.x += oper.smiley.rect.x; + roi.y += oper.smiley.rect.y; + cv::Mat prg_image = m_image(utils::make_rect(roi)); + cv::Mat prg_gray; + cv::cvtColor(prg_image, prg_gray, cv::COLOR_BGR2GRAY); - int max_white_length = 0; // 最长横扫的白色长度,即作为进度条长度 - for (int i = 0; i != prg_gray.rows; ++i) { - int cur_white_length = 0; - cv::uint8_t left_value = prg_lower_limit; - for (int j = 0; j != prg_gray.cols; ++j) { - auto value = prg_gray.at(i, j); - // 当前点的颜色,需要大于最低阈值;且与相邻点的差值不能过大,否则就认为当前点不是进度条 - if (value >= prg_lower_limit && left_value < value + prg_diff_thres) { - left_value = value; - ++cur_white_length; - if (max_white_length < cur_white_length) { - max_white_length = cur_white_length; - } - } - else { - if (max_white_length < cur_white_length) { - max_white_length = cur_white_length; - } - left_value = prg_lower_limit; - cur_white_length = 0; - break; - } - } - } + int max_white_length = 0; // 最长横扫的白色长度,即作为进度条长度 + for (int i = 0; i != prg_gray.rows; ++i) { + int cur_white_length = 0; + cv::uint8_t left_value = prg_lower_limit; + for (int j = 0; j != prg_gray.cols; ++j) { + auto value = prg_gray.at(i, j); + // 当前点的颜色,需要大于最低阈值;且与相邻点的差值不能过大,否则就认为当前点不是进度条 + if (value >= prg_lower_limit && left_value < value + prg_diff_thres) { + left_value = value; + ++cur_white_length; + if (max_white_length < cur_white_length) { + max_white_length = cur_white_length; + } + } + else { + if (max_white_length < cur_white_length) { + max_white_length = cur_white_length; + } + left_value = prg_lower_limit; + cur_white_length = 0; + break; + } + } + } - // TODO:这里的进度条长度算的并不是特别准,属于能跑就行。有空再优化下 - double ratio = static_cast(max_white_length) / roi.width; - oper.mood_ratio = ratio; + // TODO:这里的进度条长度算的并不是特别准,属于能跑就行。有空再优化下 + double ratio = static_cast(max_white_length) / roi.width; + oper.mood_ratio = ratio; #ifdef ASST_DEBUG - cv::Point p1(roi.x, roi.y); - cv::Point p2(roi.x + max_white_length, roi.y); - cv::line(m_image_draw, p1, p2, cv::Scalar(0, 255, 0), 1); - cv::putText(m_image_draw, std::to_string(ratio), p1, 1, 1.0, cv::Scalar(0, 255, 0)); + cv::Point p1(roi.x, roi.y); + cv::Point p2(roi.x + max_white_length, roi.y); + cv::line(m_image_draw, p1, p2, cv::Scalar(0, 255, 0), 1); + cv::putText(m_image_draw, std::to_string(ratio), p1, 1, 1.0, cv::Scalar(0, 255, 0)); #endif // ASST_DEBUG - } + } } void asst::InfrastOperImageAnalyzer::face_hash_analyze() { - LogTraceFunction; + LogTraceFunction; - const Rect hash_rect_move = Task.get("InfrastOperFaceHash")->rect_move; + const Rect hash_rect_move = m_task_data->get("InfrastOperFaceHash")->rect_move; - HashImageAnalyzer hash_analyzer(m_image); - for (auto&& oper : m_result) { - Rect roi = oper.smiley.rect.move(hash_rect_move); - hash_analyzer.set_roi(roi); - hash_analyzer.analyze(); - oper.face_hash = hash_analyzer.get_hash().front(); - } + HashImageAnalyzer hash_analyzer(m_image); + for (auto&& oper : m_result) { + Rect roi = oper.smiley.rect.move(hash_rect_move); + hash_analyzer.set_roi(roi); + hash_analyzer.analyze(); + oper.face_hash = hash_analyzer.get_hash().front(); + } } void asst::InfrastOperImageAnalyzer::name_hash_analyze() { - LogTraceFunction; + LogTraceFunction; - const auto task_ptr = std::dynamic_pointer_cast( - Task.get("InfrastOperNameHash")); + const auto task_ptr = std::dynamic_pointer_cast( + m_task_data->get("InfrastOperNameHash")); - HashImageAnalyzer hash_analyzer(m_image); - hash_analyzer.set_mask_range(task_ptr->mask_range); - hash_analyzer.set_need_bound(true); - for (auto&& oper : m_result) { - Rect roi = oper.smiley.rect.move(task_ptr->rect_move); - hash_analyzer.set_roi(roi); - hash_analyzer.analyze(); - oper.name_hash = hash_analyzer.get_hash().front(); - } + HashImageAnalyzer hash_analyzer(m_image); + hash_analyzer.set_mask_range(task_ptr->mask_range); + hash_analyzer.set_need_bound(true); + for (auto&& oper : m_result) { + Rect roi = oper.smiley.rect.move(task_ptr->rect_move); + hash_analyzer.set_roi(roi); + hash_analyzer.analyze(); + oper.name_hash = hash_analyzer.get_hash().front(); + } } void asst::InfrastOperImageAnalyzer::skill_analyze() { - LogTraceFunction; + LogTraceFunction; - const auto task_ptr = std::dynamic_pointer_cast( - Task.get("InfrastSkills")); - const auto bright_thres = task_ptr->special_threshold; + const auto task_ptr = std::dynamic_pointer_cast( + m_task_data->get("InfrastSkills")); + const auto bright_thres = task_ptr->special_threshold; - MatchImageAnalyzer skill_analyzer(m_image); - skill_analyzer.set_mask_range(task_ptr->mask_range); - skill_analyzer.set_threshold(task_ptr->templ_threshold); + MatchImageAnalyzer skill_analyzer(m_image); + skill_analyzer.set_mask_range(task_ptr->mask_range); + skill_analyzer.set_threshold(task_ptr->templ_threshold); - for (auto&& oper : m_result) { - Rect roi = task_ptr->rect_move; - roi.x += oper.smiley.rect.x; - roi.y += oper.smiley.rect.y; + for (auto&& oper : m_result) { + Rect roi = task_ptr->rect_move; + roi.x += oper.smiley.rect.x; + roi.y += oper.smiley.rect.y; - // roi里面是干员的所有技能(两个技能),这里先分别裁剪出来 - static int skill_width = roi.height; - static int spacing = (roi.width - roi.height * MaxNumOfSkills) / (MaxNumOfSkills - 1); - static cv::Mat mask; - if (mask.empty()) { - mask = cv::Mat(skill_width, skill_width, CV_8UC1, cv::Scalar(0)); - int radius = skill_width / 2; - cv::circle(mask, cv::Point(radius, radius), radius, cv::Scalar(255, 255, 255), -1); - } + // roi里面是干员的所有技能(两个技能),这里先分别裁剪出来 + static int skill_width = roi.height; + static int spacing = (roi.width - roi.height * MaxNumOfSkills) / (MaxNumOfSkills - 1); + static cv::Mat mask; + if (mask.empty()) { + mask = cv::Mat(skill_width, skill_width, CV_8UC1, cv::Scalar(0)); + int radius = skill_width / 2; + cv::circle(mask, cv::Point(radius, radius), radius, cv::Scalar(255, 255, 255), -1); + } - cv::Mat all_skills_img = m_image(utils::make_rect(roi)); - std::string log_str = "[ "; - for (int i = 0; i != MaxNumOfSkills; ++i) { - int x = i * skill_width + spacing * i; - Rect skill_rect_in_roi(x, 0, skill_width, roi.height); - cv::Mat skill_image = all_skills_img(utils::make_rect(skill_rect_in_roi)); + cv::Mat all_skills_img = m_image(utils::make_rect(roi)); + std::string log_str = "[ "; + for (int i = 0; i != MaxNumOfSkills; ++i) { + int x = i * skill_width + spacing * i; + Rect skill_rect_in_roi(x, 0, skill_width, roi.height); + cv::Mat skill_image = all_skills_img(utils::make_rect(skill_rect_in_roi)); - // 过滤掉亮度阈值不够的,说明是暗的技能(不是当前设施的技能) - cv::Mat skill_gray; - cv::cvtColor(skill_image, skill_gray, cv::COLOR_BGR2GRAY); - cv::Scalar avg = cv::mean(skill_gray, mask); - if (avg[0] < bright_thres) { - continue; - } - Rect skill_rect = skill_rect_in_roi; - skill_rect.x += roi.x; - skill_rect.y += roi.y; + // 过滤掉亮度阈值不够的,说明是暗的技能(不是当前设施的技能) + cv::Mat skill_gray; + cv::cvtColor(skill_image, skill_gray, cv::COLOR_BGR2GRAY); + cv::Scalar avg = cv::mean(skill_gray, mask); + if (avg[0] < bright_thres) { + continue; + } + Rect skill_rect = skill_rect_in_roi; + skill_rect.x += roi.x; + skill_rect.y += roi.y; #ifdef ASST_DEBUG - cv::rectangle(m_image_draw, utils::make_rect(skill_rect), cv::Scalar(0, 255, 0), 2); + cv::rectangle(m_image_draw, utils::make_rect(skill_rect), cv::Scalar(0, 255, 0), 2); #endif - // 针对裁剪出来的每个技能进行识别 - skill_analyzer.set_roi(skill_rect); + // 针对裁剪出来的每个技能进行识别 + skill_analyzer.set_roi(skill_rect); - std::vector> possible_skills; - // 逐个该设施内所有可能的技能,取得分最高的 - for (const auto& [id, skill] : Resrc.infrast().get_skills(m_facility)) { - skill_analyzer.set_templ_name(skill.templ_name); + std::vector> possible_skills; + // 逐个该设施内所有可能的技能,取得分最高的 + for (const auto& [id, skill] : Resrc.infrast().get_skills(m_facility)) { + skill_analyzer.set_templ_name(skill.templ_name); - if (!skill_analyzer.analyze()) { - continue; - } - possible_skills.emplace_back(std::make_pair(skill, skill_analyzer.get_result())); - } - if (possible_skills.empty()) { - Log.error("skill has no recognition result"); - continue; - } - // 可能的结果多于1个,只可能是同一个技能不同等级的结果 - // 例如:标准化a、标准化b,这两个模板非常像,然后分数都超过了阈值 - // 如果原图是标准化a,是不可能匹配上标准化b的模板的,因为b的模板左半边多了半个环 - // 相反如果原图是标准化b,却有可能匹配上标准化a的模板,因为a的模板右半边的环,b的原图中也有 - // 所以如果结果是同类型的,只需要取里面等级最高的那个即可 - infrast::Skill most_confident_skills; - if (possible_skills.size() == 1) { - most_confident_skills = possible_skills.front().first; - } - else if (possible_skills.size() > 1) { - // 匹配得分最高的id作为基准,排除有识别错误,其他的技能混进来了的情况 - // 即排除容器中,除了有同一个技能的不同等级,还有别的技能的情况 - auto max_iter = std::max_element( - possible_skills.begin(), possible_skills.end(), - [](const auto& lhs, const auto& rhs) -> bool { - return lhs.second.score < rhs.second.score; - }); - double base_score = max_iter->second.score; - std::string base_id = max_iter->first.id; - size_t level_pos = 0; - // 倒着找,第一个不是数字的。前面就是技能基础id名字,后面的数字就是技能等级 - for (size_t j = base_id.size() - 1; j != 0; --j) { - if (!std::isdigit(base_id.at(j))) { - level_pos = j + 1; - break; - } - } - base_id = base_id.substr(0, level_pos); - std::string max_level; - for (const auto& [skill, skill_mr] : possible_skills) { - // 得分差距过大的,直接忽略 - if (base_score - skill_mr.score > 0.05) { - continue; - } - if (size_t find_pos = skill.id.find(base_id); - find_pos != std::string::npos) { - std::string cur_skill_level = skill.id.substr(base_id.size()); - if (max_level.empty() || cur_skill_level > max_level) { - max_level = cur_skill_level; - most_confident_skills = skill; - } - } // 这里对应的else就是上述的其他技能混进来了的情况 - } - } - Log.trace(most_confident_skills.id, most_confident_skills.names.front()); - std::string skill_id = most_confident_skills.id; - log_str += skill_id + " - " + most_confident_skills.names.front() + "; "; + if (!skill_analyzer.analyze()) { + continue; + } + possible_skills.emplace_back(std::make_pair(skill, skill_analyzer.get_result())); + } + if (possible_skills.empty()) { + Log.error("skill has no recognition result"); + continue; + } + // 可能的结果多于1个,只可能是同一个技能不同等级的结果 + // 例如:标准化a、标准化b,这两个模板非常像,然后分数都超过了阈值 + // 如果原图是标准化a,是不可能匹配上标准化b的模板的,因为b的模板左半边多了半个环 + // 相反如果原图是标准化b,却有可能匹配上标准化a的模板,因为a的模板右半边的环,b的原图中也有 + // 所以如果结果是同类型的,只需要取里面等级最高的那个即可 + infrast::Skill most_confident_skills; + if (possible_skills.size() == 1) { + most_confident_skills = possible_skills.front().first; + } + else if (possible_skills.size() > 1) { + // 匹配得分最高的id作为基准,排除有识别错误,其他的技能混进来了的情况 + // 即排除容器中,除了有同一个技能的不同等级,还有别的技能的情况 + auto max_iter = std::max_element( + possible_skills.begin(), possible_skills.end(), + [](const auto& lhs, const auto& rhs) -> bool { + return lhs.second.score < rhs.second.score; + }); + double base_score = max_iter->second.score; + std::string base_id = max_iter->first.id; + size_t level_pos = 0; + // 倒着找,第一个不是数字的。前面就是技能基础id名字,后面的数字就是技能等级 + for (size_t j = base_id.size() - 1; j != 0; --j) { + if (!std::isdigit(base_id.at(j))) { + level_pos = j + 1; + break; + } + } + base_id = base_id.substr(0, level_pos); + std::string max_level; + for (const auto& [skill, skill_mr] : possible_skills) { + // 得分差距过大的,直接忽略 + if (base_score - skill_mr.score > 0.05) { + continue; + } + if (size_t find_pos = skill.id.find(base_id); + find_pos != std::string::npos) { + std::string cur_skill_level = skill.id.substr(base_id.size()); + if (max_level.empty() || cur_skill_level > max_level) { + max_level = cur_skill_level; + most_confident_skills = skill; + } + } // 这里对应的else就是上述的其他技能混进来了的情况 + } + } + Log.trace(most_confident_skills.id, most_confident_skills.names.front()); + std::string skill_id = most_confident_skills.id; + log_str += skill_id + " - " + most_confident_skills.names.front() + "; "; #ifdef ASST_DEBUG - cv::Mat skill_mat = m_image(utils::make_rect(skill_rect)); + cv::Mat skill_mat = m_image(utils::make_rect(skill_rect)); #endif - oper.skills.emplace(std::move(most_confident_skills)); - } - if (!oper.skills.empty()) { - ++m_num_of_opers_with_skills; - } - Log.trace(log_str, "]"); - } + oper.skills.emplace(std::move(most_confident_skills)); + } + if (!oper.skills.empty()) { + ++m_num_of_opers_with_skills; + } + Log.trace(log_str, "]"); + } } void asst::InfrastOperImageAnalyzer::selected_analyze() { - LogTraceFunction; + LogTraceFunction; - const auto selected_task_ptr = std::dynamic_pointer_cast( - Task.get("InfrastOperSelected")); - Rect rect_move = selected_task_ptr->rect_move; + const auto selected_task_ptr = std::dynamic_pointer_cast( + m_task_data->get("InfrastOperSelected")); + Rect rect_move = selected_task_ptr->rect_move; - for (auto&& oper : m_result) { - Rect selected_rect = rect_move; - selected_rect.x += oper.smiley.rect.x; - selected_rect.y += oper.smiley.rect.y; + for (auto&& oper : m_result) { + Rect selected_rect = rect_move; + selected_rect.x += oper.smiley.rect.x; + selected_rect.y += oper.smiley.rect.y; - cv::Mat roi = m_image(utils::make_rect(selected_rect)); - cv::Mat hsv, bin; - cv::cvtColor(roi, hsv, cv::COLOR_BGR2HSV); - std::vector channels; - cv::split(hsv, channels); - int mask_lowb = selected_task_ptr->mask_range.first; - int mask_uppb = selected_task_ptr->mask_range.second; + cv::Mat roi = m_image(utils::make_rect(selected_rect)); + cv::Mat hsv, bin; + cv::cvtColor(roi, hsv, cv::COLOR_BGR2HSV); + std::vector channels; + cv::split(hsv, channels); + int mask_lowb = selected_task_ptr->mask_range.first; + int mask_uppb = selected_task_ptr->mask_range.second; - int count = 0; - auto& h_channel = channels.at(0); - for (int i = 0; i != h_channel.rows; ++i) { - for (int j = 0; j != h_channel.cols; ++j) { - cv::uint8_t value = h_channel.at(i, j); - if (mask_lowb < value && value < mask_uppb) { - ++count; - } - } - } - Log.trace("selected_analyze |", count); - oper.selected = count >= selected_task_ptr->templ_threshold; - oper.rect = selected_rect; // 先凑合用( - } + int count = 0; + auto& h_channel = channels.at(0); + for (int i = 0; i != h_channel.rows; ++i) { + for (int j = 0; j != h_channel.cols; ++j) { + cv::uint8_t value = h_channel.at(i, j); + if (mask_lowb < value && value < mask_uppb) { + ++count; + } + } + } + Log.trace("selected_analyze |", count); + oper.selected = count >= selected_task_ptr->templ_threshold; + oper.rect = selected_rect; // 先凑合用( + } } void asst::InfrastOperImageAnalyzer::doing_analyze() { - LogTraceFunction; + LogTraceFunction; - const auto working_task_ptr = Task.get("InfrastOperOnShift"); - Rect rect_move = working_task_ptr->rect_move; + const auto working_task_ptr = m_task_data->get("InfrastOperOnShift"); + Rect rect_move = working_task_ptr->rect_move; - MatchImageAnalyzer working_analyzer(m_image); - working_analyzer.set_task_info(working_task_ptr); + MatchImageAnalyzer working_analyzer(m_image); + working_analyzer.set_task_info(working_task_ptr); - for (auto&& oper : m_result) { - Rect working_rect = rect_move; - working_rect.x += oper.smiley.rect.x; - working_rect.y += oper.smiley.rect.y; - working_analyzer.set_roi(working_rect); - if (working_analyzer.analyze()) { - oper.doing = infrast::Doing::Working; + for (auto&& oper : m_result) { + Rect working_rect = rect_move; + working_rect.x += oper.smiley.rect.x; + working_rect.y += oper.smiley.rect.y; + working_analyzer.set_roi(working_rect); + if (working_analyzer.analyze()) { + oper.doing = infrast::Doing::Working; #ifdef ASST_DEBUG - cv::putText(m_image_draw, "Working", cv::Point(working_rect.x, working_rect.y), 1, 1, cv::Scalar(0, 0, 255), 2); + cv::putText(m_image_draw, "Working", cv::Point(working_rect.x, working_rect.y), 1, 1, cv::Scalar(0, 0, 255), 2); #endif - } - // TODO: infrast::Doing::Resting的识别 - } -} + } + // TODO: infrast::Doing::Resting的识别 + } +} \ No newline at end of file diff --git a/src/MeoAssistant/InfrastProductionTask.cpp b/src/MeoAssistant/InfrastProductionTask.cpp index a215e74365..fffcb6da80 100644 --- a/src/MeoAssistant/InfrastProductionTask.cpp +++ b/src/MeoAssistant/InfrastProductionTask.cpp @@ -40,12 +40,12 @@ bool asst::InfrastProductionTask::shift_facility_list() if (!facility_list_detect() || need_exit()) { return false; } - const auto tab_task_ptr = Task.get("InfrastFacilityListTab" + facility_name()); + const auto tab_task_ptr = m_task_data->get("InfrastFacilityListTab" + facility_name()); MatchImageAnalyzer add_analyzer; - const auto add_task_ptr = Task.get("InfrastAddOperator" + facility_name() + m_work_mode_name); + const auto add_task_ptr = m_task_data->get("InfrastAddOperator" + facility_name() + m_work_mode_name); add_analyzer.set_task_info(add_task_ptr); MultiMatchImageAnalyzer locked_analyzer; - locked_analyzer.set_task_info("InfrastOperLocked" + facility_name()); + locked_analyzer.set_task_info(StaticTaskData::get_instance().get("InfrastOperLocked" + facility_name())); for (; m_cur_facility_index < m_facility_list_tabs.size(); ++m_cur_facility_index) { Rect tab = m_facility_list_tabs.at(m_cur_facility_index); @@ -82,7 +82,7 @@ bool asst::InfrastProductionTask::shift_facility_list() std::string cur_product = all_products.at(0); double max_score = 0; for (const std::string& product : all_products) { - product_analyzer.set_task_info("InfrastFlag" + product); + product_analyzer.set_task_info(StaticTaskData::get_instance().get("InfrastFlag" + product)); if (product_analyzer.analyze()) { double score = product_analyzer.get_result().score; if (score > max_score) { @@ -188,7 +188,7 @@ size_t asst::InfrastProductionTask::opers_detect() max_num_of_opers_per_page = (std::max)(max_num_of_opers_per_page, cur_all_opers.size()); const int face_hash_thres = std::dynamic_pointer_cast( - Task.get("InfrastOperFaceHash"))->dist_threshold; + m_task_data->get("InfrastOperFaceHash"))->dist_threshold; int cur_available_num = static_cast(cur_all_opers.size()); for (const auto& cur_oper : cur_all_opers) { if (cur_oper.skills.empty()) { @@ -292,7 +292,7 @@ bool asst::InfrastProductionTask::optimal_calc() } const int name_hash_thres = std::dynamic_pointer_cast( - Task.get("InfrastOperNameHash"))->dist_threshold; + m_task_data->get("InfrastOperNameHash"))->dist_threshold; // 遍历所有组合,找到效率最高的 auto& all_group = Resrc.infrast().get_skills_group(facility_name()); @@ -306,11 +306,12 @@ bool asst::InfrastProductionTask::optimal_calc() // 条件判断,不符合的直接过滤掉 bool meet_condition = true; for (const auto& [cond, cond_value] : group.conditions) { - if (!m_status->contains_data(cond)) { + auto cond_opt = m_status->get_data(cond); + if (!cond_opt) { continue; } // TODO:这里做成除了不等于,还可计算大于、小于等不同条件的 - int cur_value = static_cast(m_status->get_data(cond)); + int cur_value = static_cast(cond_opt.value()); if (cur_value != cond_value) { meet_condition = false; break; @@ -451,9 +452,9 @@ bool asst::InfrastProductionTask::opers_choose() int cur_max_num_of_opers = facility_info.max_num_of_opers - m_cur_num_of_lokced_opers; const int name_hash_thres = std::dynamic_pointer_cast( - Task.get("InfrastOperNameHash"))->dist_threshold; + m_task_data->get("InfrastOperNameHash"))->dist_threshold; const int face_hash_thres = std::dynamic_pointer_cast( - Task.get("InfrastOperFaceHash"))->dist_threshold; + m_task_data->get("InfrastOperFaceHash"))->dist_threshold; while (true) { if (need_exit()) { return false; @@ -600,7 +601,8 @@ asst::InfrastProductionTask::efficient_regex_calc( // TODO 报错! } std::string status_key = cur_formula.substr(pos + 1, rp_pos - pos - 1); - int64_t status_value = m_status->get_data(status_key); + auto status_opt = m_status->get_data(status_key); + const int64_t status_value = status_opt ? status_opt.value() : 0; cur_formula.replace(pos, rp_pos - pos + 1, std::to_string(status_value)); } @@ -617,7 +619,7 @@ bool asst::InfrastProductionTask::facility_list_detect() const auto image = m_ctrler->get_image(); MultiMatchImageAnalyzer mm_analyzer(image); - mm_analyzer.set_task_info("InfrastFacilityListTab" + facility_name()); + mm_analyzer.set_task_info(StaticTaskData::get_instance().get("InfrastFacilityListTab" + facility_name())); if (!mm_analyzer.analyze()) { return false; diff --git a/src/MeoAssistant/InfrastReceptionTask.cpp b/src/MeoAssistant/InfrastReceptionTask.cpp index f464f697d4..36dc7fe863 100644 --- a/src/MeoAssistant/InfrastReceptionTask.cpp +++ b/src/MeoAssistant/InfrastReceptionTask.cpp @@ -10,179 +10,179 @@ bool asst::InfrastReceptionTask::_run() { - m_all_available_opers.clear(); + m_all_available_opers.clear(); - swipe_to_the_right_of_main_ui(); - enter_facility(); - click_bottomleft_tab(); + swipe_to_the_right_of_main_ui(); + enter_facility(); + click_bottomleft_tab(); - close_end_of_clue_exchange(); + close_end_of_clue_exchange(); - get_clue(); - if (need_exit()) { - return false; - } - use_clue(); - if (need_exit()) { - return false; - } - click_return_button(); - click_bottomleft_tab(); - if (need_exit()) { - return false; - } - shift(); + get_clue(); + if (need_exit()) { + return false; + } + use_clue(); + if (need_exit()) { + return false; + } + click_return_button(); + click_bottomleft_tab(); + if (need_exit()) { + return false; + } + shift(); - return true; + return true; } bool asst::InfrastReceptionTask::close_end_of_clue_exchange() { - ProcessTask task_temp(*this, { "ReceptionFlag", "EndOfClueExchange" }); - return task_temp.run(); + ProcessTask task_temp(*this, { "ReceptionFlag", "EndOfClueExchange" }); + return task_temp.run(); } bool asst::InfrastReceptionTask::get_clue() { - ProcessTask task_temp(*this, { "InfrastClueSelfNew", "InfrastClueFriendNew", "InfrastClueSelfMaybeFull", "ReceptionFlag" }); - return task_temp.run(); + ProcessTask task_temp(*this, { "InfrastClueSelfNew", "InfrastClueFriendNew", "InfrastClueSelfMaybeFull", "ReceptionFlag" }); + return task_temp.run(); } bool asst::InfrastReceptionTask::use_clue() { - LogTraceFunction; - const static std::string clue_vacancy = "InfrastClueVacancy"; - const static std::vector clue_suffix = { - "No1", "No2", "No3", "No4", "No5", "No6", "No7" - }; + LogTraceFunction; + const static std::string clue_vacancy = "InfrastClueVacancy"; + const static std::vector clue_suffix = { + "No1", "No2", "No3", "No4", "No5", "No6", "No7" + }; - proc_clue_vacancy(); - if (unlock_clue_exchange()) { - proc_clue_vacancy(); - } + proc_clue_vacancy(); + if (unlock_clue_exchange()) { + proc_clue_vacancy(); + } - cv::Mat image = m_ctrler->get_image(); + cv::Mat image = m_ctrler->get_image(); - // 所有的空位分析一次,看看还缺哪些线索 - InfrastClueVacancyImageAnalyzer vacancy_analyzer(image); - vacancy_analyzer.set_to_be_analyzed(clue_suffix); - if (!vacancy_analyzer.analyze()) { - } - const auto& vacancy = vacancy_analyzer.get_vacancy(); - for (auto&& [id, _] : vacancy) { - Log.trace("InfrastReceptionTask | Vacancy", id); - } + // 所有的空位分析一次,看看还缺哪些线索 + InfrastClueVacancyImageAnalyzer vacancy_analyzer(image); + vacancy_analyzer.set_to_be_analyzed(clue_suffix); + if (!vacancy_analyzer.analyze()) { + } + const auto& vacancy = vacancy_analyzer.get_vacancy(); + for (auto&& [id, _] : vacancy) { + Log.trace("InfrastReceptionTask | Vacancy", id); + } - std::string product; - if (vacancy.size() == 1) { - product = vacancy.begin()->first; - } - else { - product = "General"; - } - Log.trace("InfrastReceptionTask | product", product); - set_product(product); + std::string product; + if (vacancy.size() == 1) { + product = vacancy.begin()->first; + } + else { + product = "General"; + } + Log.trace("InfrastReceptionTask | product", product); + set_product(product); - return true; + return true; } bool asst::InfrastReceptionTask::proc_clue_vacancy() { - LogTraceFunction; - const static std::string clue_vacancy = "InfrastClueVacancy"; - const static std::vector clue_suffix = { - "No1", "No2", "No3", "No4", "No5", "No6", "No7" - }; + LogTraceFunction; + const static std::string clue_vacancy = "InfrastClueVacancy"; + const static std::vector clue_suffix = { + "No1", "No2", "No3", "No4", "No5", "No6", "No7" + }; - cv::Mat image = m_ctrler->get_image(); - for (const std::string& clue : clue_suffix) { - if (need_exit()) { - return false; - } - // 先识别线索的空位 - InfrastClueVacancyImageAnalyzer vacancy_analyzer(image); - vacancy_analyzer.set_to_be_analyzed({ clue }); - if (!vacancy_analyzer.analyze()) { - continue; - } - // 点开线索的空位 - Rect vacancy = vacancy_analyzer.get_vacancy().cbegin()->second; - m_ctrler->click(vacancy); - int delay = Task.get(clue_vacancy + clue)->rear_delay; - sleep(delay); + cv::Mat image = m_ctrler->get_image(); + for (const std::string& clue : clue_suffix) { + if (need_exit()) { + return false; + } + // 先识别线索的空位 + InfrastClueVacancyImageAnalyzer vacancy_analyzer(image); + vacancy_analyzer.set_to_be_analyzed({ clue }); + if (!vacancy_analyzer.analyze()) { + continue; + } + // 点开线索的空位 + Rect vacancy = vacancy_analyzer.get_vacancy().cbegin()->second; + m_ctrler->click(vacancy); + int delay = m_task_data->get(clue_vacancy + clue)->rear_delay; + sleep(delay); - // 识别右边列表中的线索,然后用最底下的那个(一般都是剩余时间最短的) - //swipe_to_the_bottom_of_clue_list_on_the_right(); - image = m_ctrler->get_image(); - InfrastClueImageAnalyzer clue_analyzer(image); - if (!clue_analyzer.analyze()) { - continue; - } - m_ctrler->click(clue_analyzer.get_result().back().first); - sleep(delay); - } - return true; + // 识别右边列表中的线索,然后用最底下的那个(一般都是剩余时间最短的) + //swipe_to_the_bottom_of_clue_list_on_the_right(); + image = m_ctrler->get_image(); + InfrastClueImageAnalyzer clue_analyzer(image); + if (!clue_analyzer.analyze()) { + continue; + } + m_ctrler->click(clue_analyzer.get_result().back().first); + sleep(delay); + } + return true; } bool asst::InfrastReceptionTask::unlock_clue_exchange() { - ProcessTask task(*this, { "UnlockClues" }); - task.set_retry_times(2); - return task.run(); + ProcessTask task(*this, { "UnlockClues" }); + task.set_retry_times(2); + return task.run(); } bool asst::InfrastReceptionTask::send_clue() { - ProcessTask task(*this, { "SendClues" }); - return task.run(); + ProcessTask task(*this, { "SendClues" }); + return task.run(); } bool asst::InfrastReceptionTask::shift() { - LogTraceFunction; - const auto image = m_ctrler->get_image(); - MatchImageAnalyzer add_analyzer(image); + LogTraceFunction; + const auto image = m_ctrler->get_image(); + MatchImageAnalyzer add_analyzer(image); - const auto raw_task_ptr = Task.get("InfrastAddOperator" + facility_name() + m_work_mode_name); - switch (raw_task_ptr->algorithm) { - case AlgorithmType::JustReturn: - if (raw_task_ptr->action == ProcessTaskAction::ClickRect) { - m_ctrler->click(raw_task_ptr->specific_rect); - } - break; - case AlgorithmType::MatchTemplate: { - add_analyzer.set_task_info(raw_task_ptr); + const auto raw_task_ptr = m_task_data->get("InfrastAddOperator" + facility_name() + m_work_mode_name); + switch (raw_task_ptr->algorithm) { + case AlgorithmType::JustReturn: + if (raw_task_ptr->action == ProcessTaskAction::ClickRect) { + m_ctrler->click(raw_task_ptr->specific_rect); + } + break; + case AlgorithmType::MatchTemplate: { + add_analyzer.set_task_info(raw_task_ptr); - if (!add_analyzer.analyze()) { - return true; - } - m_ctrler->click(add_analyzer.get_result().rect); - } break; - default: - break; - } - sleep(raw_task_ptr->rear_delay); + if (!add_analyzer.analyze()) { + return true; + } + m_ctrler->click(add_analyzer.get_result().rect); + } break; + default: + break; + } + sleep(raw_task_ptr->rear_delay); - for (int i = 0; i <= OperSelectRetryTimes; ++i) { - if (need_exit()) { - return false; - } - click_clear_button(); + for (int i = 0; i <= OperSelectRetryTimes; ++i) { + if (need_exit()) { + return false; + } + click_clear_button(); - if (!opers_detect_with_swipe()) { - return false; - } - swipe_to_the_left_of_operlist(); + if (!opers_detect_with_swipe()) { + return false; + } + swipe_to_the_left_of_operlist(); - optimal_calc(); - bool ret = opers_choose(); - if (!ret) { - m_all_available_opers.clear(); - swipe_to_the_left_of_operlist(); - continue; - } - break; - } - click_confirm_button(); - return true; -} + optimal_calc(); + bool ret = opers_choose(); + if (!ret) { + m_all_available_opers.clear(); + swipe_to_the_left_of_operlist(); + continue; + } + break; + } + click_confirm_button(); + return true; +} \ No newline at end of file diff --git a/src/MeoAssistant/InfrastSmileyImageAnalyzer.cpp b/src/MeoAssistant/InfrastSmileyImageAnalyzer.cpp index 4a15e873ef..b690d06617 100644 --- a/src/MeoAssistant/InfrastSmileyImageAnalyzer.cpp +++ b/src/MeoAssistant/InfrastSmileyImageAnalyzer.cpp @@ -18,7 +18,7 @@ bool asst::InfrastSmileyImageAnalyzer::analyze() decltype(m_result) temp_result; for (const auto& [type, task_name] : smiley_map) { - mm_analyzer.set_task_info(task_name); + mm_analyzer.set_task_info(StaticTaskData::get_instance().get(task_name)); mm_analyzer.set_roi(m_roi); if (!mm_analyzer.analyze()) { continue; diff --git a/src/MeoAssistant/MatchImageAnalyzer.cpp b/src/MeoAssistant/MatchImageAnalyzer.cpp index b10b682583..daea614fe3 100644 --- a/src/MeoAssistant/MatchImageAnalyzer.cpp +++ b/src/MeoAssistant/MatchImageAnalyzer.cpp @@ -52,11 +52,6 @@ void asst::MatchImageAnalyzer::set_task_info(std::shared_ptr task_ptr) set_task_info(*std::dynamic_pointer_cast(task_ptr)); } -void asst::MatchImageAnalyzer::set_task_info(const std::string& task_name) -{ - set_task_info(Task.get(task_name)); -} - void asst::MatchImageAnalyzer::set_region_of_appeared(Rect region) noexcept { m_region_of_appeared = std::move(region); diff --git a/src/MeoAssistant/MatchImageAnalyzer.h b/src/MeoAssistant/MatchImageAnalyzer.h index f057d1bb56..037814cc56 100644 --- a/src/MeoAssistant/MatchImageAnalyzer.h +++ b/src/MeoAssistant/MatchImageAnalyzer.h @@ -18,7 +18,6 @@ namespace asst void set_templ_name(std::string templ_name) noexcept; void set_threshold(double templ_thres) noexcept; void set_task_info(std::shared_ptr task_ptr); - void set_task_info(const std::string& task_name); void set_region_of_appeared(Rect region) noexcept; const MatchRect& get_result() const noexcept; diff --git a/src/MeoAssistant/MeoAssistant.vcxproj b/src/MeoAssistant/MeoAssistant.vcxproj index e4c178d928..a01c444ea5 100644 --- a/src/MeoAssistant/MeoAssistant.vcxproj +++ b/src/MeoAssistant/MeoAssistant.vcxproj @@ -12,16 +12,17 @@ - + + - + @@ -117,7 +118,7 @@ - + diff --git a/src/MeoAssistant/MeoAssistant.vcxproj.filters b/src/MeoAssistant/MeoAssistant.vcxproj.filters index 4248c60706..4332e8717b 100644 --- a/src/MeoAssistant/MeoAssistant.vcxproj.filters +++ b/src/MeoAssistant/MeoAssistant.vcxproj.filters @@ -84,7 +84,7 @@ 头文件\Resource - + 头文件\Utils @@ -99,9 +99,6 @@ 头文件\Caller - - 头文件\Caller - 头文件\Task @@ -252,6 +249,12 @@ 头文件\Resource + + 头文件\Caller + + + 头文件\Caller + @@ -407,7 +410,7 @@ 源文件\TaskPlugin - + 源文件\TaskPlugin diff --git a/src/MeoAssistant/MultiMatchImageAnalyzer.cpp b/src/MeoAssistant/MultiMatchImageAnalyzer.cpp index 18dd2e9161..55a2a6c2a5 100644 --- a/src/MeoAssistant/MultiMatchImageAnalyzer.cpp +++ b/src/MeoAssistant/MultiMatchImageAnalyzer.cpp @@ -73,11 +73,6 @@ void asst::MultiMatchImageAnalyzer::set_task_info(std::shared_ptr task set_task_info(*std::dynamic_pointer_cast(task_ptr)); } -void asst::MultiMatchImageAnalyzer::set_task_info(const std::string& task_name) -{ - set_task_info(Task.get(task_name)); -} - const std::vector& asst::MultiMatchImageAnalyzer::get_result() const noexcept { return m_result; diff --git a/src/MeoAssistant/MultiMatchImageAnalyzer.h b/src/MeoAssistant/MultiMatchImageAnalyzer.h index 2919a0afe9..874bb11426 100644 --- a/src/MeoAssistant/MultiMatchImageAnalyzer.h +++ b/src/MeoAssistant/MultiMatchImageAnalyzer.h @@ -20,7 +20,6 @@ namespace asst void set_threshold(double templ_thres) noexcept; void set_task_info(std::shared_ptr task_ptr); - void set_task_info(const std::string& task_name); const std::vector& get_result() const noexcept; diff --git a/src/MeoAssistant/OcrImageAnalyzer.cpp b/src/MeoAssistant/OcrImageAnalyzer.cpp index b27da36ca2..69748fb060 100644 --- a/src/MeoAssistant/OcrImageAnalyzer.cpp +++ b/src/MeoAssistant/OcrImageAnalyzer.cpp @@ -111,11 +111,6 @@ void asst::OcrImageAnalyzer::set_task_info(std::shared_ptr task_ptr) set_task_info(*std::dynamic_pointer_cast(task_ptr)); } -void asst::OcrImageAnalyzer::set_task_info(const std::string& task_name) -{ - set_task_info(Task.get(task_name)); -} - void asst::OcrImageAnalyzer::set_region_of_appeared(Rect region) noexcept { m_region_of_appeared = std::move(region); @@ -164,5 +159,5 @@ void asst::OcrImageAnalyzer::sort_result_by_required() std::sort(m_ocr_result.begin(), m_ocr_result.end(), [&m_req_cache](const auto& lhs, const auto& rhs) -> bool { return m_req_cache[lhs.text] < m_req_cache[rhs.text]; - }); + }); } diff --git a/src/MeoAssistant/OcrImageAnalyzer.h b/src/MeoAssistant/OcrImageAnalyzer.h index cf6b97fc11..12aae9e633 100644 --- a/src/MeoAssistant/OcrImageAnalyzer.h +++ b/src/MeoAssistant/OcrImageAnalyzer.h @@ -5,7 +5,7 @@ #include #include -#include "AsstDef.h" +#include "AsstTypes.h" namespace asst { @@ -24,7 +24,6 @@ namespace asst void set_required(std::vector required, bool full_match = false) noexcept; void set_replace(std::unordered_map replace) noexcept; void set_task_info(std::shared_ptr task_ptr); - void set_task_info(const std::string& task_name); void set_region_of_appeared(Rect region) noexcept; void set_pred(const TextRectProc& pred); diff --git a/src/MeoAssistant/OcrPack.h b/src/MeoAssistant/OcrPack.h index 2214d077f8..2458c27a0a 100644 --- a/src/MeoAssistant/OcrPack.h +++ b/src/MeoAssistant/OcrPack.h @@ -3,28 +3,28 @@ #include -#include "AsstDef.h" +#include "AsstTypes.h" namespace cv { - class Mat; + class Mat; } struct paddle_ocr_t; namespace asst { - class OcrPack final : public AbstractResource - { - public: - using AbstractResource::AbstractResource; - virtual ~OcrPack(); + class OcrPack final : public AbstractResource + { + public: + using AbstractResource::AbstractResource; + virtual ~OcrPack(); - virtual bool load(const std::string& dir) override; + virtual bool load(const std::string& dir) override; - std::vector recognize(const cv::Mat image, const TextRectProc& pred = nullptr, bool without_det = false); - std::vector recognize(const cv::Mat image, const Rect& roi, const TextRectProc& pred = nullptr, bool without_det = false); + std::vector recognize(const cv::Mat image, const TextRectProc& pred = nullptr, bool without_det = false); + std::vector recognize(const cv::Mat image, const Rect& roi, const TextRectProc& pred = nullptr, bool without_det = false); - private: - paddle_ocr_t* m_ocr = nullptr; - }; + private: + paddle_ocr_t* m_ocr = nullptr; + }; } diff --git a/src/MeoAssistant/ProcessTask.cpp b/src/MeoAssistant/ProcessTask.cpp index 1934046875..27328d36fd 100644 --- a/src/MeoAssistant/ProcessTask.cpp +++ b/src/MeoAssistant/ProcessTask.cpp @@ -15,226 +15,226 @@ using namespace asst; asst::ProcessTask::ProcessTask(const AbstractTask& abs, std::vector tasks_name) - : AbstractTask(abs), - m_raw_tasks_name(std::move(tasks_name)) + : AbstractTask(abs), + m_raw_tasks_name(std::move(tasks_name)) { - m_basic_info_cache = json::value(); + m_basic_info_cache = json::value(); } asst::ProcessTask::ProcessTask(AbstractTask&& abs, std::vector tasks_name) noexcept - : AbstractTask(std::move(abs)), - m_raw_tasks_name(std::move(tasks_name)) + : AbstractTask(std::move(abs)), + m_raw_tasks_name(std::move(tasks_name)) { - m_basic_info_cache = json::value(); + m_basic_info_cache = json::value(); } bool asst::ProcessTask::run() { - m_cur_tasks_name = m_raw_tasks_name; - for (m_cur_retry = 0; m_cur_retry <= m_retry_times; ++m_cur_retry) { - if (_run()) { - return true; - } - if (need_exit()) { - return false; - } - int delay = Resrc.cfg().get_options().task_delay; - sleep(delay); + m_cur_tasks_name = m_raw_tasks_name; + for (m_cur_retry = 0; m_cur_retry <= m_retry_times; ++m_cur_retry) { + if (_run()) { + return true; + } + if (need_exit()) { + return false; + } + int delay = Resrc.cfg().get_options().task_delay; + sleep(delay); - if (!on_run_fails()) { - return false; - } - } - callback(AsstMsg::SubTaskError, basic_info()); - return false; + if (!on_run_fails()) { + return false; + } + } + callback(AsstMsg::SubTaskError, basic_info()); + return false; } asst::ProcessTask& asst::ProcessTask::set_tasks(std::vector tasks_name) noexcept { - m_raw_tasks_name = std::move(tasks_name); - return *this; + m_raw_tasks_name = std::move(tasks_name); + return *this; } ProcessTask& asst::ProcessTask::set_times_limit(std::string name, int limit) { - m_times_limit.emplace(std::move(name), limit); - return *this; + m_times_limit.emplace(std::move(name), limit); + return *this; } ProcessTask& asst::ProcessTask::set_rear_delay(std::string name, int delay) { - m_rear_delay.emplace(std::move(name), delay); - return *this; + m_rear_delay.emplace(std::move(name), delay); + return *this; } bool ProcessTask::_run() { - LogTraceFunction; + LogTraceFunction; - auto& task_delay = Resrc.cfg().get_options().task_delay; - while (!m_cur_tasks_name.empty()) { - if (need_exit()) { - return false; - } - json::value info = basic_info(); - info["details"] = json::object{ - {"to_be_recognized", json::array(m_cur_tasks_name)}, - {"cur_retry", m_cur_retry}, - {"retry_times", m_retry_times} - }; - Log.info(info.to_string()); + auto& task_delay = Resrc.cfg().get_options().task_delay; + while (!m_cur_tasks_name.empty()) { + if (need_exit()) { + return false; + } + json::value info = basic_info(); + info["details"] = json::object{ + {"to_be_recognized", json::array(m_cur_tasks_name)}, + {"cur_retry", m_cur_retry}, + {"retry_times", m_retry_times} + }; + Log.info(info.to_string()); - Rect rect; - std::shared_ptr cur_task_ptr = nullptr; + Rect rect; + std::shared_ptr cur_task_ptr = nullptr; - // 如果第一个任务是JustReturn的,那就没必要再截图并计算了 - if (auto front_task_ptr = Task.get(m_cur_tasks_name.front()); - front_task_ptr->algorithm == AlgorithmType::JustReturn) { - cur_task_ptr = front_task_ptr; - } - else { - const auto image = m_ctrler->get_image(); - ProcessTaskImageAnalyzer analyzer(image, m_cur_tasks_name); - analyzer.set_status(m_status); - if (!analyzer.analyze()) { - return false; - } - cur_task_ptr = analyzer.get_result(); - rect = analyzer.get_rect(); - } - if (need_exit()) { - return false; - } - std::string cur_name = cur_task_ptr->name; + // 如果第一个任务是JustReturn的,那就没必要再截图并计算了 + if (auto front_task_ptr = m_task_data->get(m_cur_tasks_name.front()); + front_task_ptr->algorithm == AlgorithmType::JustReturn) { + cur_task_ptr = front_task_ptr; + } + else { + const auto image = m_ctrler->get_image(); + ProcessTaskImageAnalyzer analyzer(image, m_cur_tasks_name); + analyzer.set_status(m_status); + if (!analyzer.analyze()) { + return false; + } + cur_task_ptr = analyzer.get_result(); + rect = analyzer.get_rect(); + } + if (need_exit()) { + return false; + } + std::string cur_name = cur_task_ptr->name; - const auto& res_move = cur_task_ptr->rect_move; - if (!res_move.empty()) { - rect.x += res_move.x; - rect.y += res_move.y; - rect.width = res_move.width; - rect.height = res_move.height; - } + const auto& res_move = cur_task_ptr->rect_move; + if (!res_move.empty()) { + rect.x += res_move.x; + rect.y += res_move.y; + rect.width = res_move.width; + rect.height = res_move.height; + } - int& exec_times = m_exec_times[cur_name]; + int& exec_times = m_exec_times[cur_name]; - int max_times = cur_task_ptr->max_times; - if (auto iter = m_times_limit.find(cur_name); - iter != m_times_limit.cend()) { - max_times = iter->second; - } + int max_times = cur_task_ptr->max_times; + if (auto iter = m_times_limit.find(cur_name); + iter != m_times_limit.cend()) { + max_times = iter->second; + } - if (exec_times >= max_times) { - Log.info("exec times exceeds the limit", info.to_string()); - m_cur_tasks_name = cur_task_ptr->exceeded_next; - sleep(task_delay); - continue; - } + if (exec_times >= max_times) { + Log.info("exec times exceeds the limit", info.to_string()); + m_cur_tasks_name = cur_task_ptr->exceeded_next; + sleep(task_delay); + continue; + } - m_cur_retry = 0; - ++exec_times; + m_cur_retry = 0; + ++exec_times; - info["details"] = json::object{ - { "task", cur_name }, - { "action", static_cast(cur_task_ptr->action) }, - { "exec_times", exec_times }, - { "max_times", max_times }, - { "algorithm", static_cast(cur_task_ptr->algorithm) } - }; + info["details"] = json::object{ + { "task", cur_name }, + { "action", static_cast(cur_task_ptr->action) }, + { "exec_times", exec_times }, + { "max_times", max_times }, + { "algorithm", static_cast(cur_task_ptr->algorithm) } + }; - callback(AsstMsg::SubTaskStart, info); + callback(AsstMsg::SubTaskStart, info); - // 前置固定延时 - if (!sleep(cur_task_ptr->pre_delay)) { - return false; - } + // 前置固定延时 + if (!sleep(cur_task_ptr->pre_delay)) { + return false; + } - bool need_stop = false; - switch (cur_task_ptr->action) { - case ProcessTaskAction::ClickRect: - rect = cur_task_ptr->specific_rect; - [[fallthrough]]; - case ProcessTaskAction::ClickSelf: - exec_click_task(rect); - break; - case ProcessTaskAction::ClickRand: { - auto&& [width, height] = m_ctrler->get_scale_size(); - const Rect full_rect(0, 0, width, height); - exec_click_task(full_rect); - } break; - case ProcessTaskAction::SwipeToTheLeft: - case ProcessTaskAction::SwipeToTheRight: - exec_swipe_task(cur_task_ptr->action); - break; - case ProcessTaskAction::DoNothing: - break; - case ProcessTaskAction::Stop: - Log.info("stop action", info.to_string()); - need_stop = true; - break; - default: - break; - } + bool need_stop = false; + switch (cur_task_ptr->action) { + case ProcessTaskAction::ClickRect: + rect = cur_task_ptr->specific_rect; + [[fallthrough]]; + case ProcessTaskAction::ClickSelf: + exec_click_task(rect); + break; + case ProcessTaskAction::ClickRand: { + auto&& [width, height] = m_ctrler->get_scale_size(); + const Rect full_rect(0, 0, width, height); + exec_click_task(full_rect); + } break; + case ProcessTaskAction::SwipeToTheLeft: + case ProcessTaskAction::SwipeToTheRight: + exec_swipe_task(cur_task_ptr->action); + break; + case ProcessTaskAction::DoNothing: + break; + case ProcessTaskAction::Stop: + Log.info("stop action", info.to_string()); + need_stop = true; + break; + default: + break; + } - m_status->set_data("Last" + cur_name, time(nullptr)); + m_status->set_data("Last" + cur_name, time(nullptr)); - // 减少其他任务的执行次数 - // 例如,进入吃理智药的界面了,相当于上一次点蓝色开始行动没生效 - // 所以要给蓝色开始行动的次数减一 - for (const std::string& reduce : cur_task_ptr->reduce_other_times) { - --m_exec_times[reduce]; - } + // 减少其他任务的执行次数 + // 例如,进入吃理智药的界面了,相当于上一次点蓝色开始行动没生效 + // 所以要给蓝色开始行动的次数减一 + for (const std::string& reduce : cur_task_ptr->reduce_other_times) { + --m_exec_times[reduce]; + } - // 后置固定延时 - int rear_delay = cur_task_ptr->rear_delay; - if (auto iter = m_rear_delay.find(cur_name); - iter != m_rear_delay.cend()) { - rear_delay = iter->second; - } - if (!sleep(rear_delay)) { - return false; - } + // 后置固定延时 + int rear_delay = cur_task_ptr->rear_delay; + if (auto iter = m_rear_delay.find(cur_name); + iter != m_rear_delay.cend()) { + rear_delay = iter->second; + } + if (!sleep(rear_delay)) { + return false; + } - callback(AsstMsg::SubTaskCompleted, info); + callback(AsstMsg::SubTaskCompleted, info); - if (need_stop) { - return true; - } - m_cur_tasks_name = cur_task_ptr->next; - sleep(task_delay); - } + if (need_stop) { + return true; + } + m_cur_tasks_name = cur_task_ptr->next; + sleep(task_delay); + } - return true; + return true; } void ProcessTask::exec_click_task(const Rect& matched_rect) { - m_ctrler->click(matched_rect); + m_ctrler->click(matched_rect); } void asst::ProcessTask::exec_swipe_task(ProcessTaskAction action) { - const auto&& [width, height] = m_ctrler->get_scale_size(); + const auto&& [width, height] = m_ctrler->get_scale_size(); - const static Rect right_rect( - static_cast(width * 0.8), - static_cast(height * 0.4), - static_cast(width * 0.1), - static_cast(height * 0.2)); + const static Rect right_rect( + static_cast(width * 0.8), + static_cast(height * 0.4), + static_cast(width * 0.1), + static_cast(height * 0.2)); - const static Rect left_rect( - static_cast(width * 0.1), - static_cast(height * 0.4), - static_cast(width * 0.1), - static_cast(height * 0.2)); + const static Rect left_rect( + static_cast(width * 0.1), + static_cast(height * 0.4), + static_cast(width * 0.1), + static_cast(height * 0.2)); - switch (action) { - case asst::ProcessTaskAction::SwipeToTheLeft: - m_ctrler->swipe(left_rect, right_rect); - break; - case asst::ProcessTaskAction::SwipeToTheRight: - m_ctrler->swipe(right_rect, left_rect); - break; - default: // 走不到这里,TODO 报个错 - break; - } -} + switch (action) { + case asst::ProcessTaskAction::SwipeToTheLeft: + m_ctrler->swipe(left_rect, right_rect); + break; + case asst::ProcessTaskAction::SwipeToTheRight: + m_ctrler->swipe(right_rect, left_rect); + break; + default: // 走不到这里,TODO 报个错 + break; + } +} \ No newline at end of file diff --git a/src/MeoAssistant/ProcessTask.h b/src/MeoAssistant/ProcessTask.h index facf6784ef..71e221a9c5 100644 --- a/src/MeoAssistant/ProcessTask.h +++ b/src/MeoAssistant/ProcessTask.h @@ -1,36 +1,36 @@ #pragma once #include "AbstractTask.h" -#include "AsstDef.h" +#include "AsstTypes.h" namespace asst { - // 流程任务,按照配置文件里的设置的流程运行 - class ProcessTask : public AbstractTask - { - public: - using AbstractTask::AbstractTask; - ProcessTask(const AbstractTask& abs, std::vector tasks_name); - ProcessTask(AbstractTask&& abs, std::vector tasks_name) noexcept; + // 流程任务,按照配置文件里的设置的流程运行 + class ProcessTask : public AbstractTask + { + public: + using AbstractTask::AbstractTask; + ProcessTask(const AbstractTask& abs, std::vector tasks_name); + ProcessTask(AbstractTask&& abs, std::vector tasks_name) noexcept; - virtual ~ProcessTask() = default; + virtual ~ProcessTask() = default; - virtual bool run() override; + virtual bool run() override; - ProcessTask& set_tasks(std::vector tasks_name) noexcept; - ProcessTask& set_times_limit(std::string name, int limit); - ProcessTask& set_rear_delay(std::string name, int delay); + ProcessTask& set_tasks(std::vector tasks_name) noexcept; + ProcessTask& set_times_limit(std::string name, int limit); + ProcessTask& set_rear_delay(std::string name, int delay); - protected: - virtual bool _run() override; + protected: + virtual bool _run() override; - void exec_click_task(const Rect& matched_rect); - void exec_swipe_task(ProcessTaskAction action); + void exec_click_task(const Rect& matched_rect); + void exec_swipe_task(ProcessTaskAction action); - std::vector m_raw_tasks_name; - std::vector m_cur_tasks_name; - std::unordered_map m_rear_delay; - std::unordered_map m_times_limit; - std::unordered_map m_exec_times; - }; + std::vector m_raw_tasks_name; + std::vector m_cur_tasks_name; + std::unordered_map m_rear_delay; + std::unordered_map m_times_limit; + std::unordered_map m_exec_times; + }; } diff --git a/src/MeoAssistant/ProcessTaskImageAnalyzer.cpp b/src/MeoAssistant/ProcessTaskImageAnalyzer.cpp index a6d1ceb266..2dafbbd722 100644 --- a/src/MeoAssistant/ProcessTaskImageAnalyzer.cpp +++ b/src/MeoAssistant/ProcessTaskImageAnalyzer.cpp @@ -25,7 +25,10 @@ bool asst::ProcessTaskImageAnalyzer::match_analyze(std::shared_ptr tas } const auto match_task_ptr = std::dynamic_pointer_cast(task_ptr); m_match_analyzer->set_task_info(match_task_ptr); - m_match_analyzer->set_region_of_appeared(m_status->get_region(match_task_ptr->name)); + auto region_opt = m_status->get_region(match_task_ptr->name); + if (region_opt) { + m_match_analyzer->set_region_of_appeared(region_opt.value()); + } if (m_match_analyzer->analyze()) { m_result = match_task_ptr; @@ -70,7 +73,10 @@ bool asst::ProcessTaskImageAnalyzer::ocr_analyze(std::shared_ptr task_ m_ocr_analyzer = std::make_unique(m_image); } m_ocr_analyzer->set_task_info(ocr_task_ptr); - m_ocr_analyzer->set_region_of_appeared(m_status->get_region(ocr_task_ptr->name)); + auto region_opt = m_status->get_region(ocr_task_ptr->name); + if (region_opt) { + m_ocr_analyzer->set_region_of_appeared(region_opt.value()); + } bool ret = m_ocr_analyzer->analyze(); @@ -100,7 +106,7 @@ bool asst::ProcessTaskImageAnalyzer::analyze() m_result_rect = Rect(); for (const std::string& task_name : m_tasks_name) { - auto task_ptr = Task.get(task_name); + auto task_ptr = m_task_data->get(task_name); switch (task_ptr->algorithm) { case AlgorithmType::JustReturn: diff --git a/src/MeoAssistant/ProcessTaskImageAnalyzer.h b/src/MeoAssistant/ProcessTaskImageAnalyzer.h index 61b6c17a6c..b4bf8ed397 100644 --- a/src/MeoAssistant/ProcessTaskImageAnalyzer.h +++ b/src/MeoAssistant/ProcessTaskImageAnalyzer.h @@ -5,60 +5,60 @@ #include #include -#include "AsstDef.h" +#include "AsstTypes.h" namespace asst { - class OcrImageAnalyzer; - class MatchImageAnalyzer; - class RuntimeStatus; + class OcrImageAnalyzer; + class MatchImageAnalyzer; + class RuntimeStatus; - class ProcessTaskImageAnalyzer final : public AbstractImageAnalyzer - { - public: - using AbstractImageAnalyzer::AbstractImageAnalyzer; - ProcessTaskImageAnalyzer(const cv::Mat image, const Rect& roi) = delete; - ProcessTaskImageAnalyzer(const cv::Mat image, std::vector tasks_name); - virtual ~ProcessTaskImageAnalyzer(); + class ProcessTaskImageAnalyzer final : public AbstractImageAnalyzer + { + public: + using AbstractImageAnalyzer::AbstractImageAnalyzer; + ProcessTaskImageAnalyzer(const cv::Mat image, const Rect& roi) = delete; + ProcessTaskImageAnalyzer(const cv::Mat image, std::vector tasks_name); + virtual ~ProcessTaskImageAnalyzer(); - virtual bool analyze() override; - void set_image(const cv::Mat image); + virtual bool analyze() override; + void set_image(const cv::Mat image); - void set_tasks(std::vector tasks_name); - void set_status(std::shared_ptr status) noexcept; + void set_tasks(std::vector tasks_name); + void set_status(std::shared_ptr status) noexcept; - std::shared_ptr get_result() const noexcept - { - return m_result; - } - const Rect& get_rect() const noexcept - { - return m_result_rect; - } + std::shared_ptr get_result() const noexcept + { + return m_result; + } + const Rect& get_rect() const noexcept + { + return m_result_rect; + } - ProcessTaskImageAnalyzer& operator=(const ProcessTaskImageAnalyzer&) = delete; - ProcessTaskImageAnalyzer& operator=(ProcessTaskImageAnalyzer&&) = delete; + ProcessTaskImageAnalyzer& operator=(const ProcessTaskImageAnalyzer&) = delete; + ProcessTaskImageAnalyzer& operator=(ProcessTaskImageAnalyzer&&) = delete; - private: - // 该分析器不支持外部设置ROI - virtual void set_roi(const Rect& roi) noexcept override - { - AbstractImageAnalyzer::set_roi(roi); - } - virtual void set_image(const cv::Mat image, const Rect& roi) - { - AbstractImageAnalyzer::set_image(image, roi); - } - bool match_analyze(std::shared_ptr task_ptr); - bool ocr_analyze(std::shared_ptr task_ptr); - void reset() noexcept; + private: + // 该分析器不支持外部设置ROI + virtual void set_roi(const Rect& roi) noexcept override + { + AbstractImageAnalyzer::set_roi(roi); + } + virtual void set_image(const cv::Mat image, const Rect& roi) + { + AbstractImageAnalyzer::set_image(image, roi); + } + bool match_analyze(std::shared_ptr task_ptr); + bool ocr_analyze(std::shared_ptr task_ptr); + void reset() noexcept; - std::unique_ptr m_ocr_analyzer; - std::unique_ptr m_match_analyzer; - std::vector m_tasks_name; - std::shared_ptr m_result = nullptr; - std::shared_ptr m_status = nullptr; - Rect m_result_rect; - //std::vector m_ocr_cache; - }; + std::unique_ptr m_ocr_analyzer; + std::unique_ptr m_match_analyzer; + std::vector m_tasks_name; + std::shared_ptr m_result = nullptr; + std::shared_ptr m_status = nullptr; + Rect m_result_rect; + //std::vector m_ocr_cache; + }; } diff --git a/src/MeoAssistant/RecruitConfiger.h b/src/MeoAssistant/RecruitConfiger.h index dde08cccb4..99dd8e34fc 100644 --- a/src/MeoAssistant/RecruitConfiger.h +++ b/src/MeoAssistant/RecruitConfiger.h @@ -6,53 +6,53 @@ #include #include -#include "AsstDef.h" +#include "AsstTypes.h" namespace asst { - // 干员信息,公开招募相关 - struct RecruitOperInfo - { - std::string name; - std::string type; - int level = 0; - std::string sex; - std::unordered_set tags; - bool hidden = false; - std::string name_en; - }; + // 干员信息,公开招募相关 + struct RecruitOperInfo + { + std::string name; + std::string type; + int level = 0; + std::string sex; + std::unordered_set tags; + bool hidden = false; + std::string name_en; + }; - // 公开招募的干员组合 - struct RecruitCombs - { - std::vector tags; - std::vector opers; - int max_level = 0; - int min_level = 0; - double avg_level = 0; - }; + // 公开招募的干员组合 + struct RecruitCombs + { + std::vector tags; + std::vector opers; + int max_level = 0; + int min_level = 0; + double avg_level = 0; + }; - class RecruitConfiger : public AbstractConfiger - { - public: - virtual ~RecruitConfiger() = default; - constexpr static int CorrectNumberOfTags = 5; + class RecruitConfiger : public AbstractConfiger + { + public: + virtual ~RecruitConfiger() = default; + constexpr static int CorrectNumberOfTags = 5; - const std::unordered_set& get_all_tags() const noexcept - { - return m_all_tags; - } - const std::vector& get_all_opers() const noexcept - { - return m_all_opers; - } + const std::unordered_set& get_all_tags() const noexcept + { + return m_all_tags; + } + const std::vector& get_all_opers() const noexcept + { + return m_all_opers; + } - protected: - virtual bool parse(const json::value& json) override; + protected: + virtual bool parse(const json::value& json) override; - std::unordered_set m_all_tags; - std::unordered_set m_all_types; + std::unordered_set m_all_tags; + std::unordered_set m_all_types; - std::vector m_all_opers; - }; + std::vector m_all_opers; + }; } diff --git a/src/MeoAssistant/RecruitImageAnalyzer.cpp b/src/MeoAssistant/RecruitImageAnalyzer.cpp index 5d28c84f2b..37fcd12d1a 100644 --- a/src/MeoAssistant/RecruitImageAnalyzer.cpp +++ b/src/MeoAssistant/RecruitImageAnalyzer.cpp @@ -23,7 +23,7 @@ bool asst::RecruitImageAnalyzer::tags_analyze() static OcrImageAnalyzer tags_analyzer; if (!analyzer_inited) { const auto tags_task_ptr = std::dynamic_pointer_cast( - Task.get("RecruitTags")); + m_task_data->get("RecruitTags")); tags_analyzer.set_roi(tags_task_ptr->roi); auto& all_tags_set = Resrc.recruit().get_all_tags(); std::vector all_tags_vec; @@ -52,7 +52,7 @@ bool asst::RecruitImageAnalyzer::tags_analyze() bool asst::RecruitImageAnalyzer::time_analyze() { - const auto time_task_ptr = Task.get("RecruitTime"); + const auto time_task_ptr = m_task_data->get("RecruitTime"); MatchImageAnalyzer time_analyzer(m_image); time_analyzer.set_task_info(time_task_ptr); @@ -75,7 +75,7 @@ bool asst::RecruitImageAnalyzer::time_analyze() bool asst::RecruitImageAnalyzer::confirm_analyze() { MatchImageAnalyzer confirm_analyzer(m_image); - confirm_analyzer.set_task_info("RecruitConfirm"); + confirm_analyzer.set_task_info(StaticTaskData::get_instance().get("RecruitConfirm")); if (confirm_analyzer.analyze()) { m_confirm_rect = confirm_analyzer.get_result().rect; @@ -88,7 +88,7 @@ bool asst::RecruitImageAnalyzer::confirm_analyze() bool asst::RecruitImageAnalyzer::refresh_analyze() { MatchImageAnalyzer refresh_analyzer(m_image); - refresh_analyzer.set_task_info("RecruitRefresh"); + refresh_analyzer.set_task_info(StaticTaskData::get_instance().get("RecruitRefresh")); if (refresh_analyzer.analyze()) { m_refresh_rect = refresh_analyzer.get_result().rect; diff --git a/src/MeoAssistant/RecruitImageAnalyzer.h b/src/MeoAssistant/RecruitImageAnalyzer.h index 00ee3e1794..bdde90dd29 100644 --- a/src/MeoAssistant/RecruitImageAnalyzer.h +++ b/src/MeoAssistant/RecruitImageAnalyzer.h @@ -1,54 +1,54 @@ #pragma once #include "AbstractImageAnalyzer.h" -#include "AsstDef.h" +#include "AsstTypes.h" namespace asst { - class RecruitImageAnalyzer final : public AbstractImageAnalyzer - { - public: - using AbstractImageAnalyzer::AbstractImageAnalyzer; - RecruitImageAnalyzer(const cv::Mat image, const Rect& roi) = delete; - virtual ~RecruitImageAnalyzer() = default; + class RecruitImageAnalyzer final : public AbstractImageAnalyzer + { + public: + using AbstractImageAnalyzer::AbstractImageAnalyzer; + RecruitImageAnalyzer(const cv::Mat image, const Rect& roi) = delete; + virtual ~RecruitImageAnalyzer() = default; - virtual bool analyze() override; + virtual bool analyze() override; - const std::vector& get_tags_result() const noexcept - { - return m_tags_result; - } - const std::vector& get_set_time_rect() const noexcept - { - return m_set_time_rect; - } - Rect get_confirm_rect() const noexcept - { - return m_confirm_rect; - } - Rect get_refresh_rect() const noexcept - { - return m_refresh_rect; - } + const std::vector& get_tags_result() const noexcept + { + return m_tags_result; + } + const std::vector& get_set_time_rect() const noexcept + { + return m_set_time_rect; + } + Rect get_confirm_rect() const noexcept + { + return m_confirm_rect; + } + Rect get_refresh_rect() const noexcept + { + return m_refresh_rect; + } - private: - // 该分析器不支持外部设置ROI - virtual void set_roi(const Rect& roi) noexcept override - { - AbstractImageAnalyzer::set_roi(roi); - } - virtual void set_image(const cv::Mat image, const Rect& roi) - { - AbstractImageAnalyzer::set_image(image, roi); - } - bool tags_analyze(); - bool time_analyze(); - bool confirm_analyze(); - bool refresh_analyze(); + private: + // 该分析器不支持外部设置ROI + virtual void set_roi(const Rect& roi) noexcept override + { + AbstractImageAnalyzer::set_roi(roi); + } + virtual void set_image(const cv::Mat image, const Rect& roi) + { + AbstractImageAnalyzer::set_image(image, roi); + } + bool tags_analyze(); + bool time_analyze(); + bool confirm_analyze(); + bool refresh_analyze(); - std::vector m_tags_result; - std::vector m_set_time_rect; - Rect m_confirm_rect; - Rect m_refresh_rect; - }; + std::vector m_tags_result; + std::vector m_set_time_rect; + Rect m_confirm_rect; + Rect m_refresh_rect; + }; } diff --git a/src/MeoAssistant/Resource.cpp b/src/MeoAssistant/Resource.cpp index 56aeae9ec0..39e79259b1 100644 --- a/src/MeoAssistant/Resource.cpp +++ b/src/MeoAssistant/Resource.cpp @@ -6,7 +6,7 @@ #include -#include "AsstDef.h" +#include "AsstTypes.h" #include "Logger.hpp" bool asst::Resource::load(const std::string& dir) @@ -28,8 +28,8 @@ bool asst::Resource::load(const std::string& dir) m_last_error = std::string(GeneralCfgFilename) + ": " + m_general_cfg_unique_ins.get_last_error(); return false; } - if (!Task.load(dir + TaskDataFilename)) { - m_last_error = std::string(TaskDataFilename) + ": " + Task.get_last_error(); + if (!StaticTaskData::get_instance().load(dir + TaskDataFilename)) { + m_last_error = std::string(TaskDataFilename) + ": " + StaticTaskData::get_instance().get_last_error(); return false; } @@ -50,7 +50,7 @@ bool asst::Resource::load(const std::string& dir) /* 加载模板图片资源 */ // task所需要的模板资源 - m_templ_resource_unique_ins.append_load_required(Task.get_templ_required()); + m_templ_resource_unique_ins.append_load_required(StaticTaskData::get_instance().get_templ_required()); // 基建所需要的模板资源 m_templ_resource_unique_ins.append_load_required(m_infrast_cfg_unique_ins.get_templ_required()); diff --git a/src/MeoAssistant/RoguelikeBattleTaskPlugin.cpp b/src/MeoAssistant/RoguelikeBattleTaskPlugin.cpp index d289fbb634..cd6129e6c3 100644 --- a/src/MeoAssistant/RoguelikeBattleTaskPlugin.cpp +++ b/src/MeoAssistant/RoguelikeBattleTaskPlugin.cpp @@ -59,7 +59,7 @@ bool asst::RoguelikeBattleTaskPlugin::get_stage_info() bool calced = false; if (m_stage_name.empty()) { - const auto stage_name_task_ptr = Task.get("BattleStageName"); + const auto stage_name_task_ptr = m_task_data->get("BattleStageName"); sleep(stage_name_task_ptr->pre_delay); constexpr int StageNameRetryTimes = 50; @@ -133,7 +133,7 @@ bool asst::RoguelikeBattleTaskPlugin::auto_battle() using Oper = asst::BattleImageAnalyzer::Oper; - BattleImageAnalyzer battle_analyzer(m_ctrler->get_image()); + BattleImageAnalyzer battle_analyzer(m_ctrler->get_image(), m_task_data); if (!battle_analyzer.analyze()) { return false; } @@ -171,8 +171,8 @@ bool asst::RoguelikeBattleTaskPlugin::auto_battle() Role::Tank, Role::Drone }; - const auto use_oper_task_ptr = Task.get("BattleUseOper"); - const auto swipe_oper_task_ptr = Task.get("BattleSwipeOper"); + const auto use_oper_task_ptr = m_task_data->get("BattleUseOper"); + const auto swipe_oper_task_ptr = m_task_data->get("BattleSwipeOper"); // 点击当前最合适的干员 Oper opt_oper; diff --git a/src/MeoAssistant/RoguelikeBattleTaskPlugin.h b/src/MeoAssistant/RoguelikeBattleTaskPlugin.h index 3f43f35cf7..e73b91aca1 100644 --- a/src/MeoAssistant/RoguelikeBattleTaskPlugin.h +++ b/src/MeoAssistant/RoguelikeBattleTaskPlugin.h @@ -1,49 +1,49 @@ #pragma once #include "AbstractTaskPlugin.h" -#include "AsstDef.h" +#include "AsstTypes.h" #include "TilePack.h" #include "BattleImageAnalyzer.h" namespace asst { - class RoguelikeBattleTaskPlugin : public AbstractTaskPlugin - { - using Loc = asst::TilePack::BuildableType; - using Role = asst::BattleImageAnalyzer::Role; - public: - using AbstractTaskPlugin::AbstractTaskPlugin; - virtual ~RoguelikeBattleTaskPlugin() = default; + class RoguelikeBattleTaskPlugin : public AbstractTaskPlugin + { + using Loc = asst::TilePack::BuildableType; + using Role = asst::BattleImageAnalyzer::Role; + public: + using AbstractTaskPlugin::AbstractTaskPlugin; + virtual ~RoguelikeBattleTaskPlugin() = default; - virtual bool verify(AsstMsg msg, const json::value& details) const override; + virtual bool verify(AsstMsg msg, const json::value& details) const override; - void set_stage_name(std::string stage); + void set_stage_name(std::string stage); - protected: - virtual bool _run() override; + protected: + virtual bool _run() override; - bool get_stage_info(); - bool auto_battle(); - bool speed_up(); - bool use_skill(const Rect& rect); - void clear(); + bool get_stage_info(); + bool auto_battle(); + bool speed_up(); + bool use_skill(const Rect& rect); + void clear(); - // 通过资源文件离线计算可放置干员的位置,优先使用 - // 返回 可格子的位置 - Point get_placed(Loc buildable_type); + // 通过资源文件离线计算可放置干员的位置,优先使用 + // 返回 可格子的位置 + Point get_placed(Loc buildable_type); - // 计算摆放干员的朝向 - // 返回滑动的方向 - Point calc_direction(Point loc, Role role); + // 计算摆放干员的朝向 + // 返回滑动的方向 + Point calc_direction(Point loc, Role role); - bool m_used_opers = false; - int m_pre_hp = 0; + bool m_used_opers = false; + int m_pre_hp = 0; - std::unordered_map m_side_tile_info; - std::vector m_homes; - size_t m_cur_home_index = 0; - std::unordered_set m_used_tiles; + std::unordered_map m_side_tile_info; + std::vector m_homes; + size_t m_cur_home_index = 0; + std::unordered_set m_used_tiles; - std::string m_stage_name; - }; + std::string m_stage_name; + }; } diff --git a/src/MeoAssistant/RoguelikeFormationImageAnalyzer.cpp b/src/MeoAssistant/RoguelikeFormationImageAnalyzer.cpp index 478b1f2bc9..8393130af1 100644 --- a/src/MeoAssistant/RoguelikeFormationImageAnalyzer.cpp +++ b/src/MeoAssistant/RoguelikeFormationImageAnalyzer.cpp @@ -5,10 +5,14 @@ #include "TaskData.h" #include "Logger.hpp" +asst::RoguelikeFormationImageAnalyzer::RoguelikeFormationImageAnalyzer(const cv::Mat image, std::shared_ptr task_data) + : AbstractImageAnalyzer(image, task_data) +{} + bool asst::RoguelikeFormationImageAnalyzer::analyze() { MultiMatchImageAnalyzer opers_analyzer(m_image); - opers_analyzer.set_task_info("Roguelike1FormationOper"); + opers_analyzer.set_task_info(m_task_data->get("Roguelike1FormationOper")); if (!opers_analyzer.analyze()) { return false; } @@ -46,7 +50,7 @@ bool asst::RoguelikeFormationImageAnalyzer::selected_analyze(const Rect& roi) cv::Mat hsv; const auto selected_task_ptr = std::dynamic_pointer_cast( - Task.get("Roguelike1FormationOperSelected")); + m_task_data->get("Roguelike1FormationOperSelected")); cv::cvtColor(img_roi, hsv, cv::COLOR_BGR2HSV); std::vector channels; cv::split(hsv, channels); diff --git a/src/MeoAssistant/RoguelikeFormationImageAnalyzer.h b/src/MeoAssistant/RoguelikeFormationImageAnalyzer.h index 011acc1760..fd551a96e4 100644 --- a/src/MeoAssistant/RoguelikeFormationImageAnalyzer.h +++ b/src/MeoAssistant/RoguelikeFormationImageAnalyzer.h @@ -13,7 +13,7 @@ namespace asst // TODO }; public: - using AbstractImageAnalyzer::AbstractImageAnalyzer; + RoguelikeFormationImageAnalyzer(const cv::Mat image, std::shared_ptr task_data); virtual ~RoguelikeFormationImageAnalyzer() = default; virtual bool analyze() override; diff --git a/src/MeoAssistant/RoguelikeFormationTask.cpp b/src/MeoAssistant/RoguelikeFormationTaskPlugin.cpp similarity index 97% rename from src/MeoAssistant/RoguelikeFormationTask.cpp rename to src/MeoAssistant/RoguelikeFormationTaskPlugin.cpp index ae23a8ba4e..2866e898f3 100644 --- a/src/MeoAssistant/RoguelikeFormationTask.cpp +++ b/src/MeoAssistant/RoguelikeFormationTaskPlugin.cpp @@ -22,7 +22,7 @@ bool asst::RoguelikeFormationTaskPlugin::verify(AsstMsg msg, const json::value& bool asst::RoguelikeFormationTaskPlugin::_run() { - RoguelikeFormationImageAnalyzer formation_analyzer(m_ctrler->get_image()); + RoguelikeFormationImageAnalyzer formation_analyzer(m_ctrler->get_image(), m_task_data); if (!formation_analyzer.analyze()) { return false; } diff --git a/src/MeoAssistant/RuntimeStatus.cpp b/src/MeoAssistant/RuntimeStatus.cpp index 27a3ce972e..8e5700d417 100644 --- a/src/MeoAssistant/RuntimeStatus.cpp +++ b/src/MeoAssistant/RuntimeStatus.cpp @@ -1,21 +1,16 @@ #include "RuntimeStatus.h" -int64_t asst::RuntimeStatus::get_data(const std::string& key) const noexcept +std::optional asst::RuntimeStatus::get_data(const std::string& key) const noexcept { if (auto iter = m_data.find(key); iter != m_data.cend()) { return iter->second; } else { - return 0; + return std::nullopt; } } -bool asst::RuntimeStatus::contains_data(const std::string& key) const noexcept -{ - return m_data.find(key) != m_data.cend(); -} - void asst::RuntimeStatus::set_data(std::string key, int64_t value) { m_data[std::move(key)] = value; @@ -26,14 +21,14 @@ void asst::RuntimeStatus::clear_data() noexcept m_data.clear(); } -asst::Rect asst::RuntimeStatus::get_region(const std::string& key) const noexcept +std::optional asst::RuntimeStatus::get_region(const std::string& key) const noexcept { if (auto iter = m_region_of_appeared.find(key); iter != m_region_of_appeared.cend()) { return iter->second; } else { - return Rect(); + return std::nullopt; } } @@ -41,3 +36,8 @@ void asst::RuntimeStatus::set_region(std::string key, Rect rect) { m_region_of_appeared[std::move(key)] = std::move(rect); } + +void asst::RuntimeStatus::clear_region() noexcept +{ + m_region_of_appeared.clear(); +} diff --git a/src/MeoAssistant/RuntimeStatus.h b/src/MeoAssistant/RuntimeStatus.h index 00aad74cf8..c64de42bb2 100644 --- a/src/MeoAssistant/RuntimeStatus.h +++ b/src/MeoAssistant/RuntimeStatus.h @@ -3,8 +3,9 @@ //#include #include #include +#include -#include "AsstDef.h" +#include "AsstTypes.h" namespace asst { @@ -16,13 +17,13 @@ namespace asst RuntimeStatus(RuntimeStatus&& rhs) noexcept = delete; ~RuntimeStatus() = default; - int64_t get_data(const std::string& key) const noexcept; - bool contains_data(const std::string& key) const noexcept; + std::optional get_data(const std::string& key) const noexcept; void set_data(std::string key, int64_t value); void clear_data() noexcept; - Rect get_region(const std::string& key) const noexcept; + std::optional get_region(const std::string& key) const noexcept; void set_region(std::string key, Rect rect); + void clear_region() noexcept; RuntimeStatus& operator=(const RuntimeStatus& rhs) = delete; RuntimeStatus& operator=(RuntimeStatus&& rhs) noexcept = delete; diff --git a/src/MeoAssistant/StageDropsTaskPlugin.cpp b/src/MeoAssistant/StageDropsTaskPlugin.cpp index 69ba92f13c..df27147717 100644 --- a/src/MeoAssistant/StageDropsTaskPlugin.cpp +++ b/src/MeoAssistant/StageDropsTaskPlugin.cpp @@ -21,8 +21,10 @@ bool asst::StageDropsTaskPlugin::verify(AsstMsg msg, const json::value& details) } if (details.at("details").at("task").as_string() == "EndOfAction") { - int64_t pre_start_time = m_status->get_data("LastStartButton2"); - int64_t pre_recognize_time = m_status->get_data("LastRecognizeDrops"); + auto pre_time_opt = m_status->get_data("LastStartButton2"); + int64_t pre_start_time = pre_time_opt ? pre_time_opt.value() : 0; + auto pre_reg_time_opt = m_status->get_data("LastRecognizeDrops"); + int64_t pre_recognize_time = pre_reg_time_opt ? pre_reg_time_opt.value() : 0; if (pre_start_time + RecognizationTimeOffset == pre_recognize_time) { Log.info("Recognization time too close, pass", pre_start_time, pre_recognize_time); return false; @@ -70,7 +72,7 @@ bool asst::StageDropsTaskPlugin::recognize_drops() { LogTraceFunction; - sleep(Task.get("PRTS")->rear_delay); + sleep(m_task_data->get("PRTS")->rear_delay); if (need_exit()) { return false; } @@ -79,7 +81,9 @@ bool asst::StageDropsTaskPlugin::recognize_drops() Log.trace("Results of penguin recognition:\n", res); m_cur_drops = json::parse(res).value(); - m_status->set_data("LastRecognizeDrops", m_status->get_data("LastStartButton2") + RecognizationTimeOffset); + auto last_time_opt = m_status->get_data("LastStartButton2"); + auto last_time = last_time_opt ? last_time_opt.value() : 0; + m_status->set_data("LastRecognizeDrops", last_time + RecognizationTimeOffset); return true; } @@ -125,11 +129,12 @@ void asst::StageDropsTaskPlugin::set_startbutton_delay() LogTraceFunction; if (!m_startbutton_delay_setted) { - int64_t pre_start_time = m_status->get_data("LastStartButton2"); + auto last_time_opt = m_status->get_data("LastStartButton2");; + int64_t pre_start_time = last_time_opt ? last_time_opt.value() : 0; if (pre_start_time > 0) { int64_t duration = time(nullptr) - pre_start_time; - int elapsed = Task.get("EndOfAction")->pre_delay + Task.get("PRTS")->rear_delay; + int elapsed = m_task_data->get("EndOfAction")->pre_delay + m_task_data->get("PRTS")->rear_delay; int64_t delay = duration * 1000 - elapsed; m_cast_ptr->set_rear_delay("StartButton2", static_cast(delay)); } diff --git a/src/MeoAssistant/TaskData.cpp b/src/MeoAssistant/TaskData.cpp index 9a4852416d..e9154b7331 100644 --- a/src/MeoAssistant/TaskData.cpp +++ b/src/MeoAssistant/TaskData.cpp @@ -4,12 +4,12 @@ #include -#include "AsstDef.h" +#include "AsstTypes.h" #include "GeneralConfiger.h" #include "TemplResource.h" #include "Logger.hpp" -const std::shared_ptr asst::TaskData::get(const std::string& name) const noexcept +const std::shared_ptr asst::StaticTaskData::get(const std::string& name) const noexcept { if (auto iter = m_all_tasks_info.find(name); iter != m_all_tasks_info.cend()) { @@ -20,17 +20,17 @@ const std::shared_ptr asst::TaskData::get(const std::string& nam } } -const std::unordered_set& asst::TaskData::get_templ_required() const noexcept +const std::unordered_set& asst::StaticTaskData::get_templ_required() const noexcept { return m_templ_required; } -std::shared_ptr asst::TaskData::get(std::string name) +std::shared_ptr asst::StaticTaskData::get(const std::string& name) { - return m_all_tasks_info[std::move(name)]; + return m_all_tasks_info[name]; } -bool asst::TaskData::parse(const json::value& json) +bool asst::StaticTaskData::parse(const json::value& json) { LogTraceFunction; @@ -214,3 +214,40 @@ bool asst::TaskData::parse(const json::value& json) #endif return true; } + +const std::shared_ptr asst::TaskData::get(const std::string& name) const noexcept +{ + return std::shared_ptr(); +} + +std::shared_ptr asst::TaskData::get(const std::string& name) +{ + if (auto iter = m_specal_tasks_info.find(name); + iter != m_specal_tasks_info.cend()) { + return iter->second; + } + else { + return StaticTaskData::get_instance().get(name); + } +} + +bool asst::TaskData::set_ocr_text(const std::string& key, std::vector text) +{ + if (auto iter = m_specal_tasks_info.find(key); + iter != m_specal_tasks_info.end()) { + std::dynamic_pointer_cast(iter->second)->text = std::move(text); + return true; + } + else { + auto raw_task_ptr = StaticTaskData::get_instance().get(key); + if (!raw_task_ptr) { + return false; + } + // 拷贝一份 + OcrTaskInfo info = *std::dynamic_pointer_cast(raw_task_ptr); + info.text = std::move(text); + auto specail_ptr = std::make_shared(std::move(info)); + m_specal_tasks_info.emplace(key, specail_ptr); + return true; + } +} diff --git a/src/MeoAssistant/TaskData.h b/src/MeoAssistant/TaskData.h index a92dd5dfdc..bfb1d74b5a 100644 --- a/src/MeoAssistant/TaskData.h +++ b/src/MeoAssistant/TaskData.h @@ -10,26 +10,26 @@ namespace asst { struct TaskInfo; - class TaskData : public AbstractConfiger + class StaticTaskData : public AbstractConfiger { public: - TaskData(const TaskData&) = delete; - TaskData(TaskData&&) = delete; + StaticTaskData(const StaticTaskData&) = delete; + StaticTaskData(StaticTaskData&&) = delete; - virtual ~TaskData() = default; + virtual ~StaticTaskData() = default; - static TaskData& get_instance() + static StaticTaskData& get_instance() { - static TaskData unique_instance; + static StaticTaskData unique_instance; return unique_instance; } + const std::unordered_set& get_templ_required() const noexcept; const std::shared_ptr get(const std::string& name) const noexcept; - const std::unordered_set& get_templ_required() const noexcept; - std::shared_ptr get(std::string name); + std::shared_ptr get(const std::string& name); protected: - TaskData() = default; + StaticTaskData() = default; virtual bool parse(const json::value& json); @@ -37,5 +37,18 @@ namespace asst std::unordered_set m_templ_required; }; - static auto& Task = TaskData::get_instance(); + class TaskData + { + public: + TaskData() = default; + ~TaskData() noexcept = default; + + const std::shared_ptr get(const std::string& name) const noexcept; + std::shared_ptr get(const std::string& name); + + bool set_ocr_text(const std::string& key, std::vector text); + + private: + std::unordered_map> m_specal_tasks_info; + }; } diff --git a/src/MeoAssistant/TilePack.h b/src/MeoAssistant/TilePack.h index 3945135be9..fc4fca15df 100644 --- a/src/MeoAssistant/TilePack.h +++ b/src/MeoAssistant/TilePack.h @@ -1,65 +1,65 @@ #pragma once #include "AbstractResource.h" -#include "AsstDef.h" +#include "AsstTypes.h" #include namespace Map { - class TileCalc; + class TileCalc; } namespace asst { - class TilePack final : public AbstractResource - { - public: - enum class BuildableType - { - Invalid = -1, - None = 0, - Melee = 1, - Ranged = 2, - All = 3 - }; - enum class HeightType - { - Invalid = -1, - Highland = 0, - Floor = 1 - }; - enum class TileKey - { - Invalid = -1, - Forbidden, // 不能放干员,敌人也不能走 - Wall, // 可以放高台干员的位置 - Road, // 可以放地面干员,敌人也可以走 - Home, // 蓝门(可能还有其他的情况) - EnemyHome, // 红门(可能还有其他的情况) - Floor, // 不能放干员,但敌人可以走 - Hole, // 空降兵掉下去的地方( - Telin, // 不知道是啥 - Telout // 不知道是啥 - }; + class TilePack final : public AbstractResource + { + public: + enum class BuildableType + { + Invalid = -1, + None = 0, + Melee = 1, + Ranged = 2, + All = 3 + }; + enum class HeightType + { + Invalid = -1, + Highland = 0, + Floor = 1 + }; + enum class TileKey + { + Invalid = -1, + Forbidden, // 不能放干员,敌人也不能走 + Wall, // 可以放高台干员的位置 + Road, // 可以放地面干员,敌人也可以走 + Home, // 蓝门(可能还有其他的情况) + EnemyHome, // 红门(可能还有其他的情况) + Floor, // 不能放干员,但敌人可以走 + Hole, // 空降兵掉下去的地方( + Telin, // 不知道是啥 + Telout // 不知道是啥 + }; - struct TileInfo - { - BuildableType buildable = BuildableType::Invalid; - HeightType height = HeightType::Invalid; - TileKey key = TileKey::Invalid; - Point pos; // 像素坐标 - Point loc; // 格子位置 - }; - public: - using AbstractResource::AbstractResource; - virtual ~TilePack(); + struct TileInfo + { + BuildableType buildable = BuildableType::Invalid; + HeightType height = HeightType::Invalid; + TileKey key = TileKey::Invalid; + Point pos; // 像素坐标 + Point loc; // 格子位置 + }; + public: + using AbstractResource::AbstractResource; + virtual ~TilePack(); - virtual bool load(const std::string& dir) override; + virtual bool load(const std::string& dir) override; - std::unordered_map calc(const std::string& stage_code, bool side) const; + std::unordered_map calc(const std::string& stage_code, bool side) const; - private: - std::shared_ptr m_tile_calculator = nullptr; - }; + private: + std::shared_ptr m_tile_calculator = nullptr; + }; }