Merge pull request #1519 from horror-proton/test/recruit_time

允许自定义公开招募时间
This commit is contained in:
MistEO
2022-08-12 19:33:52 +08:00
committed by GitHub
11 changed files with 120 additions and 38 deletions

View File

@@ -89,11 +89,16 @@ TaskId ASSTAPI AsstAppendTask(AsstHandle handle, const char* type, const char* p
...
],
"times": int, // 招募多少次,可选,默认 0。若仅公招计算可设置为 0
"set_time": bool, // 是否设置 9 小时。仅在 times 为 0 时生效,可选,默认 true
"set_time": bool, // 是否设置招募时限。仅在 times 为 0 时生效,可选,默认 true
"expedite": bool, // 是否使用加急许可,可选,默认 false
"expedite_times": int, // 加急次数,仅在 expedite 为 true 时有效。
// 可选,默认无限使用(直到 times 达到上限)
"skip_robot": bool // 是否在识别到小车词条时跳过,可选,默认跳过
"skip_robot": bool, // 是否在识别到小车词条时跳过,可选,默认跳过
"recruitment_time": { // Tag 等级(大于等于 3和对应的希望招募时限单位为分钟默认值都为 540即 09:00:00
"3": int,
"4": int,
...
}
}
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

View File

@@ -3682,13 +3682,12 @@
"algorithm": "JustReturn",
"action": "Stop"
},
"RecruitTimeReduce": {
"action": "ClickSelf",
"Doc": "检查到01调整时间",
"RecruitTimerDecrement": {
"Doc": "two buttons that adjust recruit timer",
"roi": [
350,
250,
200,
370,
100
]
},
@@ -3770,14 +3769,43 @@
"action": "DoNothing",
"rearDelay": 2000
},
"RecruitCheckTimeReduced": {
"action": "DoNothing",
"Doc": "检查时间是不是调整过",
"RecruitTimerH": {
"Doc": "识别公招小时数",
"algorithm": "OcrDetect",
"roi": [
350,
150,
200,
150
400,
180,
100,
90
],
"text": [
"01",
"02",
"03",
"04",
"05",
"06",
"07",
"08",
"09"
]
},
"RecruitTimerM": {
"Doc": "识别公招分钟数",
"algorithm": "OcrDetect",
"roi": [
570,
180,
100,
90
],
"text": [
"00",
"10",
"20",
"30",
"40",
"50"
]
},
"RecruitConfirm": {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -141,6 +141,13 @@ asst::AutoRecruitTask& asst::AutoRecruitTask::set_set_time(bool set_time) noexce
return *this;
}
asst::AutoRecruitTask& asst::AutoRecruitTask::set_recruitment_time(std::unordered_map<int, int> time_map) noexcept
{
m_desired_time_map = std::move(time_map);
return *this;
}
bool asst::AutoRecruitTask::_run()
{
if (m_force_discard_flag) return false;
@@ -238,7 +245,7 @@ bool asst::AutoRecruitTask::recruit_one(const Rect& button)
if (need_exit()) return false;
if (m_set_time && !check_time_reduced()) {
if (m_set_time && !check_timer(calc_result.recruitment_time)) {
// timer was not set to 09:00:00 properly, likely the tag selection was also corrupted
// see https://github.com/MaaAssistantArknights/MaaAssistantArknights/pull/300#issuecomment-1073287984
// return and try later
@@ -451,11 +458,21 @@ asst::AutoRecruitTask::calc_task_result_type asst::AutoRecruitTask::recruit_calc
}
}
// try to set the timer to 09:00:00
int recruitment_time = m_desired_time_map[(std::max)(final_combination.min_level, 3)];
if (recruitment_time == 0) recruitment_time = 9 * 60;
// try to set the timer to desired value
if (m_set_time) {
for (const Rect& rect : image_analyzer.get_set_time_rect()) {
m_ctrler->click(rect);
}
Log.info("recruitment time:", recruitment_time, "min");
const int desired_hour = recruitment_time / 60;
const int desired_minute_div_10 = (recruitment_time % 60) / 10;
const int temp = desired_hour + (desired_minute_div_10 != 0);
const int hour_delta = (1 < temp) ? (1 + 9 - temp) : (temp - 1);
const int minute_delta = (0 < desired_minute_div_10) ? (0 + 6 - desired_minute_div_10) : (0);
for (int i = 0; i < hour_delta; ++i)
m_ctrler->click(image_analyzer.get_hour_decrement_rect());
for (int i = 0; i < minute_delta; ++i)
m_ctrler->click(image_analyzer.get_minute_decrement_rect());
}
// nothing to select, leave the selection empty
@@ -463,6 +480,7 @@ asst::AutoRecruitTask::calc_task_result_type asst::AutoRecruitTask::recruit_calc
calc_task_result_type result;
result.success = true;
result.force_skip = false;
result.recruitment_time = recruitment_time;
result.tags_selected = 0;
return result;
}
@@ -488,6 +506,7 @@ asst::AutoRecruitTask::calc_task_result_type asst::AutoRecruitTask::recruit_calc
calc_task_result_type result;
result.success = true;
result.force_skip = false;
result.recruitment_time = recruitment_time;
result.tags_selected = static_cast<int>(final_combination.tags.size());
return result;
}
@@ -500,11 +519,29 @@ bool asst::AutoRecruitTask::recruit_begin()
return task.run();
}
bool asst::AutoRecruitTask::check_time_reduced()
bool asst::AutoRecruitTask::check_timer(int minutes_expected)
{
ProcessTask task(*this, { "RecruitCheckTimeReduced" });
task.set_retry_times(2);
return task.run();
const auto image = m_ctrler->get_image();
{
OcrImageAnalyzer hour_ocr(image);
hour_ocr.set_task_info("RecruitTimerH");
hour_ocr.analyze();
if (hour_ocr.get_result().empty()) return false;
std::string desired_hour_str = std::string("0") + std::to_string(minutes_expected / 60);
if (hour_ocr.get_result().front().text != desired_hour_str) return false;
}
if (minutes_expected % 60 == 0) return true; // minute counter stays untouched
{
OcrImageAnalyzer minute_ocr(image);
minute_ocr.set_task_info("RecruitTimerM");
minute_ocr.analyze();
if (minute_ocr.get_result().empty()) return false;
std::string desired_minute_str = std::to_string((minutes_expected % 60) / 10) + "0";
if (minute_ocr.get_result().front().text != desired_minute_str) return false;
}
return true;
}
bool asst::AutoRecruitTask::check_recruit_home_page()

