chore: breaking rename

This commit is contained in:
MistEO
2022-12-02 00:22:47 +08:00
parent 8ff2c5e1d0
commit d9dcbb6289
345 changed files with 374 additions and 372 deletions

465
src/MaaCore/Assistant.cpp Normal file
View File

@@ -0,0 +1,465 @@
#include "Assistant.h"
#include "Utils/NoWarningCV.h"
#include "Utils/Ranges.hpp"
#include <meojson/json.hpp>
#include "Config/GeneralConfig.h"
#include "Config/Miscellaneous/OcrPack.h"
#include "Controller.h"
#include "Status.h"
#include "Task/Interface/AwardTask.h"
#include "Task/Interface/CloseDownTask.h"
#include "Task/Interface/CopilotTask.h"
#include "Task/Interface/DepotTask.h"
#include "Task/Interface/FightTask.h"
#include "Task/Interface/InfrastTask.h"
#include "Task/Interface/MallTask.h"
#include "Task/Interface/RecruitTask.h"
#include "Task/Interface/RoguelikeTask.h"
#include "Task/Interface/StartUpTask.h"
#include "Utils/Logger.hpp"
#ifdef ASST_DEBUG
#include "Task/Interface/DebugTask.h"
#endif
using namespace asst;
bool AsstExtAPI::set_static_option(StaticOptionKey key, const std::string& value)
{
Log.info(__FUNCTION__, "| key", static_cast<int>(key), "value", value);
switch (key) {
case StaticOptionKey::OcrBackend:
if (constexpr std::string_view ONNXRuntime = "ONNXRuntime"; value == ONNXRuntime) {
WordOcr::get_instance().set_backend_before_load(OcrPack::OcrBackend::ONNXRuntime);
CharOcr::get_instance().set_backend_before_load(OcrPack::OcrBackend::ONNXRuntime);
return true;
}
else if (constexpr std::string_view PaddleInference = "PaddleInference"; value == PaddleInference) {
WordOcr::get_instance().set_backend_before_load(OcrPack::OcrBackend::PaddleInference);
CharOcr::get_instance().set_backend_before_load(OcrPack::OcrBackend::PaddleInference);
return true;
}
else {
Log.error("unknown value", value);
return false;
}
break;
}
return false;
}
Assistant::Assistant(AsstApiCallback callback, void* callback_arg) : m_callback(callback), m_callback_arg(callback_arg)
{
LogTraceFunction;
m_status = std::make_shared<Status>();
m_ctrler = std::make_shared<Controller>(async_callback, this);
m_working_thread = std::thread(&Assistant::working_proc, this);
m_msg_thread = std::thread(&Assistant::msg_proc, this);
}
Assistant::~Assistant()
{
LogTraceFunction;
m_thread_exit = true;
m_thread_idle = true;
m_condvar.notify_all();
m_msg_condvar.notify_all();
if (m_working_thread.joinable()) {
m_working_thread.join();
}
if (m_msg_thread.joinable()) {
m_msg_thread.join();
}
}
bool asst::Assistant::set_instance_option(InstanceOptionKey key, const std::string& value)
{
Log.info(__FUNCTION__, "| key", static_cast<int>(key), "value", value);
switch (key) {
case InstanceOptionKey::MinitouchEnabled:
if (constexpr std::string_view Disable = "0"; value == Disable) {
m_ctrler->set_minitouch_enabled(false);
return true;
}
else if (constexpr std::string_view Enable = "1"; value == Enable) {
m_ctrler->set_minitouch_enabled(true);
return true;
}
else {
Log.error("unknown value", value);
return false;
}
break;
}
return false;
}
bool asst::Assistant::connect(const std::string& adb_path, const std::string& address, const std::string& config)
{
LogTraceFunction;
std::unique_lock<std::mutex> lock(m_mutex);
// 仍有任务进行connect 前需要 stop
if (!m_thread_idle) {
return false;
}
m_thread_idle = false;
bool ret = m_ctrler->connect(adb_path, address, config.empty() ? "General" : config);
if (ret) {
m_uuid = m_ctrler->get_uuid();
}
m_thread_idle = true;
return ret;
}
asst::Assistant::TaskId asst::Assistant::append_task(const std::string& type, const std::string& params)
{
Log.info(__FUNCTION__, type, params);
auto ret = json::parse(params.empty() ? "{}" : params);
if (!ret) {
return 0;
}
std::shared_ptr<InterfaceTask> ptr = nullptr;
#define ASST_ASSISTANT_APPEND_TASK_FROM_STRING_IF_BRANCH(TASK) \
else if (type == TASK::TaskType) \
{ \
ptr = std::make_shared<TASK>(async_callback, this); \
}
if constexpr (false) {}
ASST_ASSISTANT_APPEND_TASK_FROM_STRING_IF_BRANCH(FightTask)
ASST_ASSISTANT_APPEND_TASK_FROM_STRING_IF_BRANCH(StartUpTask)
ASST_ASSISTANT_APPEND_TASK_FROM_STRING_IF_BRANCH(CloseDownTask)
ASST_ASSISTANT_APPEND_TASK_FROM_STRING_IF_BRANCH(AwardTask)
ASST_ASSISTANT_APPEND_TASK_FROM_STRING_IF_BRANCH(MallTask)
ASST_ASSISTANT_APPEND_TASK_FROM_STRING_IF_BRANCH(InfrastTask)
ASST_ASSISTANT_APPEND_TASK_FROM_STRING_IF_BRANCH(RecruitTask)
ASST_ASSISTANT_APPEND_TASK_FROM_STRING_IF_BRANCH(RoguelikeTask)
ASST_ASSISTANT_APPEND_TASK_FROM_STRING_IF_BRANCH(CopilotTask)
ASST_ASSISTANT_APPEND_TASK_FROM_STRING_IF_BRANCH(DepotTask)
#ifdef ASST_DEBUG
ASST_ASSISTANT_APPEND_TASK_FROM_STRING_IF_BRANCH(DebugTask)
#endif
else
{
Log.error(__FUNCTION__, "| invalid type:", type);
return 0;
}
#undef ASST_ASSISTANT_APPEND_TASK_FROM_STRING_IF_BRANCH
auto& json = ret.value();
ptr->set_enable(json.get("enable", true));
bool params_ret = ptr->set_params(json);
if (!params_ret) {
return 0;
}
std::unique_lock<std::mutex> lock(m_mutex);
++m_task_id;
ptr->set_task_id(m_task_id);
m_tasks_list.emplace_back(m_task_id, ptr);
return m_task_id;
}
bool asst::Assistant::set_task_params(TaskId task_id, const std::string& params)
{
Log.info(__FUNCTION__, task_id, params);
if (task_id <= 0) {
return false;
}
auto ret = json::parse(params.empty() ? json::value().to_string() : params);
if (!ret) {
return false;
}
auto& json = ret.value();
bool is_set = false;
std::unique_lock<std::mutex> lock(m_mutex);
for (auto&& [id, ptr] : m_tasks_list) {
if (id != task_id) {
continue;
}
bool enable = json.get("enable", true);
ptr->set_enable(enable);
is_set = ptr->set_params(json);
break;
}
return is_set;
}
std::vector<uchar> asst::Assistant::get_image() const
{
if (!inited()) {
return {};
}
cv::Mat img = m_ctrler->get_image_cache();
std::vector<uchar> buf;
cv::imencode(".png", img, buf);
return buf;
}
asst::Assistant::AsyncCallId asst::Assistant::async_connect(const std::string& adb_path, const std::string& address,
const std::string& config, bool block)
{
LogTraceFunction;
int async_call_id = ++m_call_id;
async_call([&]() -> bool { return connect(adb_path, address, config); }, async_call_id, "Connect", block);
return async_call_id;
}
asst::Assistant::AsyncCallId asst::Assistant::async_click(int x, int y, bool block)
{
LogTraceFunction;
if (!inited()) {
return 0;
}
int async_call_id = ++m_call_id;
async_call([&]() -> bool { return m_ctrler->click(Point(x, y)); }, async_call_id, "Click", block);
return async_call_id;
}
asst::Assistant::AsyncCallId asst::Assistant::async_screencap(bool block)
{
LogTraceFunction;
if (!inited()) {
return 0;
}
int async_call_id = ++m_call_id;
async_call([&]() -> bool { return m_ctrler->screencap(); }, async_call_id, "Screencap", block);
return async_call_id;
}
std::string asst::Assistant::get_uuid() const
{
return m_uuid;
}
std::vector<Assistant::TaskId> asst::Assistant::get_tasks_list() const
{
std::unique_lock<std::mutex> lock(m_mutex);
std::vector<TaskId> result(m_tasks_list.size());
ranges::copy(m_tasks_list | views::keys, result.begin());
return result;
}
bool asst::Assistant::start(bool block)
{
LogTraceFunction;
Log.trace("Start |", block ? "block" : "non block");
if (!m_thread_idle || !inited()) {
return false;
}
std::unique_lock<std::mutex> lock;
if (block) { // 外部调用
lock = std::unique_lock<std::mutex>(m_mutex);
}
m_thread_idle = false;
m_condvar.notify_one();
return true;
}
bool Assistant::stop(bool block)
{
LogTraceFunction;
Log.trace("Stop |", block ? "block" : "non block");
m_thread_idle = true;
std::unique_lock<std::mutex> lock;
if (block) { // 外部调用
lock = std::unique_lock<std::mutex>(m_mutex);
}
m_tasks_list.clear();
clear_cache();
return true;
}
bool asst::Assistant::running() const
{
return !m_thread_idle;
}
void Assistant::working_proc()
{
LogTraceFunction;
std::vector<TaskId> finished_tasks;
while (!m_thread_exit) {
// LogTraceScope("Assistant::working_proc Loop");
std::unique_lock<std::mutex> lock(m_mutex);
if (!m_thread_idle && !m_tasks_list.empty()) {
const auto [id, task_ptr] = m_tasks_list.front();
lock.unlock();
// only one instance of working_proc running, unlock here to allow set_task_param to the running
// task
json::value callback_json = json::object {
{ "taskchain", std::string(task_ptr->get_task_chain()) },
{ "taskid", id },
};
async_callback(AsstMsg::TaskChainStart, callback_json, this);
bool ret = task_ptr->run();
finished_tasks.emplace_back(id);
lock.lock();
if (!m_tasks_list.empty()) {
m_tasks_list.pop_front();
}
lock.unlock();
auto msg = m_thread_idle ? AsstMsg::TaskChainStopped
: (ret ? AsstMsg::TaskChainCompleted : AsstMsg::TaskChainError);
async_callback(msg, callback_json, this);
if (m_thread_idle) {
finished_tasks.clear();
continue;
}
if (m_tasks_list.empty()) {
callback_json["finished_tasks"] = json::array(finished_tasks);
async_callback(AsstMsg::AllTasksCompleted, callback_json, this);
finished_tasks.clear();
}
const int delay = Config.get_options().task_delay;
lock.lock();
m_condvar.wait_for(lock, std::chrono::milliseconds(delay), [&]() -> bool { return m_thread_idle; });
if (m_thread_idle) {
async_callback(AsstMsg::TaskChainStopped, callback_json, this);
}
}
else {
m_thread_idle = true;
finished_tasks.clear();
Log.flush();
m_condvar.wait(lock);
}
}
}
void Assistant::msg_proc()
{
LogTraceFunction;
while (!m_thread_exit) {
// LogTraceScope("Assistant::msg_proc Loop");
std::unique_lock<std::mutex> lock(m_msg_mutex);
if (!m_msg_queue.empty()) {
// 结构化绑定只能是引用后续的pop会使引用失效所以需要重新构造一份这里采用了move的方式
auto&& [temp_msg, temp_detail] = m_msg_queue.front();
AsstMsg msg = temp_msg;
json::value detail = std::move(temp_detail);
m_msg_queue.pop();
lock.unlock();
if (m_callback) {
m_callback(static_cast<int>(msg), detail.to_string().c_str(), m_callback_arg);
}
}
else {
m_msg_condvar.wait(lock);
}
}
}
void Assistant::async_callback(AsstMsg msg, const json::value& detail, Assistant* inst)
{
json::value more_detail = detail;
if (!more_detail.contains("uuid")) {
more_detail["uuid"] = inst->m_uuid;
}
switch (msg) {
case AsstMsg::InternalError:
case AsstMsg::InitFailed:
inst->stop(false);
break;
default:
break;
}
// 加入回调消息队列,由回调消息线程外抛给外部
inst->append_callback(msg, std::move(more_detail));
}
void asst::Assistant::append_callback(AsstMsg msg, json::value detail)
{
Log.info("Assistant::append_callback |", msg, detail.to_string());
std::unique_lock<std::mutex> lock(m_msg_mutex);
m_msg_queue.emplace(msg, std::move(detail));
m_msg_condvar.notify_one();
}
void Assistant::clear_cache()
{
m_status->clear_number();
m_status->clear_rect();
m_status->clear_str();
}
bool asst::Assistant::inited() const noexcept
{
return m_ctrler && m_ctrler->inited();
}
void asst::Assistant::async_call(std::function<bool(void)> func, int async_call_id, const std::string what, bool block)
{
auto future = std::async(std::launch::async, [&]() {
auto start = std::chrono::steady_clock::now();
bool ret = func();
auto cost =
std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start).count();
json::value info = json::object {
{ "uuid", m_uuid },
{ "what", what },
{ "async_call_id", async_call_id },
{
"details",
json::object {
{ "ret", ret },
{ "cost", cost },
},
},
};
async_callback(AsstMsg::AsyncCallInfo, info, this);
});
if (!block) {
std::unique_lock lock(m_call_pending_mutex);
m_call_pending.emplace_back(std::move(future));
}
// else 会等待 future 析构,是阻塞的
}