diff --git a/3rdparty/include/calculator/calculator.hpp b/3rdparty/include/calculator/calculator.hpp new file mode 100644 index 0000000000..ceb405f8c5 --- /dev/null +++ b/3rdparty/include/calculator/calculator.hpp @@ -0,0 +1,462 @@ +/// +/// @file calculator.hpp +/// @brief calculator::eval(const std::string&) evaluates an integer +/// arithmetic expression and returns the result. If an error +/// occurs a calculator::error exception is thrown. +/// +/// @author Kim Walisch, +/// @copyright Copyright (C) 2013-2018 Kim Walisch +/// @license BSD 2-Clause, https://opensource.org/licenses/BSD-2-Clause +/// @version 1.4 +/// +/// == Supported operators == +/// +/// OPERATOR NAME ASSOCIATIVITY PRECEDENCE +/// +/// | Bitwise Inclusive OR Left 4 +/// ^ Bitwise Exclusive OR Left 5 +/// & Bitwise AND Left 6 +/// << Shift Left Left 9 +/// >> Shift Right Left 9 +/// + Addition Left 10 +/// - Subtraction Left 10 +/// * Multiplication Left 20 +/// / Division Left 20 +/// % Modulo Left 20 +/// ** Raise to power Right 30 +/// e, E Scientific notation Right 40 +/// ~ Unary complement Left 99 +/// +/// The operator precedence has been set according to (uses the C and +/// C++ operator precedence): https://en.wikipedia.org/wiki/Order_of_operations +/// Operators with higher precedence are evaluated before operators +/// with relatively lower precedence. Unary operators are set to have +/// the highest precedence, this is not strictly correct for the power +/// operator e.g. "-3**2" = 9 but a lot of software tools (Bash shell, +/// Microsoft Excel, GNU bc, ...) use the same convention. +/// +/// == Examples of valid expressions == +/// +/// "65536 >> 15" = 2 +/// "2**16" = 65536 +/// "(0 + 0xDf234 - 1000)*3/2%999" = 828 +/// "-(2**2**2**2)" = -65536 +/// "(0 + ~(0xDF234 & 1000) *3) /-2" = 817 +/// "(2**16) + (1 << 16) >> 0X5" = 4096 +/// "5*-(2**(9+7))/3+5*(1 & 0xFf123)" = -109221 +/// +/// == About the algorithm used == +/// +/// calculator::eval(std::string&) relies on the ExpressionParser +/// class which is a simple C++ operator precedence parser with infix +/// notation for integer arithmetic expressions. +/// ExpressionParser has its roots in a JavaScript parser published +/// at: http://stackoverflow.com/questions/28256/equation-expression-parser-with-precedence/114961#114961 +/// The same author has also published an article about his operator +/// precedence algorithm at PerlMonks: +/// http://www.perlmonks.org/?node_id=554516 +/// + +#ifndef CALCULATOR_HPP +#define CALCULATOR_HPP + +#include +#include +#include +#include +#include +#include + +namespace calculator +{ + +/// calculator::eval() throws a calculator::error if it fails +/// to evaluate the expression string. +/// +class error : public std::runtime_error +{ +public: + error(const std::string& expr, const std::string& message) + : std::runtime_error(message), + expr_(expr) + { } +#if __cplusplus < 201103L + ~error() throw() { } +#endif + std::string expression() const + { + return expr_; + } +private: + std::string expr_; +}; + +template +class ExpressionParser +{ +public: + /// Evaluate an integer arithmetic expression and return its result. + /// @throw error if parsing fails. + /// + T eval(const std::string& expr) + { + T result = 0; + index_ = 0; + expr_ = expr; + try + { + result = parseExpr(); + if (!isEnd()) + unexpected(); + } + catch (const calculator::error&) + { + while(!stack_.empty()) + stack_.pop(); + throw; + } + return result; + } + + /// Get the integer value of a character. + T eval(char c) + { + std::string expr(1, c); + return eval(expr); + } + +private: + enum + { + OPERATOR_NULL, + OPERATOR_BITWISE_OR, /// | + OPERATOR_BITWISE_XOR, /// ^ + OPERATOR_BITWISE_AND, /// & + OPERATOR_BITWISE_SHL, /// << + OPERATOR_BITWISE_SHR, /// >> + OPERATOR_ADDITION, /// + + OPERATOR_SUBTRACTION, /// - + OPERATOR_MULTIPLICATION, /// * + OPERATOR_DIVISION, /// / + OPERATOR_MODULO, /// % + OPERATOR_POWER, /// ** + OPERATOR_EXPONENT /// e, E + }; + + struct Operator + { + /// Operator, one of the OPERATOR_* enum definitions + int op; + int precedence; + /// 'L' = left or 'R' = right + int associativity; + Operator(int opr, int prec, int assoc) : + op(opr), + precedence(prec), + associativity(assoc) + { } + }; + + struct OperatorValue + { + Operator op; + T value; + OperatorValue(const Operator& opr, T val) : + op(opr), + value(val) + { } + int getPrecedence() const + { + return op.precedence; + } + bool isNull() const + { + return op.op == OPERATOR_NULL; + } + }; + + /// Expression string + std::string expr_; + /// Current expression index, incremented whilst parsing + std::size_t index_; + /// The current operator and its left value + /// are pushed onto the stack if the operator on + /// top of the stack has lower precedence. + std::stack stack_; + + /// Exponentiation by squaring, x^n. + static T pow(T x, T n) + { + T res = 1; + + while (n > 0) + { + if (n % 2 != 0) + { + res *= x; + n -= 1; + } + n /= 2; + + if (n > 0) + x *= x; + } + + return res; + } + + + T checkZero(T value) const + { + if (value == 0) + { + std::string divOperators("/%"); + std::size_t division = expr_.find_last_of(divOperators, index_ - 2); + std::ostringstream msg; + msg << "Parser error: division by 0"; + if (division != std::string::npos) + msg << " (error token is \"" + << expr_.substr(division, expr_.size() - division) + << "\")"; + throw calculator::error(expr_, msg.str()); + } + return value; + } + + T calculate(T v1, T v2, const Operator& op) const + { + switch (op.op) + { + case OPERATOR_BITWISE_OR: return v1 | v2; + case OPERATOR_BITWISE_XOR: return v1 ^ v2; + case OPERATOR_BITWISE_AND: return v1 & v2; + case OPERATOR_BITWISE_SHL: return v1 << v2; + case OPERATOR_BITWISE_SHR: return v1 >> v2; + case OPERATOR_ADDITION: return v1 + v2; + case OPERATOR_SUBTRACTION: return v1 - v2; + case OPERATOR_MULTIPLICATION: return v1 * v2; + case OPERATOR_DIVISION: return v1 / checkZero(v2); + case OPERATOR_MODULO: return v1 % checkZero(v2); + case OPERATOR_POWER: return pow(v1, v2); + case OPERATOR_EXPONENT: return v1 * pow(10, v2); + default: return 0; + } + } + + bool isEnd() const + { + return index_ >= expr_.size(); + } + + /// Returns the character at the current expression index or + /// 0 if the end of the expression is reached. + /// + char getCharacter() const + { + if (!isEnd()) + return expr_[index_]; + return 0; + } + + /// Parse str at the current expression index. + /// @throw error if parsing fails. + /// + void expect(const std::string& str) + { + if (expr_.compare(index_, str.size(), str) != 0) + unexpected(); + index_ += str.size(); + } + + void unexpected() const + { + std::ostringstream msg; + msg << "Syntax error: unexpected token \"" + << expr_.substr(index_, expr_.size() - index_) + << "\" at index " + << index_; + throw calculator::error(expr_, msg.str()); + } + + /// Eat all white space characters at the + /// current expression index. + /// + void eatSpaces() + { + while (std::isspace(getCharacter()) != 0) + index_++; + } + + /// Parse a binary operator at the current expression index. + /// @return Operator with precedence and associativity. + /// + Operator parseOp() + { + eatSpaces(); + switch (getCharacter()) + { + case '|': index_++; return Operator(OPERATOR_BITWISE_OR, 4, 'L'); + case '^': index_++; return Operator(OPERATOR_BITWISE_XOR, 5, 'L'); + case '&': index_++; return Operator(OPERATOR_BITWISE_AND, 6, 'L'); + case '<': expect("<<"); return Operator(OPERATOR_BITWISE_SHL, 9, 'L'); + case '>': expect(">>"); return Operator(OPERATOR_BITWISE_SHR, 9, 'L'); + case '+': index_++; return Operator(OPERATOR_ADDITION, 10, 'L'); + case '-': index_++; return Operator(OPERATOR_SUBTRACTION, 10, 'L'); + case '/': index_++; return Operator(OPERATOR_DIVISION, 20, 'L'); + case '%': index_++; return Operator(OPERATOR_MODULO, 20, 'L'); + case '*': index_++; if (getCharacter() != '*') + return Operator(OPERATOR_MULTIPLICATION, 20, 'L'); + index_++; return Operator(OPERATOR_POWER, 30, 'R'); + case 'e': index_++; return Operator(OPERATOR_EXPONENT, 40, 'R'); + case 'E': index_++; return Operator(OPERATOR_EXPONENT, 40, 'R'); + default : return Operator(OPERATOR_NULL, 0, 'L'); + } + } + + static T toInteger(char c) + { + if (c >= '0' && c <= '9') return c -'0'; + if (c >= 'a' && c <= 'f') return c -'a' + 0xa; + if (c >= 'A' && c <= 'F') return c -'A' + 0xa; + T noDigit = 0xf + 1; + return noDigit; + } + + T getInteger() const + { + return toInteger(getCharacter()); + } + + T parseDecimal() + { + T value = 0; + for (T d; (d = getInteger()) <= 9; index_++) + value = value * 10 + d; + return value; + } + + T parseHex() + { + index_ = index_ + 2; + T value = 0; + for (T h; (h = getInteger()) <= 0xf; index_++) + value = value * 0x10 + h; + return value; + } + + bool isHex() const + { + if (index_ + 2 < expr_.size()) + { + char x = expr_[index_ + 1]; + char h = expr_[index_ + 2]; + return (std::tolower(x) == 'x' && toInteger(h) <= 0xf); + } + return false; + } + + /// Parse an integer value at the current expression index. + /// The unary `+', `-' and `~' operators and opening + /// parentheses `(' cause recursion. + /// + T parseValue() + { + T val = 0; + eatSpaces(); + switch (getCharacter()) + { + case '0': if (isHex()) + val = parseHex(); + else + val = parseDecimal(); + break; + case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + val = parseDecimal(); + break; + case '(': index_++; + val = parseExpr(); + eatSpaces(); + if (getCharacter() != ')') + { + if (!isEnd()) + unexpected(); + throw calculator::error(expr_, "Syntax error: `)' expected at end of expression"); + } + index_++; break; + case '~': index_++; val = ~parseValue(); break; + case '+': index_++; val = parseValue(); break; + case '-': index_++; val = parseValue() * static_cast(-1); + break; + default : if (!isEnd()) + unexpected(); + throw calculator::error(expr_, "Syntax error: value expected at end of expression"); + } + return val; + } + + /// Parse all operations of the current parenthesis + /// level and the levels above, when done + /// return the result (value). + /// + T parseExpr() + { + stack_.push(OperatorValue(Operator(OPERATOR_NULL, 0, 'L'), 0)); + // first parse value on the left + T value = parseValue(); + + while (!stack_.empty()) + { + // parse an operator (+, -, *, ...) + Operator op(parseOp()); + while (op.precedence < stack_.top().getPrecedence() || ( + op.precedence == stack_.top().getPrecedence() && + op.associativity == 'L')) + { + // end reached + if (stack_.top().isNull()) + { + stack_.pop(); + return value; + } + // do the calculation ("reduce"), producing a new value + value = calculate(stack_.top().value, value, stack_.top().op); + stack_.pop(); + } + + // store on stack_ and continue parsing ("shift") + stack_.push(OperatorValue(op, value)); + // parse value on the right + value = parseValue(); + } + return 0; + } +}; + +template +inline T eval(const std::string& expression) +{ + ExpressionParser parser; + return parser.eval(expression); +} + +template +inline T eval(char c) +{ + ExpressionParser parser; + return parser.eval(c); +} + +inline int eval(const std::string& expression) +{ + return eval(expression); +} + +inline int eval(char c) +{ + return eval(c); +} + +} // namespace calculator + +#endif diff --git a/resource/template/Reception.png b/resource/template/Reception.png index c16f98beda..f98f8d9d59 100644 Binary files a/resource/template/Reception.png and b/resource/template/Reception.png differ diff --git a/resource/template/ReceptionMini.png b/resource/template/ReceptionMini.png index 9ae90b86a9..fdb66a005e 100644 Binary files a/resource/template/ReceptionMini.png and b/resource/template/ReceptionMini.png differ diff --git a/src/MeoAssistance/Assistance.cpp b/src/MeoAssistance/Assistance.cpp index 60e38ccab5..2af1e1633b 100644 --- a/src/MeoAssistance/Assistance.cpp +++ b/src/MeoAssistance/Assistance.cpp @@ -20,6 +20,7 @@ #include "InfrastTradeTask.h" #include "InfrastPowerTask.h" #include "InfrastOfficeTask.h" +#include "InfrastInfoTask.h" using namespace asst; @@ -227,7 +228,7 @@ bool Assistance::start_debug_task() { constexpr static const char* DebugTaskChain = "Debug"; - auto shift_task_ptr = std::make_shared(task_callback, (void*)this); + auto shift_task_ptr = std::make_shared(task_callback, (void*)this); //shift_task_ptr->set_facility("Mfg"); //shift_task_ptr->set_product("CombatRecord"); shift_task_ptr->set_task_chain(DebugTaskChain); @@ -274,6 +275,9 @@ bool asst::Assistance::start_infrast_shift(const std::vector& order // 这个流程任务,结束的时候是处于基建主界面的。既可以用于进入基建,也可以用于从设施里返回基建主界面 append_match_task(InfrastTaskCahin, { "InfrastBegin" }); + auto info_task_ptr = std::make_shared(task_callback, (void*)this); + m_tasks_deque.emplace_back(info_task_ptr); + // 因为后期要考虑多任务间的联动等,所以这些任务的声明暂时不妨到for循环中 auto dorm_task_ptr = std::make_shared(task_callback, (void*)this); dorm_task_ptr->set_task_chain(InfrastTaskCahin); diff --git a/src/MeoAssistance/AsstDef.h b/src/MeoAssistance/AsstDef.h index ae2654642f..8da22eb7d4 100644 --- a/src/MeoAssistance/AsstDef.h +++ b/src/MeoAssistance/AsstDef.h @@ -293,7 +293,7 @@ namespace asst efficient[key] += value; } for (const auto& [key, reg] : s.efficient_regex) { - efficient_regex[key] += " + " + reg; + efficient_regex[key] += "+(" + reg + ")"; } } } diff --git a/src/MeoAssistance/InfrastAbstractTask.cpp b/src/MeoAssistance/InfrastAbstractTask.cpp index ad238e44b7..625431cf70 100644 --- a/src/MeoAssistance/InfrastAbstractTask.cpp +++ b/src/MeoAssistance/InfrastAbstractTask.cpp @@ -11,7 +11,7 @@ bool asst::InfrastAbstractTask::enter_facility(const std::string& facility, int const auto& image = ctrler.get_image(); InfrastFacilityImageAnalyzer analyzer(image); - analyzer.set_facilities({ facility }); + analyzer.set_to_be_analyzed({ facility }); if (!analyzer.analyze()) { return false; } diff --git a/src/MeoAssistance/InfrastConfiger.h b/src/MeoAssistance/InfrastConfiger.h index 1ca7cf22be..e226437453 100644 --- a/src/MeoAssistance/InfrastConfiger.h +++ b/src/MeoAssistance/InfrastConfiger.h @@ -26,6 +26,9 @@ namespace asst { const InfrastFacilityInfo& get_facility_info(const std::string& facility) const { return m_facilities_info.at(facility); } + const std::unordered_map& get_facility_info() const noexcept { + return m_facilities_info; + } protected: virtual bool parse(const json::value& json) override; diff --git a/src/MeoAssistance/InfrastFacilityImageAnalyzer.cpp b/src/MeoAssistance/InfrastFacilityImageAnalyzer.cpp index eb9502ed6d..9b39812793 100644 --- a/src/MeoAssistance/InfrastFacilityImageAnalyzer.cpp +++ b/src/MeoAssistance/InfrastFacilityImageAnalyzer.cpp @@ -32,12 +32,13 @@ bool asst::InfrastFacilityImageAnalyzer::analyze() int cor_suffix_index = -1; - for (const std::string& key : m_facilities) { - const auto find_iter = facility_task_name.find(key); - if (find_iter == facility_task_name.cend()) { - return false; // TODO 报错 + for (const auto& [key, task_name] : facility_task_name) { + if (!m_to_be_analyzed.empty()) { // 若为空,则分析所有设施 + if (std::find(m_to_be_analyzed.cbegin(), m_to_be_analyzed.cend(), key) + == m_to_be_analyzed.cend()) { + continue; + } } - const std::string& task_name = find_iter->second; std::vector cur_facility_result; // 已知基建缩放状态的时候,只识别这个缩放状态下的就行了 // 否则识别所有状态,直到找出正确的当前缩放状态 @@ -72,6 +73,10 @@ bool asst::InfrastFacilityImageAnalyzer::analyze() } } } + if (cur_facility_result.empty()) { + continue; + } + #ifdef LOG_TRACE cv::RNG rng(time(0)); cv::Scalar rand_color(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)); @@ -85,5 +90,5 @@ bool asst::InfrastFacilityImageAnalyzer::analyze() m_result.emplace(key, std::move(cur_facility_result)); } - return true; + return !m_result.empty(); } \ No newline at end of file diff --git a/src/MeoAssistance/InfrastFacilityImageAnalyzer.h b/src/MeoAssistance/InfrastFacilityImageAnalyzer.h index 34de4f748a..7e14d4efc1 100644 --- a/src/MeoAssistance/InfrastFacilityImageAnalyzer.h +++ b/src/MeoAssistance/InfrastFacilityImageAnalyzer.h @@ -11,8 +11,9 @@ namespace asst { virtual bool analyze() override; - void set_facilities(std::vector facilities) noexcept { - m_facilities = std::move(facilities); + // 若为空,则分析所有设施 + void set_to_be_analyzed(std::vector facilities) noexcept { + m_to_be_analyzed = std::move(facilities); } int get_quantity(const std::string& name) const { @@ -38,6 +39,9 @@ namespace asst { } } } + const std::unordered_map>& get_result() const noexcept { + return m_result; + } private: // 该分析器不支持外部设置ROI virtual void set_roi(const Rect& roi) noexcept override { @@ -49,7 +53,7 @@ namespace asst { // key:设施名,value:所有这种设施的当前Rect(例如所有制造站的位置) std::unordered_map> m_result; - // 需要识别的设施名 - std::vector m_facilities; + // 需要识别的设施名,若为空,则分析所有设施 + std::vector m_to_be_analyzed; }; } diff --git a/src/MeoAssistance/InfrastInfoTask.cpp b/src/MeoAssistance/InfrastInfoTask.cpp new file mode 100644 index 0000000000..f886eb6c8d --- /dev/null +++ b/src/MeoAssistance/InfrastInfoTask.cpp @@ -0,0 +1,35 @@ +#include "InfrastInfoTask.h" + +#include "Controller.h" +#include "RuntimeStatus.h" +#include "Resource.h" +#include "InfrastFacilityImageAnalyzer.h" +#include "Logger.hpp" + +bool asst::InfrastInfoTask::run() +{ + json::value task_start_json = json::object{ + { "task_type", "InfrastInfoTask" }, + { "task_chain", m_task_chain} + }; + m_callback(AsstMsg::TaskStart, task_start_json, m_callback_arg); + + const auto& image = ctrler.get_image(); + + InfrastFacilityImageAnalyzer analyzer(image); + std::vector all_facilities; + for (auto&& [key, _value] : resource.infrast().get_facility_info()) { + all_facilities.emplace_back(key); + } + if (!analyzer.analyze()) { + return false; + } + for (auto&& [name, res] : analyzer.get_result()) { + std::string key = "NumOf" + name; + int size = static_cast(res.size()); + status.set(key, size); + log.trace("InfrastInfoTask | ", key, size); + } + + return true; +} \ No newline at end of file diff --git a/src/MeoAssistance/InfrastInfoTask.h b/src/MeoAssistance/InfrastInfoTask.h new file mode 100644 index 0000000000..a3ba4ea1da --- /dev/null +++ b/src/MeoAssistance/InfrastInfoTask.h @@ -0,0 +1,13 @@ +#pragma once +#include "InfrastAbstractTask.h" + +namespace asst { + class InfrastInfoTask : public InfrastAbstractTask + { + public: + using InfrastAbstractTask::InfrastAbstractTask; + virtual ~InfrastInfoTask() = default; + + virtual bool run() override; + }; +} \ No newline at end of file diff --git a/src/MeoAssistance/InfrastProductionTask.cpp b/src/MeoAssistance/InfrastProductionTask.cpp index 74f9b4d1c0..3b5456abef 100644 --- a/src/MeoAssistance/InfrastProductionTask.cpp +++ b/src/MeoAssistance/InfrastProductionTask.cpp @@ -2,6 +2,8 @@ #include +#include + #include "Resource.h" #include "Controller.h" #include "InfrastSkillsImageAnalyzer.h" @@ -9,6 +11,7 @@ #include "MatchImageAnalyzer.h" #include "AsstUtils.hpp" #include "Logger.hpp" +#include "RuntimeStatus.h" //bool asst::InfrastProductionTask::run() //{ @@ -125,16 +128,39 @@ size_t asst::InfrastProductionTask::opers_detect() const auto& cur_all_info = skills_analyzer.get_result(); max_num_of_opers_per_page = (std::max)(max_num_of_opers_per_page, cur_all_info.size()); - // 如果两个的hash距离过小,则认为是同一个干员,不进行插入 - for (const auto& cur : cur_all_info) { + for (const auto& cur_info : cur_all_info) { auto find_iter = std::find_if(m_all_available_opers.cbegin(), m_all_available_opers.cend(), - [&cur](const InfrastOperSkillInfo& info) -> bool { - int dist = utils::hamming(cur.hash, info.hash); + [&cur_info](const InfrastOperSkillInfo& info) -> bool { + int dist = utils::hamming(cur_info.hash, info.hash); return dist < HashDistThres; }); - if (find_iter == m_all_available_opers.cend()) { - m_all_available_opers.emplace_back(cur); + // 如果两个的hash距离过小,则认为是同一个干员,不进行插入 + if (find_iter != m_all_available_opers.cend()) { + continue; } + auto pred_info = cur_info; + // 根据正则,计算当前干员的实际效率 + for (auto&& [product, formula] : pred_info.skills_comb.efficient_regex) { + std::string cur_formula = formula; + for (size_t pos = 0; pos != std::string::npos;) { + pos = cur_formula.find('[', pos); + if (pos == std::string::npos) { + break; + } + size_t rp_pos = cur_formula.find(']', pos); + if (rp_pos == std::string::npos) { + break; + // TODO 报错! + } + std::string status_key = cur_formula.substr(pos + 1, rp_pos - pos - 1); + int status_value = std::any_cast(status.get(status_key)); + cur_formula.replace(pos, rp_pos - pos + 1, std::to_string(status_value)); + } + + int eff = calculator::eval(cur_formula); + pred_info.skills_comb.efficient[product] = eff; + } + m_all_available_opers.emplace_back(std::move(pred_info)); } return cur_all_info.size(); } @@ -148,8 +174,6 @@ bool asst::InfrastProductionTask::optimal_calc() return false; } - // TODO: 处理效率的正则,将正则的结果计算到数字的efficient中 - // 先把单个的技能按效率排个序,取效率最高的几个 std::vector optimal_opers; optimal_opers.reserve(max_num_of_opers); @@ -190,9 +214,16 @@ bool asst::InfrastProductionTask::optimal_calc() std::vector cur_opers; cur_opers.reserve(max_num_of_opers); double cur_efficient = 0; - // TODO:条件判断,不符合的直接过滤掉 - for (const auto& [cond, value] : group.conditions) { - // if xxx continue; + // 条件判断,不符合的直接过滤掉 + for (const auto& [cond, cond_value] : group.conditions) { + if (!status.exist(cond)) { + continue; + } + // TODO:这里做成除了不等于,还可计算大于、小于等不同条件的 + int cur_value = std::any_cast(status.get(cond)); + if (cur_value != cond_value) { + continue; + } } // necessary里的技能,一个都不能少 for (const InfrastSkillsComb& nec_skills : group.necessary) { diff --git a/src/MeoAssistance/MeoAssistance.vcxproj b/src/MeoAssistance/MeoAssistance.vcxproj index 2df333a06a..e191b516f3 100644 --- a/src/MeoAssistance/MeoAssistance.vcxproj +++ b/src/MeoAssistance/MeoAssistance.vcxproj @@ -28,6 +28,7 @@ + @@ -49,6 +50,7 @@ + @@ -68,6 +70,7 @@ + @@ -91,6 +94,7 @@ + diff --git a/src/MeoAssistance/MeoAssistance.vcxproj.filters b/src/MeoAssistance/MeoAssistance.vcxproj.filters index bf22bbcf05..3174df0b99 100644 --- a/src/MeoAssistance/MeoAssistance.vcxproj.filters +++ b/src/MeoAssistance/MeoAssistance.vcxproj.filters @@ -192,6 +192,12 @@ 头文件\Task + + 头文件 + + + 头文件\Task + @@ -311,6 +317,12 @@ 源文件\Task + + 源文件 + + + 源文件\Task + diff --git a/src/MeoAssistance/RuntimeStatus.cpp b/src/MeoAssistance/RuntimeStatus.cpp new file mode 100644 index 0000000000..1ebc704409 --- /dev/null +++ b/src/MeoAssistance/RuntimeStatus.cpp @@ -0,0 +1 @@ +#include "RuntimeStatus.h" \ No newline at end of file diff --git a/src/MeoAssistance/RuntimeStatus.h b/src/MeoAssistance/RuntimeStatus.h new file mode 100644 index 0000000000..1555fb58c0 --- /dev/null +++ b/src/MeoAssistance/RuntimeStatus.h @@ -0,0 +1,49 @@ +#pragma once + +#include +#include + +namespace asst { + class RuntimeStatus + { + public: + RuntimeStatus(const RuntimeStatus& rhs) = delete; + RuntimeStatus(RuntimeStatus&& rhs) noexcept = delete; + ~RuntimeStatus() = default; + + static RuntimeStatus& get_instance() { + static RuntimeStatus unique_instance; + return unique_instance; + } + + std::any get(const std::string& key) const noexcept { + if (auto iter = m_data.find(key); + iter != m_data.cend()) { + return iter->second; + } + else { + return std::any(); + } + } + bool exist(const std::string& key) const noexcept { + return m_data.find(key) != m_data.cend(); + } + + template + inline void set(Args &&... args) { + static_assert( + std::is_constructible::value_type, Args...>::value, + "Parameter can't be used to construct a std::unordered_map::value_type"); + m_data.emplace(std::forward(args)...); + } + + RuntimeStatus& operator=(const RuntimeStatus& rhs) = delete; + RuntimeStatus& operator=(RuntimeStatus&& rhs) noexcept = delete; + private: + RuntimeStatus() = default; + + std::unordered_map m_data; + }; + + static auto& status = RuntimeStatus::get_instance(); +}