This commit is contained in:
MistEO
2021-08-14 01:04:01 +08:00
parent cd6183a397
commit 50c85554cb
9 changed files with 238 additions and 8 deletions

View File

@@ -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测试调试用

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -31,7 +31,8 @@
],
"infrastOcrReplace": [
[ "森蛐", "森蚺" ],
[ "森蛾", "森蚺" ]
[ "森蛾", "森蚺" ],
[ "森躺", "森蚺" ]
],
"handle_Doc": "下面的和模拟器窗口捕获逻辑有关,不需要修改",
"handle": {

View File

@@ -20,12 +20,12 @@
},
{
"comb": [
"黑角"
"月见夜"
],
"efficiency": 10
}
],
"end": "黑角",
"end": "月见夜",
"end_Doc": "识别到这个词,就认为干员遍历结束,一般用排序里最后的那个干员(?)"
},
"Trade": {