mirror of
https://github.com/MaaAssistantArknights/MaaAssistantArknights.git
synced 2026-07-19 02:23:01 +08:00
feat.新增信用商店自动购买的任务
This commit is contained in:
BIN
resource/template/special/BuyIt.png
Normal file
BIN
resource/template/special/BuyIt.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.0 KiB |
BIN
resource/template/special/CreditPoint.png
Normal file
BIN
resource/template/special/CreditPoint.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
BIN
resource/template/special/SoldOut.png
Normal file
BIN
resource/template/special/SoldOut.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.0 KiB |
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
116
src/MeoAssistance/CreditShoppingTask.cpp
Normal file
116
src/MeoAssistance/CreditShoppingTask.cpp
Normal 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;
|
||||
}
|
||||
18
src/MeoAssistance/CreditShoppingTask.h
Normal file
18
src/MeoAssistance/CreditShoppingTask.h
Normal 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:
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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(); // 往右划(只滑一下)
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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>
|
||||
16
src/MeoAssistance/ScreenCaptureTask.cpp
Normal file
16
src/MeoAssistance/ScreenCaptureTask.cpp
Normal 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);
|
||||
}
|
||||
15
src/MeoAssistance/ScreenCaptureTask.h
Normal file
15
src/MeoAssistance/ScreenCaptureTask.h
Normal 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:
|
||||
};
|
||||
}
|
||||
@@ -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"
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user