整理目录结构,分离Task

This commit is contained in:
MistEO
2021-08-20 16:24:04 +08:00
parent 9d15b33b50
commit 2af89dfed6
46 changed files with 1717 additions and 1854 deletions

View File

@@ -1,76 +1,58 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30717.126
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MeoAssistance", "MeoAssistance\MeoAssistance.vcxproj", "{362D1E30-F5AE-4279-9985-65C27B3BA300}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Sanity", "Tools\Sanity\Sanity.vcxproj", "{36BC08F3-71CF-429A-AE69-291BE8962CB2}"
ProjectSection(ProjectDependencies) = postProject
{362D1E30-F5AE-4279-9985-65C27B3BA300} = {362D1E30-F5AE-4279-9985-65C27B3BA300}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MeoAsstGui", "MeoAsstGui\MeoAsstGui.csproj", "{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}"
ProjectSection(ProjectDependencies) = postProject
{362D1E30-F5AE-4279-9985-65C27B3BA300} = {362D1E30-F5AE-4279-9985-65C27B3BA300}
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{6C4B8D52-51D1-45F8-AAEC-808035443FD6}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestCaller", "Tools\TestCaller\TestCaller.vcxproj", "{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}"
ProjectSection(ProjectDependencies) = postProject
{362D1E30-F5AE-4279-9985-65C27B3BA300} = {362D1E30-F5AE-4279-9985-65C27B3BA300}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Release|x64 = Release|x64
Release|x86 = Release|x86
RelWithDebInfo|x64 = RelWithDebInfo|x64
RelWithDebInfo|x86 = RelWithDebInfo|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Release|x64.ActiveCfg = Release|x64
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Release|x64.Build.0 = Release|x64
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Release|x86.ActiveCfg = Release|Win32
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Release|x86.Build.0 = Release|Win32
{362D1E30-F5AE-4279-9985-65C27B3BA300}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
{362D1E30-F5AE-4279-9985-65C27B3BA300}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
{362D1E30-F5AE-4279-9985-65C27B3BA300}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|Win32
{362D1E30-F5AE-4279-9985-65C27B3BA300}.RelWithDebInfo|x86.Build.0 = RelWithDebInfo|Win32
{36BC08F3-71CF-429A-AE69-291BE8962CB2}.Release|x64.ActiveCfg = Release|x64
{36BC08F3-71CF-429A-AE69-291BE8962CB2}.Release|x64.Build.0 = Release|x64
{36BC08F3-71CF-429A-AE69-291BE8962CB2}.Release|x86.ActiveCfg = Release|Win32
{36BC08F3-71CF-429A-AE69-291BE8962CB2}.Release|x86.Build.0 = Release|Win32
{36BC08F3-71CF-429A-AE69-291BE8962CB2}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
{36BC08F3-71CF-429A-AE69-291BE8962CB2}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
{36BC08F3-71CF-429A-AE69-291BE8962CB2}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|Win32
{36BC08F3-71CF-429A-AE69-291BE8962CB2}.RelWithDebInfo|x86.Build.0 = RelWithDebInfo|Win32
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Release|x64.ActiveCfg = Release|Any CPU
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Release|x64.Build.0 = Release|Any CPU
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Release|x86.ActiveCfg = Release|Any CPU
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Release|x86.Build.0 = Release|Any CPU
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Any CPU
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|Any CPU
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|Any CPU
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.RelWithDebInfo|x86.Build.0 = RelWithDebInfo|Any CPU
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.Release|x64.ActiveCfg = Release|x64
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.Release|x64.Build.0 = Release|x64
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.Release|x86.ActiveCfg = Release|Win32
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.Release|x86.Build.0 = Release|Win32
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|Win32
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.RelWithDebInfo|x86.Build.0 = RelWithDebInfo|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{36BC08F3-71CF-429A-AE69-291BE8962CB2} = {6C4B8D52-51D1-45F8-AAEC-808035443FD6}
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64} = {6C4B8D52-51D1-45F8-AAEC-808035443FD6}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4F2C0E4B-4FE9-47C6-A878-6BD2FAD8B9B2}
EndGlobalSection
EndGlobal
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30717.126
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MeoAssistance", "MeoAssistance\MeoAssistance.vcxproj", "{362D1E30-F5AE-4279-9985-65C27B3BA300}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Sanity", "Tools\Sanity\Sanity.vcxproj", "{36BC08F3-71CF-429A-AE69-291BE8962CB2}"
ProjectSection(ProjectDependencies) = postProject
{362D1E30-F5AE-4279-9985-65C27B3BA300} = {362D1E30-F5AE-4279-9985-65C27B3BA300}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MeoAsstGui", "MeoAsstGui\MeoAsstGui.csproj", "{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}"
ProjectSection(ProjectDependencies) = postProject
{362D1E30-F5AE-4279-9985-65C27B3BA300} = {362D1E30-F5AE-4279-9985-65C27B3BA300}
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{6C4B8D52-51D1-45F8-AAEC-808035443FD6}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestCaller", "Tools\TestCaller\TestCaller.vcxproj", "{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}"
ProjectSection(ProjectDependencies) = postProject
{362D1E30-F5AE-4279-9985-65C27B3BA300} = {362D1E30-F5AE-4279-9985-65C27B3BA300}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Release|x64 = Release|x64
RelWithDebInfo|x64 = RelWithDebInfo|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Release|x64.ActiveCfg = Release|x64
{362D1E30-F5AE-4279-9985-65C27B3BA300}.Release|x64.Build.0 = Release|x64
{362D1E30-F5AE-4279-9985-65C27B3BA300}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
{362D1E30-F5AE-4279-9985-65C27B3BA300}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
{36BC08F3-71CF-429A-AE69-291BE8962CB2}.Release|x64.ActiveCfg = Release|x64
{36BC08F3-71CF-429A-AE69-291BE8962CB2}.Release|x64.Build.0 = Release|x64
{36BC08F3-71CF-429A-AE69-291BE8962CB2}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
{36BC08F3-71CF-429A-AE69-291BE8962CB2}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Release|x64.ActiveCfg = Release|Any CPU
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.Release|x64.Build.0 = Release|Any CPU
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Any CPU
{FFDC8F49-8EAF-45BE-B0A8-7EF0DB9875A2}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|Any CPU
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.Release|x64.ActiveCfg = Release|x64
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.Release|x64.Build.0 = Release|x64
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{36BC08F3-71CF-429A-AE69-291BE8962CB2} = {6C4B8D52-51D1-45F8-AAEC-808035443FD6}
{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64} = {6C4B8D52-51D1-45F8-AAEC-808035443FD6}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4F2C0E4B-4FE9-47C6-A878-6BD2FAD8B9B2}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,145 @@
#include "AbstractTask.h"
#include <algorithm>
#include <filesystem>
#include <thread>
#include <opencv2/opencv.hpp>
#include "WinMacro.h"
#include "Identify.h"
#include "Configer.h"
#include "AsstAux.h"
using namespace asst;
AbstractTask::AbstractTask(AsstCallback callback, void* callback_arg)
:m_callback(callback),
m_callback_arg(callback_arg)
{
;
}
void AbstractTask::set_ptr(
std::shared_ptr<WinMacro> window_ptr,
std::shared_ptr<WinMacro> view_ptr,
std::shared_ptr<WinMacro> control_ptr,
std::shared_ptr<Identify> identify_ptr)
{
m_window_ptr = window_ptr;
m_view_ptr = view_ptr;
m_control_ptr = control_ptr;
m_identify_ptr = identify_ptr;
}
void AbstractTask::set_exit_flag(bool* exit_flag)
{
m_exit_flag = exit_flag;
}
cv::Mat AbstractTask::get_format_image(bool hd)
{
cv::Mat raw_image;
if (hd) {
raw_image = m_view_ptr->getAdbImage();
}
else {
raw_image = m_view_ptr->getImage(m_view_ptr->getWindowRect());
}
if (raw_image.empty()) {
m_callback(AsstMsg::ImageIsEmpty, json::value(), m_callback_arg);
return raw_image;
}
if (raw_image.rows < 100) {
m_callback(AsstMsg::WindowMinimized, json::value(), m_callback_arg);
return raw_image;
}
if (hd) {
set_control_scale(1.0);
return raw_image;
}
else {
// 把模拟器边框的一圈裁剪掉
const EmulatorInfo& window_info = m_view_ptr->getEmulatorInfo();
int x_offset = window_info.x_offset;
int y_offset = window_info.y_offset;
int width = raw_image.cols - x_offset - window_info.right_offset;
int height = raw_image.rows - y_offset - window_info.bottom_offset;
cv::Mat cropped(raw_image, cv::Rect(x_offset, y_offset, width, height));
// 根据图像尺寸,调整控制的缩放
set_control_scale(cropped.cols, cropped.rows);
//// 调整尺寸,与资源中截图的标准尺寸一致
//cv::Mat dst;
//cv::resize(cropped, dst, cv::Size(m_configer.DefaultWindowWidth, m_configer.DefaultWindowHeight));
return cropped;
}
}
bool asst::AbstractTask::set_control_scale(double scale)
{
m_control_ptr->setControlScale(scale, true);
return true;
}
bool AbstractTask::set_control_scale(int cur_width, int cur_height)
{
double scale_width = static_cast<double>(cur_width) / Configer::DefaultWindowWidth;
double scale_height = static_cast<double>(cur_height) / Configer::DefaultWindowHeight;
double scale = (std::max)(scale_width, scale_height);
m_control_ptr->setControlScale(scale);
return true;
}
bool AbstractTask::sleep(unsigned millisecond)
{
if (millisecond == 0) {
return true;
}
auto start = std::chrono::system_clock::now();
unsigned duration = 0;
json::value callback_json;
callback_json["time"] = millisecond;
m_callback(AsstMsg::ReadyToSleep, callback_json, m_callback_arg);
while ((m_exit_flag == NULL || *m_exit_flag == false)
&& duration < millisecond) {
duration = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now() - start).count();
std::this_thread::yield();
}
m_callback(AsstMsg::EndOfSleep, callback_json, m_callback_arg);
return (m_exit_flag == NULL || *m_exit_flag == false);
}
bool AbstractTask::print_window(const std::string& dir)
{
const cv::Mat& image = get_format_image(true);
if (image.empty()) {
return false;
}
// 现在用adb直接截图了不用裁剪了
//// 保存的截图额外再裁剪掉一圈,不然企鹅物流识别不出来
//int offset = Configer::get_instance().m_options.print_window_crop_offset;
//cv::Rect rect(offset, offset, image.cols - offset * 2, image.rows - offset * 2);
std::filesystem::create_directory(dir);
const std::string time_str = StringReplaceAll(StringReplaceAll(GetFormatTimeString(), " ", "_"), ":", "-");
const std::string filename = dir + time_str + ".png";
bool ret = cv::imwrite(filename.c_str(), image);
json::value callback_json;
callback_json["filename"] = filename;
callback_json["ret"] = ret;
callback_json["offset"] = 0;
m_callback(AsstMsg::PrintWindow, callback_json, m_callback_arg);
return ret;
}

View File

@@ -0,0 +1,76 @@
#pragma once
#include <memory>
#include "AsstMsg.h"
namespace cv
{
class Mat;
}
namespace asst {
class WinMacro;
class Identify;
enum TaskType {
TaskTypeInvalid = 0,
TaskTypeWindowZoom = 1,
TaskTypeRecognition = 2,
TaskTypeClick = 4
};
// 设施类型
enum class FacilityType {
Invalid,
Manufacturing, // 制造站
Trade, // 贸易站
PowerStation, // 发电站
ControlInterface, // 控制中枢
ReceptionRoom, // 会客室
Dormitory, // 宿舍
Office // 办公室
// 训练室和加工站用不上,不加了
};
class AbstractTask
{
public:
AbstractTask(AsstCallback callback, void* callback_arg);
virtual ~AbstractTask() = default;
AbstractTask(const AbstractTask&) = default;
AbstractTask(AbstractTask&&) = default;
virtual void set_ptr(
std::shared_ptr<WinMacro> window_ptr,
std::shared_ptr<WinMacro> view_ptr,
std::shared_ptr<WinMacro> control_ptr,
std::shared_ptr<Identify> identify_ptr);
virtual bool run() = 0;
virtual void set_exit_flag(bool* exit_flag);
virtual int get_task_type() { return m_task_type; }
virtual void set_retry_times(int times) { m_retry_times = times; }
virtual int get_retry_times() { return m_retry_times; }
virtual void set_task_chain(std::string name) { m_task_chain = std::move(name); }
virtual const std::string& get_task_chain() { return m_task_chain; }
protected:
virtual cv::Mat get_format_image(bool hd = false); // 参数hd高清截图会慢一点
virtual bool set_control_scale(double scale);
virtual bool set_control_scale(int cur_width, int cur_height);
virtual bool sleep(unsigned millisecond);
virtual bool print_window(const std::string& dir);
std::shared_ptr<WinMacro> m_window_ptr = nullptr;
std::shared_ptr<WinMacro> m_view_ptr = nullptr;
std::shared_ptr<WinMacro> m_control_ptr = nullptr;
std::shared_ptr<Identify> m_identify_ptr = nullptr;
AsstCallback m_callback;
void* m_callback_arg = NULL;
bool* m_exit_flag = NULL;
std::string m_task_chain;
int m_task_type = TaskType::TaskTypeInvalid;
int m_retry_times = INT_MAX;
};
}

View File

@@ -1,5 +1,11 @@
#include "Assistance.h"
#include <time.h>
#include <filesystem>
#include <json.h>
#include <opencv2/opencv.hpp>
#include "WinMacro.h"
#include "Configer.h"
#include "Identify.h"
@@ -9,12 +15,6 @@
#include "RecruitConfiger.h"
#include "InfrastConfiger.h"
#include <json.h>
#include <opencv2/opencv.hpp>
#include <time.h>
#include <filesystem>
using namespace asst;
Assistance::Assistance(AsstCallback callback, void* callback_arg)

View File

@@ -1,11 +1,13 @@
#include "AsstCaller.h"
#include <string.h>
#include <json_value.h>
#include "Updater.h"
#include "AsstAux.h"
#include "Assistance.h"
#include <json_value.h>
#include <string.h>
#if 0
#if _MSC_VER
// Win32平台下Dll的入口

79
MeoAssistance/AsstMsg.h Normal file
View File

