mirror of
https://github.com/MaaAssistantArknights/MaaAssistantArknights.git
synced 2026-07-19 18:47:55 +08:00
Merge pull request #1519 from horror-proton/test/recruit_time
允许自定义公开招募时间
This commit is contained in:
@@ -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 |
@@ -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 |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user