View File

@@ -22,6 +22,7 @@ namespace asst
AutoRecruitTask& set_use_expedited(bool use_or_not) noexcept;
AutoRecruitTask& set_skip_robot(bool skip_robot) noexcept;
AutoRecruitTask& set_set_time(bool set_time) noexcept;
AutoRecruitTask& set_recruitment_time(std::unordered_map<int, int>) noexcept;
protected:
virtual bool _run() override;
@@ -31,7 +32,7 @@ namespace asst
bool recruit_one(const Rect&);
bool check_recruit_home_page();
bool recruit_begin();
bool check_time_reduced();
bool check_timer(int);
bool recruit_now();
bool confirm();
bool refresh();
@@ -39,6 +40,7 @@ namespace asst
struct calc_task_result_type {
bool success = false;
bool force_skip = false;
int recruitment_time = 60;
[[maybe_unused]] int tags_selected = 0;
};
@@ -53,6 +55,7 @@ namespace asst
int m_max_times = 0;
bool m_skip_robot = true;
bool m_set_time = true;
std::unordered_map<int /*level*/, int /*minutes*/> m_desired_time_map;
int m_slot_fail = 0;
int m_cur_times = 0;

View File

@@ -1,13 +1,13 @@
#include "RecruitImageAnalyzer.h"
#include "MatchImageAnalyzer.h"
#include "MultiMatchImageAnalyzer.h"
#include "OcrImageAnalyzer.h"
#include "Resource.h"
bool asst::RecruitImageAnalyzer::analyze()
{
m_tags_result.clear();
m_set_time_rect.clear();
time_analyze();
refresh_analyze();
@@ -51,17 +51,14 @@ bool asst::RecruitImageAnalyzer::tags_analyze()
bool asst::RecruitImageAnalyzer::time_analyze()
{
const auto set_time_task_ptr = Task.get("RecruitTimeReduce");
MatchImageAnalyzer set_time_analyzer(m_image);
set_time_analyzer.set_task_info(set_time_task_ptr);
if (set_time_analyzer.analyze()) {
Rect rect = set_time_analyzer.get_result().rect;
m_set_time_rect.emplace_back(rect);
return true;
}
return false;
MultiMatchImageAnalyzer decrement_a(m_image);
decrement_a.set_task_info("RecruitTimerDecrement");
if (!decrement_a.analyze()) return false;
if (decrement_a.get_result().size() != 2) return false; // expecting two buttons
decrement_a.sort_result_horizontal();
m_hour_decrement = decrement_a.get_result().at(0).rect;
m_minute_decrement = decrement_a.get_result().at(1).rect;
return true;
}
bool asst::RecruitImageAnalyzer::refresh_analyze()

View File

@@ -18,9 +18,13 @@ namespace asst
{
return m_tags_result;
}
const std::vector<Rect>& get_set_time_rect() const noexcept
Rect get_hour_decrement_rect() const noexcept
{
return m_set_time_rect;
return m_hour_decrement;
}
Rect get_minute_decrement_rect() const noexcept
{
return m_minute_decrement;
}
Rect get_refresh_rect() const noexcept
{
@@ -38,7 +42,8 @@ namespace asst
bool refresh_analyze();
std::vector<TextRect> m_tags_result;
std::vector<Rect> m_set_time_rect;
Rect m_hour_decrement;
Rect m_minute_decrement;
Rect m_refresh_rect;
};
}

View File

@@ -41,6 +41,12 @@ bool asst::RecruitTask::set_params(const json::value& params)
[[maybe_unused]] int expedite_times = params.get("expedite_times", 0);
bool skip_robot = params.get("skip_robot", true);
std::unordered_map<int /*level*/, int /*minute*/> recruitment_time_map;
recruitment_time_map[3] = std::clamp(params.get("recruitment_time", "3", 9 * 60), 1 * 60, 9 * 60);
recruitment_time_map[4] = std::clamp(params.get("recruitment_time", "4", 9 * 60), 1 * 60, 9 * 60);
recruitment_time_map[5] = std::clamp(params.get("recruitment_time", "5", 9 * 60), 1 * 60, 9 * 60);
recruitment_time_map[6] = std::clamp(params.get("recruitment_time", "6", 9 * 60), 1 * 60, 9 * 60);
m_auto_recruit_task_ptr->set_enable(true);
@@ -50,6 +56,7 @@ bool asst::RecruitTask::set_params(const json::value& params)
.set_select_level(std::move(select))
.set_confirm_level(std::move(confirm))
.set_skip_robot(skip_robot)
.set_recruitment_time(recruitment_time_map)
.set_set_time(set_time).set_retry_times(3);
return true;