@@ -0,0 +1,79 @@
#pragma once
#include <ostream>
#include <memory>
#include <unordered_map>
#include <functional>
#include <json.h>
namespace asst {
enum class AsstMsg {
/* Error Msg */
PtrIsNull,
ImageIsEmpty,
WindowMinimized,
InitFaild,
/* Info Msg */
TaskStart,
ImageFindResult,
ImageMatched,
TaskMatched,
ReachedLimit,
ReadyToSleep,
EndOfSleep,
AppendProcessTask, // 这个消息Assistance会新增任务外部不需要处理
AppendTask, // 这个消息Assistance会新增任务外部不需要处理
TaskCompleted,
PrintWindow,
TaskStop,
TaskError,
/* Open Recruit Msg */
TextDetected,
RecruitTagsDetected,
OcrResultError,
RecruitSpecialTag,
RecruitResult,
/* Infrast Msg*/
InfrastOpers, // 识别到基建干员s
InfrastComb // 当前设置的最优干员组合
};
static std::ostream& operator<<(std::ostream& os, const AsstMsg& type)
{
static const std::unordered_map<AsstMsg, std::string> _type_name = {
{AsstMsg::PtrIsNull, "PtrIsNull"},
{AsstMsg::ImageIsEmpty, "ImageIsEmpty"},
{AsstMsg::WindowMinimized, "WindowMinimized"},
{AsstMsg::InitFaild, "InitFaild"},
{AsstMsg::TaskStart, "TaskStart"},
{AsstMsg::ImageFindResult, "ImageFindResult"},
{AsstMsg::ImageMatched, "ImageMatched"},
{AsstMsg::TaskMatched, "TaskMatched"},
{AsstMsg::ReachedLimit, "ReachedLimit"},
{AsstMsg::ReadyToSleep, "ReadyToSleep"},
{AsstMsg::EndOfSleep, "EndOfSleep"},
{AsstMsg::AppendProcessTask, "AppendProcessTask"},
{AsstMsg::TaskCompleted, "TaskCompleted"},
{AsstMsg::PrintWindow, "PrintWindow"},
{AsstMsg::TaskError, "TaskError"},
{AsstMsg::TaskStop, "TaskStop"},
{AsstMsg::TextDetected, "TextDetected"},
{AsstMsg::RecruitTagsDetected, "RecruitTagsDetected"},
{AsstMsg::OcrResultError, "OcrResultError"},
{AsstMsg::RecruitSpecialTag, "RecruitSpecialTag"},
{AsstMsg::RecruitResult, "RecruitResult"},
{AsstMsg::AppendTask, "AppendTask"},
{AsstMsg::InfrastOpers, "InfrastOpers"},
{AsstMsg::InfrastComb, "InfrastComb"}
};
return os << _type_name.at(type);
}
// AsstCallback 消息回调函数
// 参数:
// AsstMsg 消息类型
// const json::value& 消息详情json每种消息不同Todo需要补充个协议文档啥的
// void* 外部调用者自定义参数,每次回调会带出去,建议传个(void*)this指针进来
using AsstCallback = std::function<void(AsstMsg, const json::value&, void*)>;
}

View File

@@ -0,0 +1,28 @@
#include "ClickTask.h"
#include "WinMacro.h"
using namespace asst;
ClickTask::ClickTask(AsstCallback callback, void* callback_arg)
: AbstractTask(callback, callback_arg)
{
m_task_type = TaskType::TaskTypeClick;
}
bool ClickTask::run()
{
if (m_control_ptr == NULL)
{
m_callback(AsstMsg::PtrIsNull, json::value(), m_callback_arg);
return false;
}
json::value task_start_json = json::object{
{ "task_type", "ClickTask" },
{ "task_chain", m_task_chain},
};
m_callback(AsstMsg::TaskStart, task_start_json, m_callback_arg);
m_control_ptr->click(m_rect);
return true;
}

18
MeoAssistance/ClickTask.h Normal file
View File

@@ -0,0 +1,18 @@
#pragma once
#include "AsstDef.h"
#include "AbstractTask.h"
namespace asst {
class ClickTask : public AbstractTask
{
public:
ClickTask(AsstCallback callback, void* callback_arg);
virtual ~ClickTask() = default;
virtual bool run() override;
void set_rect(asst::Rect rect) { m_rect = std::move(rect); };
protected:
asst::Rect m_rect;
};
}

View File

@@ -5,6 +5,7 @@
#include <algorithm>
#include <json.h>
#include "Logger.hpp"
using namespace asst;

View File

@@ -39,7 +39,7 @@ namespace asst {
Configer(Configer&& rhs) noexcept = default;
Configer& operator=(const Configer& rhs) = default;
Configer& operator=(Configer && rhs) noexcept = default;
Configer& operator=(Configer&& rhs) noexcept = default;
bool _load(const std::string& filename);
};

View File

@@ -1,14 +1,15 @@
#include "Identify.h"
#include <filesystem>
#include <opencv2/opencv.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <opencv2/imgproc/types_c.h>
#include "Logger.hpp"
#include "AsstAux.h"
#include <algorithm>
#include <numeric>
#include <filesystem>
#include <opencv2/opencv.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <opencv2/imgproc/types_c.h>
#include "Logger.hpp"
#include "AsstAux.h"
using namespace asst;
using namespace cv;

View File

@@ -4,6 +4,7 @@
#include <sstream>
#include <json.h>
#include "Logger.hpp"
using namespace asst;

View File

@@ -30,7 +30,7 @@ namespace asst {
InfrastConfiger(InfrastConfiger&& rhs) noexcept = default;
InfrastConfiger& operator=(const InfrastConfiger& rhs) = default;
InfrastConfiger& operator=(InfrastConfiger && rhs) noexcept = default;
InfrastConfiger& operator=(InfrastConfiger&& rhs) noexcept = default;
bool _load(const std::string& filename);
};

View File

@@ -0,0 +1,224 @@
#include "InfrastStationTask.h"
#include <thread>
#include <future>
#include <algorithm>
#include <opencv2/opencv.hpp>
#include "Configer.h"
#include "InfrastConfiger.h"
#include "WinMacro.h"
#include "Identify.h"
#include "AsstAux.h"
using namespace asst;
asst::InfrastStationTask::InfrastStationTask(AsstCallback callback, void* callback_arg)
: OcrAbstractTask(callback, callback_arg)
{
}
bool asst::InfrastStationTask::run()
{
if (m_view_ptr == NULL
|| m_identify_ptr == NULL)
{
m_callback(AsstMsg::PtrIsNull, json::value(), m_callback_arg);
return false;
}
std::vector<std::vector<std::string>> all_oper_combs; // 所有的干员组合
std::unordered_map<std::string, std::string> feature_cond_default; // 特征检测关键字如果OCR识别到了key的内容但是却没有value的内容则进行特征检测进一步确认
std::unordered_set<std::string> feature_whatever_default; // 无论如何都进行特征检测的
json::value task_start_json = json::object{
{ "task_type", "InfrastStationTask" },
{ "task_chain", m_task_chain},
};
m_callback(AsstMsg::TaskStart, task_start_json, m_callback_arg);
auto swipe_foo = [&](bool reverse = false) -> bool {
bool ret = false;
if (!reverse) {
ret = m_control_ptr->swipe(m_swipe_begin, m_swipe_end);
}
else {
ret = m_control_ptr->swipe(m_swipe_end, m_swipe_begin);
}
ret &= sleep(m_swipe_delay);
return ret;
};
std::unordered_map<std::string, std::string> feature_cond = feature_cond_default;
std::unordered_set<std::string> feature_whatever = feature_whatever_default;
auto detect_foo = [&](const cv::Mat& image) -> std::vector<TextArea> {
std::vector<TextArea> all_text_area = ocr_detect(image);
/* 过滤出所有制造站中的干员名 */
std::vector<TextArea> cur_name_textarea = text_search(
all_text_area,
InfrastConfiger::get_instance().m_all_opers_name,
Configer::get_instance().m_infrast_ocr_replace);
// 用特征检测再筛选一遍OCR识别漏了的
for (const TextArea& textarea : all_text_area) {
for (auto iter = feature_cond.begin(); iter != feature_cond.end(); ++iter) {
auto& [key, value] = *iter;
// 识别到了key但是没识别到value这种情况就需要进行特征检测进一步确认了
if (textarea.text.find(key) != std::string::npos
&& textarea.text.find(value) == std::string::npos) {
// 把key所在的矩形放大一点送去做特征检测不需要把整张图片都送去检测
Rect magnified_area = textarea.rect.center_zoom(2.0);
magnified_area.x = (std::max)(0, magnified_area.x);
magnified_area.y = (std::max)(0, magnified_area.y);
if (magnified_area.x + magnified_area.width >= image.cols) {
magnified_area.width = image.cols - magnified_area.x - 1;
}
if (magnified_area.y + magnified_area.height >= image.rows) {
magnified_area.height = image.rows - magnified_area.y - 1;
}
cv::Rect cv_rect(magnified_area.x, magnified_area.y, magnified_area.width, magnified_area.height);
// key是关键字而已真正要识别的是value
auto&& ret = m_identify_ptr->feature_match(image(cv_rect), value);
if (ret) {
cur_name_textarea.emplace_back(value, textarea.rect);
iter = feature_cond.erase(iter);
--iter;
}
}
}
}
for (auto iter = feature_whatever.begin(); iter != feature_whatever.end(); ++iter) {
auto&& ret = m_identify_ptr->feature_match(image, *iter);
if (ret) {
cur_name_textarea.emplace_back(std::move(ret.value()));
iter = feature_whatever.erase(iter);
--iter;
}
}
return cur_name_textarea;
};
std::unordered_set<OperInfrastInfo> detected_opers;
// 一边识别一边滑动,把所有制造站干员名字抓出来
while (true) {
const cv::Mat& image = get_format_image(true);
// 异步进行滑动操作
std::future<bool> swipe_future = std::async(std::launch::async, swipe_foo);
auto cur_name_textarea = detect_foo(image);
int oper_numer = detected_opers.size();
for (const TextArea& textarea : cur_name_textarea)
{
cv::Rect elite_rect;
// 因为有的名字长有的名字短,但是右对齐的,所以跟着右边走
elite_rect.x = textarea.rect.x + textarea.rect.width - 250;
elite_rect.y = textarea.rect.y - 200;
if (elite_rect.x < 0 || elite_rect.y < 0) {
continue;
}
elite_rect.width = 100;
elite_rect.height = 150;
cv::Mat elite_mat = image(elite_rect);
// for debug
static cv::Mat elite1 = cv::imread(GetResourceDir() + "operators\\Elite1.png");
static cv::Mat elite2 = cv::imread(GetResourceDir() + "operators\\Elite2.png");
auto&& [score1, point1] = m_identify_ptr->match_template(elite_mat, elite1);
auto&& [score2, point2] = m_identify_ptr->match_template(elite_mat, elite2);
std::cout << "elite1:" << score1 << ", elite2:" << score2 << std::endl;
OperInfrastInfo info;
info.name = textarea.text;
if (score1 > score2 && score1 > 0.7) {
info.elite = 1;
}
else if (score2 > score1 && score2 > 0.7) {
info.elite = 2;
}
else {
info.elite = 0;
}
detected_opers.emplace(std::move(info));
}
json::value opers_json;
std::vector<json::value> opers_json_vec;
for (const OperInfrastInfo& info : detected_opers) {
json::value info_json;
info_json["name"] = Utf8ToGbk(info.name);
info_json["elite"] = info.elite;
//info_json["level"] = info.level;
opers_json_vec.emplace_back(std::move(info_json));
}
opers_json["all"] = json::array(opers_json_vec);
m_callback(AsstMsg::InfrastOpers, opers_json, m_callback_arg);
// 阻塞等待滑动结束
if (!swipe_future.get()) {
return false;
}
// 说明本次识别一个新的都没识别到,应该是滑动到最后了,直接结束循环
if (oper_numer == detected_opers.size()) {
break;
}
}
//// 配置文件中的干员组合,和抓出来的干员名比对,如果组合中的干员都有,那就用这个组合
//// Todo 时间复杂度起飞了,需要优化下
//std::vector<std::string> optimal_comb;
//for (auto&& name_vec : all_oper_combs) {
// int count = 0;
// for (std::string& name : name_vec) {
// if (detected_names.find(name) != detected_names.cend()) {
// ++count;
// }
// else {
// break;
// }
// }
// if (count == name_vec.size()) {
// optimal_comb = name_vec;
// break;
// }
//}
//std::vector<std::string> optimal_comb_gbk; // 给回调json用的gbk的
//for (const std::string& name : optimal_comb)
//{
// optimal_comb_gbk.emplace_back(Utf8ToGbk(name));
//}
//opers_json["comb"] = json::array(optimal_comb_gbk);
//m_callback(AsstMsg::InfrastComb, opers_json, m_callback_arg);
//// 重置特征检测的条件后面不用了这次直接move
//feature_cond = std::move(feature_cond_default);
//feature_whatever = std::move(feature_whatever_default);
//// 一边滑动一边点击最优解中的干员
//for (int i = 0; i != m_swipe_max_times; ++i) {
// const cv::Mat& image = get_format_image(true);
// auto cur_name_textarea = detect_foo(image);
// for (TextArea& text_area : cur_name_textarea) {
// // 点过了就不会再点了直接从最优解vector里面删了
// auto iter = std::find(optimal_comb.begin(), optimal_comb.end(), text_area.text);
// if (iter != optimal_comb.end()) {
// m_control_ptr->click(text_area.rect);
// optimal_comb.erase(iter);
// }
// }
// if (optimal_comb.empty()) {
// break;
// }
// // 因为滑动和点击是矛盾的,这里没法异步做
// if (!swipe_foo(true)) {
// return false;
// }
//}
return true;
}

View File

@@ -0,0 +1,32 @@
#pragma once
#include "OcrAbstractTask.h"
namespace asst {
// »ù½¨½ø×¤ÈÎÎñ
class InfrastStationTask : public OcrAbstractTask
{
public:
InfrastStationTask(AsstCallback callback, void* callback_arg);
virtual ~InfrastStationTask() = default;
virtual bool run() override;
void set_swipe_param(int delay, const Rect& begin_rect, const Rect& end_rect, int max_times = 20)
{
m_swipe_delay = delay;
m_swipe_begin = begin_rect;
m_swipe_end = end_rect;
m_swipe_max_times = max_times;
}
void set_facility(const std::string& facility)
{
m_facility = facility;
}
private:
std::string m_facility;
int m_swipe_delay = 0;
Rect m_swipe_begin;
Rect m_swipe_end;
int m_swipe_max_times = 0;
};
}

