diff options
Diffstat (limited to 'src/openvic-simulation/scripts')
-rw-r--r-- | src/openvic-simulation/scripts/Condition.cpp | 57 | ||||
-rw-r--r-- | src/openvic-simulation/scripts/Condition.hpp | 38 | ||||
-rw-r--r-- | src/openvic-simulation/scripts/ConditionScript.cpp | 2 | ||||
-rw-r--r-- | src/openvic-simulation/scripts/ConditionScript.hpp | 8 | ||||
-rw-r--r-- | src/openvic-simulation/scripts/ConditionalWeight.cpp | 81 | ||||
-rw-r--r-- | src/openvic-simulation/scripts/ConditionalWeight.hpp | 19 |
6 files changed, 130 insertions, 75 deletions
diff --git a/src/openvic-simulation/scripts/Condition.cpp b/src/openvic-simulation/scripts/Condition.cpp index fd1f4fa..bb8b662 100644 --- a/src/openvic-simulation/scripts/Condition.cpp +++ b/src/openvic-simulation/scripts/Condition.cpp @@ -7,12 +7,12 @@ using namespace OpenVic; using namespace OpenVic::NodeTools; using enum value_type_t; -using enum scope_t; +using enum scope_type_t; using enum identifier_type_t; Condition::Condition( - std::string_view new_identifier, value_type_t new_value_type, scope_t new_scope, - scope_t new_scope_change, identifier_type_t new_key_identifier_type, + std::string_view new_identifier, value_type_t new_value_type, scope_type_t new_scope, + scope_type_t new_scope_change, identifier_type_t new_key_identifier_type, identifier_type_t new_value_identifier_type ) : HasIdentifier { new_identifier }, value_type { new_value_type }, scope { new_scope }, scope_change { new_scope_change }, key_identifier_type { new_key_identifier_type }, @@ -26,7 +26,7 @@ ConditionNode::ConditionNode( condition_key_item { new_condition_key_item }, condition_value_item { new_condition_key_item } {} bool ConditionManager::add_condition( - std::string_view identifier, value_type_t value_type, scope_t scope, scope_t scope_change, + std::string_view identifier, value_type_t value_type, scope_type_t scope, scope_type_t scope_change, identifier_type_t key_identifier_type, identifier_type_t value_identifier_type ) { if (identifier.empty()) { @@ -337,8 +337,8 @@ bool ConditionManager::setup_conditions(DefinitionManager const& definition_mana const auto import_identifiers = [this, &ret]( std::vector<std::string_view> const& identifiers, value_type_t value_type, - scope_t scope, - scope_t scope_change = NO_SCOPE, + scope_type_t scope, + scope_type_t scope_change = NO_SCOPE, identifier_type_t key_identifier_type = NO_IDENTIFIER, identifier_type_t value_identifier_type = NO_IDENTIFIER ) -> void { @@ -523,10 +523,10 @@ callback_t<std::string_view> ConditionManager::expect_parse_identifier( } node_callback_t ConditionManager::expect_condition_node( - DefinitionManager const& definition_manager, Condition const& condition, scope_t this_scope, - scope_t from_scope, scope_t cur_scope, callback_t<ConditionNode&&> callback + DefinitionManager const& definition_manager, Condition const& condition, scope_type_t current_scope, + scope_type_t this_scope, scope_type_t from_scope, callback_t<ConditionNode&&> callback ) const { - return [this, &definition_manager, &condition, callback, this_scope, from_scope, cur_scope]( + return [this, &definition_manager, &condition, callback, current_scope, this_scope, from_scope]( ast::NodeCPtr node ) -> bool { bool ret = false; @@ -534,8 +534,8 @@ node_callback_t ConditionManager::expect_condition_node( const std::string_view identifier = condition.get_identifier(); const value_type_t value_type = condition.get_value_type(); - const scope_t scope = condition.get_scope(); - const scope_t scope_change = condition.get_scope_change(); + const scope_type_t scope = condition.get_scope(); + const scope_type_t scope_change = condition.get_scope_change(); const identifier_type_t key_identifier_type = condition.get_key_identifier_type(); const identifier_type_t value_identifier_type = condition.get_value_identifier_type(); @@ -647,23 +647,24 @@ node_callback_t ConditionManager::expect_condition_node( if (!ret && share_value_type(value_type, GROUP)) { ConditionNode::condition_list_t node_list; ret |= expect_condition_node_list( - definition_manager, this_scope, from_scope, - scope_change == NO_SCOPE ? cur_scope : scope_change, - false, + definition_manager, + scope_change == NO_SCOPE ? current_scope : scope_change, + this_scope, + from_scope, vector_callback(node_list) )(node); value = std::move(node_list); } // scope validation - scope_t effective_current_scope = cur_scope; - if (share_scope(effective_current_scope, THIS)) { + scope_type_t effective_current_scope = current_scope; + if (share_scope_type(effective_current_scope, THIS)) { effective_current_scope = this_scope; - } else if (share_scope(effective_current_scope, FROM)) { + } else if (share_scope_type(effective_current_scope, FROM)) { effective_current_scope = from_scope; } - if (!share_scope(scope, effective_current_scope) && effective_current_scope > scope) { + if (!share_scope_type(scope, effective_current_scope) && effective_current_scope > scope) { Logger::warning( "Condition or scope ", identifier, " was found in wrong scope ", effective_current_scope, ", expected ", scope, "!" @@ -706,15 +707,15 @@ static bool top_scope_fallback(std::string_view id, ast::NodeCPtr node) { }; node_callback_t ConditionManager::expect_condition_node_list( - DefinitionManager const& definition_manager, scope_t this_scope, scope_t from_scope, - scope_t cur_scope, bool top_scope, callback_t<ConditionNode&&> callback + DefinitionManager const& definition_manager, scope_type_t current_scope, scope_type_t this_scope, scope_type_t from_scope, + callback_t<ConditionNode&&> callback, bool top_scope ) const { - return [this, &definition_manager, callback, this_scope, from_scope, cur_scope, top_scope](ast::NodeCPtr node) -> bool { + return [this, &definition_manager, callback, current_scope, this_scope, from_scope, top_scope](ast::NodeCPtr node) -> bool { const auto expect_node = [ - this, &definition_manager, callback, this_scope, from_scope, cur_scope + this, &definition_manager, callback, current_scope, this_scope, from_scope ](Condition const& condition, ast::NodeCPtr node) -> bool { return expect_condition_node( - definition_manager, condition, this_scope, from_scope, cur_scope, callback + definition_manager, condition, current_scope, this_scope, from_scope, callback )(node); }; @@ -729,19 +730,19 @@ node_callback_t ConditionManager::expect_condition_node_list( } node_callback_t ConditionManager::expect_condition_script( - DefinitionManager const& definition_manager, scope_t initial_scope, scope_t this_scope, - scope_t from_scope, callback_t<ConditionNode&&> callback + DefinitionManager const& definition_manager, scope_type_t initial_scope, scope_type_t this_scope, + scope_type_t from_scope, callback_t<ConditionNode&&> callback ) const { return [this, &definition_manager, initial_scope, this_scope, from_scope, callback](ast::NodeCPtr node) -> bool { ConditionNode::condition_list_t conds; bool ret = expect_condition_node_list( definition_manager, + initial_scope, this_scope, from_scope, - initial_scope, - true, - NodeTools::vector_callback(conds) + NodeTools::vector_callback(conds), + true )(node); ret &= callback({ root_condition, std::move(conds), true }); diff --git a/src/openvic-simulation/scripts/Condition.hpp b/src/openvic-simulation/scripts/Condition.hpp index 8d4d246..1f4929a 100644 --- a/src/openvic-simulation/scripts/Condition.hpp +++ b/src/openvic-simulation/scripts/Condition.hpp @@ -27,7 +27,7 @@ namespace OpenVic { // Order matters in this enum, for the fallback system to work // smaller entities must have smaller integers associated! - enum class scope_t : uint8_t { //TODO: maybe distinguish TRANSPARENT from NO_SCOPE + enum class scope_type_t : uint8_t { //TODO: maybe distinguish TRANSPARENT from NO_SCOPE NO_SCOPE = 0, POP = 1 << 0, PROVINCE = 1 << 1, @@ -74,15 +74,15 @@ namespace OpenVic { /* Allows enum types to be used with bitwise operators. */ template<> struct enable_bitfield<value_type_t> : std::true_type {}; - template<> struct enable_bitfield<scope_t> : std::true_type {}; + template<> struct enable_bitfield<scope_type_t> : std::true_type {}; template<> struct enable_bitfield<identifier_type_t> : std::true_type {}; /* Returns true if the values have any bit in common. */ inline constexpr bool share_value_type(value_type_t lhs, value_type_t rhs) { return (lhs & rhs) != value_type_t::NO_TYPE; } - inline constexpr bool share_scope(scope_t lhs, scope_t rhs) { - return (lhs & rhs) != scope_t::NO_SCOPE; + inline constexpr bool share_scope_type(scope_type_t lhs, scope_type_t rhs) { + return (lhs & rhs) != scope_type_t::NO_SCOPE; } inline constexpr bool share_identifier_type(identifier_type_t lhs, identifier_type_t rhs) { return (lhs & rhs) != identifier_type_t::NO_IDENTIFIER; @@ -122,10 +122,10 @@ namespace OpenVic { } #undef BUILD_STRING -#define BUILD_STRING(entry) _BUILD_STRING(entry, share_scope) +#define BUILD_STRING(entry) _BUILD_STRING(entry, share_scope_type) - inline std::ostream& operator<<(std::ostream& stream, scope_t value) { - using enum scope_t; + inline std::ostream& operator<<(std::ostream& stream, scope_type_t value) { + using enum scope_type_t; if (value == NO_SCOPE) { return stream << "[NO_SCOPE]"; } @@ -198,14 +198,14 @@ namespace OpenVic { private: const value_type_t PROPERTY(value_type); - const scope_t PROPERTY(scope); - const scope_t PROPERTY(scope_change); + const scope_type_t PROPERTY(scope); + const scope_type_t PROPERTY(scope_change); const identifier_type_t PROPERTY(key_identifier_type); const identifier_type_t PROPERTY(value_identifier_type); Condition( - std::string_view new_identifier, value_type_t new_value_type, scope_t new_scope, - scope_t new_scope_change, identifier_type_t new_key_identifier_type, + std::string_view new_identifier, value_type_t new_value_type, scope_type_t new_scope, + scope_type_t new_scope_change, identifier_type_t new_key_identifier_type, identifier_type_t new_value_identifier_type ); @@ -249,8 +249,8 @@ namespace OpenVic { Condition const* root_condition = nullptr; bool add_condition( - std::string_view identifier, value_type_t value_type, scope_t scope, - scope_t scope_change = scope_t::NO_SCOPE, + std::string_view identifier, value_type_t value_type, scope_type_t scope, + scope_type_t scope_change = scope_type_t::NO_SCOPE, identifier_type_t key_identifier_type = identifier_type_t::NO_IDENTIFIER, identifier_type_t value_identifier_type = identifier_type_t::NO_IDENTIFIER ); @@ -261,21 +261,21 @@ namespace OpenVic { ) const; NodeTools::node_callback_t expect_condition_node( - DefinitionManager const& definition_manager, Condition const& condition, scope_t this_scope, - scope_t from_scope, scope_t cur_scope, NodeTools::callback_t<ConditionNode&&> callback + DefinitionManager const& definition_manager, Condition const& condition, scope_type_t current_scope, + scope_type_t this_scope, scope_type_t from_scope, NodeTools::callback_t<ConditionNode&&> callback ) const; NodeTools::node_callback_t expect_condition_node_list( - DefinitionManager const& definition_manager, scope_t this_scope, scope_t from_scope, - scope_t cur_scope, bool top_scope, NodeTools::callback_t<ConditionNode&&> callback + DefinitionManager const& definition_manager, scope_type_t current_scope, scope_type_t this_scope, + scope_type_t from_scope, NodeTools::callback_t<ConditionNode&&> callback, bool top_scope = false ) const; public: bool setup_conditions(DefinitionManager const& definition_manager); NodeTools::node_callback_t expect_condition_script( - DefinitionManager const& definition_manager, scope_t initial_scope, scope_t this_scope, scope_t from_scope, - NodeTools::callback_t<ConditionNode&&> callback + DefinitionManager const& definition_manager, scope_type_t initial_scope, scope_type_t this_scope, + scope_type_t from_scope, NodeTools::callback_t<ConditionNode&&> callback ) const; }; } diff --git a/src/openvic-simulation/scripts/ConditionScript.cpp b/src/openvic-simulation/scripts/ConditionScript.cpp index bee4d07..c556bd2 100644 --- a/src/openvic-simulation/scripts/ConditionScript.cpp +++ b/src/openvic-simulation/scripts/ConditionScript.cpp @@ -6,7 +6,7 @@ using namespace OpenVic; using namespace OpenVic::NodeTools; ConditionScript::ConditionScript( - scope_t new_initial_scope, scope_t new_this_scope, scope_t new_from_scope + scope_type_t new_initial_scope, scope_type_t new_this_scope, scope_type_t new_from_scope ) : initial_scope { new_initial_scope }, this_scope { new_this_scope }, from_scope { new_from_scope } {} bool ConditionScript::_parse_script(ast::NodeCPtr root, DefinitionManager const& definition_manager) { diff --git a/src/openvic-simulation/scripts/ConditionScript.hpp b/src/openvic-simulation/scripts/ConditionScript.hpp index e6ed255..aa386e8 100644 --- a/src/openvic-simulation/scripts/ConditionScript.hpp +++ b/src/openvic-simulation/scripts/ConditionScript.hpp @@ -10,14 +10,14 @@ namespace OpenVic { private: ConditionNode PROPERTY_REF(condition_root); - scope_t PROPERTY(initial_scope); - scope_t PROPERTY(this_scope); - scope_t PROPERTY(from_scope); + scope_type_t PROPERTY(initial_scope); + scope_type_t PROPERTY(this_scope); + scope_type_t PROPERTY(from_scope); protected: bool _parse_script(ast::NodeCPtr root, DefinitionManager const& definition_manager) override; public: - ConditionScript(scope_t new_initial_scope, scope_t new_this_scope, scope_t new_from_scope); + ConditionScript(scope_type_t new_initial_scope, scope_type_t new_this_scope, scope_type_t new_from_scope); }; } diff --git a/src/openvic-simulation/scripts/ConditionalWeight.cpp b/src/openvic-simulation/scripts/ConditionalWeight.cpp index 7c3e0a0..1bb83d0 100644 --- a/src/openvic-simulation/scripts/ConditionalWeight.cpp +++ b/src/openvic-simulation/scripts/ConditionalWeight.cpp @@ -3,12 +3,12 @@ using namespace OpenVic; using namespace OpenVic::NodeTools; -ConditionalWeight::ConditionalWeight(scope_t new_initial_scope, scope_t new_this_scope, scope_t new_from_scope) +ConditionalWeight::ConditionalWeight(scope_type_t new_initial_scope, scope_type_t new_this_scope, scope_type_t new_from_scope) : initial_scope { new_initial_scope }, this_scope { new_this_scope }, from_scope { new_from_scope } {} template<typename T> static NodeCallback auto expect_modifier( - std::vector<T>& items, scope_t initial_scope, scope_t this_scope, scope_t from_scope + std::vector<T>& items, scope_type_t initial_scope, scope_type_t this_scope, scope_type_t from_scope ) { return [&items, initial_scope, this_scope, from_scope](ast::NodeCPtr node) -> bool { fixed_point_t weight = 0; @@ -26,23 +26,86 @@ static NodeCallback auto expect_modifier( } node_callback_t ConditionalWeight::expect_conditional_weight(base_key_t base_key) { - return expect_dictionary_keys( - // TODO - add days and years as options with a shared expected count of ONE_EXACTLY - base_key_to_string(base_key), ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(base)), - "days", ZERO_OR_ONE, success_callback, - "years", ZERO_OR_ONE, success_callback, + key_map_t key_map; + bool successfully_set_up_base_keys = true; + + switch (base_key) { + case BASE: + { + successfully_set_up_base_keys &= add_key_map_entry( + key_map, + "base", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(base)) + ); + + break; + } + case FACTOR: + { + successfully_set_up_base_keys &= add_key_map_entry( + key_map, + "factor", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(base)) + ); + + break; + } + case TIME: + { + const auto time_callback = [this](std::string_view key, Timespan (*to_timespan)(Timespan::day_t)) -> auto { + return [this, key, to_timespan](uint32_t value) -> bool { + if (base == fixed_point_t::_0()) { + base = fixed_point_t::parse((*to_timespan)(value).to_int()); + return true; + } else { + Logger::error( + "ConditionalWeight cannot have multiple base values - trying to set base to ", value, " ", key, + " when it already has a value equivalent to ", base, " days!" + ); + return false; + } + }; + }; + + successfully_set_up_base_keys &= add_key_map_entries( + key_map, + "days", ZERO_OR_ONE, expect_uint<uint32_t>(time_callback("days", Timespan::from_days)), + "months", ZERO_OR_ONE, expect_uint<uint32_t>(time_callback("months", Timespan::from_months)), + "years", ZERO_OR_ONE, expect_uint<uint32_t>(time_callback("years", Timespan::from_years)) + ); + + break; + } + default: + { + successfully_set_up_base_keys = false; + } + } + + if (!successfully_set_up_base_keys) { + return [base_key](ast::NodeCPtr node) -> bool { + Logger::error( + "Failed to set up base keys for ConditionalWeight with base value: ", static_cast<uint32_t>(base_key) + ); + return false; + }; + } + + return expect_dictionary_key_map( + std::move(key_map), "modifier", ZERO_OR_MORE, expect_modifier(condition_weight_items, initial_scope, this_scope, from_scope), "group", ZERO_OR_MORE, [this](ast::NodeCPtr node) -> bool { condition_weight_group_t items; + const bool ret = expect_dictionary_keys( "modifier", ONE_OR_MORE, expect_modifier(items, initial_scope, this_scope, from_scope) )(node); + if (!items.empty()) { condition_weight_items.emplace_back(std::move(items)); return ret; + } else { + Logger::error("ConditionalWeight group must have at least one modifier!"); + return false; } - Logger::error("ConditionalWeight group must have at least one modifier!"); - return false; } ); } diff --git a/src/openvic-simulation/scripts/ConditionalWeight.hpp b/src/openvic-simulation/scripts/ConditionalWeight.hpp index c99d6b0..fcab0a6 100644 --- a/src/openvic-simulation/scripts/ConditionalWeight.hpp +++ b/src/openvic-simulation/scripts/ConditionalWeight.hpp @@ -14,32 +14,23 @@ namespace OpenVic { using condition_weight_item_t = std::variant<condition_weight_t, condition_weight_group_t>; enum class base_key_t : uint8_t { - BASE, FACTOR, MONTHS + BASE, FACTOR, TIME }; using enum base_key_t; private: fixed_point_t PROPERTY(base); std::vector<condition_weight_item_t> PROPERTY(condition_weight_items); - scope_t PROPERTY(initial_scope); - scope_t PROPERTY(this_scope); - scope_t PROPERTY(from_scope); + scope_type_t PROPERTY(initial_scope); + scope_type_t PROPERTY(this_scope); + scope_type_t PROPERTY(from_scope); struct parse_scripts_visitor_t; public: - ConditionalWeight(scope_t new_initial_scope, scope_t new_this_scope, scope_t new_from_scope); + ConditionalWeight(scope_type_t new_initial_scope, scope_type_t new_this_scope, scope_type_t new_from_scope); ConditionalWeight(ConditionalWeight&&) = default; - static constexpr std::string_view base_key_to_string(base_key_t base_key) { - switch (base_key) { - case base_key_t::BASE: return "base"; - case base_key_t::FACTOR: return "factor"; - case base_key_t::MONTHS: return "months"; // TODO - add functionality for days or months or years - default: return "INVALID BASE KEY"; - } - } - NodeTools::node_callback_t expect_conditional_weight(base_key_t base_key); bool parse_scripts(DefinitionManager const& definition_manager); |