mirror of
https://github.com/MaaAssistantArknights/MaaAssistantArknights.git
synced 2026-07-17 18:01:26 +08:00
170 lines
4.3 KiB
C++
170 lines
4.3 KiB
C++
#include "AbstractTask.h"
|
|
|
|
#include <algorithm>
|
|
#include <filesystem>
|
|
#include <thread>
|
|
#include <regex>
|
|
|
|
#include <opencv2/opencv.hpp>
|
|
|
|
#include "AsstUtils.hpp"
|
|
#include "Controller.h"
|
|
#include "Logger.hpp"
|
|
#include "Resource.h"
|
|
#include "AbstractTaskPlugin.h"
|
|
|
|
using namespace asst;
|
|
|
|
AbstractTask::AbstractTask(AsstCallback callback, void* callback_arg, std::string task_chain)
|
|
: m_callback(callback),
|
|
m_callback_arg(callback_arg),
|
|
m_task_chain(std::move(task_chain))
|
|
{
|
|
;
|
|
}
|
|
|
|
bool asst::AbstractTask::run()
|
|
{
|
|
callback(AsstMsg::SubTaskStart, basic_info());
|
|
for (m_cur_retry = 0; m_cur_retry <= m_retry_times; ++m_cur_retry) {
|
|
if (_run()) {
|
|
callback(AsstMsg::SubTaskCompleted, basic_info());
|
|
return true;
|
|
}
|
|
if (need_exit()) {
|
|
return false;
|
|
}
|
|
int delay = Resrc.cfg().get_options().task_delay;
|
|
sleep(delay);
|
|
|
|
if (!on_run_fails()) {
|
|
callback(AsstMsg::SubTaskError, basic_info());
|
|
return false;
|
|
}
|
|
}
|
|
callback(AsstMsg::SubTaskError, basic_info());
|
|
return false;
|
|
}
|
|
|
|
AbstractTask& asst::AbstractTask::set_exit_flag(bool* exit_flag) noexcept
|
|
{
|
|
m_exit_flag = exit_flag;
|
|
return *this;
|
|
}
|
|
|
|
AbstractTask& asst::AbstractTask::set_retry_times(int times) noexcept
|
|
{
|
|
m_retry_times = times;
|
|
return *this;
|
|
}
|
|
|
|
void asst::AbstractTask::clear_plugin() noexcept
|
|
{
|
|
m_plugins.clear();
|
|
}
|
|
|
|
json::value asst::AbstractTask::basic_info() const
|
|
{
|
|
if (m_basic_info_cache.empty()) {
|
|
std::string class_name = typeid(*this).name();
|
|
std::string task_name;
|
|
// typeid.name() 结果可能和编译器有关,所以这里使用正则尽可能保证结果正确。
|
|
// 但还是不能完全保证,如果不行的话建议 override
|
|
std::regex regex("[a-zA-Z]+Task");
|
|
std::smatch match_obj;
|
|
if (std::regex_search(class_name, match_obj, regex)) {
|
|
task_name = match_obj[0].str();
|
|
}
|
|
else {
|
|
task_name = class_name;
|
|
}
|
|
|
|
m_basic_info_cache = json::object{
|
|
{ "taskchain", m_task_chain },
|
|
{ "class", class_name },
|
|
{ "subtask", task_name },
|
|
{ "details", json::object() }
|
|
//{ "CurRetryTimes", m_cur_retry },
|
|
//{ "MaxRetryTimes", m_retry_times }
|
|
};
|
|
}
|
|
return m_basic_info_cache;
|
|
}
|
|
|
|
json::value asst::AbstractTask::basic_info_with_what(std::string what) const
|
|
{
|
|
json::value info = basic_info();
|
|
info["what"] = std::move(what);
|
|
return info;
|
|
}
|
|
|
|
bool AbstractTask::sleep(unsigned millisecond)
|
|
{
|
|
if (need_exit()) {
|
|
return false;
|
|
}
|
|
if (millisecond == 0) {
|
|
return true;
|
|
}
|
|
auto start = std::chrono::steady_clock::now();
|
|
long long duration = 0;
|
|
|
|
Log.trace("ready to sleep", millisecond);
|
|
|
|
while (!need_exit() && duration < millisecond) {
|
|
duration = std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
std::chrono::steady_clock::now() - start).count();
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
std::this_thread::yield();
|
|
}
|
|
Log.trace("end of sleep", millisecond);
|
|
|
|
return !need_exit();
|
|
}
|
|
|
|
bool AbstractTask::save_image(const cv::Mat image, const std::string& dir)
|
|
{
|
|
std::filesystem::create_directory(dir);
|
|
const std::string time_str = utils::string_replace_all(utils::string_replace_all(utils::get_format_time(), " ", "_"), ":", "-");
|
|
const std::string filename = dir + time_str + ".png";
|
|
|
|
bool ret = cv::imwrite(filename, image);
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool asst::AbstractTask::need_exit() const
|
|
{
|
|
return m_exit_flag != nullptr && *m_exit_flag == true;
|
|
}
|
|
|
|
void asst::AbstractTask::callback(AsstMsg msg, const json::value& detail)
|
|
{
|
|
for (TaskPluginPtr plugin : m_plugins) {
|
|
plugin->set_exit_flag(m_exit_flag);
|
|
plugin->set_task_ptr(this);
|
|
|
|
if (!plugin->verify(msg, detail)) {
|
|
continue;
|
|
}
|
|
|
|
plugin->run();
|
|
|
|
if (plugin->block()) {
|
|
break;
|
|
}
|
|
}
|
|
m_callback(msg, detail, m_callback_arg);
|
|
}
|
|
|
|
void asst::AbstractTask::click_return_button()
|
|
{
|
|
LogTraceFunction;
|
|
const auto return_task_ptr = Task.get("Return");
|
|
|
|
Rect ReturnButtonRect = return_task_ptr->specific_rect;
|
|
|
|
Ctrler.click(ReturnButtonRect);
|
|
sleep(return_task_ptr->rear_delay);
|
|
}
|