Files
MaaAssistantArknights/src/MeoAssistant/ProcessTask.cpp

264 lines
7.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "ProcessTask.h"
#include <chrono>
#include <random>
#include <meojson/json.hpp>
#include "AsstUtils.hpp"
#include "Controller.h"
#include "ProcessTaskImageAnalyzer.h"
#include "Resource.h"
#include "Logger.hpp"
#include "RuntimeStatus.h"
using namespace asst;
asst::ProcessTask::ProcessTask(const AbstractTask& abs, std::vector<std::string> tasks_name)
: AbstractTask(abs),
m_raw_tasks_name(std::move(tasks_name))
{
m_basic_info_cache = json::value();
}
asst::ProcessTask::ProcessTask(AbstractTask&& abs, std::vector<std::string> tasks_name) noexcept
: AbstractTask(std::move(abs)),
m_raw_tasks_name(std::move(tasks_name))
{
m_basic_info_cache = json::value();
}
bool asst::ProcessTask::run()
{
m_cur_tasks_name = m_raw_tasks_name;
for (m_cur_retry = 0; m_cur_retry <= m_retry_times; ++m_cur_retry) {
if (_run()) {
return true;
}
if (need_exit()) {
return false;
}
int delay = Resrc.cfg().get_options().task_delay;
sleep(delay);
if (!on_run_fails()) {
return false;
}
}
callback(AsstMsg::SubTaskError, basic_info());
return false;
}
asst::ProcessTask& asst::ProcessTask::set_tasks(std::vector<std::string> tasks_name) noexcept
{
m_raw_tasks_name = std::move(tasks_name);
return *this;
}
ProcessTask& asst::ProcessTask::set_times_limit(std::string name, int limit)
{
m_times_limit[std::move(name)] = limit;
return *this;
}
ProcessTask& asst::ProcessTask::set_rear_delay(std::string name, int delay)
{
m_rear_delay[std::move(name)] = delay;
return *this;
}
bool ProcessTask::_run()
{
LogTraceFunction;
auto& task_delay = Resrc.cfg().get_options().task_delay;
while (!m_cur_tasks_name.empty()) {
if (need_exit()) {
return false;
}
json::value info = basic_info();
info["details"] = json::object{
{"to_be_recognized", json::array(m_cur_tasks_name)},
{"cur_retry", m_cur_retry},
{"retry_times", m_retry_times}
};
Log.info(info.to_string());
Rect rect;
std::shared_ptr<TaskInfo> cur_task_ptr = nullptr;
// 如果第一个任务是JustReturn的那就没必要再截图并计算了
if (auto front_task_ptr = Task.get(m_cur_tasks_name.front());
front_task_ptr->algorithm == AlgorithmType::JustReturn) {
cur_task_ptr = front_task_ptr;
}
else {
const auto image = Ctrler.get_image();
ProcessTaskImageAnalyzer analyzer(image, m_cur_tasks_name);
if (!analyzer.analyze()) {
return false;
}
cur_task_ptr = analyzer.get_result();
rect = analyzer.get_rect();
}
if (need_exit()) {
return false;
}
std::string cur_name = cur_task_ptr->name;
const auto& res_move = cur_task_ptr->rect_move;
if (!res_move.empty()) {
rect.x += res_move.x;
rect.y += res_move.y;
rect.width = res_move.width;
rect.height = res_move.height;
}
int& exec_times = m_exec_times[cur_name];
int max_times = cur_task_ptr->max_times;
if (auto iter = m_times_limit.find(cur_name);
iter != m_times_limit.cend()) {
max_times = iter->second;
}
if (exec_times >= max_times) {
Log.info("exec times exceeds the limit", info.to_string());
m_cur_tasks_name = cur_task_ptr->exceeded_next;
sleep(task_delay);
continue;
}
m_cur_retry = 0;
++exec_times;
info["details"] = json::object{
{ "task", cur_name },
{ "action", static_cast<int>(cur_task_ptr->action) },
{ "exec_times", exec_times },
{ "max_times", max_times },
{ "algorithm", static_cast<int>(cur_task_ptr->algorithm) }
};
callback(AsstMsg::SubTaskStart, info);
// 前置固定延时
if (!sleep(cur_task_ptr->pre_delay)) {
return false;
}
bool need_stop = false;
switch (cur_task_ptr->action) {
case ProcessTaskAction::ClickRect:
rect = cur_task_ptr->specific_rect;
[[fallthrough]];
case ProcessTaskAction::ClickSelf:
exec_click_task(rect);
break;
case ProcessTaskAction::ClickRand: {
auto&& [width, height] = Ctrler.get_scale_size();
const Rect full_rect(0, 0, width, height);
exec_click_task(full_rect);
} break;
case ProcessTaskAction::SwipeToTheLeft:
case ProcessTaskAction::SwipeToTheRight:
exec_swipe_task(cur_task_ptr->action);
break;
case ProcessTaskAction::SlowlySwipeToTheLeft:
case ProcessTaskAction::SlowlySwipeToTheRight:
exec_slowly_swipe_task(cur_task_ptr->action);
break;
case ProcessTaskAction::DoNothing:
break;
case ProcessTaskAction::Stop:
Log.info("stop action", info.to_string());
need_stop = true;
break;
default:
break;
}
Status.set("Last" + cur_name, time(nullptr));
// 减少其他任务的执行次数
// 例如,进入吃理智药的界面了,相当于上一次点蓝色开始行动没生效
// 所以要给蓝色开始行动的次数减一
for (const std::string& reduce : cur_task_ptr->reduce_other_times) {
--m_exec_times[reduce];
}
// 后置固定延时
int rear_delay = cur_task_ptr->rear_delay;
if (auto iter = m_rear_delay.find(cur_name);
iter != m_rear_delay.cend()) {
rear_delay = iter->second;
}
if (!sleep(rear_delay)) {
return false;
}
callback(AsstMsg::SubTaskCompleted, info);
if (need_stop) {
return true;
}
m_cur_tasks_name = cur_task_ptr->next;
sleep(task_delay);
}
return true;
}
void ProcessTask::exec_click_task(const Rect& matched_rect)
{
Ctrler.click(matched_rect);
}
void asst::ProcessTask::exec_swipe_task(ProcessTaskAction action)
{
const auto&& [width, height] = Ctrler.get_scale_size();
const static Rect right_rect(
static_cast<int>(width * 0.8),
static_cast<int>(height * 0.4),
static_cast<int>(width * 0.1),
static_cast<int>(height * 0.2));
const static Rect left_rect(
static_cast<int>(width * 0.1),
static_cast<int>(height * 0.4),
static_cast<int>(width * 0.1),
static_cast<int>(height * 0.2));
switch (action) {
case asst::ProcessTaskAction::SwipeToTheLeft:
Ctrler.swipe(left_rect, right_rect);
break;
case asst::ProcessTaskAction::SwipeToTheRight:
Ctrler.swipe(right_rect, left_rect);
break;
default: // 走不到这里TODO 报个错
break;
}
}
void asst::ProcessTask::exec_slowly_swipe_task(ProcessTaskAction action)
{
LogTraceFunction;
static Rect right_rect = Task.get("ProcessTaskSlowlySwipeRightRect")->specific_rect;
static Rect left_rect = Task.get("ProcessTaskSlowlySwipeLeftRect")->specific_rect;
static int duration = Task.get("ProcessTaskSlowlySwipeRightRect")->pre_delay;
static int extra_delay = Task.get("ProcessTaskSlowlySwipeRightRect")->rear_delay;
switch (action) {
case asst::ProcessTaskAction::SlowlySwipeToTheLeft:
Ctrler.swipe(left_rect, right_rect, duration, true, extra_delay, true);
break;
case asst::ProcessTaskAction::SlowlySwipeToTheRight:
Ctrler.swipe(right_rect, left_rect, duration, true, extra_delay, true);
break;
default: // 走不到这里TODO 报个错
break;
}
}