mirror of
https://github.com/MaaAssistantArknights/MaaAssistantArknights.git
synced 2026-07-18 10:10:45 +08:00
Merge pull request #2116 from MaaAssistantArknights/feat/at
feat: 增加模板任务逻辑
This commit is contained in:
1372
resource/tasks.json
1372
resource/tasks.json
File diff suppressed because it is too large
Load Diff
@@ -9,12 +9,7 @@ asst::StartUpTask::StartUpTask(AsstCallback callback, void* callback_arg)
|
||||
m_start_game_task_ptr(std::make_shared<StartGameTaskPlugin>(m_callback, m_callback_arg, TaskType)),
|
||||
m_start_up_task_ptr(std::make_shared<ProcessTask>(m_callback, m_callback_arg, TaskType))
|
||||
{
|
||||
m_start_up_task_ptr->set_tasks({ "StartUp" })
|
||||
.set_times_limit("ReturnToTerminal", 0)
|
||||
.set_times_limit("Terminal", 0)
|
||||
.set_times_limit("EndOfAction", 0)
|
||||
.set_task_delay(1000)
|
||||
.set_retry_times(30);
|
||||
m_start_up_task_ptr->set_tasks({ "StartUp" }).set_task_delay(1000).set_retry_times(30);
|
||||
m_subtasks.emplace_back(m_start_game_task_ptr);
|
||||
m_subtasks.emplace_back(m_start_up_task_ptr);
|
||||
}
|
||||
|
||||
@@ -135,12 +135,7 @@ bool ProcessTask::_run()
|
||||
|
||||
int& exec_times = m_exec_times[cur_name];
|
||||
|
||||
int max_times = m_cur_task_ptr->max_times;
|
||||
TimesLimitType limit_type = TimesLimitType::Pre;
|
||||
if (auto iter = m_times_limit.find(cur_name); iter != m_times_limit.cend()) {
|
||||
max_times = iter->second.times;
|
||||
limit_type = iter->second.type;
|
||||
}
|
||||
auto [max_times, limit_type] = calc_time_limit();
|
||||
|
||||
if (limit_type == TimesLimitType::Pre && exec_times >= max_times) {
|
||||
info["what"] = "ExceededLimit";
|
||||
@@ -287,6 +282,21 @@ bool asst::ProcessTask::on_run_fails()
|
||||
return run();
|
||||
}
|
||||
|
||||
std::pair<int, asst::ProcessTask::TimesLimitType> asst::ProcessTask::calc_time_limit() const
|
||||
{
|
||||
// eg. "C@B@A" 的 max_times 取 "C@B@A", "B@A", "A" 中有 max_times 定义的最靠前者
|
||||
for (std::string cur_base_name = m_cur_task_ptr->name;;) {
|
||||
if (auto iter = m_times_limit.find(cur_base_name); iter != m_times_limit.cend()) {
|
||||
return { iter->second.times, iter->second.type };
|
||||
}
|
||||
size_t at_pos = cur_base_name.find('@');
|
||||
if (at_pos == std::string::npos) {
|
||||
return { m_cur_task_ptr->max_times, TimesLimitType::Pre };
|
||||
}
|
||||
cur_base_name = cur_base_name.substr(at_pos + 1);
|
||||
}
|
||||
}
|
||||
|
||||
json::value asst::ProcessTask::basic_info() const
|
||||
{
|
||||
return AbstractTask::basic_info() |
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
namespace asst
|
||||
{
|
||||
// 流程任务,按照配置文件里的设置的流程运行
|
||||
class ProcessTask : public AbstractTask
|
||||
class ProcessTask final : public AbstractTask
|
||||
{
|
||||
public:
|
||||
enum class TimesLimitType
|
||||
@@ -40,6 +40,7 @@ namespace asst
|
||||
virtual bool on_run_fails() override;
|
||||
virtual json::value basic_info() const override;
|
||||
|
||||
std::pair<int, TimesLimitType> calc_time_limit() const;
|
||||
void exec_click_task(const Rect& matched_rect);
|
||||
void exec_swipe_task(ProcessTaskAction action);
|
||||
void exec_slowly_swipe_task(ProcessTaskAction action);
|
||||
|
||||
@@ -170,7 +170,7 @@ bool asst::TaskData::parse(const json::value& json)
|
||||
#ifdef ASST_DEBUG
|
||||
for (const auto& [name, task] : m_all_tasks_info) {
|
||||
for (const auto& next : task->next) {
|
||||
if (m_all_tasks_info.find(next) == m_all_tasks_info.cend()) {
|
||||
if (get(next) == nullptr) {
|
||||
Log.error(name, "'s next", next, "is null");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
#include <unordered_set>
|
||||
|
||||
#include "Utils/AsstTypes.h"
|
||||
#ifdef ASST_DEBUG
|
||||
#include "Utils/Logger.hpp"
|
||||
#endif
|
||||
|
||||
namespace asst
|
||||
{
|
||||
@@ -14,33 +17,112 @@ namespace asst
|
||||
|
||||
class TaskData final : public SingletonHolder<TaskData>, public AbstractConfigerWithTempl
|
||||
{
|
||||
private:
|
||||
static std::shared_ptr<TaskInfo> generate_task_info(const std::shared_ptr<TaskInfo>& base_ptr,
|
||||
const std::string& task_prefix)
|
||||
{
|
||||
std::shared_ptr<TaskInfo> task_info_ptr;
|
||||
switch (base_ptr->algorithm) {
|
||||
case AlgorithmType::MatchTemplate:
|
||||
task_info_ptr = std::make_shared<MatchTaskInfo>(*std::dynamic_pointer_cast<MatchTaskInfo>(base_ptr));
|
||||
break;
|
||||
case AlgorithmType::OcrDetect:
|
||||
task_info_ptr = std::make_shared<OcrTaskInfo>(*std::dynamic_pointer_cast<OcrTaskInfo>(base_ptr));
|
||||
break;
|
||||
case AlgorithmType::Hash:
|
||||
task_info_ptr = std::make_shared<HashTaskInfo>(*std::dynamic_pointer_cast<HashTaskInfo>(base_ptr));
|
||||
break;
|
||||
default:
|
||||
task_info_ptr = std::make_shared<TaskInfo>(*base_ptr);
|
||||
break;
|
||||
}
|
||||
using tasklist_t = std::vector<std::string>;
|
||||
auto generate_tasks = [&](tasklist_t& task_list, const tasklist_t& base_task_list) {
|
||||
task_list = {};
|
||||
for (const std::string& base : base_task_list) {
|
||||
std::string_view base_view = base;
|
||||
size_t l = 0;
|
||||
bool has_same_prefix = false;
|
||||
// base 任务里已经存在相同前缀,则不加前缀
|
||||
// https://github.com/MaaAssistantArknights/MaaAssistantArknights/pull/2116#issuecomment-1270115238
|
||||
for (size_t r = base_view.find('@'); r != std::string_view::npos; r = base_view.find('@', l)) {
|
||||
if (task_prefix == base_view.substr(l, r - l)) {
|
||||
has_same_prefix = true;
|
||||
break;
|
||||
}
|
||||
l = r + 1;
|
||||
}
|
||||
if (has_same_prefix) {
|
||||
task_list.emplace_back(base);
|
||||
}
|
||||
else {
|
||||
task_list.emplace_back(task_prefix + "@" + base);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
generate_tasks(task_info_ptr->next, base_ptr->next);
|
||||
generate_tasks(task_info_ptr->exceeded_next, base_ptr->exceeded_next);
|
||||
generate_tasks(task_info_ptr->on_error_next, base_ptr->on_error_next);
|
||||
generate_tasks(task_info_ptr->reduce_other_times, base_ptr->reduce_other_times);
|
||||
|
||||
return task_info_ptr;
|
||||
}
|
||||
|
||||
public:
|
||||
virtual ~TaskData() override = default;
|
||||
virtual const std::unordered_set<std::string>& get_templ_required() const noexcept override;
|
||||
|
||||
template <typename TargetTaskInfoType>
|
||||
requires std::derived_from<TargetTaskInfoType, TaskInfo> &&
|
||||
(!std::same_as<TargetTaskInfoType, TaskInfo>) // Parameter must be a TaskInfo and not same as TaskInfo
|
||||
std::shared_ptr<TargetTaskInfoType> get(const std::string& name)
|
||||
{
|
||||
auto it = m_all_tasks_info.find(name);
|
||||
if (it == m_all_tasks_info.cend()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::dynamic_pointer_cast<TargetTaskInfoType>(it->second);
|
||||
}
|
||||
|
||||
template <typename TargetTaskInfoType = TaskInfo>
|
||||
requires std::same_as<TargetTaskInfoType, TaskInfo> // Parameter must be a TaskInfo
|
||||
requires(std::derived_from<TargetTaskInfoType, TaskInfo> ||
|
||||
std::same_as<TargetTaskInfoType, TaskInfo>) // Parameter must be a TaskInfo
|
||||
std::shared_ptr<TargetTaskInfoType> get(const std::string& name)
|
||||
{
|
||||
auto it = m_all_tasks_info.find(name);
|
||||
if (it == m_all_tasks_info.cend()) {
|
||||
// 普通 task 或已经生成过的 `@` 型 task
|
||||
if (auto it = m_all_tasks_info.find(name); it != m_all_tasks_info.cend()) [[likely]] {
|
||||
if constexpr (std::same_as<TargetTaskInfoType, TaskInfo>) {
|
||||
return it->second;
|
||||
}
|
||||
else {
|
||||
return std::dynamic_pointer_cast<TargetTaskInfoType>(it->second);
|
||||
}
|
||||
}
|
||||
|
||||
size_t at_pos = name.find('@');
|
||||
if (at_pos == std::string::npos) [[unlikely]] {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return it->second;
|
||||
// `@` 前面的字符长度
|
||||
size_t name_len = at_pos;
|
||||
auto base_task_iter = get(name.substr(name_len + 1));
|
||||
if (base_task_iter == nullptr) [[unlikely]] {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string derived_task_name = name.substr(0, name_len);
|
||||
auto task_info_ptr = generate_task_info(base_task_iter, derived_task_name);
|
||||
if (task_info_ptr == nullptr) [[unlikely]] {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// tasks 个数超过上限时不再 emplace,返回临时值
|
||||
constexpr size_t MAX_TASKS_SIZE = 65535;
|
||||
if (m_all_tasks_info.size() < MAX_TASKS_SIZE) {
|
||||
m_all_tasks_info.emplace(name, task_info_ptr);
|
||||
}
|
||||
#ifdef ASST_DEBUG
|
||||
else {
|
||||
Log.debug("Task count has exceeded the upper limit:", MAX_TASKS_SIZE, "current task:", name);
|
||||
}
|
||||
#endif // ASST_DEBUG
|
||||
|
||||
if constexpr (std::same_as<TargetTaskInfoType, TaskInfo>) {
|
||||
return task_info_ptr;
|
||||
}
|
||||
else {
|
||||
return std::dynamic_pointer_cast<TargetTaskInfoType>(task_info_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
Reference in New Issue
Block a user