diff --git a/resource/template/special/BuyIt.png b/resource/template/special/BuyIt.png new file mode 100644 index 0000000000..f622d7ddce Binary files /dev/null and b/resource/template/special/BuyIt.png differ diff --git a/resource/template/special/CreditPoint.png b/resource/template/special/CreditPoint.png new file mode 100644 index 0000000000..cf6c5f088a Binary files /dev/null and b/resource/template/special/CreditPoint.png differ diff --git a/resource/template/special/SoldOut.png b/resource/template/special/SoldOut.png new file mode 100644 index 0000000000..91a075de63 Binary files /dev/null and b/resource/template/special/SoldOut.png differ diff --git a/src/MeoAssistance/AbstractTask.cpp b/src/MeoAssistance/AbstractTask.cpp index 18dc862ed2..69bf975cf4 100644 --- a/src/MeoAssistance/AbstractTask.cpp +++ b/src/MeoAssistance/AbstractTask.cpp @@ -10,6 +10,7 @@ #include "Identify.h" #include "Configer.h" #include "AsstAux.h" +#include "Logger.hpp" using namespace asst; @@ -58,7 +59,7 @@ bool AbstractTask::sleep(unsigned millisecond) return !need_exit(); } -bool AbstractTask::print_window(const std::string& dir) +bool AbstractTask::print_window(const std::string& dir, bool raw) { //const cv::Mat& image = m_controller_ptr->get_image(true); //if (image.empty()) { @@ -73,7 +74,7 @@ bool AbstractTask::print_window(const std::string& dir) const std::string time_str = StringReplaceAll(StringReplaceAll(GetFormatTimeString(), " ", "_"), ":", "-"); const std::string filename = dir + time_str + ".png"; - bool ret = cv::imwrite(filename, m_controller_ptr->get_image(true)); + bool ret = cv::imwrite(filename, m_controller_ptr->get_image(raw)); json::value callback_json; callback_json["filename"] = filename; @@ -97,4 +98,12 @@ bool asst::AbstractTask::is_ptr_inited() const noexcept return false; } return true; +} + +bool asst::AbstractTask::click_return_button() +{ + DebugTraceFunction; + + const static Rect ConfirmButtonRect(20, 20, 135, 35); + return m_controller_ptr->click(ConfirmButtonRect); } \ No newline at end of file diff --git a/src/MeoAssistance/AbstractTask.h b/src/MeoAssistance/AbstractTask.h index 45ec43c3ab..abf73bfe1c 100644 --- a/src/MeoAssistance/AbstractTask.h +++ b/src/MeoAssistance/AbstractTask.h @@ -32,10 +32,12 @@ namespace asst { virtual void on_run_fails(int retry_times) { ; } protected: virtual bool sleep(unsigned millisecond); - virtual bool print_window(const std::string& dir); + virtual bool print_window(const std::string& dir, bool raw = true); virtual bool need_exit() const noexcept; virtual bool is_ptr_inited() const noexcept; + virtual bool click_return_button(); + std::shared_ptr m_controller_ptr = nullptr; std::shared_ptr m_identify_ptr = nullptr; diff --git a/src/MeoAssistance/Assistance.cpp b/src/MeoAssistance/Assistance.cpp index e5aedbfea9..5329b4906e 100644 --- a/src/MeoAssistance/Assistance.cpp +++ b/src/MeoAssistance/Assistance.cpp @@ -285,9 +285,9 @@ bool Assistance::start_debug_task() // m_tasks_deque.emplace_back(shift_task_ptr); //} { - constexpr static const char* InfrastTaskCahin = "Debug"; - auto shift_task_ptr = std::make_shared(task_callback, (void*)this); - shift_task_ptr->set_task_chain(InfrastTaskCahin); + constexpr static const char* DebugTaskChain = "Debug"; + auto shift_task_ptr = std::make_shared(task_callback, (void*)this); + shift_task_ptr->set_task_chain(DebugTaskChain); m_tasks_deque.emplace_back(shift_task_ptr); } diff --git a/src/MeoAssistance/CreditShoppingTask.cpp b/src/MeoAssistance/CreditShoppingTask.cpp new file mode 100644 index 0000000000..5c39937de2 --- /dev/null +++ b/src/MeoAssistance/CreditShoppingTask.cpp @@ -0,0 +1,116 @@ +#include "CreditShoppingTask.h" + +#include +#include + +#include + +#include "Identify.h" +#include "WinMacro.h" +#include "Configer.h" + +bool asst::CreditShoppingTask::run() +{ + if (m_controller_ptr == nullptr + || m_identify_ptr == nullptr) + { + m_callback(AsstMsg::PtrIsNull, json::value(), m_callback_arg); + return false; + } + + cv::Mat image = m_controller_ptr->get_image(); + + // 识别信用点的图标 + auto find_res_vec = m_identify_ptr->find_all_images(image, "CreditPoint", Configer::TemplThresholdDefault, false); + + // 按位置排个序 + std::sort(find_res_vec.begin(), find_res_vec.end(), []( + const auto& lhs, const auto& rhs) -> bool { + if (std::abs(lhs.rect.y - rhs.rect.y) < 5) { // y差距较小则理解为是同一排的,按x排序 + return lhs.rect.x < rhs.rect.x; + } + else { + return lhs.rect.y < rhs.rect.y; + } + }); + + // 计算哪些商品是需要买的 + std::vector need_to_buy; + for (const auto& res : find_res_vec) { + cv::Rect name_rect; + name_rect.x = res.rect.x - 80; + name_rect.y = res.rect.y - 210; + name_rect.width = 230; + name_rect.height = 70; + if (name_rect.x < 0) { + name_rect.x = 0; + } + // 过滤掉不买的 + // TODO,哪些要买哪些不买,提供个接口出去 + static const std::vector not_to_buy_names = { "碳", "家具" }; + const auto& ocr_res = m_identify_ptr->ocr_detect(image(name_rect)); + auto find_iter = std::find_first_of(ocr_res.cbegin(), ocr_res.cend(), not_to_buy_names.cbegin(), not_to_buy_names.cend(), + [](const auto& lhs, const std::string& rhs) -> bool { + return lhs.text.find(rhs) != std::string::npos; + }); + if (find_iter != ocr_res.cend()) { +#ifdef LOG_TRACE + cv::putText(image, "Not to buy", cv::Point(res.rect.x, res.rect.y), 1, 2, cv::Scalar(255, 0, 0)); +#endif // LOG_TRACE + continue; + } + Rect commodity_rect(res.rect.x - 60, res.rect.y - 180, 220, 220); + // 识别“售罄” + auto sold_out_res = m_identify_ptr->find_image(image(make_rect(commodity_rect)), "SoldOut"); + +#ifdef LOG_TRACE + cv::rectangle(image, make_rect(commodity_rect), cv::Scalar(0, 0, 255)); + if (sold_out_res.score >= Configer::TemplThresholdDefault) { + cv::putText(image, "Sold Out", cv::Point(commodity_rect.x, commodity_rect.y), 1, 2, cv::Scalar(255, 0, 0)); + } +#endif // LOG_TRACE + + if (sold_out_res.score >= Configer::TemplThresholdDefault) { + continue; + } + need_to_buy.emplace_back(commodity_rect.center_zoom(0.8)); + } + + for (const Rect& commodity_rect : need_to_buy) { + m_controller_ptr->click(commodity_rect); + sleep(1000); + image = m_controller_ptr->get_image(); + + // “购买商品”按钮 + static Rect buy_it_rect; + if (buy_it_rect.width == 0) { + auto buy_it_res = m_identify_ptr->find_image(image, "BuyIt", Configer::TemplThresholdDefault); + if (buy_it_res.score < Configer::TemplThresholdDefault) { + // 没事别到“购买商品”按钮,不应该出现这种情况,TODO 报错 + return false; + } + buy_it_rect = buy_it_res.rect; + } + + m_controller_ptr->click(buy_it_rect); + sleep(1000); + // 识别是否信用不足无法购买 + image = m_controller_ptr->get_image(); + static const std::vector shopping_finished = { "信用不足", "无法购买" }; + const auto& ocr_res = ocr_detect(image(cv::Rect(940, 60, 339, 110))); + auto find_iter = std::find_first_of(ocr_res.cbegin(), ocr_res.cend(), shopping_finished.cbegin(), shopping_finished.cend(), + [](const auto& lhs, const std::string& rhs) -> bool { + return lhs.text.find(rhs) != std::string::npos; + }); + if (find_iter != ocr_res.cend()) { + click_return_button(); + return true; + } + + // 这里随便点一下都行,把购买完弹出来物品的界面取消掉 + m_controller_ptr->click(buy_it_rect); + sleep(1000); + } + + return true; +} diff --git a/src/MeoAssistance/CreditShoppingTask.h b/src/MeoAssistance/CreditShoppingTask.h new file mode 100644 index 0000000000..f7c7f9ab90 --- /dev/null +++ b/src/MeoAssistance/CreditShoppingTask.h @@ -0,0 +1,18 @@ +#pragma once +#include "OcrAbstractTask.h" + +#include + +#include "AsstDef.h" + +namespace asst { + class CreditShoppingTask : public OcrAbstractTask + { + public: + using OcrAbstractTask::OcrAbstractTask; + virtual ~CreditShoppingTask() = default; + virtual bool run() override; + private: + }; + +} \ No newline at end of file diff --git a/src/MeoAssistance/InfrastAbstractTask.cpp b/src/MeoAssistance/InfrastAbstractTask.cpp index ce88393e62..be130de386 100644 --- a/src/MeoAssistance/InfrastAbstractTask.cpp +++ b/src/MeoAssistance/InfrastAbstractTask.cpp @@ -59,14 +59,6 @@ bool asst::InfrastAbstractTask::click_confirm_button() return m_controller_ptr->click(ConfirmButtonRect); } -bool asst::InfrastAbstractTask::click_return_button() -{ - DebugTraceFunction; - - const static Rect ConfirmButtonRect(20, 20, 135, 35); - return m_controller_ptr->click(ConfirmButtonRect); -} - bool asst::InfrastAbstractTask::swipe(bool reverse) { DebugTraceFunction; diff --git a/src/MeoAssistance/InfrastAbstractTask.h b/src/MeoAssistance/InfrastAbstractTask.h index 830baf73cd..f2cfb51c56 100644 --- a/src/MeoAssistance/InfrastAbstractTask.h +++ b/src/MeoAssistance/InfrastAbstractTask.h @@ -17,7 +17,6 @@ namespace asst { virtual bool swipe_to_the_left(); // 滑动到最左侧 virtual bool click_clear_button(); virtual bool click_confirm_button(); - virtual bool click_return_button(); virtual bool swipe(bool reverse = false); virtual bool swipe_left(); // 往左划(只滑一下) virtual bool swipe_right(); // 往右划(只滑一下) diff --git a/src/MeoAssistance/MeoAssistance.vcxproj b/src/MeoAssistance/MeoAssistance.vcxproj index 3ecb2695df..03bd41b182 100644 --- a/src/MeoAssistance/MeoAssistance.vcxproj +++ b/src/MeoAssistance/MeoAssistance.vcxproj @@ -20,6 +20,7 @@ + @@ -33,6 +34,7 @@ + @@ -42,6 +44,7 @@ + @@ -57,6 +60,7 @@ + diff --git a/src/MeoAssistance/MeoAssistance.vcxproj.filters b/src/MeoAssistance/MeoAssistance.vcxproj.filters index 01e227157f..edf3f64123 100644 --- a/src/MeoAssistance/MeoAssistance.vcxproj.filters +++ b/src/MeoAssistance/MeoAssistance.vcxproj.filters @@ -117,6 +117,12 @@ 头文件\Configer + + 头文件\Task + + + 头文件\Task + @@ -179,5 +185,11 @@ 源文件\Configer + + 源文件\Task + + + 源文件\Task + \ No newline at end of file diff --git a/src/MeoAssistance/ScreenCaptureTask.cpp b/src/MeoAssistance/ScreenCaptureTask.cpp new file mode 100644 index 0000000000..1fbd7257a6 --- /dev/null +++ b/src/MeoAssistance/ScreenCaptureTask.cpp @@ -0,0 +1,16 @@ +#include "ScreenCaptureTask.h" + +#include "AsstAux.h" + +bool asst::ScreenCaptureTask::run() +{ + if (m_controller_ptr == nullptr + || m_identify_ptr == nullptr) + { + m_callback(AsstMsg::PtrIsNull, json::value(), m_callback_arg); + return false; + } + + static const std::string dirname = GetCurrentDir() + "template\\"; + return print_window(dirname, false); +} \ No newline at end of file diff --git a/src/MeoAssistance/ScreenCaptureTask.h b/src/MeoAssistance/ScreenCaptureTask.h new file mode 100644 index 0000000000..c42cae61dd --- /dev/null +++ b/src/MeoAssistance/ScreenCaptureTask.h @@ -0,0 +1,15 @@ +#pragma once +#include "AbstractTask.h" + +namespace asst { + // 截图任务,主要是调试用的,制作模板匹配的素材啥的 + class ScreenCaptureTask : public AbstractTask + { + public: + using AbstractTask::AbstractTask; + virtual ~ScreenCaptureTask() = default; + + virtual bool run() override; + private: + }; +} \ No newline at end of file diff --git a/src/MeoAssistance/Task.h b/src/MeoAssistance/Task.h index dad8d3014a..2232ed7e6d 100644 --- a/src/MeoAssistance/Task.h +++ b/src/MeoAssistance/Task.h @@ -6,4 +6,6 @@ #include "InfrastProductionTask.h" #include "InfrastDormTask.h" #include "InfrastPowerTask.h" -#include "InfrastOfficeTask.h" \ No newline at end of file +#include "InfrastOfficeTask.h" +#include "ScreenCaptureTask.h" +#include "CreditShoppingTask.h" \ No newline at end of file diff --git a/src/MeoAssistance/WinMacro.cpp b/src/MeoAssistance/WinMacro.cpp index d31f34147c..a88de13b1a 100644 --- a/src/MeoAssistance/WinMacro.cpp +++ b/src/MeoAssistance/WinMacro.cpp @@ -333,12 +333,19 @@ void asst::WinMacro::wait(unsigned id) const noexcept } } -void asst::WinMacro::screencap() +bool asst::WinMacro::screencap() { DebugTraceFunction; auto data = call_command(m_emulator_info.adb.screencap); - m_cache_image = cv::imdecode(data, cv::IMREAD_COLOR); + if (!data.empty()) { + m_cache_image = cv::imdecode(data, cv::IMREAD_COLOR); + return true; + } + else { + DebugTraceError("Screencap is empty!"); + return false; + } //cv::Mat temp_image = cv::imdecode(data, cv::IMREAD_COLOR); ////std::unique_lock image_lock(m_image_mutex); @@ -418,7 +425,9 @@ int asst::WinMacro::swipe_without_scale(const Rect& r1, const Rect& r2, int dura cv::Mat asst::WinMacro::get_image(bool raw) { - screencap(); + if (!screencap()) { + return cv::Mat(); + } //std::shared_lock image_lock(m_image_mutex); if (raw) { return m_cache_image; diff --git a/src/MeoAssistance/WinMacro.h b/src/MeoAssistance/WinMacro.h index d2e2ad6e61..cc94d37a68 100644 --- a/src/MeoAssistance/WinMacro.h +++ b/src/MeoAssistance/WinMacro.h @@ -46,7 +46,7 @@ namespace asst { std::vector call_command(const std::string& cmd); int push_cmd(const std::string& cmd); void wait(unsigned id) const noexcept; - void screencap(); + bool screencap(); Point rand_point_in_rect(const Rect& rect); diff --git a/tools/TestCaller/main.cpp b/tools/TestCaller/main.cpp index c7616017c8..f7411e2922 100644 --- a/tools/TestCaller/main.cpp +++ b/tools/TestCaller/main.cpp @@ -17,8 +17,8 @@ int main(int argc, char** argv) char ch = 0; while (ch != 'q') { //AsstStartIndertifyOpers(ptr); - AsstStartInfrast(ptr); - //AsstStartDebugTask(ptr); + //AsstStartInfrast(ptr); + AsstStartDebugTask(ptr); //{ // const int required[] = { 3, 4, 5, 6 }; // AsstStartOpenRecruit(ptr, required, sizeof(required)/sizeof(int), true);