View File

@@ -1,49 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="RelWithDebInfo|Win32">
<Configuration>RelWithDebInfo</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="RelWithDebInfo|x64">
<Configuration>RelWithDebInfo</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\Assistance.h" />
<ClInclude Include="include\AsstAux.h" />
<ClInclude Include="include\AsstCaller.h" />
<ClInclude Include="include\AsstDef.h" />
<ClInclude Include="include\AsstPort.h" />
<ClInclude Include="include\Configer.h" />
<ClInclude Include="include\Identify.h" />
<ClInclude Include="include\InfrastConfiger.h" />
<ClInclude Include="include\Logger.hpp" />
<ClInclude Include="include\RecruitConfiger.h" />
<ClInclude Include="include\Task.h" />
<ClInclude Include="include\Updater.h" />
<ClInclude Include="include\Version.h" />
<ClInclude Include="include\WinMacro.h" />
<ClInclude Include="..\include\AsstCaller.h" />
<ClInclude Include="..\include\AsstPort.h" />
<ClInclude Include="AbstractTask.h" />
<ClInclude Include="Assistance.h" />
<ClInclude Include="AsstAux.h" />
<ClInclude Include="AsstDef.h" />
<ClInclude Include="AsstMsg.h" />
<ClInclude Include="ClickTask.h" />
<ClInclude Include="Configer.h" />
<ClInclude Include="Identify.h" />
<ClInclude Include="InfrastConfiger.h" />
<ClInclude Include="InfrastStationTask.h" />
<ClInclude Include="Logger.hpp" />
<ClInclude Include="OcrAbstractTask.h" />
<ClInclude Include="OpenRecruitTask.h" />
<ClInclude Include="ProcessTask.h" />
<ClInclude Include="RecruitConfiger.h" />
<ClInclude Include="Task.h" />
<ClInclude Include="TestOcrTask.h" />
<ClInclude Include="Updater.h" />
<ClInclude Include="Version.h" />
<ClInclude Include="WinMacro.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="AbstractTask.cpp" />
<ClCompile Include="ClickTask.cpp" />
<ClCompile Include="InfrastConfiger.cpp" />
<ClCompile Include="src\Assistance.cpp" />
<ClCompile Include="src\AsstCaller.cpp" />
<ClCompile Include="src\Configer.cpp" />
<ClCompile Include="src\Identify.cpp" />
<ClCompile Include="src\RecruitConfiger.cpp" />
<ClCompile Include="src\Task.cpp" />
<ClCompile Include="src\Updater.cpp" />
<ClCompile Include="src\WinMacro.cpp" />
<ClCompile Include="Assistance.cpp" />
<ClCompile Include="AsstCaller.cpp" />
<ClCompile Include="Configer.cpp" />
<ClCompile Include="Identify.cpp" />
<ClCompile Include="InfrastStationTask.cpp" />
<ClCompile Include="OcrAbstractTask.cpp" />
<ClCompile Include="OpenRecruitTask.cpp" />
<ClCompile Include="ProcessTask.cpp" />
<ClCompile Include="RecruitConfiger.cpp" />
<ClCompile Include="TestOcrTask.cpp" />
<ClCompile Include="Updater.cpp" />
<ClCompile Include="WinMacro.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="..\resource\infrast.json" />
@@ -58,20 +64,6 @@
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
@@ -91,12 +83,6 @@
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
@@ -104,54 +90,16 @@
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(ProjectDir)include;$(SolutionDir)3rdPart\include;$(SolutionDir)3rdPart\include\meojson;$(SolutionDir)\3rdPart\include\opencv;$(SolutionDir)\3rdPart\include\opencv2;$(SolutionDir)3drPart\include\OcrLiteNcnn;;$(IncludePath)</IncludePath>
<IncludePath>$(SolutionDir)include;$(SolutionDir)3rdPart\include;$(SolutionDir)3rdPart\include\meojson;$(SolutionDir)\3rdPart\include\opencv;$(SolutionDir)\3rdPart\include\opencv2;$(SolutionDir)3drPart\include\OcrLiteNcnn;;$(IncludePath)</IncludePath>
<LibraryPath>$(TargetDir);$(Solution)\3rdPart\lib;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(ProjectDir)include;$(SolutionDir)3rdPart\include;$(SolutionDir)3rdPart\include\meojson;$(SolutionDir)3rdPart\include\opencv;$(SolutionDir)3rdPart\include\opencv2;$(SolutionDir)3drPart\include\OcrLiteNcnn;$(IncludePath)</IncludePath>
<IncludePath>$(SolutionDir)include;$(SolutionDir)3rdPart\include;$(SolutionDir)3rdPart\include\meojson;$(SolutionDir)3rdPart\include\opencv;$(SolutionDir)3rdPart\include\opencv2;$(SolutionDir)3drPart\include\OcrLiteNcnn;$(IncludePath)</IncludePath>
<LibraryPath>$(TargetDir);$(Solution)\3rdPart\lib;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
@@ -179,7 +127,7 @@
</Command>
</PreBuildEvent>
<PostBuildEvent>
<Command>xcopy /e /y /i $(SolutionDir)resource $(TargetDir)resource
<Command>xcopy /e /y /i $(SolutionDir)resource $(TargetDir)resource
xcopy /e /y /i $(SolutionDir)3rdPart\resource $(TargetDir)resource</Command>
</PostBuildEvent>
<PostBuildEvent>
@@ -222,7 +170,7 @@ xcopy /e /y /i $(SolutionDir)3rdPart\resource $(TargetDir)resource</Command>
</Command>
</PreBuildEvent>
<PostBuildEvent>
<Command>xcopy /e /y /i $(SolutionDir)resource $(TargetDir)resource
<Command>xcopy /e /y /i $(SolutionDir)resource $(TargetDir)resource
xcopy /e /y /i $(SolutionDir)3rdPart\resource $(TargetDir)resource</Command>
</PostBuildEvent>
<PostBuildEvent>

View File

@@ -13,87 +13,147 @@
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="头文件\configer">
<Filter Include="头文件\Caller">
<UniqueIdentifier>{81d86994-0d89-4cc2-aa6f-d726a0bd0490}</UniqueIdentifier>
</Filter>
<Filter Include="头文件\Configer">
<UniqueIdentifier>{07a812fe-6b28-4be0-b6d4-33554824d3c5}</UniqueIdentifier>
</Filter>
<Filter Include="源文件\configer">
<Filter Include="源文件\Configer">
<UniqueIdentifier>{74bd94e1-4973-412a-a17a-d8457de387af}</UniqueIdentifier>
</Filter>
<Filter Include="头文件\type">
<Filter Include="头文件\Aux">
<UniqueIdentifier>{87c9dee5-847b-41e6-818e-387a6385ea8b}</UniqueIdentifier>
</Filter>
<Filter Include="头文件\Task">
<UniqueIdentifier>{3b93d9f2-728c-4a22-bc13-57ce7df5806c}</UniqueIdentifier>
</Filter>
<Filter Include="源文件\Task">
<UniqueIdentifier>{1ef28df7-c174-4032-bbcf-9722ae53852d}</UniqueIdentifier>
</Filter>
<Filter Include="源文件\Caller">
<UniqueIdentifier>{557d6d96-11d9-46e1-b611-b2b8216abea6}</UniqueIdentifier>
</Filter>
<Filter Include="源文件\Updater">
<UniqueIdentifier>{08846a78-d9cf-4d06-aecc-e983ef5c7c83}</UniqueIdentifier>
</Filter>
<Filter Include="头文件\Updater">
<UniqueIdentifier>{b39a4ef9-28ad-4173-bc52-68221b765396}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\Identify.h">
<ClInclude Include="Identify.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="include\WinMacro.h">
<ClInclude Include="WinMacro.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="include\Assistance.h">
<ClInclude Include="Assistance.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="include\AsstCaller.h">
<Filter>头文件</Filter>
<ClInclude Include="InfrastConfiger.h">
<Filter>头文件\Configer</Filter>
</ClInclude>
<ClInclude Include="include\Updater.h">
<Filter>头文件</Filter>
<ClInclude Include="RecruitConfiger.h">
<Filter>头文件\Configer</Filter>
</ClInclude>
<ClInclude Include="include\Task.h">
<Filter>头文件</Filter>
<ClInclude Include="Configer.h">
<Filter>头文件\Configer</Filter>
</ClInclude>
<ClInclude Include="include\InfrastConfiger.h">
<Filter>头文件\configer</Filter>
<ClInclude Include="AsstDef.h">
<Filter>头文件\Aux</Filter>
</ClInclude>
<ClInclude Include="include\RecruitConfiger.h">
<Filter>头文件\configer</Filter>
<ClInclude Include="AsstAux.h">
<Filter>头文件\Aux</Filter>
</ClInclude>
<ClInclude Include="include\Configer.h">
<Filter>头文件\configer</Filter>
<ClInclude Include="Version.h">
<Filter>头文件\Aux</Filter>
</ClInclude>
<ClInclude Include="include\AsstDef.h">
<Filter>头文件\type</Filter>
<ClInclude Include="Logger.hpp">
<Filter>头文件\Aux</Filter>
</ClInclude>
<ClInclude Include="include\AsstAux.h">
<Filter>头文件\type</Filter>
<ClInclude Include="..\include\AsstCaller.h">
<Filter>头文件\Caller</Filter>
</ClInclude>
<ClInclude Include="include\AsstPort.h">
<Filter>头文件\type</Filter>
<ClInclude Include="..\include\AsstPort.h">
<Filter>头文件\Caller</Filter>
</ClInclude>
<ClInclude Include="include\Version.h">
<Filter>头文件\type</Filter>
<ClInclude Include="AbstractTask.h">
<Filter>头文件\Task</Filter>
</ClInclude>
<ClInclude Include="include\Logger.hpp">
<Filter>头文件\type</Filter>
<ClInclude Include="ClickTask.h">
<Filter>头文件\Task</Filter>
</ClInclude>
<ClInclude Include="InfrastStationTask.h">
<Filter>头文件\Task</Filter>
</ClInclude>
<ClInclude Include="OcrAbstractTask.h">
<Filter>头文件\Task</Filter>
</ClInclude>
<ClInclude Include="OpenRecruitTask.h">
<Filter>头文件\Task</Filter>
</ClInclude>
<ClInclude Include="ProcessTask.h">
<Filter>头文件\Task</Filter>
</ClInclude>
<ClInclude Include="TestOcrTask.h">
<Filter>头文件\Task</Filter>
</ClInclude>
<ClInclude Include="AsstMsg.h">
<Filter>头文件\Aux</Filter>
</ClInclude>
<ClInclude Include="Task.h">
<Filter>头文件\Task</Filter>
</ClInclude>
<ClInclude Include="Updater.h">
<Filter>头文件\Updater</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\WinMacro.cpp">
<ClCompile Include="WinMacro.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\Assistance.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\AsstCaller.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\Updater.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\Task.cpp">
<ClCompile Include="Assistance.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="InfrastConfiger.cpp">
<Filter>源文件\configer</Filter>
<Filter>源文件\Configer</Filter>
</ClCompile>
<ClCompile Include="src\Identify.cpp">
<ClCompile Include="Identify.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\RecruitConfiger.cpp">
<Filter>源文件\configer</Filter>
<ClCompile Include="RecruitConfiger.cpp">
<Filter>源文件\Configer</Filter>
</ClCompile>
<ClCompile Include="src\Configer.cpp">
<Filter>源文件\configer</Filter>
<ClCompile Include="Configer.cpp">
<Filter>源文件\Configer</Filter>
</ClCompile>
<ClCompile Include="AbstractTask.cpp">
<Filter>源文件\Task</Filter>
</ClCompile>
<ClCompile Include="ClickTask.cpp">
<Filter>源文件\Task</Filter>
</ClCompile>
<ClCompile Include="InfrastStationTask.cpp">
<Filter>源文件\Task</Filter>
</ClCompile>
<ClCompile Include="OcrAbstractTask.cpp">
<Filter>源文件\Task</Filter>
</ClCompile>
<ClCompile Include="OpenRecruitTask.cpp">
<Filter>源文件\Task</Filter>
</ClCompile>
<ClCompile Include="ProcessTask.cpp">
<Filter>源文件\Task</Filter>
</ClCompile>
<ClCompile Include="TestOcrTask.cpp">
<Filter>源文件\Task</Filter>
</ClCompile>
<ClCompile Include="AsstCaller.cpp">
<Filter>源文件\Caller</Filter>
</ClCompile>
<ClCompile Include="Updater.cpp">
<Filter>源文件\Updater</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>

View File

@@ -0,0 +1,37 @@
#include "OcrAbstractTask.h"
#include <opencv2/opencv.hpp>
#include "AsstAux.h"
#include "Identify.h"
using namespace asst;
OcrAbstractTask::OcrAbstractTask(AsstCallback callback, void* callback_arg)
: AbstractTask(callback, callback_arg)
{
;
}
std::vector<TextArea> OcrAbstractTask::ocr_detect()
{
const cv::Mat& image = get_format_image();
return ocr_detect(image);
}
std::vector<TextArea> OcrAbstractTask::ocr_detect(const cv::Mat& image)
{
std::vector<TextArea> dst = m_identify_ptr->ocr_detect(image);
std::vector<json::value> all_text_json_vector;
for (const TextArea& text_area : dst) {
all_text_json_vector.emplace_back(Utf8ToGbk(text_area.text));
}
json::value all_text_json;
all_text_json["text"] = json::array(all_text_json_vector);
all_text_json["task_chain"] = m_task_chain;
m_callback(AsstMsg::TextDetected, all_text_json, m_callback_arg);
return dst;
}

View File

