From 594dc77a2acaed2e1e57b974cd654f34e1dd7b9e Mon Sep 17 00:00:00 2001 From: MistEO Date: Fri, 23 Jul 2021 23:48:00 +0800 Subject: [PATCH] restructure configer, improve thread safety --- MeoAssistance/include/Assistance.h | 7 ++- MeoAssistance/include/AsstDef.h | 16 +++++++ MeoAssistance/include/Configer.h | 29 +++++++----- MeoAssistance/include/Identify.h | 2 +- MeoAssistance/include/WinMacro.h | 4 +- MeoAssistance/src/Assistance.cpp | 66 ++++++++++++++------------- MeoAssistance/src/AsstCaller.cpp | 4 +- MeoAssistance/src/Configer.cpp | 72 +++++++++++++++++++++--------- MeoAssistance/src/Identify.cpp | 8 ++-- MeoAssistance/src/WinMacro.cpp | 30 ++++++------- 10 files changed, 147 insertions(+), 91 deletions(-) diff --git a/MeoAssistance/include/Assistance.h b/MeoAssistance/include/Assistance.h index 8234503580..7a2ce8820c 100644 --- a/MeoAssistance/include/Assistance.h +++ b/MeoAssistance/include/Assistance.h @@ -8,6 +8,7 @@ #include #include "AsstDef.h" +#include "Configer.h" namespace asst { class WinMacro; @@ -24,8 +25,8 @@ namespace asst { void start(const std::string & task); void stop(bool block = true); - bool setParam(const std::string& type, const std::string& param, const std::string& value); - std::optional getParam(const std::string& type, const std::string& param); + bool set_param(const std::string& type, const std::string& param, const std::string& value); + std::optional get_param(const std::string& type, const std::string& param); private: static void workingProc(Assistance* pThis); @@ -41,6 +42,8 @@ namespace asst { bool m_thread_exit = false; bool m_thread_running = false; std::vector m_next_tasks; + + Configer m_configer; }; } \ No newline at end of file diff --git a/MeoAssistance/include/AsstDef.h b/MeoAssistance/include/AsstDef.h index 7f25f31ce8..8fa475336c 100644 --- a/MeoAssistance/include/AsstDef.h +++ b/MeoAssistance/include/AsstDef.h @@ -52,6 +52,21 @@ namespace asst { }; return os << _type_name.at(task); } + + enum class AlgorithmType { + JustReturn, + MatchTemplate, + CompareHist + }; + static std::ostream& operator<<(std::ostream& os, const AlgorithmType& type) + { + static std::unordered_map _type_name = { + {AlgorithmType::JustReturn, "JustReturn"}, + {AlgorithmType::MatchTemplate, "MatchTemplate"}, + {AlgorithmType::CompareHist, "CompareHist"} + }; + return os << _type_name.at(type); + } struct Point { @@ -94,6 +109,7 @@ namespace asst { }; struct SimulatorInfo { + std::string name; std::vector window; std::vector view; std::vector control; diff --git a/MeoAssistance/include/Configer.h b/MeoAssistance/include/Configer.h index 883a9d120d..dc1b988f63 100644 --- a/MeoAssistance/include/Configer.h +++ b/MeoAssistance/include/Configer.h @@ -2,7 +2,6 @@ #include #include -#include #include #include "AsstDef.h" @@ -12,25 +11,31 @@ namespace asst { class Configer { public: + Configer() = default; ~Configer() = default; - static bool reload(); + Configer(const Configer& rhs); + Configer(Configer&& rhs) noexcept; - static std::string m_version; - static Options m_options; - static std::unordered_map m_tasks; - static std::unordered_map m_handles; + bool reload(const std::string& filename); - static bool setParam(const std::string& type, const std::string& param, const std::string& value); - static std::optional getParam(const std::string& type, const std::string& param); + bool set_param(const std::string& type, const std::string& param, const std::string& value); + std::optional get_param(const std::string& type, const std::string& param); - static void clearExecTimes(); + void clear_exec_times(); + + Configer& operator=(const Configer& rhs); + Configer& operator=(Configer&& rhs) noexcept; constexpr static double DefaultThreshold = 0.9; constexpr static double DefaultCacheThreshold = 0.9; - private: - Configer() = default; - static std::string m_curDir; + std::string m_version; + Options m_options; + std::unordered_map m_tasks; + std::unordered_map m_handles; + + private: + }; } diff --git a/MeoAssistance/include/Identify.h b/MeoAssistance/include/Identify.h index 048d228499..eddbd4ff99 100644 --- a/MeoAssistance/include/Identify.h +++ b/MeoAssistance/include/Identify.h @@ -22,7 +22,7 @@ namespace asst { bool addImage(const std::string& name, const std::string& path); // return tuple< algorithmType, suitability, scaled asst::rect> - std::tuple findImage(const cv::Mat& image, const std::string& templ, double threshold = 0.99); + std::tuple findImage(const cv::Mat& image, const std::string& templ, double threshold = 0.99); void clear_cache(); private: diff --git a/MeoAssistance/include/WinMacro.h b/MeoAssistance/include/WinMacro.h index 5d00a256c9..6b3642e970 100644 --- a/MeoAssistance/include/WinMacro.h +++ b/MeoAssistance/include/WinMacro.h @@ -11,7 +11,7 @@ namespace asst { class WinMacro { public: - WinMacro(const std::string & simulator_name, HandleType type); + WinMacro(const SimulatorInfo & info, HandleType type); ~WinMacro() = default; bool captured() const noexcept; @@ -27,7 +27,7 @@ namespace asst { private: bool findHandle(); - const std::string m_simulator_name; + const SimulatorInfo m_simulator_info; const HandleType m_handle_type; HWND m_handle = NULL; bool m_is_adb = false; diff --git a/MeoAssistance/src/Assistance.cpp b/MeoAssistance/src/Assistance.cpp index bbc2faa7e2..5f33bb9905 100644 --- a/MeoAssistance/src/Assistance.cpp +++ b/MeoAssistance/src/Assistance.cpp @@ -12,17 +12,16 @@ Assistance::Assistance() { DebugTraceFunction; - Configer::reload(); + m_configer.reload(GetResourceDir() + "config.json"); m_pIder = std::make_shared(); - for (auto&& [name, info] : Configer::m_tasks) + for (auto&& [name, info] : m_configer.m_tasks) { m_pIder->addImage(name, GetResourceDir() + info.filename); } - m_pIder->setUseCache(Configer::m_options.identify_cache); + m_pIder->setUseCache(m_configer.m_options.identify_cache); m_working_thread = std::thread(workingProc, this); - } Assistance::~Assistance() @@ -48,10 +47,10 @@ std::optional Assistance::setSimulator(const std::string& simulator stop(); - auto create_handles = [&](const std::string& name) -> bool { - m_pWindow = std::make_shared(name, HandleType::Window); - m_pView = std::make_shared(name, HandleType::View); - m_pCtrl = std::make_shared(name, HandleType::Control); + auto create_handles = [&](const SimulatorInfo& info) -> bool { + m_pWindow = std::make_shared(info, HandleType::Window); + m_pView = std::make_shared(info, HandleType::View); + m_pCtrl = std::make_shared(info, HandleType::Control); return m_pWindow->captured() && m_pView->captured() && m_pCtrl->captured(); }; @@ -61,9 +60,9 @@ std::optional Assistance::setSimulator(const std::string& simulator std::unique_lock lock(m_mutex); if (simulator_name.empty()) { - for (auto&& [name, value] : Configer::m_handles) + for (auto&& [name, info] : m_configer.m_handles) { - ret = create_handles(name); + ret = create_handles(info); if (ret) { cor_name = name; break; @@ -71,7 +70,7 @@ std::optional Assistance::setSimulator(const std::string& simulator } } else { - ret = create_handles(simulator_name); + ret = create_handles(m_configer.m_handles[simulator_name]); } if (ret && m_pWindow->showWindow() && m_pWindow->resizeWindow()) { m_inited = true; @@ -94,8 +93,8 @@ void Assistance::start(const std::string& task) } std::unique_lock lock(m_mutex); + m_configer.clear_exec_times(); - Configer::clearExecTimes(); m_pIder->clear_cache(); m_next_tasks.clear(); m_next_tasks.emplace_back(task); @@ -106,31 +105,33 @@ void Assistance::start(const std::string& task) void Assistance::stop(bool block) { DebugTraceFunction; - DebugTrace("Stop |", block); + DebugTrace("Stop |", block ? "block" : "non block"); std::unique_lock lock; if (block) { // Íⲿµ÷Óà lock = std::unique_lock(m_mutex); - Configer::clearExecTimes(); + m_configer.clear_exec_times(); } m_thread_running = false; m_next_tasks.clear(); m_pIder->clear_cache(); } -bool Assistance::setParam(const std::string& type, const std::string& param, const std::string& value) +bool Assistance::set_param(const std::string& type, const std::string& param, const std::string& value) { DebugTraceFunction; DebugTrace("SetParam |", type, param, value); - return Configer::setParam(type, param, value); + std::unique_lock lock(m_mutex); + return m_configer.set_param(type, param, value); } -std::optional Assistance::getParam(const std::string& type, const std::string& param) +std::optional Assistance::get_param(const std::string& type, const std::string& param) { // DebugTraceFunction; - return Configer::getParam(type, param); + std::unique_lock lock(m_mutex); + return m_configer.get_param(type, param); } void Assistance::workingProc(Assistance* pThis) @@ -144,14 +145,17 @@ void Assistance::workingProc(Assistance* pThis) std::string matched_task; Rect matched_rect; + for (auto&& task_name : pThis->m_next_tasks) { - auto&& task = Configer::m_tasks[task_name]; - double threshold = task.threshold; + + double threshold = pThis->m_configer.m_tasks[task_name].threshold; + double cache_threshold = pThis->m_configer.m_tasks[task_name].cache_threshold; + auto&& [algorithm, value, rect] = pThis->m_pIder->findImage(curImg, task_name, threshold); DebugTrace(task_name, "Type:", algorithm, "Value:", value); - if (algorithm == 0 || - (algorithm == 1 && value >= threshold) - || (algorithm == 2 && value >= task.cache_threshold)) { + if (algorithm == AlgorithmType::JustReturn || + (algorithm == AlgorithmType::MatchTemplate && value >= threshold) + || (algorithm == AlgorithmType::CompareHist && value >= cache_threshold)) { matched_task = task_name; matched_rect = rect; break; @@ -159,7 +163,7 @@ void Assistance::workingProc(Assistance* pThis) } if (!matched_task.empty()) { - auto&& task = Configer::m_tasks[matched_task]; + auto&& task = pThis->m_configer.m_tasks[matched_task]; DebugTraceInfo("***Matched***", matched_task, "Type:", task.type); if (task.pre_delay > 0) { DebugTrace("PreDelay", task.pre_delay); @@ -174,9 +178,9 @@ void Assistance::workingProc(Assistance* pThis) } if (task.exec_times < task.max_times) { if ((task.type & TaskType::BasicClick) - && Configer::m_options.control_delay_upper != 0) { + && pThis->m_configer.m_options.control_delay_upper != 0) { static std::default_random_engine rand_engine(std::chrono::system_clock::now().time_since_epoch().count()); - static std::uniform_int_distribution rand_uni(Configer::m_options.control_delay_lower, Configer::m_options.control_delay_upper); + static std::uniform_int_distribution rand_uni(pThis->m_configer.m_options.control_delay_lower, pThis->m_configer.m_options.control_delay_upper); int delay = rand_uni(rand_engine); DebugTraceInfo("Random Delay", delay, "ms"); bool cv_ret = pThis->m_condvar.wait_for(lock, std::chrono::milliseconds(delay), @@ -206,8 +210,8 @@ void Assistance::workingProc(Assistance* pThis) } ++task.exec_times; for (auto&& reduce : task.reduce_other_times) { - --Configer::m_tasks[reduce].exec_times; - DebugTrace("Reduce exec times", reduce, Configer::m_tasks[reduce].exec_times); + --pThis->m_configer.m_tasks[reduce].exec_times; + DebugTrace("Reduce exec times", reduce, pThis->m_configer.m_tasks[reduce].exec_times); } if (task.rear_delay > 0) { DebugTrace("RearDelay", task.rear_delay); @@ -216,11 +220,11 @@ void Assistance::workingProc(Assistance* pThis) [&]() -> bool { return !pThis->m_thread_running; }); if (cv_ret) { continue; } } - pThis->m_next_tasks = Configer::m_tasks[matched_task].next; + pThis->m_next_tasks = pThis->m_configer.m_tasks[matched_task].next; } else { DebugTraceInfo("Reached limit"); - pThis->m_next_tasks = Configer::m_tasks[matched_task].exceeded_next; + pThis->m_next_tasks = pThis->m_configer.m_tasks[matched_task].exceeded_next; } std::string nexts_str; @@ -233,7 +237,7 @@ void Assistance::workingProc(Assistance* pThis) DebugTrace("Next:", nexts_str); } pThis->m_condvar.wait_for(lock, - std::chrono::milliseconds(Configer::m_options.identify_delay), + std::chrono::milliseconds(pThis->m_configer.m_options.identify_delay), [&]() -> bool { return !pThis->m_thread_running; }); } else { diff --git a/MeoAssistance/src/AsstCaller.cpp b/MeoAssistance/src/AsstCaller.cpp index 481f77c98e..ac05ed7205 100644 --- a/MeoAssistance/src/AsstCaller.cpp +++ b/MeoAssistance/src/AsstCaller.cpp @@ -56,7 +56,7 @@ bool AsstSetParam(asst::Assistance* p_asst, const char* type, const char* param, return false; } - return p_asst->setParam(type, param, value); + return p_asst->set_param(type, param, value); } bool AsstGetParam(asst::Assistance* p_asst, const char* type, const char* param, char * buffer, int buffer_size) @@ -64,7 +64,7 @@ bool AsstGetParam(asst::Assistance* p_asst, const char* type, const char* param, if (p_asst == NULL) { return false; } - auto ret = p_asst->getParam(type, param); + auto ret = p_asst->get_param(type, param); if (!ret) { return false; } diff --git a/MeoAssistance/src/Configer.cpp b/MeoAssistance/src/Configer.cpp index 6234f6944c..7b1764ed92 100644 --- a/MeoAssistance/src/Configer.cpp +++ b/MeoAssistance/src/Configer.cpp @@ -3,24 +3,30 @@ #include #include #include -#include #include "json.h" -#include "AsstDef.h" -#include "AsstAux.h" #include "Logger.hpp" using namespace asst; -std::string Configer::m_curDir; -std::string Configer::m_version; -Options Configer::m_options; -std::unordered_map Configer::m_tasks; -std::unordered_map Configer::m_handles; - -bool Configer::reload() +Configer::Configer(const Configer& rhs) + : m_version(rhs.m_version), + m_options(rhs.m_options), + m_tasks(rhs.m_tasks), + m_handles(rhs.m_handles) +{ +} + +Configer::Configer(Configer&& rhs) noexcept + : m_version(std::move(rhs.m_version)), + m_options(std::move(rhs.m_options)), + m_tasks(std::move(rhs.m_tasks)), + m_handles(std::move(rhs.m_handles)) +{ +} + +bool Configer::reload(const std::string& filename) { - std::string filename = GetResourceDir() + "config.json"; std::ifstream ifs(filename, std::ios::in); if (!ifs.is_open()) { return false; @@ -37,14 +43,15 @@ bool Configer::reload() auto root = std::move(ret).value(); + Configer temp; try { - m_version = root["version"].as_string(); + temp.m_version = root["version"].as_string(); auto options_obj = root["options"].as_object(); - m_options.identify_delay = options_obj["identifyDelay"].as_integer(); - m_options.identify_cache = options_obj["identifyCache"].as_boolean(); - m_options.control_delay_lower = options_obj["controlDelayRange"][0].as_integer(); - m_options.control_delay_upper = options_obj["controlDelayRange"][1].as_integer(); + temp.m_options.identify_delay = options_obj["identifyDelay"].as_integer(); + temp.m_options.identify_cache = options_obj["identifyCache"].as_boolean(); + temp.m_options.control_delay_lower = options_obj["controlDelayRange"][0].as_integer(); + temp.m_options.control_delay_upper = options_obj["controlDelayRange"][1].as_integer(); auto tasks_obj = root["tasks"].as_object(); for (auto&& [name, task_json] : tasks_obj) { @@ -120,12 +127,13 @@ bool Configer::reload() task_info.next.emplace_back(name.as_string()); } - m_tasks.emplace(name, task_info); + temp.m_tasks.emplace(name, task_info); } auto handle_obj = root["handle"].as_object(); for (auto&& [name, simulator_json] : handle_obj) { SimulatorInfo simulator_info; + simulator_info.name = name; auto window_arr = simulator_json["window"].as_array(); for (auto&& info : window_arr) { @@ -160,7 +168,7 @@ bool Configer::reload() simulator_info.x_offset = simulator_json["xOffset"].as_integer(); simulator_info.y_offset = simulator_json["yOffset"].as_integer(); - m_handles.emplace(name, simulator_info); + temp.m_handles.emplace(name, simulator_info); } } catch (json::exception& e) { @@ -168,10 +176,12 @@ bool Configer::reload() return false; } + *this = std::move(temp); + return true; } -bool Configer::setParam(const std::string& type, const std::string& param, const std::string& value) +bool Configer::set_param(const std::string& type, const std::string& param, const std::string& value) { if (type == "task.type") { if (m_tasks.find(param) == m_tasks.cend()) { @@ -209,7 +219,7 @@ bool Configer::setParam(const std::string& type, const std::string& param, const return true; } -std::optional Configer::getParam(const std::string& type, const std::string& param) +std::optional Configer::get_param(const std::string& type, const std::string& param) { if (type == "task.execTimes" && m_tasks.find(param) != m_tasks.cend()) { return std::to_string(m_tasks.at(param).exec_times); @@ -217,9 +227,29 @@ std::optional Configer::getParam(const std::string& type, const std return std::nullopt; } -void Configer::clearExecTimes() +void Configer::clear_exec_times() { for (auto&& t : m_tasks) { t.second.exec_times = 0; } +} + +Configer& asst::Configer::operator=(const Configer& rhs) +{ + m_version = rhs.m_version; + m_options = rhs.m_options; + m_tasks = rhs.m_tasks; + m_handles = rhs.m_handles; + + return *this; +} + +Configer& asst::Configer::operator=(Configer&& rhs) noexcept +{ + m_version = std::move(rhs.m_version); + m_options = std::move(rhs.m_options); + m_tasks = std::move(rhs.m_tasks); + m_handles = std::move(rhs.m_handles); + + return *this; } \ No newline at end of file diff --git a/MeoAssistance/src/Identify.cpp b/MeoAssistance/src/Identify.cpp index c2cc74785d..150f93dd62 100644 --- a/MeoAssistance/src/Identify.cpp +++ b/MeoAssistance/src/Identify.cpp @@ -68,16 +68,16 @@ std::pair Identify::findImage(const cv::Mat& image, const cv: return { maxVal, maxLoc }; } -std::tuple Identify::findImage(const Mat& cur, const std::string& templ, double threshold) +std::tuple Identify::findImage(const Mat& cur, const std::string& templ, double threshold) { if (m_mat_map.find(templ) == m_mat_map.cend()) { - return { 0, 0, asst::Rect() }; + return { AlgorithmType::JustReturn, 0, asst::Rect() }; } if (m_use_cache && m_cache_map.find(templ) != m_cache_map.cend()) { auto&& [rect, hist] = m_cache_map.at(templ); double value = imageHistComp(cur(rect), hist); - return { 2, value, cvRect2Rect(rect).center_zoom(0.8) }; + return { AlgorithmType::CompareHist, value, cvRect2Rect(rect).center_zoom(0.8) }; } else { auto&& templ_mat = m_mat_map.at(templ); @@ -88,7 +88,7 @@ std::tuple Identify::findImage(const Mat& cur, const st m_cache_map.emplace(templ, std::make_pair(raw_rect, image2Hist(cur(raw_rect)))); } - return { 1, value, cvRect2Rect(raw_rect).center_zoom(0.8) }; + return { AlgorithmType::MatchTemplate, value, cvRect2Rect(raw_rect).center_zoom(0.8) }; } } diff --git a/MeoAssistance/src/WinMacro.cpp b/MeoAssistance/src/WinMacro.cpp index d19ff7f125..64a636dfd7 100644 --- a/MeoAssistance/src/WinMacro.cpp +++ b/MeoAssistance/src/WinMacro.cpp @@ -8,14 +8,13 @@ #include #include -#include "Configer.h" #include "AsstDef.h" #include "Logger.hpp" using namespace asst; -WinMacro::WinMacro(const std::string& simulator_name, HandleType type) - : m_simulator_name(simulator_name), +WinMacro::WinMacro(const SimulatorInfo& info, HandleType type) + : m_simulator_info(info), m_handle_type(type), m_rand_engine(std::chrono::system_clock::now().time_since_epoch().count()) { @@ -30,21 +29,20 @@ bool WinMacro::captured() const noexcept bool WinMacro::findHandle() { std::vector handle_vec; - auto&& info = Configer::m_handles[m_simulator_name]; switch (m_handle_type) { case HandleType::Window: - m_width = info.width; - m_height = info.height; - handle_vec = info.window; + m_width = m_simulator_info.width; + m_height = m_simulator_info.height; + handle_vec = m_simulator_info.window; break; case HandleType::View: - handle_vec = info.view; + handle_vec = m_simulator_info.view; break; case HandleType::Control: - m_is_adb = info.is_adb; - m_x_offset = info.x_offset; - m_y_offset = info.y_offset; - handle_vec = info.control; + m_is_adb = m_simulator_info.is_adb; + m_x_offset = m_simulator_info.x_offset; + m_y_offset = m_simulator_info.y_offset; + handle_vec = m_simulator_info.control; break; default: DebugTraceError("Handle type error!", m_handle_type); @@ -95,14 +93,14 @@ bool WinMacro::findHandle() } size_t pos = adb_dir.find_last_of('\\') + 1; adb_dir = adb_dir.substr(0, pos); - adb_dir = '"' + StringReplaceAll(info.adb.path, "[EmulatorPath]", adb_dir) + '"'; - std::string connect_cmd = adb_dir + info.adb.connect; + adb_dir = '"' + StringReplaceAll(m_simulator_info.adb.path, "[EmulatorPath]", adb_dir) + '"'; + std::string connect_cmd = adb_dir + m_simulator_info.adb.connect; int ret = system(connect_cmd.c_str()); DebugTrace("Call", connect_cmd, "¡ª¡ª ret", ret); - m_click_cmd = adb_dir + info.adb.click; + m_click_cmd = adb_dir + m_simulator_info.adb.click; } - DebugTrace("Handle:", m_handle, "Name:", m_simulator_name, "Type:", m_handle_type); + DebugTrace("Handle:", m_handle, "Name:", m_simulator_info.name, "Type:", m_handle_type); if (m_handle != NULL) { return true;