diff options
Diffstat (limited to 'src/openvic-simulation/country/CountryDefinition.cpp')
-rw-r--r-- | src/openvic-simulation/country/CountryDefinition.cpp | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/src/openvic-simulation/country/CountryDefinition.cpp b/src/openvic-simulation/country/CountryDefinition.cpp new file mode 100644 index 0000000..e414e9e --- /dev/null +++ b/src/openvic-simulation/country/CountryDefinition.cpp @@ -0,0 +1,215 @@ +#include "CountryDefinition.hpp" + +#include <string_view> + +#include "openvic-simulation/dataloader/Dataloader.hpp" +#include "openvic-simulation/dataloader/NodeTools.hpp" +#include "openvic-simulation/DefinitionManager.hpp" +#include "openvic-simulation/politics/Government.hpp" +#include "openvic-simulation/politics/Ideology.hpp" +#include "openvic-simulation/politics/Issue.hpp" +#include "openvic-simulation/pop/Culture.hpp" +#include "openvic-simulation/types/Colour.hpp" +#include "openvic-simulation/types/IdentifierRegistry.hpp" +#include <openvic-dataloader/v2script/AbstractSyntaxTree.hpp> + +using namespace OpenVic; +using namespace OpenVic::NodeTools; + +CountryParty::CountryParty( + std::string_view new_identifier, Date new_start_date, Date new_end_date, Ideology const& new_ideology, + policy_map_t&& new_policies +) : HasIdentifierAndColour { new_identifier, new_ideology.get_colour(), false }, start_date { new_start_date }, + end_date { new_end_date }, ideology { new_ideology }, policies { std::move(new_policies) } {} + +CountryDefinition::CountryDefinition( + std::string_view new_identifier, + colour_t new_colour, + size_t new_index, + GraphicalCultureType const& new_graphical_culture, + IdentifierRegistry<CountryParty>&& new_parties, + unit_names_map_t&& new_unit_names, + bool new_dynamic_tag, + government_colour_map_t&& new_alternative_colours, + colour_t new_primary_unit_colour, + colour_t new_secondary_unit_colour, + colour_t new_tertiary_unit_colour +) : HasIdentifierAndColour { new_identifier, new_colour, false }, + index { new_index }, + graphical_culture { new_graphical_culture }, + parties { std::move(new_parties) }, + unit_names { std::move(new_unit_names) }, + dynamic_tag { new_dynamic_tag }, + alternative_colours { std::move(new_alternative_colours) }, + primary_unit_colour { new_primary_unit_colour }, + secondary_unit_colour { new_secondary_unit_colour }, + tertiary_unit_colour { new_tertiary_unit_colour } {} + +bool CountryDefinitionManager::add_country( + std::string_view identifier, colour_t colour, GraphicalCultureType const* graphical_culture, + IdentifierRegistry<CountryParty>&& parties, CountryDefinition::unit_names_map_t&& unit_names, bool dynamic_tag, + CountryDefinition::government_colour_map_t&& alternative_colours +) { + if (identifier.empty()) { + Logger::error("Invalid country identifier - empty!"); + return false; + } + if (!valid_basic_identifier(identifier)) { + Logger::error( + "Invalid country identifier: ", identifier, " (can only contain alphanumeric characters and underscores)" + ); + return false; + } + if (graphical_culture == nullptr) { + Logger::error("Null graphical culture for country ", identifier); + return false; + } + + static constexpr colour_t default_colour = colour_t::fill_as(colour_t::max_value); + + return country_definitions.add_item({ + identifier, colour, get_country_definition_count(), *graphical_culture, std::move(parties), std::move(unit_names), + dynamic_tag, std::move(alternative_colours), + /* Default to country colour for the chest and grey for the others. Update later if necessary. */ + colour, default_colour, default_colour + }); +} + +bool CountryDefinitionManager::load_countries( + DefinitionManager const& definition_manager, Dataloader const& dataloader, ast::NodeCPtr root +) { + static constexpr std::string_view common_dir = "common/"; + bool is_dynamic = false; + + const bool ret = expect_dictionary_reserve_length( + country_definitions, + [this, &definition_manager, &is_dynamic, &dataloader](std::string_view key, ast::NodeCPtr value) -> bool { + if (key == "dynamic_tags") { + return expect_bool([&is_dynamic](bool val) -> bool { + if (val == is_dynamic) { + Logger::warning("Redundant \"is_dynamic\", already ", val ? "true" : "false"); + } else { + if (is_dynamic) { + Logger::warning("Changing \"is_dynamic\" back to false"); + } + is_dynamic = val; + } + return true; + })(value); + } + if (expect_string( + [this, &definition_manager, is_dynamic, &dataloader, &key](std::string_view filepath) -> bool { + if (load_country_data_file( + definition_manager, key, is_dynamic, + Dataloader::parse_defines( + dataloader.lookup_file(StringUtils::append_string_views(common_dir, filepath)) + ).get_file_node() + )) { + return true; + } + Logger::error("Failed to load country data file: ", filepath); + return false; + } + )(value)) { + return true; + } + Logger::error("Failed to load country: ", key); + return false; + } + )(root); + lock_country_definitions(); + return ret; +} + +bool CountryDefinitionManager::load_country_colours(ast::NodeCPtr root){ + return country_definitions.expect_item_dictionary([](CountryDefinition& country, ast::NodeCPtr colour_node) -> bool { + return expect_dictionary_keys( + "color1", ONE_EXACTLY, expect_colour(assign_variable_callback(country.primary_unit_colour)), + "color2", ONE_EXACTLY, expect_colour(assign_variable_callback(country.secondary_unit_colour)), + "color3", ONE_EXACTLY, expect_colour(assign_variable_callback(country.tertiary_unit_colour)) + )(colour_node); + })(root); +} + +node_callback_t CountryDefinitionManager::load_country_party( + PoliticsManager const& politics_manager, IdentifierRegistry<CountryParty>& country_parties +) const { + return [&politics_manager, &country_parties](ast::NodeCPtr value) -> bool { + std::string_view party_name; + Date start_date, end_date; + Ideology const* ideology; + CountryParty::policy_map_t policies; + + bool ret = expect_dictionary_keys_and_default( + [&politics_manager, &policies, &party_name](std::string_view key, ast::NodeCPtr value) -> bool { + return politics_manager.get_issue_manager().expect_issue_group_str( + [&politics_manager, &policies, value, &party_name](IssueGroup const& group) -> bool { + if (policies.contains(&group)) { + Logger::error("Country party ", party_name, " has duplicate entry for ", group.get_identifier()); + return false; + } + return politics_manager.get_issue_manager().expect_issue_identifier( + [&policies, &group](Issue const& issue) -> bool { + if (&issue.get_group() == &group) { + return map_callback(policies, &group)(&issue); + } + // TODO - change this back to error/false once TGC no longer has this issue + Logger::warning("Invalid policy ", issue.get_identifier(), ", group is ", + issue.get_group().get_identifier(), " when ", group.get_identifier(), " was expected"); + return true; + } + )(value); + } + )(key); + }, + "name", ONE_EXACTLY, expect_string(assign_variable_callback(party_name)), + "start_date", ONE_EXACTLY, expect_date(assign_variable_callback(start_date)), + "end_date", ONE_EXACTLY, expect_date(assign_variable_callback(end_date)), + "ideology", ONE_EXACTLY, + politics_manager.get_ideology_manager().expect_ideology_identifier(assign_variable_callback_pointer(ideology)) + )(value); + + ret &= country_parties.add_item( + { party_name, start_date, end_date, *ideology, std::move(policies) }, duplicate_warning_callback + ); + + return ret; + }; +} + +bool CountryDefinitionManager::load_country_data_file( + DefinitionManager const& definition_manager, std::string_view name, bool is_dynamic, ast::NodeCPtr root +) { + colour_t colour; + GraphicalCultureType const* graphical_culture; + IdentifierRegistry<CountryParty> parties { "country parties" }; + CountryDefinition::unit_names_map_t unit_names; + CountryDefinition::government_colour_map_t alternative_colours; + bool ret = expect_dictionary_keys_and_default( + [&definition_manager, &alternative_colours](std::string_view key, ast::NodeCPtr value) -> bool { + return definition_manager.get_politics_manager().get_government_type_manager().expect_government_type_str( + [&alternative_colours, value](GovernmentType const& government_type) -> bool { + return expect_colour(map_callback(alternative_colours, &government_type))(value); + } + )(key); + }, + "color", ONE_EXACTLY, expect_colour(assign_variable_callback(colour)), + "graphical_culture", ONE_EXACTLY, + definition_manager.get_pop_manager().get_culture_manager().expect_graphical_culture_type_identifier( + assign_variable_callback_pointer(graphical_culture) + ), + "party", ZERO_OR_MORE, load_country_party(definition_manager.get_politics_manager(), parties), + "unit_names", ZERO_OR_ONE, + definition_manager.get_military_manager().get_unit_type_manager().expect_unit_type_dictionary_reserve_length( + unit_names, + [&unit_names](UnitType const& unit, ast::NodeCPtr value) -> bool { + return name_list_callback(map_callback(unit_names, &unit))(value); + } + ) + )(root); + + ret &= add_country( + name, colour, graphical_culture, std::move(parties), std::move(unit_names), is_dynamic, std::move(alternative_colours) + ); + return ret; +} |