@@ -0,0 +1,61 @@
#pragma once
#include "AbstractTask.h"
#include "AsstDef.h"
#include "AsstAux.h"
namespace asst {
class OcrAbstractTask : public AbstractTask
{
public:
OcrAbstractTask(AsstCallback callback, void* callback_arg);
virtual ~OcrAbstractTask() = default;
virtual bool run() override = 0;
protected:
std::vector<TextArea> ocr_detect();
std::vector<TextArea> ocr_detect(const cv::Mat& image);
// 文字匹配,要求相等
template<typename FilterArray, typename ReplaceMap>
std::vector<TextArea> text_match(const std::vector<TextArea>& src,
const FilterArray& filter_array, const ReplaceMap& replace_map)
{
std::vector<TextArea> dst;
for (const TextArea& text_area : src) {
TextArea temp = text_area;
for (const auto& [old_str, new_str] : replace_map) {
temp.text = StringReplaceAll(temp.text, old_str, new_str);
}
for (const auto& text : filter_array) {
if (temp.text == text) {
dst.emplace_back(std::move(temp));
}
}
}
return dst;
}
// 文字搜索,是子串即可
template<typename FilterArray, typename ReplaceMap>
std::vector<TextArea> text_search(const std::vector<TextArea>& src,
const FilterArray& filter_array, const ReplaceMap& replace_map)
{
std::vector<TextArea> dst;
for (const TextArea& text_area : src) {
TextArea temp = text_area;
for (const auto& [old_str, new_str] : replace_map) {
temp.text = StringReplaceAll(temp.text, old_str, new_str);
}
for (const auto& text : filter_array) {
if (temp.text.find(text) != std::string::npos) {
dst.emplace_back(text, std::move(temp.rect));
}
}
}
return dst;
}
};
}

View File

@@ -0,0 +1,224 @@
#include "OpenRecruitTask.h"
#include <map>
#include <vector>
#include <algorithm>
#include "Configer.h"
#include "RecruitConfiger.h"
#include "AsstAux.h"
using namespace asst;
OpenRecruitTask::OpenRecruitTask(AsstCallback callback, void* callback_arg)
: OcrAbstractTask(callback, callback_arg)
{
m_task_type = TaskType::TaskTypeRecognition & TaskType::TaskTypeClick;
}
bool OpenRecruitTask::run()
{
if (m_view_ptr == NULL
|| m_identify_ptr == NULL)
{
m_callback(AsstMsg::PtrIsNull, json::value(), m_callback_arg);
return false;
}
json::value task_start_json = json::object{
{ "task_type", "OpenRecruitTask" },
{ "task_chain", m_task_chain},
};
m_callback(AsstMsg::TaskStart, task_start_json, m_callback_arg);
/* Find all text */
std::vector<TextArea> all_text_area = ocr_detect();
/* Filter out all tags from all text */
std::vector<TextArea> all_tags = text_match(
all_text_area, RecruitConfiger::get_instance().m_all_tags, Configer::get_instance().m_recruit_ocr_replace);
std::unordered_set<std::string> all_tags_name;
std::vector<json::value> all_tags_json_vector;
for (const TextArea& text_area : all_tags) {
all_tags_name.emplace(text_area.text);
all_tags_json_vector.emplace_back(Utf8ToGbk(text_area.text));
}
json::value all_tags_json;
all_tags_json["tags"] = json::array(all_tags_json_vector);
m_callback(AsstMsg::RecruitTagsDetected, all_tags_json, m_callback_arg);
/* 过滤tags数量不足的情况可能是识别漏了 */
if (all_tags.size() != RecruitConfiger::CorrectNumberOfTags) {
all_tags_json["type"] = "OpenRecruit";
m_callback(AsstMsg::OcrResultError, all_tags_json, m_callback_arg);
return false;
}
/* 设置招募时间9小时加入任务队列*/
if (m_set_time) {
json::value settime_json;
settime_json["task"] = "RecruitTime";
// 只有tag数量对了才能走到这里界面一定是对的所以找不到时间设置就说明时间已经手动修改过了不用重试了
settime_json["retry_times"] = 0;
settime_json["task_chain"] = m_task_chain;
m_callback(AsstMsg::AppendProcessTask, settime_json, m_callback_arg);
}
/* 针对一星干员的额外回调消息 */
static const std::string SupportMachine_GBK = "支援机械";
static const std::string SupportMachine = GbkToUtf8(SupportMachine_GBK);
if (std::find(all_tags_name.cbegin(), all_tags_name.cend(), SupportMachine) != all_tags_name.cend()) {
json::value special_tag_json;
special_tag_json["tag"] = SupportMachine_GBK;
m_callback(AsstMsg::RecruitSpecialTag, special_tag_json, m_callback_arg);
}
// 识别到的5个Tags全组合排列
std::vector<std::vector<std::string>> all_combs;
int len = all_tags.size();
int count = std::pow(2, len);
for (int i = 0; i < count; ++i) {
std::vector<std::string> temp;
for (int j = 0, mask = 1; j < len; ++j) {
if ((i & mask) != 0) { // What the fuck???
temp.emplace_back(all_tags.at(j).text);
}
mask = mask * 2;
}
// 游戏里最多选择3个tag
if (!temp.empty() && temp.size() <= 3) {
all_combs.emplace_back(std::move(temp));
}
}
// key: tags comb, value: 干员组合
// 例如 key: { "狙击"、"群攻" }value: OperRecruitCombs.opers{ "陨星", "白雪", "空爆" }
std::map<std::vector<std::string>, OperRecruitCombs> result_map;
for (const std::vector<std::string>& comb : all_combs) {
for (const OperRecruitInfo& cur_oper : RecruitConfiger::get_instance().m_all_opers) {
int matched_count = 0;
for (const std::string& tag : comb) {
if (cur_oper.tags.find(tag) != cur_oper.tags.cend()) {
++matched_count;
}
else {
break;
}
}
// 单个tags comb中的每一个tag这个干员都有才算该干员符合这个tags comb
if (matched_count != comb.size()) {
continue;
}
if (cur_oper.level == 6) {
// 高资tag和六星强绑定如果没有高资tag即使其他tag匹配上了也不可能出六星
static const std::string SeniorOper = GbkToUtf8("高级资深干员");
if (std::find(comb.cbegin(), comb.cend(), SeniorOper) == comb.cend()) {
continue;
}
}
OperRecruitCombs& oper_combs = result_map[comb];
oper_combs.opers.emplace_back(cur_oper);
if (cur_oper.level == 1 || cur_oper.level == 2) {
if (oper_combs.min_level == 0) oper_combs.min_level = cur_oper.level;
if (oper_combs.max_level == 0) oper_combs.max_level = cur_oper.level;
// 一星、二星干员不计入最低等级因为拉满9小时之后不可能出1、2星
continue;
}
if (oper_combs.min_level == 0 || oper_combs.min_level > cur_oper.level) {
oper_combs.min_level = cur_oper.level;
}
if (oper_combs.max_level == 0 || oper_combs.max_level < cur_oper.level) {
oper_combs.max_level = cur_oper.level;
}
oper_combs.avg_level += cur_oper.level;
}
if (result_map.find(comb) != result_map.cend()) {
OperRecruitCombs& oper_combs = result_map[comb];
oper_combs.avg_level /= oper_combs.opers.size();
}
}
// map没法按值排序转个vector再排序
std::vector<std::pair<std::vector<std::string>, OperRecruitCombs>> result_vector;
for (auto&& pair : result_map) {
result_vector.emplace_back(std::move(pair));
}
std::sort(result_vector.begin(), result_vector.end(), [](const auto& lhs, const auto& rhs)
->bool {
// 最小等级大的,排前面
if (lhs.second.min_level != rhs.second.min_level) {
return lhs.second.min_level > rhs.second.min_level;
}
// 最大等级大的,排前面
else if (lhs.second.max_level != rhs.second.max_level) {
return lhs.second.max_level > rhs.second.max_level;
}
// 平均等级高的,排前面
else if (std::fabs(lhs.second.avg_level - rhs.second.avg_level) < DoubleDiff) {
return lhs.second.avg_level > rhs.second.avg_level;
}
// Tag数量少的排前面
else {
return lhs.first.size() < rhs.first.size();
}
});
/* 整理识别结果 */
std::vector<json::value> result_json_vector;
for (const auto& [tags_comb, oper_comb] : result_vector) {
json::value comb_json;
std::vector<json::value> tags_json_vector;
for (const std::string& tag : tags_comb) {
tags_json_vector.emplace_back(Utf8ToGbk(tag));
}
comb_json["tags"] = json::array(std::move(tags_json_vector));
std::vector<json::value> opers_json_vector;
for (const OperRecruitInfo& oper_info : oper_comb.opers) {
json::value oper_json;
oper_json["name"] = Utf8ToGbk(oper_info.name);
oper_json["level"] = oper_info.level;
opers_json_vector.emplace_back(std::move(oper_json));
}
comb_json["opers"] = json::array(std::move(opers_json_vector));
comb_json["tag_level"] = oper_comb.min_level;
result_json_vector.emplace_back(std::move(comb_json));
}
json::value results_json;
results_json["result"] = json::array(std::move(result_json_vector));
m_callback(AsstMsg::RecruitResult, results_json, m_callback_arg);
/* 点击最优解的tags添加点击任务 */
if (!m_required_level.empty() && !result_vector.empty()) {
if (std::find(m_required_level.cbegin(), m_required_level.cend(), result_vector[0].second.min_level)
== m_required_level.cend()) {
return true;
}
const std::vector<std::string>& final_tags_name = result_vector[0].first;
json::value task_json;
task_json["type"] = "ClickTask";
for (const TextArea& text_area : all_tags) {
if (std::find(final_tags_name.cbegin(), final_tags_name.cend(), text_area.text) != final_tags_name.cend()) {
task_json["elite_rect"] = json::array({ text_area.rect.x, text_area.rect.y, text_area.rect.width, text_area.rect.height });
task_json["retry_times"] = m_retry_times;
task_json["task_chain"] = m_task_chain;
m_callback(AsstMsg::AppendTask, task_json, m_callback_arg);
}
}
}
return true;
}
void OpenRecruitTask::set_param(std::vector<int> required_level, bool set_time)
{
m_required_level = std::move(required_level);
m_set_time = set_time;
}

View File

@@ -0,0 +1,46 @@
#pragma once
#include "OcrAbstractTask.h"
namespace asst {
class OpenRecruitTask : public OcrAbstractTask
{
public:
OpenRecruitTask(AsstCallback callback, void* callback_arg);
virtual ~OpenRecruitTask() = default;
virtual bool run() override;
virtual void set_param(std::vector<int> required_level, bool set_time = true);
protected:
std::vector<int> m_required_level;
bool m_set_time = false;
};
// »ù½¨½ø×¤ÈÎÎñ
class InfrastStationTask : public OcrAbstractTask
{
public:
InfrastStationTask(AsstCallback callback, void* callback_arg);
virtual ~InfrastStationTask() = default;
virtual bool run() override;
void set_swipe_param(int delay, const Rect& begin_rect, const Rect& end_rect, int max_times = 20)
{
m_swipe_delay = delay;
m_swipe_begin = begin_rect;
m_swipe_end = end_rect;
m_swipe_max_times = max_times;
}
void set_facility(const std::string& facility)
{
m_facility = facility;
}
private:
std::string m_facility;
int m_swipe_delay = 0;
Rect m_swipe_begin;
Rect m_swipe_end;
int m_swipe_max_times = 0;
};
}

View File

