Files
MaaAssistantArknights/src/MeoAssistance/AsstDef.h
2021-11-09 01:40:26 +08:00

336 lines
13 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#pragma once
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <ostream>
#include <functional>
namespace json
{
class value;
}
namespace asst {
constexpr double DoubleDiff = 1e-12;
struct Point
{
Point() = default;
Point(const Point&) noexcept = default;
Point(Point&&) noexcept = default;
Point(int x, int y) : x(x), y(y) {}
Point& operator=(const Point&) noexcept = default;
Point& operator=(Point&&) noexcept = default;
int x = 0;
int y = 0;
};
struct Rect
{
Rect() = default;
Rect(const Rect&) noexcept = default;
Rect(Rect&&) noexcept = default;
Rect(int x, int y, int width, int height)
: x(x), y(y), width(width), height(height) {}
Rect operator*(double rhs) const
{
return { x, y, static_cast<int>(width * rhs), static_cast<int>(height * rhs) };
}
Rect center_zoom(double scale, int max_width = INT_MAX, int max_height = INT_MAX) const
{
int half_width_scale = static_cast<int>(width * (1 - scale) / 2);
int half_hight_scale = static_cast<int>(height * (1 - scale) / 2);
Rect dst(x + half_width_scale, y + half_hight_scale,
static_cast<int>(width * scale), static_cast<int>(height * scale));
if (dst.x < 0) { dst.x = 0; }
if (dst.y < 0) { dst.y = 0; }
if (dst.width + dst.x >= max_width) { dst.width = max_width - dst.x; }
if (dst.height + dst.y >= max_height) { dst.height = max_height - dst.y; }
return dst;
}
Rect& operator=(const Rect&) noexcept = default;
Rect& operator=(Rect&&) noexcept = default;
bool empty() const noexcept { return width == 0 || height == 0; }
bool operator==(const Rect& rhs) const noexcept
{
return x == rhs.x && y == rhs.y && width == rhs.width && height == rhs.height;
}
bool include(const Rect& rhs) const noexcept
{
return x <= rhs.x
&& y <= rhs.y
&& (x + width) >= (rhs.x + rhs.width)
&& (y + height) >= (rhs.y + rhs.height);
}
std::string to_string() const {
return "[ " + std::to_string(x) + ", "
+ std::to_string(y) + ", "
+ std::to_string(width) + ", "
+ std::to_string(height) + " ]";
}
int x = 0;
int y = 0;
int width = 0;
int height = 0;
};
struct TextRect {
TextRect() = default;
TextRect(const TextRect&) = default;
TextRect(TextRect&&) noexcept = default;
explicit operator std::string() const noexcept { return text; }
explicit operator Rect() const noexcept { return rect; }
std::string to_string() const {
return text + " : " + rect.to_string();
}
TextRect& operator=(const TextRect&) = default;
TextRect& operator=(TextRect&&) noexcept = default;
bool operator==(const TextRect& rhs) const noexcept {
return text == rhs.text && rect == rhs.rect;
}
std::string text;
Rect rect;
};
using TextRectProc = std::function<bool(TextRect&)>;
enum class AlgorithmType {
Invaild = -1,
JustReturn,
MatchTemplate,
CompareHist,
OcrDetect
};
struct MatchRect {
MatchRect() = default;
MatchRect(const MatchRect&) = default;
MatchRect(MatchRect&&) noexcept = default;
explicit operator Rect() const noexcept { return rect; }
MatchRect& operator=(const MatchRect&) = default;
MatchRect& operator=(MatchRect&&) noexcept = default;
AlgorithmType algorithm;
double score = 0.0;
Rect rect;
};
}
namespace std {
template<>
class hash<asst::Rect> {
public:
size_t operator()(const asst::Rect& rect) const
{
return std::hash<int>()(rect.x)
^ std::hash<int>()(rect.y)
^ std::hash<int>()(rect.width)
^ std::hash<int>()(rect.height);
}
};
template<>
class hash<asst::TextRect> {
public:
size_t operator()(const asst::TextRect& tr) const
{
return std::hash<std::string>()(tr.text)
^ std::hash<asst::Rect>()(tr.rect);
}
};
}
namespace asst {
enum class ProcessTaskAction {
Invalid = 0,
BasicClick = 0x100,
ClickSelf = BasicClick | 1, // 点击自身位置
ClickRect = BasicClick | 2, // 点击指定区域
ClickRand = BasicClick | 4, // 点击随机区域
DoNothing = 0x200, // 什么都不做
Stop = 0x400, // 停止当前Task
StageDrops = 0x800, // 关卡结束,特化动作
BasicSwipe = 0x1000,
SwipeToTheLeft = BasicSwipe | 1, // 往左划一下
SwipeToTheRight = BasicSwipe | 2, // 往右划一下
};
// 任务信息
struct TaskInfo {
virtual ~TaskInfo() = default;
std::string name; // 任务名
AlgorithmType algorithm = // 图像算法类型
AlgorithmType::Invaild;
ProcessTaskAction action = // 要进行的操作
ProcessTaskAction::Invalid;
std::vector<std::string> next; // 下一个可能的任务(列表)
int exec_times = 0; // 任务已执行了多少次
int max_times = INT_MAX; // 任务最多执行多少次
std::vector<std::string> exceeded_next; // 达到最多次数了之后,下一个可能的任务(列表)
std::vector<std::string> reduce_other_times; // 执行了该任务后,需要减少别的任务的执行次数。例如执行了吃理智药,则说明上一次点击蓝色开始行动按钮没生效,所以蓝色开始行动要-1
asst::Rect specific_rect; // 指定区域目前仅针对ClickRect任务有用会点这个区域
int pre_delay = 0; // 执行该任务前的延时
int rear_delay = 0; // 执行该任务后的延时
int retry_times = INT_MAX; // 未找到图像时的重试次数
Rect roi; // 要识别的区域若为0则全图识别
Rect rect_move; // 识别结果移动有些结果识别到的和要点击的不是同一个位置。即识别到了res点击res + result_move的位置
};
// 文字识别任务的信息
struct OcrTaskInfo : public TaskInfo {
virtual ~OcrTaskInfo() = default;
std::vector<std::string> text; // 文字的容器,匹配到这里面任一个,就算匹配上了
bool need_full_match = false; // 是否需要全匹配,否则搜索到子串就算匹配上了
std::unordered_map<std::string, std::string>
replace_map; // 部分文字容易识别错字符串强制replace之后再进行匹配
bool cache = false; // 是否使用历史区域
std::unordered_set<Rect> region_of_appeared; // 曾经出现过的区域上次处理该任务时在一些rect里识别到过text这次优先在这些rect里识别省点性能
};
// 图片匹配任务的信息
struct MatchTaskInfo : public TaskInfo {
virtual ~MatchTaskInfo() = default;
std::string templ_name; // 匹配模板图片文件名
double templ_threshold = 0; // 模板匹配阈值
double hist_threshold = 0; // 直方图比较阈值
std::pair<int, int> mask_range; // 掩码的二值化范围
bool cache = false; // 是否使用缓存直方图false时就一直用模板匹配。默认为true
};
struct HandleInfo {
std::string class_name;
std::string window_name;
};
struct AdbCmd {
std::string path;
std::string devices;
std::string address_regex;
std::string address;
std::string connect;
std::string click;
std::string swipe;
std::string display;
std::string display_format;
std::string screencap;
//std::string pullscreen;
int display_width = 0;
int display_height = 0;
};
struct EmulatorInfo {
std::string name;
HandleInfo handle;
AdbCmd adb;
std::string path;
};
/* 基建相关 */
// 设施信息
struct InfrastFacilityInfo {
std::string id;
std::vector<std::string> products;
int max_num_of_opers = 0;
};
enum class InfrastSmileyType {
Invalid = -1,
Rest, // 休息完成,绿色笑脸
Work, // 工作中,黄色笑脸
Distract // 注意力涣散,红色哭脸
};
struct InfrastSmileyInfo {
InfrastSmileyType type;
Rect rect;
};
struct InfrastOperMoodInfo {
std::string hash; // 干员部分立绘的hash作为唯一标识
InfrastSmileyInfo smiley;
double percentage = 0; // 心情进度条的百分比
Rect rect;
bool working = false; // 干员是否在工作中
bool selected = false; // 干员是否已被选择(蓝色的选择框)
};
struct InfrastSkill {
std::string id;
std::string templ_name;
std::vector<std::string> names; // 很多基建技能是一样的就是名字不同。所以一个技能id可能对应多个名字
std::string intro;
std::unordered_map<std::string, double>
efficient; // 技能效率key产品名赤金、经验书等, value: 效率数值
std::unordered_map<std::string, std::string>
efficient_regex; // 技能效率正则key产品名赤金、经验书等, value: 效率正则。如不为空会先对正则进行计算再加上efficient里面的值
bool operator==(const InfrastSkill& skill) const noexcept {
return id == skill.id;
}
};
}
namespace std {
template<>
class hash<asst::InfrastSkill> {
public:
size_t operator()(const asst::InfrastSkill& skill) const
{
return std::hash<std::string>()(skill.id);
}
};
}
namespace asst
{
// 基建单个干员的技能
struct InfrastSkillsComb {
InfrastSkillsComb() = default;
InfrastSkillsComb(std::unordered_set<InfrastSkill> skill_vec) {
skills = std::move(skill_vec);
for (const auto& s : skills) {
for (const auto& [key, value] : s.efficient) {
efficient[key] += value;
}
for (const auto& [key, reg] : s.efficient_regex) {
efficient_regex[key] += "+(" + reg + ")";
}
}
}
bool operator==(const InfrastSkillsComb& rhs) const {
return skills == rhs.skills;
}
std::string intro;
std::unordered_set<InfrastSkill> skills;
std::unordered_map<std::string, double> efficient;
std::unordered_map<std::string, std::string> efficient_regex;
};
// 基建 干员技能信息
struct InfrastOperSkillInfo {
InfrastOperSkillInfo() = default;
InfrastOperSkillInfo(InfrastSkillsComb skills_comb) : skills_comb(std::move(skills_comb)) {}
std::string hash; // 有些干员的技能是完全一样的做个hash区分一下不同干员
InfrastSkillsComb skills_comb;
Rect rect;
bool selected = false; // 干员是否已被选择(蓝色的选择框)
};
// 基建技能组
struct InfrastSkillsGroup {
std::string intro; // 文字介绍,实际不起作用
std::unordered_map<std::string, int> conditions; // 技能组合可用条件例如key 发电站数量value 3
std::vector<InfrastSkillsComb> necessary; // 必选技能。这里面的缺少任一,则该技能组合不可用
std::vector<InfrastSkillsComb> optional; // 可选技能。
bool allow_external = false; // 当干员数没满3个的时候是否允许补充外部干员
};
enum class InfrastWorkMode {
Invaild = -1,
Gentle, // 温和换班模式:会对干员人数不满的设施进行换班,计算单设施内最优解,尽量不破坏原有的干员组合;即若设施内干员是满的,则不对该设施进行换班
Aggressive, // 激进换班模式:会对每一个设施进行换班,计算单设施内最优解,但不会将其他设施中的干员替换过来;即按工作状态排序,仅选择前面的干员
Extreme // 偏激换班模式:会对每一个设施进行换班,计算全局的单设施内最优解,为追求更高效率,会将其他设施内的干员也替换过来;即按技能排序,计算所有拥有该设施技能的干员效率,无论他在不在其他地方工作
};
}