mirror of
https://github.com/MaaAssistantArknights/MaaAssistantArknights.git
synced 2026-07-15 17:30:27 +08:00
feat: 尝试把 sharp_task 的生成变为预处理,大幅修改 TaskData
This commit is contained in:
@@ -79,67 +79,6 @@ ProcessTask& asst::ProcessTask::set_rear_delay(std::string name, int delay)
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool ProcessTask::generate_tasks(const std::vector<std::string>& raw_tasks, std::unordered_set<std::string>& tasks_set)
|
||||
{
|
||||
for (const std::string& task : raw_tasks) {
|
||||
if (tasks_set.contains(task)) [[unlikely]] {
|
||||
// 对于相同的 task,第一次识别后第二次就不再识别了
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t pos = task.find('#');
|
||||
if (pos == std::string::npos) [[likely]] {
|
||||
m_cur_tasks_name.emplace_back(task);
|
||||
tasks_set.emplace(task);
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string other_task_name = task.substr(0, pos);
|
||||
std::string_view type = std::string_view(task).substr(pos + 1);
|
||||
auto other_tasklist_ref = Task.get(other_task_name);
|
||||
if (other_tasklist_ref == nullptr) {
|
||||
Log.error(task, "not found");
|
||||
continue;
|
||||
}
|
||||
|
||||
#define ASST_PROCESSTASK_GENERATE_TASKS(t) \
|
||||
else if (type == #t) \
|
||||
{ \
|
||||
if (!generate_tasks(other_tasklist_ref->t, tasks_set)) { \
|
||||
return false; \
|
||||
} \
|
||||
}
|
||||
if constexpr (false) {}
|
||||
ASST_PROCESSTASK_GENERATE_TASKS(next)
|
||||
ASST_PROCESSTASK_GENERATE_TASKS(sub)
|
||||
ASST_PROCESSTASK_GENERATE_TASKS(on_error_next)
|
||||
ASST_PROCESSTASK_GENERATE_TASKS(exceeded_next)
|
||||
ASST_PROCESSTASK_GENERATE_TASKS(reduce_other_times)
|
||||
else {
|
||||
Log.error("Unknown type", type);
|
||||
return false;
|
||||
}
|
||||
#undef ASST_PROCESSTASK_GENERATE_TASKS
|
||||
|
||||
tasks_set.emplace(task);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ProcessTask::generate_tasks()
|
||||
{
|
||||
// std::move 后 m_cur_tasks_name 已经为空
|
||||
std::vector<std::string> cur_tasks_name = std::move(m_cur_tasks_name);
|
||||
std::unordered_set<std::string> tasks_set {};
|
||||
if (!generate_tasks(cur_tasks_name, tasks_set)) [[unlikely]] {
|
||||
Log.error("Generate task failed. pre_task:", m_pre_task_name);
|
||||
m_cur_tasks_name.clear();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ProcessTask::_run()
|
||||
{
|
||||
LogTraceFunction;
|
||||
@@ -151,9 +90,6 @@ bool ProcessTask::_run()
|
||||
if (m_cur_task_ptr && m_pre_task_name != m_cur_task_ptr->name) {
|
||||
m_pre_task_name = m_cur_task_ptr->name;
|
||||
}
|
||||
if (!generate_tasks()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
json::value info = basic_info();
|
||||
info["details"] = json::object {
|
||||
|
||||
@@ -41,8 +41,6 @@ namespace asst
|
||||
virtual json::value basic_info() const override;
|
||||
|
||||
std::pair<int, TimesLimitType> calc_time_limit() const;
|
||||
bool generate_tasks(const std::vector<std::string>& raw_tasks, std::unordered_set<std::string>& tasks_set);
|
||||
bool generate_tasks();
|
||||
void exec_click_task(const Rect& matched_rect);
|
||||
void exec_swipe_task(ProcessTaskAction action);
|
||||
void exec_slowly_swipe_task(ProcessTaskAction action);
|
||||
|
||||
@@ -18,13 +18,14 @@ const std::unordered_set<std::string>& asst::TaskData::get_templ_required() cons
|
||||
bool asst::TaskData::parse(const json::value& json)
|
||||
{
|
||||
LogTraceFunction;
|
||||
using tasklist_t = std::vector<std::string>;
|
||||
|
||||
const auto& json_obj = json.as_object();
|
||||
|
||||
{
|
||||
std::unordered_map<std::string, bool> to_be_generated;
|
||||
std::unordered_map<std::string_view, bool> to_be_generated;
|
||||
for (const std::string& name : json_obj | views::keys) {
|
||||
to_be_generated[name] = true;
|
||||
to_be_generated[task_name_view(name)] = true;
|
||||
}
|
||||
|
||||
auto generate_task_and_its_base = [&](const std::string& name) -> bool {
|
||||
@@ -34,17 +35,17 @@ bool asst::TaskData::parse(const json::value& json)
|
||||
if (task_info_ptr == nullptr) {
|
||||
return false;
|
||||
}
|
||||
to_be_generated[name] = false;
|
||||
m_all_tasks_info[name] = task_info_ptr;
|
||||
to_be_generated[task_name_view(name)] = false;
|
||||
insert_or_assign_raw_task(name, task_info_ptr);
|
||||
return true;
|
||||
};
|
||||
std::function<bool(const std::string&, bool)> generate_fun;
|
||||
// must_true 若为真,那么 return false 了就是炸了。
|
||||
// 否则可能只是某个 B@A 的任务没定义 A(这不是少见现象,例如 Roguelike@Abandon)
|
||||
generate_fun = [&](const std::string& name, bool must_true) -> bool {
|
||||
if (!to_be_generated[name]) {
|
||||
if (!to_be_generated[task_name_view(name)]) {
|
||||
// 已生成(它是之前加载过的某个资源的 base)
|
||||
if (m_all_tasks_info.contains(name)) {
|
||||
if (m_raw_all_tasks_info.contains(name)) {
|
||||
return true;
|
||||
}
|
||||
// 不在 json 内且未生成(例如生成 C@B@A 时没有定义 B@A,而是定义了 A)
|
||||
@@ -60,12 +61,12 @@ bool asst::TaskData::parse(const json::value& json)
|
||||
const json::value& task_json = json_obj.at(name);
|
||||
if (auto opt = task_json.find<std::string>("baseTask")) {
|
||||
std::string base = opt.value();
|
||||
return generate_fun(base, must_true) && generate_task(name, "", get(base, false), task_json);
|
||||
return generate_fun(base, must_true) && generate_task(name, "", get_raw(base), task_json);
|
||||
}
|
||||
|
||||
if (size_t p = name.find('@'); p != std::string::npos) {
|
||||
if (std::string base = name.substr(p + 1); generate_fun(base, false)) {
|
||||
return generate_task(name, name.substr(0, p), get(base, false), task_json);
|
||||
return generate_task(name, name.substr(0, p), get_raw(base), task_json);
|
||||
}
|
||||
// 这类任务有点多,非必要不输出(
|
||||
// Log.debug("Task", name, "based on unknown task, just use task_json.");
|
||||
@@ -78,6 +79,80 @@ bool asst::TaskData::parse(const json::value& json)
|
||||
for (const std::string& name : json_obj | views::keys) {
|
||||
generate_task_and_its_base(name);
|
||||
}
|
||||
|
||||
// 生成 # 型任务
|
||||
for (const auto& [name, old_task] : m_raw_all_tasks_info) {
|
||||
bool task_changed = false;
|
||||
auto task_info = _generate_task_info(old_task);
|
||||
auto generate_sharp_task = [&](tasklist_t& new_task_list, const tasklist_t& task_list,
|
||||
std::string_view list_type) {
|
||||
new_task_list.clear();
|
||||
std::function<bool(const tasklist_t&)> generate_tasks;
|
||||
std::unordered_set<std::string_view> tasks_set {};
|
||||
generate_tasks = [&](const tasklist_t& raw_tasks) {
|
||||
for (std::string_view task : raw_tasks) {
|
||||
if (tasks_set.contains(task)) [[unlikely]] {
|
||||
task_changed = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t pos = task.find('#');
|
||||
if (pos == std::string_view::npos) [[likely]] {
|
||||
new_task_list.emplace_back(task);
|
||||
tasks_set.emplace(task_name_view(task));
|
||||
continue;
|
||||
}
|
||||
|
||||
task_changed = true;
|
||||
std::string_view type = task.substr(pos + 1);
|
||||
auto other_tasklist_ref = get_raw(task.substr(0, pos));
|
||||
#define ASST_TASKDATA_GENERATE_TASKS(t) \
|
||||
else if (type == #t) \
|
||||
{ \
|
||||
if (!generate_tasks(other_tasklist_ref->t)) { \
|
||||
return false; \
|
||||
} \
|
||||
}
|
||||
if (other_tasklist_ref == nullptr) {
|
||||
Log.error("Task", task, "not found");
|
||||
return false;
|
||||
}
|
||||
ASST_TASKDATA_GENERATE_TASKS(next)
|
||||
ASST_TASKDATA_GENERATE_TASKS(sub)
|
||||
ASST_TASKDATA_GENERATE_TASKS(on_error_next)
|
||||
ASST_TASKDATA_GENERATE_TASKS(exceeded_next)
|
||||
ASST_TASKDATA_GENERATE_TASKS(reduce_other_times)
|
||||
else {
|
||||
Log.error("Unknown type", type, "in", task);
|
||||
return false;
|
||||
}
|
||||
#undef ASST_TASKDATA_GENERATE_TASKS
|
||||
|
||||
tasks_set.emplace(task_name_view(task));
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
if (!generate_tasks(task_list)) {
|
||||
Log.error(Logger::separator::none, "Generate task_list ", name, "->", list_type, " failed.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
#define ASST_TASKDATA_GENERATE_SHARP_TASK(type) \
|
||||
if (!generate_sharp_task(task_info->type, old_task->type, #type)) { \
|
||||
return false; \
|
||||
}
|
||||
ASST_TASKDATA_GENERATE_SHARP_TASK(next);
|
||||
ASST_TASKDATA_GENERATE_SHARP_TASK(sub);
|
||||
ASST_TASKDATA_GENERATE_SHARP_TASK(exceeded_next);
|
||||
ASST_TASKDATA_GENERATE_SHARP_TASK(on_error_next);
|
||||
ASST_TASKDATA_GENERATE_SHARP_TASK(reduce_other_times);
|
||||
#undef ASST_TASKDATA_GENERATE_SHARP_TASK
|
||||
|
||||
insert_or_assign_task(name, task_changed ? task_info : old_task);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ASST_DEBUG
|
||||
@@ -89,134 +164,40 @@ bool asst::TaskData::parse(const json::value& json)
|
||||
validity &= syntax_check(name, task_json);
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, std::vector<std::string>> dependency_graph; // "#" 型任务依赖关系 (有向图邻接表)
|
||||
std::unordered_map<std::string, int> checked; // 拓扑排序相关的标志
|
||||
static const std::unordered_set<std::string> accepted_type = {
|
||||
"next", "sub", "on_error_next", "exceeded_next", "reduce_other_times",
|
||||
};
|
||||
|
||||
for (const auto& [name, task] : m_all_tasks_info) {
|
||||
auto check_and_link = [&](const std::vector<std::string>& task_list, std::string node_name) {
|
||||
for (const auto& task_name : task_list) {
|
||||
size_t pos = task_name.find('#');
|
||||
// next、sub 等的存在性检查
|
||||
if (pos == std::string::npos) {
|
||||
if (get(task_name, false) == nullptr) {
|
||||
Log.error(node_name, task_name, "is null");
|
||||
validity = false;
|
||||
}
|
||||
auto check_tasklist = [&](const tasklist_t& task_list, std::string_view list_type,
|
||||
bool enable_justreturn_check = false) {
|
||||
std::unordered_set<std::string_view> tasks_set {};
|
||||
std::string justreturn_task_name = "";
|
||||
for (const std::string& task_name : task_list) {
|
||||
if (tasks_set.contains(task_name)) [[unlikely]] {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string other_task_name = task_name.substr(0, pos);
|
||||
if (get(other_task_name, false) == nullptr) {
|
||||
Log.error(node_name, task_name, "is null");
|
||||
// 检查是否有 JustReturn 任务不是最后一个任务
|
||||
if (enable_justreturn_check && !justreturn_task_name.empty()) [[unlikely]] {
|
||||
Log.error(Logger::separator::none, name, "->", list_type,
|
||||
" has a not-final JustReturn task: ", justreturn_task_name);
|
||||
validity = false;
|
||||
}
|
||||
std::string type = task_name.substr(pos + 1);
|
||||
if (!accepted_type.contains(type)) {
|
||||
Log.error(node_name, task_name, "has unknown type:", type);
|
||||
|
||||
if (auto ptr = get_raw(task_name); ptr == nullptr) {
|
||||
Log.error(Logger::separator::none, task_name, " in ", name, "->", list_type, " is null");
|
||||
validity = false;
|
||||
}
|
||||
else {
|
||||
// 建立一条依赖关系 (有向边)
|
||||
dependency_graph[node_name].emplace_back(task_name);
|
||||
else if (ptr->algorithm == AlgorithmType::JustReturn) {
|
||||
justreturn_task_name = ptr->name;
|
||||
}
|
||||
|
||||
tasks_set.emplace(task_name_view(task_name));
|
||||
}
|
||||
};
|
||||
check_and_link(task->next, name + "#next");
|
||||
check_and_link(task->sub, name + "#sub");
|
||||
check_and_link(task->exceeded_next, name + "#exceeded_next");
|
||||
check_and_link(task->on_error_next, name + "#on_error_next");
|
||||
check_and_link(task->reduce_other_times, name + "#reduce_other_times");
|
||||
|
||||
// 检查是否有 JustReturn 任务不是最后一个任务
|
||||
auto check_justreturn = [&](const std::vector<std::string>& task_list, std::string node_name) {
|
||||
std::function<bool(const std::vector<std::string>&)> generate_tasks;
|
||||
std::unordered_set<std::string> tasks_set {};
|
||||
bool has_justreturn = false;
|
||||
generate_tasks = [&](const std::vector<std::string>& raw_tasks) {
|
||||
for (const std::string& task : raw_tasks) {
|
||||
if (tasks_set.contains(task)) [[unlikely]] {
|
||||
continue;
|
||||
}
|
||||
if (has_justreturn) [[unlikely]] {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t pos = task.find('#');
|
||||
if (pos == std::string::npos) [[likely]] {
|
||||
if (auto ptr = get(task, false); ptr != nullptr) {
|
||||
has_justreturn |= ptr->algorithm == AlgorithmType::JustReturn;
|
||||
}
|
||||
tasks_set.emplace(task);
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string other_task_name = task.substr(0, pos);
|
||||
std::string_view type = std::string_view(task).substr(pos + 1);
|
||||
auto other_tasklist_ref = get(other_task_name, false);
|
||||
if (other_tasklist_ref == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
#define ASST_PROCESSTASK_GENERATE_TASKS(t) \
|
||||
else if (type == #t) \
|
||||
{ \
|
||||
if (!generate_tasks(other_tasklist_ref->t)) { \
|
||||
return false; \
|
||||
} \
|
||||
}
|
||||
if constexpr (false) {}
|
||||
ASST_PROCESSTASK_GENERATE_TASKS(next)
|
||||
ASST_PROCESSTASK_GENERATE_TASKS(sub)
|
||||
ASST_PROCESSTASK_GENERATE_TASKS(on_error_next)
|
||||
ASST_PROCESSTASK_GENERATE_TASKS(exceeded_next)
|
||||
ASST_PROCESSTASK_GENERATE_TASKS(reduce_other_times)
|
||||
#undef ASST_PROCESSTASK_GENERATE_TASKS
|
||||
|
||||
tasks_set.emplace(task);
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
if (!generate_tasks(task_list)) {
|
||||
Log.error(node_name, "has justreturn task that is not the last one");
|
||||
validity = false;
|
||||
}
|
||||
};
|
||||
check_justreturn(task->next, name + "#next");
|
||||
check_justreturn(task->exceeded_next, name + "#exceeded_next");
|
||||
check_justreturn(task->on_error_next, name + "#on_error_next");
|
||||
}
|
||||
|
||||
// dfs 检查 "#" 型任务是否循环依赖 (有向无环图)
|
||||
auto check_circle = [&](const std::string& x) {
|
||||
std::function<bool(const std::string&)> dfs;
|
||||
dfs = [&](const std::string& x) {
|
||||
checked[x] = -1;
|
||||
for (const auto& y : dependency_graph[x]) {
|
||||
if (checked[y] == 0) {
|
||||
if (!dfs(y)) [[unlikely]] {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (checked[y] < 0) [[unlikely]] {
|
||||
Log.error("Task", y, "has circular dependency.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
checked[x] = 1;
|
||||
return true;
|
||||
};
|
||||
return dfs(x);
|
||||
};
|
||||
|
||||
for (const auto& name : dependency_graph | views::keys) {
|
||||
if (!checked[name] && !check_circle(name)) {
|
||||
validity = false;
|
||||
break;
|
||||
}
|
||||
check_tasklist(task->next, "next", true);
|
||||
check_tasklist(task->sub, "sub");
|
||||
check_tasklist(task->exceeded_next, "exceeded_next", true);
|
||||
check_tasklist(task->on_error_next, "on_error_next", true);
|
||||
check_tasklist(task->reduce_other_times, "reduce_other_times");
|
||||
}
|
||||
|
||||
if (!validity) return false;
|
||||
|
||||
@@ -76,7 +76,7 @@ namespace asst
|
||||
};
|
||||
// 运行时动态生成任务
|
||||
static std::shared_ptr<TaskInfo> _generate_task_info(const std::shared_ptr<TaskInfo>& base_ptr,
|
||||
const std::string& task_prefix)
|
||||
std::string_view task_prefix = "")
|
||||
{
|
||||
std::shared_ptr<TaskInfo> task_info_ptr;
|
||||
switch (base_ptr->algorithm) {
|
||||
@@ -94,16 +94,28 @@ namespace asst
|
||||
break;
|
||||
}
|
||||
|
||||
task_info_ptr->name = task_prefix + "@" + base_ptr->name;
|
||||
task_info_ptr->sub = append_prefix(base_ptr->sub, task_prefix);
|
||||
task_info_ptr->next = append_prefix(base_ptr->next, task_prefix);
|
||||
task_info_ptr->exceeded_next = append_prefix(base_ptr->exceeded_next, task_prefix);
|
||||
task_info_ptr->on_error_next = append_prefix(base_ptr->on_error_next, task_prefix);
|
||||
task_info_ptr->reduce_other_times = append_prefix(base_ptr->reduce_other_times, task_prefix);
|
||||
if (!task_prefix.empty()) {
|
||||
task_info_ptr->name = std::string(task_prefix) + "@" + base_ptr->name;
|
||||
task_info_ptr->sub = append_prefix(base_ptr->sub, task_prefix);
|
||||
task_info_ptr->next = append_prefix(base_ptr->next, task_prefix);
|
||||
task_info_ptr->exceeded_next = append_prefix(base_ptr->exceeded_next, task_prefix);
|
||||
task_info_ptr->on_error_next = append_prefix(base_ptr->on_error_next, task_prefix);
|
||||
task_info_ptr->reduce_other_times = append_prefix(base_ptr->reduce_other_times, task_prefix);
|
||||
}
|
||||
|
||||
return task_info_ptr;
|
||||
}
|
||||
|
||||
std::string_view task_name_view(std::string_view task_name) { return *m_task_names.emplace(task_name).first; }
|
||||
void insert_or_assign_raw_task(std::string_view task_name, std::shared_ptr<TaskInfo> task_info_ptr)
|
||||
{
|
||||
m_raw_all_tasks_info.insert_or_assign(task_name_view(task_name), task_info_ptr);
|
||||
}
|
||||
void insert_or_assign_task(std::string_view task_name, std::shared_ptr<TaskInfo> task_info_ptr)
|
||||
{
|
||||
m_all_tasks_info.insert_or_assign(task_name_view(task_name), task_info_ptr);
|
||||
}
|
||||
|
||||
public:
|
||||
virtual ~TaskData() override = default;
|
||||
virtual const std::unordered_set<std::string>& get_templ_required() const noexcept override;
|
||||
@@ -111,7 +123,7 @@ namespace asst
|
||||
template <typename TargetTaskInfoType = 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, bool with_emplace = true)
|
||||
std::shared_ptr<TargetTaskInfoType> get(std::string_view name)
|
||||
{
|
||||
// 普通 task 或已经生成过的 `@` 型 task
|
||||
if (auto it = m_all_tasks_info.find(name); it != m_all_tasks_info.cend()) [[likely]] {
|
||||
@@ -124,18 +136,18 @@ namespace asst
|
||||
}
|
||||
|
||||
size_t at_pos = name.find('@');
|
||||
if (at_pos == std::string::npos) [[unlikely]] {
|
||||
if (at_pos == std::string_view::npos) [[unlikely]] {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// `@` 前面的字符长度
|
||||
size_t name_len = at_pos;
|
||||
auto base_task_iter = get(name.substr(name_len + 1), with_emplace);
|
||||
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);
|
||||
std::string_view 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;
|
||||
@@ -143,16 +155,14 @@ namespace asst
|
||||
|
||||
// tasks 个数超过上限时不再 emplace,返回临时值
|
||||
constexpr size_t MAX_TASKS_SIZE = 65535;
|
||||
if (with_emplace) {
|
||||
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 (m_all_tasks_info.size() < MAX_TASKS_SIZE) [[likely]] {
|
||||
insert_or_assign_task(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;
|
||||
@@ -165,13 +175,56 @@ namespace asst
|
||||
protected:
|
||||
virtual bool parse(const json::value& json) override;
|
||||
|
||||
template <typename TargetTaskInfoType = TaskInfo>
|
||||
requires(std::derived_from<TargetTaskInfoType, TaskInfo> ||
|
||||
std::same_as<TargetTaskInfoType, TaskInfo>) // Parameter must be a TaskInfo
|
||||
std::shared_ptr<TargetTaskInfoType> get_raw(std::string_view name) const
|
||||
{
|
||||
// 普通 task 或已经生成过的 `@` 型 task
|
||||
if (auto it = m_raw_all_tasks_info.find(name); it != m_raw_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_view::npos) [[unlikely]] {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// `@` 前面的字符长度
|
||||
size_t name_len = at_pos;
|
||||
auto base_task_iter = get_raw(name.substr(name_len + 1));
|
||||
if (base_task_iter == nullptr) [[unlikely]] {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string_view 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;
|
||||
}
|
||||
|
||||
if constexpr (std::same_as<TargetTaskInfoType, TaskInfo>) {
|
||||
return task_info_ptr;
|
||||
}
|
||||
else {
|
||||
return std::dynamic_pointer_cast<TargetTaskInfoType>(task_info_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
#ifdef ASST_DEBUG
|
||||
bool syntax_check(const std::string& task_name, const json::value& task_json);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
std::unordered_map<std::string, std::shared_ptr<TaskInfo>> m_all_tasks_info;
|
||||
std::unordered_set<std::string> m_task_names;
|
||||
std::unordered_map<std::string_view, std::shared_ptr<TaskInfo>> m_raw_all_tasks_info;
|
||||
std::unordered_map<std::string_view, std::shared_ptr<TaskInfo>> m_all_tasks_info;
|
||||
std::unordered_set<std::string> m_templ_required;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user