@@ -0,0 +1,270 @@
#include "ProcessTask.h"
#include <chrono>
#include <random>
#include <opencv2/opencv.hpp>
#include "AsstAux.h"
#include "Configer.h"
#include "WinMacro.h"
#include "Identify.h"
using namespace asst;
ProcessTask::ProcessTask(AsstCallback callback, void* callback_arg)
: OcrAbstractTask(callback, callback_arg)
{
m_task_type = TaskType::TaskTypeRecognition | TaskType::TaskTypeClick;
}
bool ProcessTask::run()
{
if (m_view_ptr == NULL
|| m_control_ptr == NULL
|| m_identify_ptr == NULL
|| m_control_ptr == NULL)
{
m_callback(AsstMsg::PtrIsNull, json::value(), m_callback_arg);
return false;
}
json::value task_start_json = json::object{
{ "task_type", "ProcessTask" },
{ "task_chain", m_task_chain},
};
m_callback(AsstMsg::TaskStart, task_start_json, m_callback_arg);
std::shared_ptr<TaskInfo> task_info_ptr = nullptr;
Rect rect;
task_info_ptr = match_image(&rect);
if (!task_info_ptr) {
return false;
}
json::value callback_json = json::object{
{ "name", task_info_ptr->name },
{ "type", static_cast<int>(task_info_ptr->type) },
{ "exec_times", task_info_ptr->exec_times },
{ "max_times", task_info_ptr->max_times },
{ "task_type", "ProcessTask"},
{ "algorithm", static_cast<int>(task_info_ptr->algorithm)}
};
m_callback(AsstMsg::TaskMatched, callback_json, m_callback_arg);
if (task_info_ptr->exec_times >= task_info_ptr->max_times)
{
m_callback(AsstMsg::ReachedLimit, callback_json, m_callback_arg);
json::value next_json = callback_json;
next_json["tasks"] = json::array(task_info_ptr->exceeded_next);
next_json["retry_times"] = m_retry_times;
next_json["task_chain"] = m_task_chain;
m_callback(AsstMsg::AppendProcessTask, next_json, m_callback_arg);
return true;
}
// 前置固定延时
if (!sleep(task_info_ptr->pre_delay))
{
return false;
}
bool need_stop = false;
switch (task_info_ptr->type) {
case ProcessTaskType::ClickRect:
rect = task_info_ptr->specific_area;
[[fallthrough]];
case ProcessTaskType::ClickSelf:
exec_click_task(rect);
break;
case ProcessTaskType::DoNothing:
break;
case ProcessTaskType::Stop:
m_callback(AsstMsg::TaskStop, json::object{ {"task_chain", m_task_chain} }, m_callback_arg);
need_stop = true;
break;
case ProcessTaskType::PrintWindow:
{
if (!sleep(Configer::get_instance().m_options.print_window_delay))
{
return false;
}
static const std::string dirname = GetCurrentDir() + "screenshot\\";
print_window(dirname);
}
break;
default:
break;
}
++task_info_ptr->exec_times;
// 减少其他任务的执行次数
// 例如,进入吃理智药的界面了,相当于上一次点蓝色开始行动没生效
// 所以要给蓝色开始行动的次数减一
for (const std::string& reduce : task_info_ptr->reduce_other_times) {
--Configer::get_instance().m_all_tasks_info[reduce]->exec_times;
}
if (need_stop) {
return true;
}
callback_json["exec_times"] = task_info_ptr->exec_times;
m_callback(AsstMsg::TaskCompleted, callback_json, m_callback_arg);
// 后置固定延时
if (!sleep(task_info_ptr->rear_delay)) {
return false;
}
json::value next_json = callback_json;
next_json["task_chain"] = m_task_chain;
next_json["retry_times"] = m_retry_times;
next_json["tasks"] = json::array(task_info_ptr->next);
m_callback(AsstMsg::AppendProcessTask, next_json, m_callback_arg);
return true;
}
std::shared_ptr<TaskInfo> ProcessTask::match_image(Rect* matched_rect)
{
//// 如果当前仅有一个任务且这个任务的阈值是0说明是justreturn的就不抓图像识别了直接返回就行
//if (m_cur_tasks_name.size() == 1)
//{
// // 能走到这个函数里的肯定是ProcessTaskInfo直接转
// auto task_info_ptr = std::dynamic_pointer_cast<MatchTaskInfo>(
// Configer::get_instance().m_all_tasks_info[m_cur_tasks_name[0]]);
// if (task_info_ptr->templ_threshold == 0) {
// json::value callback_json;
// callback_json["threshold"] = 0.0;
// callback_json["algorithm"] = "JustReturn";
// callback_json["rect"] = json::array({ 0, 0, 0, 0 });
// callback_json["name"] = m_cur_tasks_name[0];
// callback_json["algorithm_id"] = static_cast<std::underlying_type<ProcessTaskType>::type>(
// AlgorithmType::JustReturn);
// callback_json["value"] = 0;
// m_callback(AsstMsg::ImageFindResult, callback_json, m_callback_arg);
// m_callback(AsstMsg::ImageMatched, callback_json, m_callback_arg);
// return task_info_ptr;
// }
//}
const cv::Mat& cur_image = get_format_image();
if (cur_image.empty() || cur_image.rows < 100) {
return nullptr;
}
// 逐个匹配当前可能的任务
for (const std::string& task_name : m_cur_tasks_name) {
std::shared_ptr<TaskInfo> task_info_ptr = Configer::get_instance().m_all_tasks_info[task_name];
if (task_info_ptr == nullptr) {
m_callback(AsstMsg::PtrIsNull, json::value(), m_callback_arg);
continue;
}
json::value callback_json;
bool matched = false;
Rect rect;
switch (task_info_ptr->algorithm)
{
case AlgorithmType::JustReturn:
callback_json["algorithm"] = "JustReturn";
matched = true;
break;
case AlgorithmType::MatchTemplate:
{
std::shared_ptr<MatchTaskInfo> process_task_info_ptr =
std::dynamic_pointer_cast<MatchTaskInfo>(task_info_ptr);
double templ_threshold = process_task_info_ptr->templ_threshold;
double hist_threshold = process_task_info_ptr->hist_threshold;
auto&& [algorithm, value, temp_rect] = m_identify_ptr->find_image(cur_image, task_name, templ_threshold);
rect = std::move(temp_rect);
callback_json["value"] = value;
if (algorithm == AlgorithmType::MatchTemplate) {
callback_json["threshold"] = templ_threshold;
callback_json["algorithm"] = "MatchTemplate";
if (value >= templ_threshold) {
matched = true;
}
}
else if (algorithm == AlgorithmType::CompareHist) {
callback_json["threshold"] = hist_threshold;
callback_json["algorithm"] = "CompareHist";
if (value >= hist_threshold) {
matched = true;
}
}
else {
continue;
}
}
break;
case AlgorithmType::OcrDetect:
{
std::shared_ptr<OcrTaskInfo> ocr_task_info_ptr =
std::dynamic_pointer_cast<OcrTaskInfo>(task_info_ptr);
std::vector<TextArea> all_text_area = ocr_detect(cur_image);
std::vector<TextArea> match_result;
if (ocr_task_info_ptr->need_match) {
match_result = text_match(all_text_area,
ocr_task_info_ptr->text, ocr_task_info_ptr->replace_map);
}
else {
match_result = text_search(all_text_area,
ocr_task_info_ptr->text, ocr_task_info_ptr->replace_map);
}
// TODO如果搜出来多个结果怎么处理
// 暂时通过配置文件保证尽量只搜出来一个结果or一个都搜不到
if (!match_result.empty()) {
callback_json["text"] = Utf8ToGbk(match_result.at(0).text);
rect = match_result.at(0).rect;
matched = true;
}
}
break;
//CompareHist是MatchTemplate的衍生算法不应作为单独的配置参数出现
//case AlgorithmType::CompareHist:
// break;
default:
// TODO抛个报错的回调出去
break;
}
callback_json["elite_rect"] = json::array({ rect.x, rect.y, rect.width, rect.height });
callback_json["name"] = task_name;
if (matched_rect != NULL) {
*matched_rect = std::move(rect);
}
m_callback(AsstMsg::ImageFindResult, callback_json, m_callback_arg);
if (matched) {
m_callback(AsstMsg::ImageMatched, callback_json, m_callback_arg);
return task_info_ptr;
}
}
return nullptr;
}
void ProcessTask::exec_click_task(const Rect& matched_rect)
{
// 随机延时功能
if (Configer::get_instance().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<unsigned> rand_uni(
Configer::get_instance().m_options.control_delay_lower,
Configer::get_instance().m_options.control_delay_upper);
unsigned rand_delay = rand_uni(rand_engine);
if (!sleep(rand_delay)) {
return;
}
}
m_control_ptr->click(matched_rect);
}

View File

@@ -0,0 +1,25 @@
#pragma once
#include "OcrAbstractTask.h"
namespace asst {
// 流程任务,按照配置文件里的设置的流程运行
class ProcessTask : public OcrAbstractTask
{
public:
ProcessTask(AsstCallback callback, void* callback_arg);
virtual ~ProcessTask() = default;
virtual bool run() override;
virtual void set_tasks(const std::vector<std::string>& cur_tasks_name) {
m_cur_tasks_name = cur_tasks_name;
}
protected:
std::shared_ptr<TaskInfo> match_image(asst::Rect* matched_rect = NULL);
void exec_click_task(const asst::Rect& matched_rect);
std::vector<std::string> m_cur_tasks_name;
};
}

View File

@@ -5,6 +5,7 @@
#include <algorithm>
#include <json.h>
#include "Logger.hpp"
using namespace asst;

View File

@@ -32,7 +32,7 @@ namespace asst {
RecruitConfiger(RecruitConfiger&& rhs) noexcept = default;
RecruitConfiger& operator=(const RecruitConfiger& rhs) = default;
RecruitConfiger& operator=(RecruitConfiger && rhs) noexcept = default;
RecruitConfiger& operator=(RecruitConfiger&& rhs) noexcept = default;
bool _load(const std::string& filename);
};

7
MeoAssistance/Task.h Normal file
View File

@@ -0,0 +1,7 @@
#pragma once
#include "ClickTask.h"
#include "InfrastConfiger.h"
#include "OpenRecruitTask.h"
#include "ProcessTask.h"
#include "TestOcrTask.h"

View File

@@ -0,0 +1,69 @@
#include "TestOcrTask.h"
#include <opencv2/opencv.hpp>
#include "AsstAux.h"
#include "WinMacro.h"
#include "Identify.h"
#include "Configer.h"
#include "InfrastConfiger.h"
using namespace asst;
TestOcrTask::TestOcrTask(AsstCallback callback, void* callback_arg)
: OcrAbstractTask(callback, callback_arg)
{
m_task_type = TaskType::TaskTypeRecognition & TaskType::TaskTypeClick;
}
bool TestOcrTask::run()
{
if (m_view_ptr == NULL
|| m_identify_ptr == NULL)
{
m_callback(AsstMsg::PtrIsNull, json::value(), m_callback_arg);
return false;
}
auto detect_foo = [&](const cv::Mat& image) -> std::vector<TextArea> {
std::vector<TextArea> all_text_area = ocr_detect(image);
/* 过滤出所有制造站中的干员名 */
std::vector<TextArea> cur_name_textarea = text_search(
all_text_area,
InfrastConfiger::get_instance().m_all_opers_name,
Configer::get_instance().m_infrast_ocr_replace);
return cur_name_textarea;
};
const cv::Mat& image = get_format_image(true);
auto cur_name_textarea = detect_foo(image);
// for debug
cv::Mat elite1 = cv::imread(GetResourceDir() + "operators\\Elite1.png");
cv::Mat elite2 = cv::imread(GetResourceDir() + "operators\\Elite2.png");
for (const TextArea& textarea : cur_name_textarea)
{
cv::Rect elite_rect;
elite_rect.x = textarea.rect.x - 200;
elite_rect.y = textarea.rect.y - 200;
elite_rect.width = 100;
elite_rect.height = 150;
auto&& [score1, point1] = m_identify_ptr->match_template(image(elite_rect), elite1);
auto&& [score2, point2] = m_identify_ptr->match_template(image(elite_rect), elite2);
if (score1 > score2 && score1 > 0.7) {
std::cout << Utf8ToGbk(textarea.text) << ",精一, elite1: " << score1 << ", eilte2: " << score2 << std::endl;
}
else if (score2 > score1 && score2 > 0.7) {
std::cout << Utf8ToGbk(textarea.text) << ",精二, elite1: " << score1 << ", eilte2: " << score2 << std::endl;
}
else {
std::cout << Utf8ToGbk(textarea.text) << ",未精英化, elite1: " << score1 << ", eilte2: " << score2 << std::endl;
}
//m_identify_ptr->feature_match(image(elite_rect), "Elite1");
//m_identify_ptr->feature_match(image(elite_rect), "Elite2");
}
return true;
}

View File

@@ -0,0 +1,29 @@
#pragma once
#include "OcrAbstractTask.h"
namespace asst {
// for debug
class TestOcrTask : public OcrAbstractTask
{
public:
TestOcrTask(AsstCallback callback, void* callback_arg);
virtual ~TestOcrTask() = default;
virtual bool run() override;
void set_text(std::string text, bool need_click = false)
{
m_text_vec.clear();
m_text_vec.emplace_back(std::move(text));
m_need_click = need_click;
}
void set_text(std::vector<std::string> text_vec, bool need_click = false)
{
m_text_vec = std::move(text_vec);
m_need_click = need_click;
}
private:
std::vector<std::string> m_text_vec;
bool m_need_click = false;
};
}

View File

@@ -1,10 +1,12 @@
#include "Updater.h"
#include <stdio.h>
#include <Windows.h>
#include <WinInet.h>
#include <json.h>
#include "AsstDef.h"
#include "Logger.hpp"
#include "Version.h"

View File

@@ -1,13 +1,13 @@
#include "WinMacro.h"
#include <stdint.h>
#include <WinUser.h>
#include <vector>
#include <utility>
#include <algorithm>
#include <chrono>
#include <stdint.h>
#include <WinUser.h>
#include <opencv2/opencv.hpp>
#include "AsstDef.h"
@@ -99,7 +99,7 @@ bool WinMacro::findHandle()
adb_dir = adb_dir.substr(0, pos);
adb_dir = '"' + StringReplaceAll(m_emulator_info.adb.path, "[EmulatorPath]", adb_dir) + '"';
if (m_handle_type == HandleType::Control)
if (m_handle_type == HandleType::Control)
{
std::string connect_cmd = StringReplaceAll(m_emulator_info.adb.connect, "[Adb]", adb_dir);
if (!callCmd(connect_cmd)) {
@@ -120,7 +120,7 @@ bool WinMacro::findHandle()
m_click_cmd = StringReplaceAll(m_emulator_info.adb.click, "[Adb]", adb_dir);
m_swipe_cmd = StringReplaceAll(m_emulator_info.adb.swipe, "[Adb]", adb_dir);
}
else if (m_handle_type == HandleType::View)
else if (m_handle_type == HandleType::View)
{
m_screencap_cmd = StringReplaceAll(
StringReplaceAll(m_emulator_info.adb.screencap, "[Adb]", adb_dir),
@@ -445,4 +445,4 @@ cv::Mat asst::WinMacro::getAdbImage()
}
}
return cv::Mat();
}
}

View File

@@ -3,6 +3,7 @@
#include <string>
#include <random>
#include <optional>
#include <Windows.h>
#include "AsstDef.h"

View File

