From a5523a83c7dbcc6a49ae99dcf4ebe9592b88f84d Mon Sep 17 00:00:00 2001 From: MistEO Date: Thu, 12 Jan 2023 22:50:42 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E5=B9=B2?= =?UTF-8?q?=E5=91=98=E5=A4=B4=E5=83=8F=E7=BC=93=E5=AD=98=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Miscellaneous/AvatarCacheManager.cpp | 69 +++++++++++++++++ .../Config/Miscellaneous/AvatarCacheManager.h | 34 +++++++++ .../Config/Miscellaneous/BattleDataConfig.h | 5 ++ src/MaaCore/Config/ResourceLoader.cpp | 13 ++++ src/MaaCore/MaaCore.vcxproj | 2 + src/MaaCore/MaaCore.vcxproj.filters | 6 ++ src/MaaCore/Task/BattleHelper.cpp | 76 ++----------------- src/MaaCore/Task/BattleHelper.h | 8 -- .../Task/Miscellaneous/BattleProcessTask.cpp | 14 +--- .../Task/Miscellaneous/BattleProcessTask.h | 1 - .../Roguelike/RoguelikeBattleTaskPlugin.cpp | 14 ---- .../Roguelike/RoguelikeBattleTaskPlugin.h | 1 - 12 files changed, 137 insertions(+), 106 deletions(-) create mode 100644 src/MaaCore/Config/Miscellaneous/AvatarCacheManager.cpp create mode 100644 src/MaaCore/Config/Miscellaneous/AvatarCacheManager.h diff --git a/src/MaaCore/Config/Miscellaneous/AvatarCacheManager.cpp b/src/MaaCore/Config/Miscellaneous/AvatarCacheManager.cpp new file mode 100644 index 0000000000..e3cd1b707b --- /dev/null +++ b/src/MaaCore/Config/Miscellaneous/AvatarCacheManager.cpp @@ -0,0 +1,69 @@ +#include "AvatarCacheManager.h" + +#include "BattleDataConfig.h" +#include "Utils/ImageIo.hpp" +#include "Utils/Logger.hpp" + +bool asst::AvatarCacheManager::load(const std::filesystem::path& path) +{ + LogTraceFunction; + + if (!std::filesystem::exists(path)) { + return true; + } + + for (const auto& entry : std::filesystem::directory_iterator(path)) { + if (!entry.is_regular_file()) { + continue; + } + + const std::filesystem::path& filepath = entry.path(); + std::string name = utils::path_to_utf8_string(filepath.stem()); + auto role = BattleData.get_role(name); + if (role == battle::Role::Unknown) { + Log.warn("unknown oper", name); + continue; + } + Log.trace(filepath); + cv::Mat avatar = asst::imread(filepath); + if (avatar.empty()) { + Log.warn("failed to read", filepath); + continue; + } + m_avatars[role].emplace(name, std::move(avatar)); + } + + m_path = path; + return true; +} + +const asst::AvatarCacheManager::AvatarsMap& asst::AvatarCacheManager::get_avatars(battle::Role role) +{ + return m_avatars[role]; +} + +void asst::AvatarCacheManager::set_avatar(const std::string& name, battle::Role role, const cv::Mat& avatar, + bool overlay) +{ + LogTraceFunction; + Log.info(__FUNCTION__, name, ", overlay:", overlay); + + if (overlay) { + m_avatars[role].insert_or_assign(name, avatar); + } + else { + m_avatars[role].try_emplace(name, avatar); + return; + } + + if (BattleData.is_name_invalid(name)) { + Log.error("invalid name", name); + return; + } + + std::filesystem::create_directories(m_path); + auto path = m_path / utils::path(name + CacheExtension); + Log.info(path); + + asst::imwrite(path, avatar); +} diff --git a/src/MaaCore/Config/Miscellaneous/AvatarCacheManager.h b/src/MaaCore/Config/Miscellaneous/AvatarCacheManager.h new file mode 100644 index 0000000000..d55bb8035f --- /dev/null +++ b/src/MaaCore/Config/Miscellaneous/AvatarCacheManager.h @@ -0,0 +1,34 @@ +#pragma once + +#pragma once +#include "Config/AbstractResource.h" + +#include + +#include "Utils/NoWarningCVMat.h" + +#include "Common/AsstBattleDef.h" +#include "Common/AsstTypes.h" + +namespace asst +{ + class AvatarCacheManager final : public SingletonHolder, public AbstractResource + { + public: + using AvatarsMap = std::unordered_map; + inline static const std::string CacheExtension = ".png"; + + public: + virtual ~AvatarCacheManager() override = default; + + virtual bool load(const std::filesystem::path& path) override; + + const AvatarsMap& get_avatars(battle::Role role); + void set_avatar(const std::string& name, battle::Role role, const cv::Mat& avatar, bool overlay = true); + + private: + std::unordered_map> m_avatars; + std::filesystem::path m_path; + }; + inline static auto& AvatarCache = AvatarCacheManager::get_instance(); +} diff --git a/src/MaaCore/Config/Miscellaneous/BattleDataConfig.h b/src/MaaCore/Config/Miscellaneous/BattleDataConfig.h index 30bece6647..30290e6f3c 100644 --- a/src/MaaCore/Config/Miscellaneous/BattleDataConfig.h +++ b/src/MaaCore/Config/Miscellaneous/BattleDataConfig.h @@ -74,6 +74,11 @@ namespace asst return char_iter->second.tokens; } + bool is_name_invalid(const std::string& name) const + { + return name.empty() || m_chars.find(name) == m_chars.cend(); + } + protected: virtual bool parse(const json::value& json) override; diff --git a/src/MaaCore/Config/ResourceLoader.cpp b/src/MaaCore/Config/ResourceLoader.cpp index 5406c33596..0ce54188ff 100644 --- a/src/MaaCore/Config/ResourceLoader.cpp +++ b/src/MaaCore/Config/ResourceLoader.cpp @@ -4,6 +4,7 @@ #include #include "GeneralConfig.h" +#include "Miscellaneous/AvatarCacheManager.h" #include "Miscellaneous/BattleDataConfig.h" #include "Miscellaneous/CopilotConfig.h" #include "Miscellaneous/InfrastConfig.h" @@ -44,6 +45,13 @@ bool asst::ResourceLoader::load(const std::filesystem::path& path) } \ } +#define LoadCacheWithoutRet(Config, Dir) \ + { \ + LogTraceScope(std::string("LoadCacheWithoutRet ") + #Config); \ + auto full_path = UserDir.get() / "cache"_p / Dir; \ + load_resource(full_path); \ + } + LogTraceFunction; using namespace asst::utils::path_literals; @@ -61,6 +69,10 @@ bool asst::ResourceLoader::load(const std::filesystem::path& path) LoadResourceWithTemplAndCheckRet(TaskData, "tasks.json"_p, "template"_p); LoadResourceWithTemplAndCheckRet(InfrastConfig, "infrast.json"_p, "template"_p / "infrast"_p); LoadResourceWithTemplAndCheckRet(ItemConfig, "item_index.json"_p, "template"_p / "items"_p); + + /* load cache */ + LoadCacheWithoutRet(AvatarCacheManager, "avatars"_p); + return true; }); @@ -79,6 +91,7 @@ bool asst::ResourceLoader::load(const std::filesystem::path& path) #undef LoadTemplByConfigAndCheckRet #undef LoadResourceAndCheckRet +#undef LoadCacheWithoutRet m_loaded = true; m_loaded &= config_future.get(); diff --git a/src/MaaCore/MaaCore.vcxproj b/src/MaaCore/MaaCore.vcxproj index f093c27b0f..c9e0db6b3e 100644 --- a/src/MaaCore/MaaCore.vcxproj +++ b/src/MaaCore/MaaCore.vcxproj @@ -28,6 +28,7 @@ + @@ -149,6 +150,7 @@ + diff --git a/src/MaaCore/MaaCore.vcxproj.filters b/src/MaaCore/MaaCore.vcxproj.filters index 005985b86d..fb35470177 100644 --- a/src/MaaCore/MaaCore.vcxproj.filters +++ b/src/MaaCore/MaaCore.vcxproj.filters @@ -471,6 +471,9 @@ 源文件\Task\Miscellaneous + + 源文件\Config\Miscellaneous + @@ -773,5 +776,8 @@ 源文件\Task\Miscellaneous + + 源文件\Config\Miscellaneous + \ No newline at end of file diff --git a/src/MaaCore/Task/BattleHelper.cpp b/src/MaaCore/Task/BattleHelper.cpp index 261de79299..d724746eaf 100644 --- a/src/MaaCore/Task/BattleHelper.cpp +++ b/src/MaaCore/Task/BattleHelper.cpp @@ -3,6 +3,7 @@ #include #include +#include "Config/Miscellaneous/AvatarCacheManager.h" #include "Config/Miscellaneous/BattleDataConfig.h" #include "Config/TaskData.h" #include "Controller.h" @@ -40,7 +41,6 @@ void asst::BattleHelper::clear() m_in_battle = false; m_kills = 0; m_total_kills = 0; - m_all_deployment_avatars.clear(); m_cur_deployment_opers.clear(); m_battlefield_opers.clear(); m_used_tiles.clear(); @@ -60,55 +60,6 @@ bool asst::BattleHelper::calc_tiles_info(const std::string& stage_name, double s return true; } -bool asst::BattleHelper::load_avatar_cache(const std::string& name, bool with_token) -{ - LogTraceFunction; - - if (name.empty()) { - return false; - } - auto path = avatar_cache_dir() / utils::path(name + CacheExtension); - Log.info(path); - - if (!std::filesystem::exists(path)) { - Log.info(path, "not exists"); - return false; - } - cv::Mat avatar = asst::imread(path); - if (avatar.empty()) { - Log.info(path, "image is empty"); - return false; - } - m_all_deployment_avatars.emplace(name, std::move(avatar)); - Log.info(path, "loaded"); - - if (with_token) { - if (auto tokens = BattleData.get_tokens(name); !tokens.empty()) { - for (const std::string& token_name : tokens) { - load_avatar_cache(token_name); - } - } - } - - return true; -} - -void asst::BattleHelper::save_avatar_cache(const std::string& name, const cv::Mat& avatar) -{ - LogTraceFunction; - - if (BattleData.get_rarity(name) == 0) { - Log.error("wrong oper name", name); - return; - } - - auto path = avatar_cache_dir() / utils::path(name + CacheExtension); - Log.info(path); - - std::filesystem::create_directories(avatar_cache_dir()); - asst::imwrite(path, avatar); -} - bool asst::BattleHelper::pause() { LogTraceFunction; @@ -181,7 +132,8 @@ bool asst::BattleHelper::update_deployment(bool init, const cv::Mat& reusable) } double max_socre = 0; - for (const auto& [name, avatar] : m_all_deployment_avatars) { + auto& avatar_cache = AvatarCache.get_avatars(oper.role); + for (const auto& [name, avatar] : avatar_cache) { avatar_analyzer.set_templ(avatar); if (!avatar_analyzer.analyze()) { continue; @@ -239,14 +191,14 @@ bool asst::BattleHelper::update_deployment(bool init, const cv::Mat& reusable) OcrWithPreprocessImageAnalyzer preproc_analyzer; std::string name = analyze(preproc_analyzer); - if (name.empty() || is_name_invalid(name)) { + if (BattleData.is_name_invalid(name)) { Log.warn("ocr with preprocess got a invalid name, try to use detect model", name); OcrImageAnalyzer det_analyzer; std::string det_name = analyze(det_analyzer); if (det_name.empty()) { Log.warn("ocr with det model failed"); } - else if (name.empty() || !is_name_invalid(det_name)) { + else if (BattleData.is_name_invalid(det_name)) { Log.info("use ocr with det", det_name); name = det_name; } @@ -266,12 +218,11 @@ bool asst::BattleHelper::update_deployment(bool init, const cv::Mat& reusable) // 而且由于 cd 干员头像阈值设置的非常低,为了防止把正确的干员覆盖掉了 // 所以不进行覆盖 m_cur_deployment_opers.emplace(name, oper); - m_all_deployment_avatars.emplace(name, oper.avatar); + AvatarCache.set_avatar(name, oper.role, oper.avatar, false); } else { m_cur_deployment_opers.insert_or_assign(name, oper); - m_all_deployment_avatars.insert_or_assign(name, oper.avatar); - save_avatar_cache(name, oper.avatar); + AvatarCache.set_avatar(name, oper.role, oper.avatar); } } @@ -641,11 +592,6 @@ bool asst::BattleHelper::move_camera(const std::pair& move_loc) return true; } -bool asst::BattleHelper::is_name_invalid(const std::string& name) -{ - return BattleData.get_rarity(name) <= 0; -} - std::optional asst::BattleHelper::get_oper_rect_on_deployment(const std::string& name) const { LogTraceFunction; @@ -658,11 +604,3 @@ std::optional asst::BattleHelper::get_oper_rect_on_deployment(const return oper_iter->second.rect; } - -const std::filesystem::path& asst::BattleHelper::avatar_cache_dir() -{ - using namespace asst::utils::path_literals; - - static const auto dir = UserDir.get() / "cache"_p / "avatars"_p; - return dir; -} diff --git a/src/MaaCore/Task/BattleHelper.h b/src/MaaCore/Task/BattleHelper.h index 65facf14fb..314a749461 100644 --- a/src/MaaCore/Task/BattleHelper.h +++ b/src/MaaCore/Task/BattleHelper.h @@ -16,8 +16,6 @@ namespace asst { class BattleHelper { - inline static const std::string CacheExtension = ".png"; - public: ~BattleHelper() = default; @@ -32,8 +30,6 @@ namespace asst virtual bool do_strategic_action(const cv::Mat& reusable = cv::Mat()); bool calc_tiles_info(const std::string& stage_name, double shift_x = 0, double shift_y = 0); - bool load_avatar_cache(const std::string& name, bool with_token = false); - void save_avatar_cache(const std::string& name, const cv::Mat& avatar); bool pause(); bool speed_up(); @@ -65,7 +61,6 @@ namespace asst bool cancel_oper_selection(); bool move_camera(const std::pair& move_loc); - bool is_name_invalid(const std::string& name); std::optional get_oper_rect_on_deployment(const std::string& name) const; std::string m_stage_name; @@ -80,15 +75,12 @@ namespace asst int m_total_kills = 0; int m_cost = 0; - std::map m_all_deployment_avatars; std::map m_cur_deployment_opers; std::map m_battlefield_opers; std::map m_used_tiles; private: - static const std::filesystem::path& avatar_cache_dir(); - InstHelper m_inst_helper; }; } // namespace asst diff --git a/src/MaaCore/Task/Miscellaneous/BattleProcessTask.cpp b/src/MaaCore/Task/Miscellaneous/BattleProcessTask.cpp index eac71b8db1..4efcc92f32 100644 --- a/src/MaaCore/Task/Miscellaneous/BattleProcessTask.cpp +++ b/src/MaaCore/Task/Miscellaneous/BattleProcessTask.cpp @@ -27,6 +27,7 @@ using namespace asst::battle::copilot; asst::BattleProcessTask::BattleProcessTask(const AsstCallback& callback, Assistant* inst, std::string_view task_chain) : AbstractTask(callback, inst, task_chain), BattleHelper(inst) {} + bool asst::BattleProcessTask::_run() { LogTraceFunction; @@ -37,7 +38,6 @@ bool asst::BattleProcessTask::_run() return false; } - load_cache(); update_deployment(true); to_group(); @@ -78,18 +78,6 @@ bool asst::BattleProcessTask::set_stage_name(const std::string& stage_name) return true; } -void asst::BattleProcessTask::load_cache() -{ - LogTraceFunction; - - for (const auto& oper_list : get_combat_data().groups | views::values) { - for (const auto& oper : oper_list) { - load_avatar_cache(oper.name, true); - } - } - // TODO: 识别编队,额外加载编队中有的干员的缓存 -} - bool asst::BattleProcessTask::to_group() { std::unordered_map> groups; diff --git a/src/MaaCore/Task/Miscellaneous/BattleProcessTask.h b/src/MaaCore/Task/Miscellaneous/BattleProcessTask.h index f54cd82464..7f0c89a9f1 100644 --- a/src/MaaCore/Task/Miscellaneous/BattleProcessTask.h +++ b/src/MaaCore/Task/Miscellaneous/BattleProcessTask.h @@ -26,7 +26,6 @@ namespace asst virtual battle::copilot::CombatData& get_combat_data() { return m_combat_data; } virtual bool need_to_wait_until_end() const { return false; } - void load_cache(); bool to_group(); bool do_action(size_t action_index); diff --git a/src/MaaCore/Task/Roguelike/RoguelikeBattleTaskPlugin.cpp b/src/MaaCore/Task/Roguelike/RoguelikeBattleTaskPlugin.cpp index 7ba6f6e5cd..5e0d72e4ef 100644 --- a/src/MaaCore/Task/Roguelike/RoguelikeBattleTaskPlugin.cpp +++ b/src/MaaCore/Task/Roguelike/RoguelikeBattleTaskPlugin.cpp @@ -61,7 +61,6 @@ bool asst::RoguelikeBattleTaskPlugin::_run() if (!calc_stage_info()) { return false; } - load_cache(); update_deployment(true); speed_up(); @@ -210,19 +209,6 @@ bool asst::RoguelikeBattleTaskPlugin::calc_stage_info() return true; } -void asst::RoguelikeBattleTaskPlugin::load_cache() -{ - if (auto overview = status()->get_str(Status::RoguelikeCharOverview)) { - json::value json = json::parse(*overview).value_or(json::value()); - for (const auto& name : json.as_object() | views::keys) { - load_avatar_cache(name, true); - } - } - for (const std::string& dice : DiceSet) { - load_avatar_cache(dice); - } -} - asst::battle::LocationType asst::RoguelikeBattleTaskPlugin::get_oper_location_type( const battle::DeploymentOper& oper) const { diff --git a/src/MaaCore/Task/Roguelike/RoguelikeBattleTaskPlugin.h b/src/MaaCore/Task/Roguelike/RoguelikeBattleTaskPlugin.h index 0e8bf112e5..7138ea3c02 100644 --- a/src/MaaCore/Task/Roguelike/RoguelikeBattleTaskPlugin.h +++ b/src/MaaCore/Task/Roguelike/RoguelikeBattleTaskPlugin.h @@ -31,7 +31,6 @@ namespace asst bool do_once(); bool calc_stage_info(); - void load_cache(); void all_melee_retreat();