Files
MaaAssistantArknights/src/MeoAssistant/Task/Interface/InfrastTask.cpp
2022-11-26 05:16:23 +08:00

345 lines
14 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 "InfrastTask.h"
#include "Utils/Logger.hpp"
#include "Task/Infrast/DronesForShamareTaskPlugin.h"
#include "Task/Infrast/InfrastControlTask.h"
#include "Task/Infrast/InfrastDormTask.h"
#include "Task/Infrast/InfrastInfoTask.h"
#include "Task/Infrast/InfrastMfgTask.h"
#include "Task/Infrast/InfrastOfficeTask.h"
#include "Task/Infrast/InfrastPowerTask.h"
#include "Task/Infrast/InfrastReceptionTask.h"
#include "Task/Infrast/InfrastTradeTask.h"
#include "Task/Infrast/ReplenishOriginiumShardTaskPlugin.h"
#include "Task/ProcessTask.h"
asst::InfrastTask::InfrastTask(const AsstCallback& callback, void* callback_arg)
: InterfaceTask(callback, callback_arg, TaskType),
m_infrast_begin_task_ptr(std::make_shared<ProcessTask>(callback, callback_arg, TaskType)),
m_info_task_ptr(std::make_shared<InfrastInfoTask>(callback, callback_arg, TaskType)),
m_mfg_task_ptr(std::make_shared<InfrastMfgTask>(callback, callback_arg, TaskType)),
m_trade_task_ptr(std::make_shared<InfrastTradeTask>(callback, callback_arg, TaskType)),
m_power_task_ptr(std::make_shared<InfrastPowerTask>(callback, callback_arg, TaskType)),
m_control_task_ptr(std::make_shared<InfrastControlTask>(callback, callback_arg, TaskType)),
m_reception_task_ptr(std::make_shared<InfrastReceptionTask>(callback, callback_arg, TaskType)),
m_office_task_ptr(std::make_shared<InfrastOfficeTask>(callback, callback_arg, TaskType)),
m_dorm_task_ptr(std::make_shared<InfrastDormTask>(callback, callback_arg, TaskType))
{
m_infrast_begin_task_ptr->set_tasks({ "InfrastBegin" }).set_ignore_error(true);
m_replenish_task_ptr = m_mfg_task_ptr->register_plugin<ReplenishOriginiumShardTaskPlugin>();
m_info_task_ptr->set_ignore_error(true);
m_mfg_task_ptr->set_ignore_error(true);
m_trade_task_ptr->set_ignore_error(true);
m_power_task_ptr->set_ignore_error(true);
m_control_task_ptr->set_ignore_error(true);
m_reception_task_ptr->set_ignore_error(true);
m_office_task_ptr->set_ignore_error(true);
m_dorm_task_ptr->set_ignore_error(true);
m_subtasks.emplace_back(m_infrast_begin_task_ptr);
}
bool asst::InfrastTask::set_params(const json::value& params)
{
LogTraceFunction;
int mode = params.get("mode", 0);
bool is_custom = static_cast<Mode>(mode) == Mode::Custom;
if (!m_running) {
auto facility_opt = params.find<json::array>("facility");
if (!facility_opt) {
return false;
}
auto append_infrast_begin = [&]() { m_subtasks.emplace_back(m_infrast_begin_task_ptr); };
m_subtasks.clear();
append_infrast_begin();
m_subtasks.emplace_back(m_info_task_ptr);
for (const auto& facility_json : facility_opt.value()) {
if (!facility_json.is_string()) {
m_subtasks.clear();
append_infrast_begin();
return false;
}
std::string facility = facility_json.as_string();
if (facility == "Dorm") {
m_subtasks.emplace_back(m_dorm_task_ptr);
}
else if (facility == "Mfg") {
m_subtasks.emplace_back(m_mfg_task_ptr);
}
else if (facility == "Trade") {
m_subtasks.emplace_back(m_trade_task_ptr);
}
else if (facility == "Power") {
m_subtasks.emplace_back(m_power_task_ptr);
}
else if (facility == "Office") {
m_subtasks.emplace_back(m_office_task_ptr);
}
else if (facility == "Reception") {
m_subtasks.emplace_back(m_reception_task_ptr);
}
else if (facility == "Control") {
m_subtasks.emplace_back(m_control_task_ptr);
}
else {
Log.error(__FUNCTION__, "| Unknown facility", facility);
m_subtasks.clear();
append_infrast_begin();
return false;
}
append_infrast_begin();
}
}
if (!is_custom) {
std::string drones = params.get("drones", "_NotUse");
m_mfg_task_ptr->set_uses_of_drone(drones);
m_trade_task_ptr->set_uses_of_drone(drones);
m_trade_task_ptr->register_plugin<DronesForShamareTaskPlugin>()->set_retry_times(0);
}
double threshold = params.get("threshold", 0.3);
m_info_task_ptr->set_mood_threshold(threshold);
m_mfg_task_ptr->set_mood_threshold(threshold);
m_trade_task_ptr->set_mood_threshold(threshold);
m_power_task_ptr->set_mood_threshold(threshold);
m_control_task_ptr->set_mood_threshold(threshold);
m_reception_task_ptr->set_mood_threshold(threshold);
m_office_task_ptr->set_mood_threshold(threshold);
m_dorm_task_ptr->set_mood_threshold(threshold);
bool dorm_notstationed_enabled = params.get("dorm_notstationed_enabled", false);
m_dorm_task_ptr->set_notstationed_enabled(dorm_notstationed_enabled);
bool drom_trust_enabled = params.get("drom_trust_enabled", true);
m_dorm_task_ptr->set_trust_enabled(drom_trust_enabled);
bool replenish = params.get("replenish", false);
m_replenish_task_ptr->set_enable(replenish);
if (is_custom && !m_running) {
std::string filename = params.at("filename").as_string();
int index = params.get("plan_index", 0);
try {
return parse_and_set_custom_config(utils::path(filename), index);
}
catch (const json::exception& e) {
Log.error("Json parse failed", utils::path(filename), e.what());
return false;
}
catch (const std::exception& e) {
Log.error("Json parse failed", utils::path(filename), e.what());
return false;
}
}
return true;
}
bool asst::InfrastTask::parse_and_set_custom_config(const std::filesystem::path& path, int index)
{
LogTraceFunction;
if (!std::filesystem::exists(path) || !std::filesystem::is_regular_file(path)) {
Log.error("custom infrast file does not exist:", path);
return false;
}
auto custom_json_opt = json::open(path);
if (!custom_json_opt) {
Log.error("failed to open json file:", path);
return false;
}
auto& custom_json = custom_json_opt.value();
Log.trace(__FUNCTION__, "| custom json:", custom_json.to_string());
auto& all_plans = custom_json.at("plans").as_array();
if (index < 0 || index >= int(all_plans.size())) {
Log.error("index is out of range, plans size:", all_plans.size(), ", index:", index);
return false;
}
auto& cur_plan = all_plans.at(index);
for (const auto& [facility, facility_info] : cur_plan.at("rooms").as_object()) {
infrast::CustomFacilityConfig facility_config;
for (const auto& room_info : facility_info.as_array()) {
infrast::CustomRoomConfig room_config;
room_config.skip = room_info.get("skip", false);
room_config.autofill = room_info.get("autofill", false);
room_config.sort = room_info.get("sort", false);
static std::unordered_map<std::string, infrast::CustomRoomConfig::Product> ProductNames = {
{ "Battle Record", infrast::CustomRoomConfig::Product::BattleRecord },
{ "Pure Gold", infrast::CustomRoomConfig::Product::PureGold },
{ "Dualchip", infrast::CustomRoomConfig::Product::Dualchip },
{ "Originium Shard", infrast::CustomRoomConfig::Product::OriginiumShard },
{ "LMD", infrast::CustomRoomConfig::Product::LMD },
{ "Orundum", infrast::CustomRoomConfig::Product::Orundum },
};
std::string product = room_info.get("product", std::string());
if (!product.empty()) {
if (auto iter = ProductNames.find(product); iter != ProductNames.cend()) {
room_config.product = iter->second;
}
else {
Log.error("Unknown product", product);
return false;
}
}
if (auto opers_opt = room_info.find<json::array>("operators")) {
for (const auto& oper_name : opers_opt.value()) {
std::string name = oper_name.as_string();
if (name.empty()) {
Log.warn("operators.name is empty");
continue;
}
room_config.names.emplace_back(std::move(name));
}
}
if (auto candidates_opt = room_info.find<json::array>("candidates")) {
for (const auto& candidate_name : candidates_opt.value()) {
std::string name = candidate_name.as_string();
if (name.empty()) {
Log.warn("operators.candidates is empty");
continue;
}
room_config.candidates.emplace_back(std::move(name));
}
}
facility_config.emplace_back(std::move(room_config));
}
if (facility == "control") {
m_control_task_ptr->set_custom_config(facility_config);
}
else if (facility == "manufacture") {
m_mfg_task_ptr->set_custom_config(facility_config);
}
else if (facility == "trading") {
m_trade_task_ptr->set_custom_config(facility_config);
}
else if (facility == "power") {
m_power_task_ptr->set_custom_config(facility_config);
}
else if (facility == "meeting") {
m_reception_task_ptr->set_custom_config(facility_config);
}
else if (facility == "hire") {
m_office_task_ptr->set_custom_config(facility_config);
}
else if (facility == "dormitory") {
m_dorm_task_ptr->set_custom_config(facility_config);
}
else {
Log.error(__FUNCTION__, "unknown facility", facility);
return false;
}
}
bool Fia_is_pre = false;
do {
auto Fia_opt = cur_plan.find<json::object>("Fiammetta");
if (!Fia_opt) {
break;
}
const auto& Fia_json = Fia_opt.value();
bool enable = Fia_json.get("enable", true);
if (!enable) {
break;
}
std::string target = Fia_json.get("target", std::string());
if (target.empty()) {
Log.warn("Fiammetta's target is unsetted or empty");
break;
}
Log.trace("Fiammetta's target:", target);
static const std::string FiaName = "菲亚梅塔";
// 如果肥鸭在换班前就在宿舍的第二个位置,直接换并不会让她的技能生效(位置没变,还在第二个位置)
// 所以强制给他换个顺序
infrast::CustomFacilityConfig pre_facility_config(1);
auto& pre_room_config = pre_facility_config.front();
pre_room_config.names = { target };
auto pre_task_ptr = std::make_shared<InfrastDormTask>(m_callback, m_callback_arg, TaskType);
pre_task_ptr->set_custom_config(std::move(pre_facility_config));
infrast::CustomFacilityConfig facility_config(1);
auto& room_config = facility_config.front();
room_config.names = { target, FiaName };
room_config.sort = true;
auto Fia_task_ptr = std::make_shared<InfrastDormTask>(m_callback, m_callback_arg, TaskType);
Fia_task_ptr->set_custom_config(std::move(facility_config));
if (Fia_json.get("order", "pre") != "post") {
m_subtasks.insert(m_subtasks.begin(), { m_infrast_begin_task_ptr, pre_task_ptr, Fia_task_ptr });
Fia_is_pre = true;
}
else {
m_subtasks.insert(m_subtasks.end(), { pre_task_ptr, Fia_task_ptr, m_infrast_begin_task_ptr });
}
} while (false);
do {
auto drones_opt = cur_plan.find<json::object>("drones");
if (!drones_opt) {
break;
}
const auto& drones_json = drones_opt.value();
bool enable = drones_json.get("enable", true);
if (!enable) {
break;
}
infrast::CustomDronesConfig drones_config;
drones_config.index = drones_json.get("index", 1) - 1;
drones_config.order = drones_json.get("order", "pre") == "post" ? infrast::CustomDronesConfig::Order::Post
: infrast::CustomDronesConfig::Order::Pre;
bool additional_advance_drones = Fia_is_pre && drones_config.order == infrast::CustomDronesConfig::Order::Pre;
std::string room = drones_json.get("room", std::string());
if (room.empty()) {
Log.warn("drones room is unsetted or empty");
break;
}
else if (room != "trading" && room != "manufacture") {
Log.error("error drones config, unknown room", room);
return false;
}
// 无人机和肥鸭同时为true时优先使用无人机
if (additional_advance_drones) {
std::shared_ptr<InfrastProductionTask> drones_only_task_ptr = nullptr;
if (room == "trading") {
drones_only_task_ptr = std::make_shared<InfrastTradeTask>(m_callback, m_callback_arg, TaskType);
}
else if (room == "manufacture") {
drones_only_task_ptr = std::make_shared<InfrastMfgTask>(m_callback, m_callback_arg, TaskType);
}
drones_only_task_ptr->set_custom_config(
infrast::CustomFacilityConfig(drones_config.index + 1, infrast::CustomRoomConfig { .skip = true }));
drones_only_task_ptr->set_custom_drones_config(std::move(drones_config));
m_subtasks.insert(m_subtasks.begin(), { m_infrast_begin_task_ptr, drones_only_task_ptr });
}
else {
if (room == "trading") {
m_trade_task_ptr->set_custom_drones_config(std::move(drones_config));
}
else if (room == "manufacture") {
m_mfg_task_ptr->set_custom_drones_config(std::move(drones_config));
}
}
} while (false);
return true;
}