@@ -1,310 +0,0 @@
#pragma once
#include <string>
#include <vector>
#include <memory>
#include <optional>
#include <functional>
#include <unordered_map>
#include "AsstDef.h"
#include "AsstAux.h"
#include <json.h>
namespace cv
{
class Mat;
}
namespace json
{
class value;
}
namespace asst {
class WinMacro;
class Identify;
class Configer;
class RecruitConfiger;
enum TaskType {
TaskTypeInvalid = 0,
TaskTypeWindowZoom = 1,
TaskTypeRecognition = 2,
TaskTypeClick = 4
};
enum class AsstMsg {
/* Error Msg */
PtrIsNull,
ImageIsEmpty,
WindowMinimized,
InitFaild,
/* Info Msg */
TaskStart,
ImageFindResult,
ImageMatched,
TaskMatched,
ReachedLimit,
ReadyToSleep,
EndOfSleep,
AppendProcessTask, // 这个消息Assistance会新增任务外部不需要处理
AppendTask, // 这个消息Assistance会新增任务外部不需要处理
TaskCompleted,
PrintWindow,
TaskStop,
TaskError,
/* Open Recruit Msg */
TextDetected,
RecruitTagsDetected,
OcrResultError,
RecruitSpecialTag,
RecruitResult,
/* Infrast Msg*/
InfrastOpers, // 识别到基建干员s
InfrastComb // 当前设置的最优干员组合
};
// 设施类型
enum class FacilityType {
Invalid,
Manufacturing, // 制造站
Trade, // 贸易站
PowerStation, // 发电站
ControlInterface, // 控制中枢
ReceptionRoom, // 会客室
Dormitory, // 宿舍
Office // 办公室
// 训练室和加工站用不上,不加了
};
static std::ostream& operator<<(std::ostream& os, const AsstMsg& type)
{
static const std::unordered_map<AsstMsg, std::string> _type_name = {
{AsstMsg::PtrIsNull, "PtrIsNull"},
{AsstMsg::ImageIsEmpty, "ImageIsEmpty"},
{AsstMsg::WindowMinimized, "WindowMinimized"},
{AsstMsg::InitFaild, "InitFaild"},
{AsstMsg::TaskStart, "TaskStart"},
{AsstMsg::ImageFindResult, "ImageFindResult"},
{AsstMsg::ImageMatched, "ImageMatched"},
{AsstMsg::TaskMatched, "TaskMatched"},
{AsstMsg::ReachedLimit, "ReachedLimit"},
{AsstMsg::ReadyToSleep, "ReadyToSleep"},
{AsstMsg::EndOfSleep, "EndOfSleep"},
{AsstMsg::AppendProcessTask, "AppendProcessTask"},
{AsstMsg::TaskCompleted, "TaskCompleted"},
{AsstMsg::PrintWindow, "PrintWindow"},
{AsstMsg::TaskError, "TaskError"},
{AsstMsg::TaskStop, "TaskStop"},
{AsstMsg::TextDetected, "TextDetected"},
{AsstMsg::RecruitTagsDetected, "RecruitTagsDetected"},
{AsstMsg::OcrResultError, "OcrResultError"},
{AsstMsg::RecruitSpecialTag, "RecruitSpecialTag"},
{AsstMsg::RecruitResult, "RecruitResult"},
{AsstMsg::AppendTask, "AppendTask"},
{AsstMsg::InfrastOpers, "InfrastOpers"},
{AsstMsg::InfrastComb, "InfrastComb"}
};
return os << _type_name.at(type);
}
// AsstCallback 消息回调函数
// 参数:
// AsstMsg 消息类型
// const json::value& 消息详情json每种消息不同Todo需要补充个协议文档啥的
// void* 外部调用者自定义参数,每次回调会带出去,建议传个(void*)this指针进来
using AsstCallback = std::function<void(AsstMsg, const json::value&, void*)>;
class AbstractTask
{
public:
AbstractTask(AsstCallback callback, void* callback_arg);
virtual ~AbstractTask() = default;
AbstractTask(const AbstractTask&) = default;
AbstractTask(AbstractTask&&) = default;
virtual void set_ptr(
std::shared_ptr<WinMacro> window_ptr,
std::shared_ptr<WinMacro> view_ptr,
std::shared_ptr<WinMacro> control_ptr,
std::shared_ptr<Identify> identify_ptr);
virtual bool run() = 0;
virtual void set_exit_flag(bool* exit_flag);
virtual int get_task_type() { return m_task_type; }
virtual void set_retry_times(int times) { m_retry_times = times; }
virtual int get_retry_times() { return m_retry_times; }
virtual void set_task_chain(std::string name) { m_task_chain = std::move(name); }
virtual const std::string& get_task_chain() { return m_task_chain; }
protected:
virtual cv::Mat get_format_image(bool hd = false); // 参数hd高清截图会慢一点
virtual bool set_control_scale(double scale);
virtual bool set_control_scale(int cur_width, int cur_height);
virtual bool sleep(unsigned millisecond);
virtual bool print_window(const std::string& dir);
std::shared_ptr<WinMacro> m_window_ptr = nullptr;
std::shared_ptr<WinMacro> m_view_ptr = nullptr;
std::shared_ptr<WinMacro> m_control_ptr = nullptr;
std::shared_ptr<Identify> m_identify_ptr = nullptr;
AsstCallback m_callback;
void* m_callback_arg = NULL;
bool* m_exit_flag = NULL;
std::string m_task_chain;
int m_task_type = TaskType::TaskTypeInvalid;
int m_retry_times = INT_MAX;
};
class ClickTask : public AbstractTask
{
public:
ClickTask(AsstCallback callback, void* callback_arg);
virtual ~ClickTask() = default;
virtual bool run() override;
void set_rect(asst::Rect rect) { m_rect = std::move(rect); };
protected:
asst::Rect m_rect;
};
class OcrAbstractTask : public AbstractTask
{
public:
OcrAbstractTask(AsstCallback callback, void* callback_arg);
virtual ~OcrAbstractTask() = default;
virtual bool run() override = 0;
protected:
std::vector<TextArea> ocr_detect();
std::vector<TextArea> ocr_detect(const cv::Mat& image);
// 文字匹配,要求相等
template<typename FilterArray, typename ReplaceMap>
std::vector<TextArea> text_match(const std::vector<TextArea>& src,
const FilterArray& filter_array, const ReplaceMap& replace_map)
{
std::vector<TextArea> dst;
for (const TextArea& text_area : src) {
TextArea temp = text_area;
for (const auto& [old_str, new_str] : replace_map) {
temp.text = StringReplaceAll(temp.text, old_str, new_str);
}
for (const auto& text : filter_array) {
if (temp.text == text) {
dst.emplace_back(std::move(temp));
}
}
}
return dst;
}
// 文字搜索,是子串即可
template<typename FilterArray, typename ReplaceMap>
std::vector<TextArea> text_search(const std::vector<TextArea>& src,
const FilterArray& filter_array, const ReplaceMap& replace_map)
{
std::vector<TextArea> dst;
for (const TextArea& text_area : src) {
TextArea temp = text_area;
for (const auto& [old_str, new_str] : replace_map) {
temp.text = StringReplaceAll(temp.text, old_str, new_str);
}
for (const auto& text : filter_array) {
if (temp.text.find(text) != std::string::npos) {
dst.emplace_back(text, std::move(temp.rect));
}
}
}
return dst;
}
};
// 流程任务,按照配置文件里的设置的流程运行
class ProcessTask : public OcrAbstractTask
{
public:
ProcessTask(AsstCallback callback, void* callback_arg);
virtual ~ProcessTask() = default;
virtual bool run() override;
virtual void set_tasks(const std::vector<std::string>& cur_tasks_name) {
m_cur_tasks_name = cur_tasks_name;
}
protected:
std::shared_ptr<TaskInfo> match_image(asst::Rect* matched_rect = NULL);
void exec_click_task(const asst::Rect& matched_rect);
std::vector<std::string> m_cur_tasks_name;
};
class OpenRecruitTask : public OcrAbstractTask
{
public:
OpenRecruitTask(AsstCallback callback, void* callback_arg);
virtual ~OpenRecruitTask() = default;
virtual bool run() override;
virtual void set_param(std::vector<int> required_level, bool set_time = true);
protected:
std::vector<int> m_required_level;
bool m_set_time = false;
};
// 基建进驻任务
class InfrastStationTask : public OcrAbstractTask
{
public:
InfrastStationTask(AsstCallback callback, void* callback_arg);
virtual ~InfrastStationTask() = default;
virtual bool run() override;
void set_swipe_param(int delay, const Rect& begin_rect, const Rect& end_rect, int max_times = 20)
{
m_swipe_delay = delay;
m_swipe_begin = begin_rect;
m_swipe_end = end_rect;
m_swipe_max_times = max_times;
}
void set_facility(const std::string& facility)
{
m_facility = facility;
}
private:
std::string m_facility;
int m_swipe_delay = 0;
Rect m_swipe_begin;
Rect m_swipe_end;
int m_swipe_max_times = 0;
};
// for debug
class TestOcrTask : public OcrAbstractTask
{
public:
TestOcrTask(AsstCallback callback, void* callback_arg);
virtual ~TestOcrTask() = default;
virtual bool run() override;
void set_text(std::string text, bool need_click = false)
{
m_text_vec.clear();
m_text_vec.emplace_back(std::move(text));
m_need_click = need_click;
}
void set_text(std::vector<std::string> text_vec, bool need_click = false)
{
m_text_vec = std::move(text_vec);
m_need_click = need_click;
}
private:
std::vector<std::string> m_text_vec;
bool m_need_click = false;
};
}

View File

