feat:不自动招募1/5/6星干员时,不计入最大确认招募次数 (#11380)

* feat:不自动招募1/5/6星干员时,不计入最大确认招募次数
test:添加相应的测试函数(仅Relwithdebinfo生效)
fix:添加calc_task_result_type结构体的构造函数。修改其用法,使得代码更直观。

* chore: Auto update by pre-commit hooks [skip changelog]

* fix:修复跳过特定招募计数功能中的逻辑错误#11380

* chore: Auto update by pre-commit hooks [skip changelog]

* Revert "fix:修复跳过特定招募计数功能中的逻辑错误#11380"

This reverts commit 4870e127aa.

* fix:修复跳过特定招募计数功能中的逻辑错误#11380

* chore: Auto update by pre-commit hooks [skip changelog]

* fix: do not return early for calc only task

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Horror Proton <107091537+horror-proton@users.noreply.github.com>
This commit is contained in:
Roland125
2025-01-04 19:41:40 +08:00
committed by GitHub
parent 81b1465cd1
commit 1e29fe6525
3 changed files with 145 additions and 26 deletions

View File

@@ -348,6 +348,14 @@ bool asst::AutoRecruitTask::recruit_one(const Rect& button)
return false;
}
if (calc_result.for_special_tags_skip || calc_result.for_robot_tags_skip) {
// Mark the slot as completed and return
// without incrementing the count
m_force_skipped.emplace(slot_index_from_rect(button));
click_return_button();
return false;
}
if (calc_result.force_skip) {
// mark the slot as completed and return
m_force_skipped.emplace(slot_index_from_rect(button));
@@ -404,6 +412,21 @@ asst::AutoRecruitTask::calc_task_result_type asst::AutoRecruitTask::recruit_calc
continue;
}
#ifdef ASST_DEBUG
// mock_test_001: 1/5/6 Star Operators appear when first recruited.
static bool RunRecruitMockTest_001 = true;
if (RunRecruitMockTest_001) {
static int skip_once = 0;
if (skip_once == 0) {
// image_analyzer.mock_set_special(asst::RecruitImageAnalyzer::operator_type::robot);
image_analyzer.mock_set_special(asst::RecruitImageAnalyzer::operator_type::senior);
// image_analyzer.mock_set_special(asst::RecruitImageAnalyzer::operator_type::top);
// image_analyzer.mock_set_special(asst::RecruitImageAnalyzer::operator_type::highvalue);
skip_once++;
}
}
#endif
const std::vector<TextRect>& tags = image_analyzer.get_tags_result();
m_has_refresh = !image_analyzer.get_refresh_rect().empty();
m_has_permit = image_analyzer.get_permit_rect().empty();
@@ -566,8 +589,8 @@ asst::AutoRecruitTask::calc_task_result_type asst::AutoRecruitTask::recruit_calc
}
// refresh
if (m_need_refresh && m_has_refresh && !has_special_tag &&
(final_combination.min_level == 3 && !has_preferred_tag) && !(m_skip_robot && has_robot_tag)) {
if (m_need_refresh && m_has_refresh && !has_special_tag && !(m_skip_robot && has_robot_tag) &&
(final_combination.min_level == 3 && !has_preferred_tag)) {
if (refresh_count > refresh_limit) [[unlikely]] {
json::value cb_info = basic_info();
cb_info["what"] = "RecruitError";
@@ -615,26 +638,28 @@ asst::AutoRecruitTask::calc_task_result_type asst::AutoRecruitTask::recruit_calc
callback(AsstMsg::SubTaskExtraInfo, cb_info);
Log.trace("No recruit permit");
calc_task_result_type result;
result.success = true;
result.force_skip = true;
calc_task_result_type result(calc_task_result::no_permit);
return result;
}
if (!is_calc_only_task()) {
// do not confirm, force skip
if (!(final_combination.min_level == 3 && has_preferred_tag) &&
ranges::none_of(m_confirm_level, [&](const auto& i) { return i == final_combination.min_level; })) {
calc_task_result_type result;
result.success = true;
result.force_skip = true;
if (!(has_robot_tag || has_special_tag)) {
// do not confirm, force skip
if (!(final_combination.min_level == 3 && has_preferred_tag) &&
is_recruitment_level_invalid(final_combination.min_level)) {
calc_task_result_type result(calc_task_result::force_skip);
return result;
}
}
// "Automatically recruit 5/6 Star operators" is not checked.
if (has_special_tag && is_recruitment_level_invalid(final_combination.min_level)) {
calc_task_result_type result(calc_task_result::special_tag_skip);
return result;
}
if (m_skip_robot && has_robot_tag) {
calc_task_result_type result;
result.success = true;
result.force_skip = true;
if (has_robot_tag && m_skip_robot) {
calc_task_result_type result(calc_task_result::robot_tag_skip);
return result;
}
}
@@ -662,12 +687,8 @@ asst::AutoRecruitTask::calc_task_result_type asst::AutoRecruitTask::recruit_calc
// nothing to select, leave the selection empty
if (!(final_combination.min_level == 3 && has_preferred_tag) &&
ranges::none_of(m_select_level, [&](const auto& i) { return i == final_combination.min_level; })) {
calc_task_result_type result;
result.success = true;
result.force_skip = false;
result.recruitment_time = recruitment_time;
result.tags_selected = 0;
is_recruitment_level_invalid(final_combination.min_level)) {
calc_task_result_type result(calc_task_result::nothing_to_select, recruitment_time);
return result;
}
@@ -689,11 +710,10 @@ asst::AutoRecruitTask::calc_task_result_type asst::AutoRecruitTask::recruit_calc
callback(AsstMsg::SubTaskExtraInfo, cb_info);
}
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());
calc_task_result_type result(
calc_task_result::success,
recruitment_time,
static_cast<int>(final_combination.tags.size()));
return result;
}

View File

@@ -8,6 +8,8 @@
#include "Common/AsstTypes.h"
#include "Config/Miscellaneous/RecruitConfig.h"
#include <ranges>
namespace asst
{
class ReportDataTask;
@@ -66,14 +68,83 @@ protected:
using slot_index = size_t;
enum calc_task_result
{
init = 0,
no_permit = 1,
force_skip = 2,
special_tag_skip = 3,
nothing_to_select = 4,
success = 5,
robot_tag_skip = 6
};
struct calc_task_result_type
{
bool success = false;
bool force_skip = false;
bool for_special_tags_skip = false; // Get the definition by searching for "SpecialTags".
bool for_robot_tags_skip = false;
int recruitment_time = 60;
[[maybe_unused]] int tags_selected = 0;
calc_task_result_type(calc_task_result res, const int _recruitment_time = 60, const int _tag_selected = 0)
{
switch (res) {
case calc_task_result::init:
success = false;
force_skip = false;
for_special_tags_skip = false;
for_robot_tags_skip = false;
recruitment_time = _recruitment_time;
tags_selected = _tag_selected;
break;
case calc_task_result::special_tag_skip:
success = true;
force_skip = true;
for_special_tags_skip = true;
for_robot_tags_skip = false;
recruitment_time = _recruitment_time;
tags_selected = _tag_selected;
break;
case calc_task_result::no_permit:
case calc_task_result::force_skip:
success = true;
force_skip = true;
for_special_tags_skip = false;
for_robot_tags_skip = false;
recruitment_time = _recruitment_time;
tags_selected = _tag_selected;
break;
case calc_task_result::nothing_to_select:
case calc_task_result::success:
success = true;
force_skip = false;
for_special_tags_skip = false;
for_robot_tags_skip = false;
recruitment_time = _recruitment_time;
tags_selected = _tag_selected;
break;
case calc_task_result::robot_tag_skip:
success = true;
force_skip = true;
for_special_tags_skip = false;
for_robot_tags_skip = true;
recruitment_time = _recruitment_time;
tags_selected = _tag_selected;
break;
}
};
calc_task_result_type() :
calc_task_result_type(init) {};
};
bool is_recruitment_level_invalid(int opr_level)
{
return std::ranges::none_of(this->m_confirm_level, [&](const int& i) { return i == opr_level; });
}
calc_task_result_type recruit_calc_task(slot_index = 0);
std::vector<int> m_select_level;

View File

@@ -24,6 +24,34 @@ public:
Rect get_permit_rect() const noexcept { return m_permit_rect; }
#ifdef ASST_DEBUG
// mock function
enum operator_type
{
top = 6,
senior = 5,
robot = 1,
highvalue = 11
};
void mock_set_special(operator_type type)
{
if (type == top) {
m_tags_result[0].text = "高级资深干员";
}
if (type == senior) {
m_tags_result[0].text = "资深干员";
}
if (type == robot) {
m_tags_result[0].text = "支援机械";
}
if (type == highvalue) {
m_tags_result[0].text = "资深干员";
m_tags_result[1].text = "高级资深干员";
}
}
#endif // ASST_DEBUG
private:
// 该分析器不支持外部设置ROI
using VisionHelper::set_roi;