mirror of
https://github.com/MaaAssistantArknights/MaaAssistantArknights.git
synced 2026-07-15 17:30:27 +08:00
stash
This commit is contained in:
@@ -29,11 +29,14 @@ namespace asst {
|
||||
|
||||
// 开始刷理智
|
||||
void start_sanity();
|
||||
// 开始访问基建
|
||||
// 开始访问好友基建
|
||||
void start_visit();
|
||||
|
||||
// 开始公开招募操作
|
||||
void start_open_recruit(const std::vector<int>& required_level, bool set_time = true);
|
||||
// 开始基建换班任务
|
||||
void start_infrast();
|
||||
|
||||
// 开始匹配任务,调试用
|
||||
void start_match_task(const std::string& task, int retry_times = ProcessTaskRetryTimesDefault, bool block = true);
|
||||
// 开始OCR测试,调试用
|
||||
|
||||
@@ -18,6 +18,7 @@ extern "C" {
|
||||
MEOAPI_PORT void AsstStop(asst::Assistance* p_asst);
|
||||
MEOAPI_PORT bool AsstSetParam(asst::Assistance* p_asst, const char* type, const char* param, const char* value);
|
||||
MEOAPI_PORT bool AsstRunOpenRecruit(asst::Assistance* p_asst, const int required_level[], bool set_time);
|
||||
MEOAPI_PORT bool AsstStartInfrast(asst::Assistance* p_asst);
|
||||
MEOAPI_PORT bool AsstTestOcr(asst::Assistance* p_asst, const char** text_array, int array_size, bool need_click);
|
||||
|
||||
MEOAPI_PORT bool CheckVersionUpdate(char* tag_buffer, int tag_bufsize, char* html_url_buffer, int html_bufsize, char* body_buffer, int body_bufsize);
|
||||
|
||||
@@ -59,8 +59,25 @@ namespace asst {
|
||||
RecruitTagsDetected,
|
||||
OcrResultError,
|
||||
RecruitSpecialTag,
|
||||
RecruitResult
|
||||
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 = {
|
||||
@@ -85,7 +102,10 @@ namespace asst {
|
||||
{AsstMsg::OcrResultError, "OcrResultError"},
|
||||
{AsstMsg::RecruitSpecialTag, "RecruitSpecialTag"},
|
||||
{AsstMsg::RecruitResult, "RecruitResult"},
|
||||
{AsstMsg::AppendTask, "AppendTask"}
|
||||
{AsstMsg::AppendTask, "AppendTask"},
|
||||
{AsstMsg::InfrastOpers, "InfrastOpers"},
|
||||
{AsstMsg::InfrastComb, "InfrastComb"}
|
||||
|
||||
};
|
||||
return os << _type_name.at(type);
|
||||
}
|
||||
@@ -236,6 +256,33 @@ namespace asst {
|
||||
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(FacilityType facility)
|
||||
{
|
||||
m_facility = facility;
|
||||
}
|
||||
private:
|
||||
FacilityType m_facility = FacilityType::Invalid;
|
||||
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
|
||||
{
|
||||
|
||||
@@ -214,6 +214,27 @@ void Assistance::start_open_recruit(const std::vector<int>& required_level, bool
|
||||
m_condvar.notify_one();
|
||||
}
|
||||
|
||||
void asst::Assistance::start_infrast()
|
||||
{
|
||||
DebugTraceFunction;
|
||||
if (!m_thread_idle || !m_inited)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
|
||||
auto task_ptr = std::make_shared<InfrastStationTask>(task_callback, (void*)this);
|
||||
// TODO 这个参数写到配置文件里
|
||||
task_ptr->set_swipe_param(2000, Rect(600, 300, 0, 0), Rect(450, 300, 0, 0), 20);
|
||||
task_ptr->set_facility(FacilityType::Manufacturing);
|
||||
task_ptr->set_task_chain("Infrast");
|
||||
m_tasks_queue.emplace(task_ptr);
|
||||
|
||||
m_thread_idle = false;
|
||||
m_condvar.notify_one();
|
||||
}
|
||||
|
||||
void Assistance::stop(bool block)
|
||||
{
|
||||
DebugTraceFunction;
|
||||
|
||||
@@ -111,6 +111,15 @@ bool AsstRunOpenRecruit(asst::Assistance* p_asst, const int required_level[], bo
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AsstStartInfrast(asst::Assistance* p_asst)
|
||||
{
|
||||
if (p_asst == NULL) {
|
||||
return false;
|
||||
}
|
||||
p_asst->start_infrast();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AsstTestOcr(asst::Assistance* p_asst, const char** text_array, int array_size, bool need_click)
|
||||
{
|
||||
if (p_asst == NULL || text_array == nullptr) {
|
||||
|
||||
@@ -791,4 +791,146 @@ bool TestOcrTask::run()
|
||||
//}
|
||||
|
||||
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_set<std::string> all_oper_name; // 所有干员名
|
||||
std::string oper_end_flag; // 干员名结束标记,识别到这个string就认为识别完成了
|
||||
|
||||
switch (m_facility) {
|
||||
case FacilityType::Manufacturing:
|
||||
all_oper_combs = InfrastConfiger::get_instance().m_mfg_combs;
|
||||
all_oper_name = InfrastConfiger::get_instance().m_mfg_opers;
|
||||
oper_end_flag = InfrastConfiger::get_instance().m_mfg_end;
|
||||
break;
|
||||
// TODO 贸易站和其他啥的,有空再做
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
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_set<std::string> detected_names;
|
||||
|
||||
// 一边识别一边滑动,把所有制造站干员名字抓出来
|
||||
for (int i = 0; i != m_swipe_max_times; ++i) {
|
||||
const cv::Mat& image = get_format_image();
|
||||
// 异步进行滑动操作
|
||||
std::future<bool> swipe_future = std::async(std::launch::async, swipe_foo);
|
||||
|
||||
std::vector<TextArea> all_text_area = ocr_detect(image);
|
||||
/* 过滤出所有制造站中的干员名 */
|
||||
std::vector<TextArea> cur_names = text_search(
|
||||
all_text_area,
|
||||
all_oper_name,
|
||||
Configer::get_instance().m_infrast_ocr_replace);
|
||||
|
||||
for (TextArea& text_area : cur_names) {
|
||||
detected_names.emplace(std::move(text_area.text));
|
||||
}
|
||||
bool break_flag = false;
|
||||
// 识别到了结束标记,就直接退出循环
|
||||
if (detected_names.find(oper_end_flag) != detected_names.cend()) {
|
||||
break_flag = true;
|
||||
}
|
||||
// 阻塞等待滑动结束
|
||||
if (!swipe_future.get()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (break_flag) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
json::value opers_json;
|
||||
std::vector<json::value> all_names_vector;
|
||||
for (const std::string& name : detected_names) {
|
||||
all_names_vector.emplace_back(Utf8ToGbk(name));
|
||||
}
|
||||
opers_json["names"] = json::array(all_names_vector);
|
||||
|
||||
m_callback(AsstMsg::InfrastOpers, opers_json, m_callback_arg);
|
||||
|
||||
// 配置文件中的干员组合,和抓出来的干员名比对,如果组合中的干员都有,那就用这个组合
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
opers_json["comb"] = json::array(optimal_comb);
|
||||
m_callback(AsstMsg::InfrastComb, opers_json, m_callback_arg);
|
||||
|
||||
|
||||
// 一边滑动一边点击最优解中的干员
|
||||
for (int i = 0; i != m_swipe_max_times; ++i) {
|
||||
const cv::Mat& image = get_format_image();
|
||||
std::vector<TextArea> all_text_area = ocr_detect(image);
|
||||
/* 过滤出所有制造站中的干员名 */
|
||||
std::vector<TextArea> cur_names = text_search(
|
||||
all_text_area,
|
||||
optimal_comb,
|
||||
Configer::get_instance().m_infrast_ocr_replace);
|
||||
|
||||
for (TextArea& text_area : cur_names) {
|
||||
m_control_ptr->click(text_area.rect);
|
||||
// 点过了就不会再点了,直接从最优解vector里面删了
|
||||
auto iter = std::find(optimal_comb.begin(), optimal_comb.end(), text_area.text);
|
||||
if (iter != optimal_comb.end()) {
|
||||
optimal_comb.erase(iter);
|
||||
}
|
||||
}
|
||||
if (optimal_comb.empty()) {
|
||||
break;
|
||||
}
|
||||
// 因为滑动和点击是矛盾的,这里没法异步做
|
||||
if (!swipe_foo(true)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ using namespace asst;
|
||||
|
||||
void test_dorm(Assistance* ptr);
|
||||
void test_swipe(Assistance* ptr);
|
||||
void test_infrast(Assistance* ptr);
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
@@ -23,7 +24,7 @@ int main(int argc, char** argv)
|
||||
char ch = 0;
|
||||
while (ch != 'q') {
|
||||
|
||||
test_dorm(ptr);
|
||||
test_infrast(ptr);
|
||||
//test_swipe(ptr);
|
||||
|
||||
ch = getchar();
|
||||
@@ -47,4 +48,9 @@ void test_dorm(Assistance* ptr)
|
||||
const char* text_array[] = { "×¢ÒâÁ¦" };
|
||||
|
||||
AsstTestOcr(ptr, text_array, sizeof(text_array) / sizeof(char*), true);
|
||||
}
|
||||
|
||||
void test_infrast(Assistance* ptr)
|
||||
{
|
||||
AsstStartInfrast(ptr);
|
||||
}
|
||||
@@ -31,7 +31,8 @@
|
||||
],
|
||||
"infrastOcrReplace": [
|
||||
[ "森蛐", "森蚺" ],
|
||||
[ "森蛾", "森蚺" ]
|
||||
[ "森蛾", "森蚺" ],
|
||||
[ "森躺", "森蚺" ]
|
||||
],
|
||||
"handle_Doc": "下面的和模拟器窗口捕获逻辑有关,不需要修改",
|
||||
"handle": {
|
||||
|
||||
@@ -20,12 +20,12 @@
|
||||
},
|
||||
{
|
||||
"comb": [
|
||||
"黑角"
|
||||
"月见夜"
|
||||
],
|
||||
"efficiency": 10
|
||||
}
|
||||
],
|
||||
"end": "黑角",
|
||||
"end": "月见夜",
|
||||
"end_Doc": "识别到这个词,就认为干员遍历结束,一般用排序里最后的那个干员(?)"
|
||||
},
|
||||
"Trade": {
|
||||
|
||||
Reference in New Issue
Block a user