@@ -1,938 +0,0 @@
#include "Task.h"
#include "AsstDef.h"
#include "WinMacro.h"
#include "Identify.h"
#include "Configer.h"
#include "RecruitConfiger.h"
#include "InfrastConfiger.h"
#include <json.h>
#include "AsstAux.h"
#include <chrono>
#include <thread>
#include <utility>
#include <cmath>
#include <mutex>
#include <filesystem>
#include <future>
using namespace asst;
AbstractTask::AbstractTask(AsstCallback callback, void* callback_arg)
:m_callback(callback),
m_callback_arg(callback_arg)
{
;
}
void AbstractTask::set_ptr(
std::shared_ptr<WinMacro> window_ptr,
std::shared_ptr<WinMacro> view_ptr,
std::shared_ptr<WinMacro> control_ptr,
std::shared_ptr<Identify> identify_ptr)
{
m_window_ptr = window_ptr;
m_view_ptr = view_ptr;
m_control_ptr = control_ptr;
m_identify_ptr = identify_ptr;
}
void AbstractTask::set_exit_flag(bool* exit_flag)
{
m_exit_flag = exit_flag;
}
cv::Mat AbstractTask::get_format_image(bool hd)
{
cv::Mat raw_image;
if (hd) {
raw_image = m_view_ptr->getAdbImage();
}
else {
raw_image = m_view_ptr->getImage(m_view_ptr->getWindowRect());
}
if (raw_image.empty()) {
m_callback(AsstMsg::ImageIsEmpty, json::value(), m_callback_arg);
return raw_image;
}
if (raw_image.rows < 100) {
m_callback(AsstMsg::WindowMinimized, json::value(), m_callback_arg);
return raw_image;
}
if (hd) {
set_control_scale(1.0);
return raw_image;
}
else {
// 把模拟器边框的一圈裁剪掉
const EmulatorInfo& window_info = m_view_ptr->getEmulatorInfo();
int x_offset = window_info.x_offset;
int y_offset = window_info.y_offset;
int width = raw_image.cols - x_offset - window_info.right_offset;
int height = raw_image.rows - y_offset - window_info.bottom_offset;
cv::Mat cropped(raw_image, cv::Rect(x_offset, y_offset, width, height));
// 根据图像尺寸,调整控制的缩放
set_control_scale(cropped.cols, cropped.rows);
//// 调整尺寸,与资源中截图的标准尺寸一致
//cv::Mat dst;
//cv::resize(cropped, dst, cv::Size(m_configer.DefaultWindowWidth, m_configer.DefaultWindowHeight));
return cropped;
}
}
bool asst::AbstractTask::set_control_scale(double scale)
{
m_control_ptr->setControlScale(scale, true);
return true;
}
bool AbstractTask::set_control_scale(int cur_width, int cur_height)
{
double scale_width = static_cast<double>(cur_width) / Configer::DefaultWindowWidth;
double scale_height = static_cast<double>(cur_height) / Configer::DefaultWindowHeight;
double scale = std::max(scale_width, scale_height);
m_control_ptr->setControlScale(scale);
return true;
}
bool AbstractTask::sleep(unsigned millisecond)
{
if (millisecond == 0) {
return true;
}
auto start = std::chrono::system_clock::now();
unsigned duration = 0;
json::value callback_json;
callback_json["time"] = millisecond;
m_callback(AsstMsg::ReadyToSleep, callback_json, m_callback_arg);
while ((m_exit_flag == NULL || *m_exit_flag == false)
&& duration < millisecond) {
duration = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now() - start).count();
std::this_thread::yield();
}
m_callback(AsstMsg::EndOfSleep, callback_json, m_callback_arg);
return (m_exit_flag == NULL || *m_exit_flag == false);
}
bool AbstractTask::print_window(const std::string& dir)
{
const cv::Mat& image = get_format_image();
if (image.empty()) {
return false;
}
// 保存的截图额外再裁剪掉一圈,不然企鹅物流识别不出来
int offset = Configer::get_instance().m_options.print_window_crop_offset;
cv::Rect rect(offset, offset, image.cols - offset * 2, image.rows - offset * 2);
std::filesystem::create_directory(dir);
const std::string time_str = StringReplaceAll(StringReplaceAll(GetFormatTimeString(), " ", "_"), ":", "-");
const std::string filename = dir + time_str + ".png";
bool ret = cv::imwrite(filename.c_str(), image(rect));
json::value callback_json;
callback_json["filename"] = filename;
callback_json["ret"] = ret;
callback_json["offset"] = offset;
m_callback(AsstMsg::PrintWindow, callback_json, m_callback_arg);
return ret;
}
ProcessTask::ProcessTask(AsstCallback callback, void* callback_arg)
: OcrAbstractTask(callback, callback_arg)
{
m_task_type = TaskType::TaskTypeRecognition | TaskType::TaskTypeClick;
}
bool ProcessTask::run()
{
if (m_view_ptr == NULL
|| m_control_ptr == NULL
|| m_identify_ptr == NULL
|| m_control_ptr == NULL)
{
m_callback(AsstMsg::PtrIsNull, json::value(), m_callback_arg);
return false;
}
json::value task_start_json = json::object{
{ "task_type", "ProcessTask" },
{ "task_chain", m_task_chain},
};
m_callback(AsstMsg::TaskStart, task_start_json, m_callback_arg);
std::shared_ptr<TaskInfo> task_info_ptr = nullptr;
Rect rect;
task_info_ptr = match_image(&rect);
if (!task_info_ptr) {
return false;
}
json::value callback_json = json::object{
{ "name", task_info_ptr->name },
{ "type", static_cast<int>(task_info_ptr->type) },
{ "exec_times", task_info_ptr->exec_times },
{ "max_times", task_info_ptr->max_times },
{ "task_type", "ProcessTask"},
{ "algorithm", static_cast<int>(task_info_ptr->algorithm)}
};
m_callback(AsstMsg::TaskMatched, callback_json, m_callback_arg);
if (task_info_ptr->exec_times >= task_info_ptr->max_times)
{
m_callback(AsstMsg::ReachedLimit, callback_json, m_callback_arg);
json::value next_json = callback_json;
next_json["tasks"] = json::array(task_info_ptr->exceeded_next);
next_json["retry_times"] = m_retry_times;
next_json["task_chain"] = m_task_chain;
m_callback(AsstMsg::AppendProcessTask, next_json, m_callback_arg);
return true;
}
// 前置固定延时
if (!sleep(task_info_ptr->pre_delay))
{
return false;
}
bool need_stop = false;
switch (task_info_ptr->type) {
case ProcessTaskType::ClickRect:
rect = task_info_ptr->specific_area;
[[fallthrough]];
case ProcessTaskType::ClickSelf:
exec_click_task(rect);
break;
case ProcessTaskType::DoNothing:
break;
case ProcessTaskType::Stop:
m_callback(AsstMsg::TaskStop, json::object{ {"task_chain", m_task_chain} }, m_callback_arg);
need_stop = true;
break;
case ProcessTaskType::PrintWindow:
{
if (!sleep(Configer::get_instance().m_options.print_window_delay))
{
return false;
}
static const std::string dirname = GetCurrentDir() + "screenshot\\";
print_window(dirname);
}
break;
default:
break;
}
++task_info_ptr->exec_times;
// 减少其他任务的执行次数
// 例如,进入吃理智药的界面了,相当于上一次点蓝色开始行动没生效
// 所以要给蓝色开始行动的次数减一
for (const std::string& reduce : task_info_ptr->reduce_other_times) {
--Configer::get_instance().m_all_tasks_info[reduce]->exec_times;
}
if (need_stop) {
return true;
}
callback_json["exec_times"] = task_info_ptr->exec_times;
m_callback(AsstMsg::TaskCompleted, callback_json, m_callback_arg);
// 后置固定延时
if (!sleep(task_info_ptr->rear_delay)) {
return false;
}
json::value next_json = callback_json;
next_json["task_chain"] = m_task_chain;
next_json["retry_times"] = m_retry_times;
next_json["tasks"] = json::array(task_info_ptr->next);
m_callback(AsstMsg::AppendProcessTask, next_json, m_callback_arg);
return true;
}
std::shared_ptr<TaskInfo> ProcessTask::match_image(Rect* matched_rect)
{
//// 如果当前仅有一个任务且这个任务的阈值是0说明是justreturn的就不抓图像识别了直接返回就行
//if (m_cur_tasks_name.size() == 1)
//{
// // 能走到这个函数里的肯定是ProcessTaskInfo直接转
// auto task_info_ptr = std::dynamic_pointer_cast<MatchTaskInfo>(
// Configer::get_instance().m_all_tasks_info[m_cur_tasks_name[0]]);
// if (task_info_ptr->templ_threshold == 0) {
// json::value callback_json;
// callback_json["threshold"] = 0.0;
// callback_json["algorithm"] = "JustReturn";
// callback_json["rect"] = json::array({ 0, 0, 0, 0 });
// callback_json["name"] = m_cur_tasks_name[0];
// callback_json["algorithm_id"] = static_cast<std::underlying_type<ProcessTaskType>::type>(
// AlgorithmType::JustReturn);
// callback_json["value"] = 0;
// m_callback(AsstMsg::ImageFindResult, callback_json, m_callback_arg);
// m_callback(AsstMsg::ImageMatched, callback_json, m_callback_arg);
// return task_info_ptr;
// }
//}
const cv::Mat& cur_image = get_format_image();
if (cur_image.empty() || cur_image.rows < 100) {
return nullptr;
}
// 逐个匹配当前可能的任务
for (const std::string& task_name : m_cur_tasks_name) {
std::shared_ptr<TaskInfo> task_info_ptr = Configer::get_instance().m_all_tasks_info[task_name];
if (task_info_ptr == nullptr) {
m_callback(AsstMsg::PtrIsNull, json::value(), m_callback_arg);
continue;
}
json::value callback_json;
bool matched = false;
Rect rect;
switch (task_info_ptr->algorithm)
{
case AlgorithmType::JustReturn:
callback_json["algorithm"] = "JustReturn";
matched = true;
break;
case AlgorithmType::MatchTemplate:
{
std::shared_ptr<MatchTaskInfo> process_task_info_ptr =
std::dynamic_pointer_cast<MatchTaskInfo>(task_info_ptr);
double templ_threshold = process_task_info_ptr->templ_threshold;
double hist_threshold = process_task_info_ptr->hist_threshold;
auto&& [algorithm, value, temp_rect] = m_identify_ptr->find_image(cur_image, task_name, templ_threshold);
rect = std::move(temp_rect);
callback_json["value"] = value;
if (algorithm == AlgorithmType::MatchTemplate) {
callback_json["threshold"] = templ_threshold;
callback_json["algorithm"] = "MatchTemplate";
if (value >= templ_threshold) {
matched = true;
}
}
else if (algorithm == AlgorithmType::CompareHist) {
callback_json["threshold"] = hist_threshold;
callback_json["algorithm"] = "CompareHist";
if (value >= hist_threshold) {
matched = true;
}
}
else {
continue;
}
}
break;
case AlgorithmType::OcrDetect:
{
std::shared_ptr<OcrTaskInfo> ocr_task_info_ptr =
std::dynamic_pointer_cast<OcrTaskInfo>(task_info_ptr);
std::vector<TextArea> all_text_area = ocr_detect(cur_image);
std::vector<TextArea> match_result;
if (ocr_task_info_ptr->need_match) {
match_result = text_match(all_text_area,
ocr_task_info_ptr->text, ocr_task_info_ptr->replace_map);
}
else {
match_result = text_search(all_text_area,
ocr_task_info_ptr->text, ocr_task_info_ptr->replace_map);
}
// TODO如果搜出来多个结果怎么处理
// 暂时通过配置文件保证尽量只搜出来一个结果or一个都搜不到
if (!match_result.empty()) {
callback_json["text"] = Utf8ToGbk(match_result.at(0).text);
rect = match_result.at(0).rect;
matched = true;
}
}
break;
//CompareHist是MatchTemplate的衍生算法不应作为单独的配置参数出现
//case AlgorithmType::CompareHist:
// break;
default:
// TODO抛个报错的回调出去
break;
}
callback_json["elite_rect"] = json::array({ rect.x, rect.y, rect.width, rect.height });
callback_json["name"] = task_name;
if (matched_rect != NULL) {
*matched_rect = std::move(rect);
}
m_callback(AsstMsg::ImageFindResult, callback_json, m_callback_arg);
if (matched) {
m_callback(AsstMsg::ImageMatched, callback_json, m_callback_arg);
return task_info_ptr;
}
}
return nullptr;
}
void ProcessTask::exec_click_task(const Rect& matched_rect)
{
// 随机延时功能
if (Configer::get_instance().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<unsigned> rand_uni(
Configer::get_instance().m_options.control_delay_lower,
Configer::get_instance().m_options.control_delay_upper);
unsigned rand_delay = rand_uni(rand_engine);
if (!sleep(rand_delay)) {
return;
}
}
m_control_ptr->click(matched_rect);
}
OcrAbstractTask::OcrAbstractTask(AsstCallback callback, void* callback_arg)
: AbstractTask(callback, callback_arg)
{
;
}
std::vector<TextArea> OcrAbstractTask::ocr_detect()
{
const cv::Mat& image = get_format_image();
return ocr_detect(image);
}
std::vector<TextArea> OcrAbstractTask::ocr_detect(const cv::Mat& image)
{
std::vector<TextArea> dst = m_identify_ptr->ocr_detect(image);
std::vector<json::value> all_text_json_vector;
for (const TextArea& text_area : dst) {
all_text_json_vector.emplace_back(Utf8ToGbk(text_area.text));
}
json::value all_text_json;
all_text_json["text"] = json::array(all_text_json_vector);
all_text_json["task_chain"] = m_task_chain;
m_callback(AsstMsg::TextDetected, all_text_json, m_callback_arg);
return dst;
}
OpenRecruitTask::OpenRecruitTask(AsstCallback callback, void* callback_arg)
: OcrAbstractTask(callback, callback_arg)
{
m_task_type = TaskType::TaskTypeRecognition & TaskType::TaskTypeClick;
}
bool OpenRecruitTask::run()
{
if (m_view_ptr == NULL
|| m_identify_ptr == NULL)
{
m_callback(AsstMsg::PtrIsNull, json::value(), m_callback_arg);
return false;
}
json::value task_start_json = json::object{
{ "task_type", "OpenRecruitTask" },
{ "task_chain", m_task_chain},
};
m_callback(AsstMsg::TaskStart, task_start_json, m_callback_arg);
/* Find all text */
std::vector<TextArea> all_text_area = ocr_detect();
/* Filter out all tags from all text */
std::vector<TextArea> all_tags = text_match(
all_text_area, RecruitConfiger::get_instance().m_all_tags, Configer::get_instance().m_recruit_ocr_replace);
std::unordered_set<std::string> all_tags_name;
std::vector<json::value> all_tags_json_vector;
for (const TextArea& text_area : all_tags) {
all_tags_name.emplace(text_area.text);
all_tags_json_vector.emplace_back(Utf8ToGbk(text_area.text));
}
json::value all_tags_json;
all_tags_json["tags"] = json::array(all_tags_json_vector);
m_callback(AsstMsg::RecruitTagsDetected, all_tags_json, m_callback_arg);
/* 过滤tags数量不足的情况可能是识别漏了 */
if (all_tags.size() != RecruitConfiger::CorrectNumberOfTags) {
all_tags_json["type"] = "OpenRecruit";
m_callback(AsstMsg::OcrResultError, all_tags_json, m_callback_arg);
return false;
}
/* 设置招募时间9小时加入任务队列*/
if (m_set_time) {
json::value settime_json;
settime_json["task"] = "RecruitTime";
// 只有tag数量对了才能走到这里界面一定是对的所以找不到时间设置就说明时间已经手动修改过了不用重试了
settime_json["retry_times"] = 0;
settime_json["task_chain"] = m_task_chain;
m_callback(AsstMsg::AppendProcessTask, settime_json, m_callback_arg);
}
/* 针对一星干员的额外回调消息 */
static const std::string SupportMachine_GBK = "支援机械";
static const std::string SupportMachine = GbkToUtf8(SupportMachine_GBK);
if (std::find(all_tags_name.cbegin(), all_tags_name.cend(), SupportMachine) != all_tags_name.cend()) {
json::value special_tag_json;
special_tag_json["tag"] = SupportMachine_GBK;
m_callback(AsstMsg::RecruitSpecialTag, special_tag_json, m_callback_arg);
}
// 识别到的5个Tags全组合排列
std::vector<std::vector<std::string>> all_combs;
int len = all_tags.size();
int count = std::pow(2, len);
for (int i = 0; i < count; ++i) {
std::vector<std::string> temp;
for (int j = 0, mask = 1; j < len; ++j) {
if ((i & mask) != 0) { // What the fuck???
temp.emplace_back(all_tags.at(j).text);
}
mask = mask * 2;
}
// 游戏里最多选择3个tag
if (!temp.empty() && temp.size() <= 3) {
all_combs.emplace_back(std::move(temp));
}
}
// key: tags comb, value: 干员组合
// 例如 key: { "狙击"、"群攻" }value: OperRecruitCombs.opers{ "陨星", "白雪", "空爆" }
std::map<std::vector<std::string>, OperRecruitCombs> result_map;
for (const std::vector<std::string>& comb : all_combs) {
for (const OperRecruitInfo& cur_oper : RecruitConfiger::get_instance().m_all_opers) {
int matched_count = 0;
for (const std::string& tag : comb) {
if (cur_oper.tags.find(tag) != cur_oper.tags.cend()) {
++matched_count;
}
else {
break;
}
}
// 单个tags comb中的每一个tag这个干员都有才算该干员符合这个tags comb
if (matched_count != comb.size()) {
continue;
}
if (cur_oper.level == 6) {
// 高资tag和六星强绑定如果没有高资tag即使其他tag匹配上了也不可能出六星
static const std::string SeniorOper = GbkToUtf8("高级资深干员");
if (std::find(comb.cbegin(), comb.cend(), SeniorOper) == comb.cend()) {
continue;
}
}
OperRecruitCombs& oper_combs = result_map[comb];
oper_combs.opers.emplace_back(cur_oper);
if (cur_oper.level == 1 || cur_oper.level == 2) {
if (oper_combs.min_level == 0) oper_combs.min_level = cur_oper.level;
if (oper_combs.max_level == 0) oper_combs.max_level = cur_oper.level;
// 一星、二星干员不计入最低等级因为拉满9小时之后不可能出1、2星
continue;
}
if (oper_combs.min_level == 0 || oper_combs.min_level > cur_oper.level) {
oper_combs.min_level = cur_oper.level;
}
if (oper_combs.max_level == 0 || oper_combs.max_level < cur_oper.level) {
oper_combs.max_level = cur_oper.level;
}
oper_combs.avg_level += cur_oper.level;
}
if (result_map.find(comb) != result_map.cend()) {
OperRecruitCombs& oper_combs = result_map[comb];
oper_combs.avg_level /= oper_combs.opers.size();
}
}
// map没法按值排序转个vector再排序
std::vector<std::pair<std::vector<std::string>, OperRecruitCombs>> result_vector;
for (auto&& pair : result_map) {
result_vector.emplace_back(std::move(pair));
}
std::sort(result_vector.begin(), result_vector.end(), [](const auto& lhs, const auto& rhs)
->bool {
// 最小等级大的,排前面
if (lhs.second.min_level != rhs.second.min_level) {
return lhs.second.min_level > rhs.second.min_level;
}
// 最大等级大的,排前面
else if (lhs.second.max_level != rhs.second.max_level) {
return lhs.second.max_level > rhs.second.max_level;
}
// 平均等级高的,排前面
else if (std::fabs(lhs.second.avg_level - rhs.second.avg_level) < DoubleDiff) {
return lhs.second.avg_level > rhs.second.avg_level;
}
// Tag数量少的排前面
else {
return lhs.first.size() < rhs.first.size();
}
});
/* 整理识别结果 */
std::vector<json::value> result_json_vector;
for (const auto& [tags_comb, oper_comb] : result_vector) {
json::value comb_json;
std::vector<json::value> tags_json_vector;
for (const std::string& tag : tags_comb) {
tags_json_vector.emplace_back(Utf8ToGbk(tag));
}
comb_json["tags"] = json::array(std::move(tags_json_vector));
std::vector<json::value> opers_json_vector;
for (const OperRecruitInfo& oper_info : oper_comb.opers) {
json::value oper_json;
oper_json["name"] = Utf8ToGbk(oper_info.name);
oper_json["level"] = oper_info.level;
opers_json_vector.emplace_back(std::move(oper_json));
}
comb_json["opers"] = json::array(std::move(opers_json_vector));
comb_json["tag_level"] = oper_comb.min_level;
result_json_vector.emplace_back(std::move(comb_json));
}
json::value results_json;
results_json["result"] = json::array(std::move(result_json_vector));
m_callback(AsstMsg::RecruitResult, results_json, m_callback_arg);
/* 点击最优解的tags添加点击任务 */
if (!m_required_level.empty() && !result_vector.empty()) {
if (std::find(m_required_level.cbegin(), m_required_level.cend(), result_vector[0].second.min_level)
== m_required_level.cend()) {
return true;
}
const std::vector<std::string>& final_tags_name = result_vector[0].first;
json::value task_json;
task_json["type"] = "ClickTask";
for (const TextArea& text_area : all_tags) {
if (std::find(final_tags_name.cbegin(), final_tags_name.cend(), text_area.text) != final_tags_name.cend()) {
task_json["elite_rect"] = json::array({ text_area.rect.x, text_area.rect.y, text_area.rect.width, text_area.rect.height });
task_json["retry_times"] = m_retry_times;
task_json["task_chain"] = m_task_chain;
m_callback(AsstMsg::AppendTask, task_json, m_callback_arg);
}
}
}
return true;
}
void OpenRecruitTask::set_param(std::vector<int> required_level, bool set_time)
{
m_required_level = std::move(required_level);
m_set_time = set_time;
}
ClickTask::ClickTask(AsstCallback callback, void* callback_arg)
: AbstractTask(callback, callback_arg)
{
m_task_type = TaskType::TaskTypeClick;
}
bool ClickTask::run()
{
if (m_control_ptr == NULL)
{
m_callback(AsstMsg::PtrIsNull, json::value(), m_callback_arg);
return false;
}
json::value task_start_json = json::object{
{ "task_type", "ClickTask" },
{ "task_chain", m_task_chain},
};
m_callback(AsstMsg::TaskStart, task_start_json, m_callback_arg);
m_control_ptr->click(m_rect);
return true;
}
TestOcrTask::TestOcrTask(AsstCallback callback, void* callback_arg)
: OcrAbstractTask(callback, callback_arg)
{
m_task_type = TaskType::TaskTypeRecognition & TaskType::TaskTypeClick;
}
bool TestOcrTask::run()
{
if (m_view_ptr == NULL
|| m_identify_ptr == NULL)
{
m_callback(AsstMsg::PtrIsNull, json::value(), m_callback_arg);
return false;
}
auto detect_foo = [&](const cv::Mat& image) -> std::vector<TextArea> {
std::vector<TextArea> all_text_area = ocr_detect(image);
/* 过滤出所有制造站中的干员名 */
std::vector<TextArea> cur_name_textarea = text_search(
all_text_area,
InfrastConfiger::get_instance().m_all_opers_name,
Configer::get_instance().m_infrast_ocr_replace);
return cur_name_textarea;
};
const cv::Mat& image = get_format_image(true);
auto cur_name_textarea = detect_foo(image);
// for debug
cv::Mat elite1 = cv::imread(GetResourceDir() + "operators\\Elite1.png");
cv::Mat elite2 = cv::imread(GetResourceDir() + "operators\\Elite2.png");
for (const TextArea& textarea : cur_name_textarea)
{
cv::Rect elite_rect;
elite_rect.x = textarea.rect.x - 200;
elite_rect.y = textarea.rect.y - 200;
elite_rect.width = 100;
elite_rect.height = 150;
auto&& [score1, point1] = m_identify_ptr->match_template(image(elite_rect), elite1);
auto&& [score2, point2] = m_identify_ptr->match_template(image(elite_rect), elite2);
if (score1 > score2 && score1 > 0.7) {
std::cout << Utf8ToGbk(textarea.text) << ",精一, elite1: " << score1 << ", eilte2: " << score2 << std::endl;
}
else if (score2 > score1 && score2 > 0.7) {
std::cout << Utf8ToGbk(textarea.text) << ",精二, elite1: " << score1 << ", eilte2: " << score2 << std::endl;
}
else {
std::cout << Utf8ToGbk(textarea.text) << ",未精英化, elite1: " << score1 << ", eilte2: " << score2 << std::endl;
}
//m_identify_ptr->feature_match(image(elite_rect), "Elite1");
//m_identify_ptr->feature_match(image(elite_rect), "Elite2");
}
return true;
}
asst::InfrastStationTask::InfrastStationTask(AsstCallback callback, void* callback_arg)
: OcrAbstractTask(callback, callback_arg)
{
}
bool asst::InfrastStationTask::run()
{
if (m_view_ptr == NULL
|| m_identify_ptr == NULL)
{
m_callback(AsstMsg::PtrIsNull, json::value(), m_callback_arg);
return false;
}
std::vector<std::vector<std::string>> all_oper_combs; // 所有的干员组合
std::unordered_map<std::string, std::string> feature_cond_default; // 特征检测关键字如果OCR识别到了key的内容但是却没有value的内容则进行特征检测进一步确认
std::unordered_set<std::string> feature_whatever_default; // 无论如何都进行特征检测的
json::value task_start_json = json::object{
{ "task_type", "InfrastStationTask" },
{ "task_chain", m_task_chain},
};
m_callback(AsstMsg::TaskStart, task_start_json, m_callback_arg);
auto swipe_foo = [&](bool reverse = false) -> bool {
bool ret = false;
if (!reverse) {
ret = m_control_ptr->swipe(m_swipe_begin, m_swipe_end);
}
else {
ret = m_control_ptr->swipe(m_swipe_end, m_swipe_begin);
}
ret &= sleep(m_swipe_delay);
return ret;
};
std::unordered_map<std::string, std::string> feature_cond = feature_cond_default;
std::unordered_set<std::string> feature_whatever = feature_whatever_default;
auto detect_foo = [&](const cv::Mat& image) -> std::vector<TextArea> {
std::vector<TextArea> all_text_area = ocr_detect(image);
/* 过滤出所有制造站中的干员名 */
std::vector<TextArea> cur_name_textarea = text_search(
all_text_area,
InfrastConfiger::get_instance().m_all_opers_name,
Configer::get_instance().m_infrast_ocr_replace);
// 用特征检测再筛选一遍OCR识别漏了的
for (const TextArea& textarea : all_text_area) {
for (auto iter = feature_cond.begin(); iter != feature_cond.end(); ++iter) {
auto& [key, value] = *iter;
// 识别到了key但是没识别到value这种情况就需要进行特征检测进一步确认了
if (textarea.text.find(key) != std::string::npos
&& textarea.text.find(value) == std::string::npos) {
// 把key所在的矩形放大一点送去做特征检测不需要把整张图片都送去检测
Rect magnified_area = textarea.rect.center_zoom(2.0);
magnified_area.x = std::max(0, magnified_area.x);
magnified_area.y = std::max(0, magnified_area.y);
if (magnified_area.x + magnified_area.width >= image.cols) {
magnified_area.width = image.cols - magnified_area.x - 1;
}
if (magnified_area.y + magnified_area.height >= image.rows) {
magnified_area.height = image.rows - magnified_area.y - 1;
}
cv::Rect cv_rect(magnified_area.x, magnified_area.y, magnified_area.width, magnified_area.height);
// key是关键字而已真正要识别的是value
auto&& ret = m_identify_ptr->feature_match(image(cv_rect), value);
if (ret) {
cur_name_textarea.emplace_back(value, textarea.rect);
iter = feature_cond.erase(iter);
--iter;
}
}
}
}
for (auto iter = feature_whatever.begin(); iter != feature_whatever.end(); ++iter) {
auto&& ret = m_identify_ptr->feature_match(image, *iter);
if (ret) {
cur_name_textarea.emplace_back(std::move(ret.value()));
iter = feature_whatever.erase(iter);
--iter;
}
}
return cur_name_textarea;
};
std::unordered_set<OperInfrastInfo> detected_opers;
// 一边识别一边滑动,把所有制造站干员名字抓出来
while (true) {
const cv::Mat& image = get_format_image(true);
// 异步进行滑动操作
std::future<bool> swipe_future = std::async(std::launch::async, swipe_foo);
auto cur_name_textarea = detect_foo(image);
int oper_numer = detected_opers.size();
for (const TextArea& textarea : cur_name_textarea)
{
cv::Rect elite_rect;
// 因为有的名字长有的名字短,但是右对齐的,所以跟着右边走
elite_rect.x = textarea.rect.x + textarea.rect.width - 250;
elite_rect.y = textarea.rect.y - 200;
if (elite_rect.x < 0 || elite_rect.y < 0) {
continue;
}
elite_rect.width = 100;
elite_rect.height = 150;
cv::Mat elite_mat = image(elite_rect);
// for debug
static cv::Mat elite1 = cv::imread(GetResourceDir() + "operators\\Elite1.png");
static cv::Mat elite2 = cv::imread(GetResourceDir() + "operators\\Elite2.png");
auto&& [score1, point1] = m_identify_ptr->match_template(elite_mat, elite1);
auto&& [score2, point2] = m_identify_ptr->match_template(elite_mat, elite2);
std::cout << "elite1:" << score1 << ", elite2:" << score2 << std::endl;
OperInfrastInfo info;
info.name = textarea.text;
if (score1 > score2 && score1 > 0.7) {
info.elite = 1;
}
else if (score2 > score1 && score2 > 0.7) {
info.elite = 2;
}
else {
info.elite = 0;
}
detected_opers.emplace(std::move(info));
}
json::value opers_json;
std::vector<json::value> opers_json_vec;
for (const OperInfrastInfo& info : detected_opers) {
json::value info_json;
info_json["name"] = Utf8ToGbk(info.name);
info_json["elite"] = info.elite;
//info_json["level"] = info.level;
opers_json_vec.emplace_back(std::move(info_json));
}
opers_json["all"] = json::array(opers_json_vec);
m_callback(AsstMsg::InfrastOpers, opers_json, m_callback_arg);
// 阻塞等待滑动结束
if (!swipe_future.get()) {
return false;
}
// 说明本次识别一个新的都没识别到,应该是滑动到最后了,直接结束循环
if (oper_numer == detected_opers.size()) {
break;
}
}
//// 配置文件中的干员组合,和抓出来的干员名比对,如果组合中的干员都有,那就用这个组合
//// Todo 时间复杂度起飞了,需要优化下
//std::vector<std::string> optimal_comb;
//for (auto&& name_vec : all_oper_combs) {
// int count = 0;
// for (std::string& name : name_vec) {
// if (detected_names.find(name) != detected_names.cend()) {
// ++count;
// }
// else {
// break;
// }
// }
// if (count == name_vec.size()) {
// optimal_comb = name_vec;
// break;
// }
//}
//std::vector<std::string> optimal_comb_gbk; // 给回调json用的gbk的
//for (const std::string& name : optimal_comb)
//{
// optimal_comb_gbk.emplace_back(Utf8ToGbk(name));
//}
//opers_json["comb"] = json::array(optimal_comb_gbk);
//m_callback(AsstMsg::InfrastComb, opers_json, m_callback_arg);
//// 重置特征检测的条件后面不用了这次直接move
//feature_cond = std::move(feature_cond_default);
//feature_whatever = std::move(feature_whatever_default);
//// 一边滑动一边点击最优解中的干员
//for (int i = 0; i != m_swipe_max_times; ++i) {
// const cv::Mat& image = get_format_image(true);
// auto cur_name_textarea = detect_foo(image);
// for (TextArea& text_area : cur_name_textarea) {
// // 点过了就不会再点了直接从最优解vector里面删了
// auto iter = std::find(optimal_comb.begin(), optimal_comb.end(), text_area.text);
// if (iter != optimal_comb.end()) {
// m_control_ptr->click(text_area.rect);
// optimal_comb.erase(iter);
// }
// }
// if (optimal_comb.empty()) {
// break;
// }
// // 因为滑动和点击是矛盾的,这里没法异步做
// if (!swipe_foo(true)) {
// return false;
// }
//}
return true;
}

