feat.新增信用商店自动购买的任务

This commit is contained in:
MistEO
2021-09-24 21:19:59 +08:00
parent 1d438b6df8
commit 780c3e1cf1
18 changed files with 216 additions and 22 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -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);
}

View File

@@ -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<WinMacro> m_controller_ptr = nullptr;
std::shared_ptr<Identify> m_identify_ptr = nullptr;

View File

@@ -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<InfrastOfficeTask>(task_callback, (void*)this);
shift_task_ptr->set_task_chain(InfrastTaskCahin);
constexpr static const char* DebugTaskChain = "Debug";
auto shift_task_ptr = std::make_shared<CreditShoppingTask>(task_callback, (void*)this);
shift_task_ptr->set_task_chain(DebugTaskChain);
m_tasks_deque.emplace_back(shift_task_ptr);
}

View File

@@ -0,0 +1,116 @@
#include "CreditShoppingTask.h"
#include <vector>
#include <algorithm>
#include <opencv2/opencv.hpp>
#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<Rect> 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<std::string> 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<cv::Rect>(commodity_rect)), "SoldOut");
#ifdef LOG_TRACE
cv::rectangle(image, make_rect<cv::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<std::string> 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;
}

View File

@@ -0,0 +1,18 @@
#pragma once
#include "OcrAbstractTask.h"
#include <vector>
#include "AsstDef.h"
namespace asst {
class CreditShoppingTask : public OcrAbstractTask
{
public:
using OcrAbstractTask::OcrAbstractTask;
virtual ~CreditShoppingTask() = default;
virtual bool run() override;
private:
};
}

View File

@@ -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;

View File

@@ -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(); // 往右划(只滑一下)

View File

@@ -20,6 +20,7 @@
<ClInclude Include="AsstDef.h" />
<ClInclude Include="AsstMsg.h" />
<ClInclude Include="Configer.h" />
<ClInclude Include="CreditShoppingTask.h" />
<ClInclude Include="Identify.h" />
<ClInclude Include="IdentifyOperTask.h" />
<ClInclude Include="InfrastAbstractTask.h" />
@@ -33,6 +34,7 @@
<ClInclude Include="OpenRecruitTask.h" />
<ClInclude Include="ProcessTask.h" />
<ClInclude Include="RecruitConfiger.h" />
<ClInclude Include="ScreenCaptureTask.h" />
<ClInclude Include="Task.h" />
<ClInclude Include="TaskConfiger.h" />
<ClInclude Include="UserConfiger.h" />
@@ -42,6 +44,7 @@
<ItemGroup>
<ClCompile Include="AbstractConfiger.cpp" />
<ClCompile Include="AbstractTask.cpp" />
<ClCompile Include="CreditShoppingTask.cpp" />
<ClCompile Include="IdentifyOperTask.cpp" />
<ClCompile Include="InfrastAbstractTask.cpp" />
<ClCompile Include="InfrastConfiger.cpp" />
@@ -57,6 +60,7 @@
<ClCompile Include="OpenRecruitTask.cpp" />
<ClCompile Include="ProcessTask.cpp" />
<ClCompile Include="RecruitConfiger.cpp" />
<ClCompile Include="ScreenCaptureTask.cpp" />
<ClCompile Include="TaskConfiger.cpp" />
<ClCompile Include="UserConfiger.cpp" />
<ClCompile Include="WinMacro.cpp" />

View File

@@ -117,6 +117,12 @@
<ClInclude Include="UserConfiger.h">
<Filter>头文件\Configer</Filter>
</ClInclude>
<ClInclude Include="ScreenCaptureTask.h">
<Filter>头文件\Task</Filter>
</ClInclude>
<ClInclude Include="CreditShoppingTask.h">
<Filter>头文件\Task</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="WinMacro.cpp">
@@ -179,5 +185,11 @@
<ClCompile Include="UserConfiger.cpp">
<Filter>源文件\Configer</Filter>
</ClCompile>
<ClCompile Include="ScreenCaptureTask.cpp">
<Filter>源文件\Task</Filter>
</ClCompile>
<ClCompile Include="CreditShoppingTask.cpp">
<Filter>源文件\Task</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -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);
}

View File

@@ -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:
};
}

View File

@@ -6,4 +6,6 @@
#include "InfrastProductionTask.h"
#include "InfrastDormTask.h"
#include "InfrastPowerTask.h"
#include "InfrastOfficeTask.h"
#include "InfrastOfficeTask.h"
#include "ScreenCaptureTask.h"
#include "CreditShoppingTask.h"

View File

@@ -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<std::shared_mutex> 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<std::shared_mutex> image_lock(m_image_mutex);
if (raw) {
return m_cache_image;

View File

@@ -46,7 +46,7 @@ namespace asst {
std::vector<unsigned char> 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);

View File

@@ -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);