View File

@@ -1,26 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="RelWithDebInfo|Win32">
<Configuration>RelWithDebInfo</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="RelWithDebInfo|x64">
<Configuration>RelWithDebInfo</Configuration>
<Platform>x64</Platform>
@@ -38,32 +22,6 @@
<ProjectName>Sanity</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
@@ -83,18 +41,6 @@
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
@@ -102,90 +48,16 @@
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(SolutionDir)meojson\include;$(SolutionDir)MeoAssistance\include;$(IncludePath)</IncludePath>
<LibraryPath>$(TargetDir);$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(SolutionDir)meojson\include;$(SolutionDir)MeoAssistance\include;$(IncludePath)</IncludePath>
<IncludePath>$(SolutionDir)\include;$(IncludePath)</IncludePath>
<LibraryPath>$(TargetDir);$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(SolutionDir)meojson\include;$(SolutionDir)MeoAssistance\include;$(IncludePath)</IncludePath>
<IncludePath>$(SolutionDir)\include;$(IncludePath)</IncludePath>
<LibraryPath>$(TargetDir);$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<LanguageStandard_C>stdc11</LanguageStandard_C>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>MeoAssistance.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(TargetDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>

View File

@@ -1,235 +1,107 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="RelWithDebInfo|Win32">
<Configuration>RelWithDebInfo</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="RelWithDebInfo|x64">
<Configuration>RelWithDebInfo</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}</ProjectGuid>
<RootNamespace>Tools</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>TestCaller</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(SolutionDir)meojson\include;$(SolutionDir)MeoAssistance\include;$(IncludePath)</IncludePath>
<LibraryPath>$(TargetDir);$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(SolutionDir)meojson\include;$(SolutionDir)MeoAssistance\include;$(IncludePath)</IncludePath>
<LibraryPath>$(TargetDir);$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(SolutionDir)MeoAssistance\include;$(IncludePath)</IncludePath>
<LibraryPath>$(TargetDir);$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<LanguageStandard_C>stdc11</LanguageStandard_C>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>MeoAssistance.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(TargetDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<LanguageStandard_C>stdc11</LanguageStandard_C>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>MeoAssistance.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(TargetDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>false</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>LOG_TRACE;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<LanguageStandard_C>stdc11</LanguageStandard_C>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<Optimization>Disabled</Optimization>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>MeoAssistance.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(TargetDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="RelWithDebInfo|x64">
<Configuration>RelWithDebInfo</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{63B4F1A2-291C-4C85-91E1-A1F6DAE30D64}</ProjectGuid>
<RootNamespace>Tools</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>TestCaller</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(SolutionDir)\include</IncludePath>
<LibraryPath>$(TargetDir);$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(SolutionDir)\include</IncludePath>
<LibraryPath>$(TargetDir);$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<LanguageStandard_C>stdc11</LanguageStandard_C>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>MeoAssistance.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(TargetDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>false</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>LOG_TRACE;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<LanguageStandard_C>stdc11</LanguageStandard_C>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<Optimization>Disabled</Optimization>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>MeoAssistance.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(TargetDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -9,7 +9,6 @@ void test_infrast(Assistance* ptr);
int main(int argc, char** argv)
{
Assistance* ptr = AsstCreate();
auto ret = AsstCatchEmulator(ptr);
if (!ret) {
@@ -23,7 +22,6 @@ int main(int argc, char** argv)
char ch = 0;
while (ch != 'q') {
test_infrast(ptr);
//test_swipe(ptr);

View File

@@ -255,4 +255,4 @@
"伊芙利特",
"THRM-EX"
]
}
}