aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation/history
diff options
context:
space:
mode:
author hop311 <hop3114@gmail.com>2023-11-06 21:39:40 +0100
committer hop311 <hop3114@gmail.com>2023-11-07 19:35:38 +0100
commitd30421fa7d7f6ad87d3f90cc0ab491742f0d2548 (patch)
tree601591215af0c6724766019ebb577141ea5807c5 /src/openvic-simulation/history
parentb5bbeb47febc823517a5baba4eca66f32fb3609c (diff)
History loading generalisation
Diffstat (limited to 'src/openvic-simulation/history')
-rw-r--r--src/openvic-simulation/history/CountryHistory.cpp412
-rw-r--r--src/openvic-simulation/history/CountryHistory.hpp103
-rw-r--r--src/openvic-simulation/history/HistoryMap.cpp15
-rw-r--r--src/openvic-simulation/history/HistoryMap.hpp110
-rw-r--r--src/openvic-simulation/history/ProvinceHistory.cpp345
-rw-r--r--src/openvic-simulation/history/ProvinceHistory.hpp98
6 files changed, 411 insertions, 672 deletions
diff --git a/src/openvic-simulation/history/CountryHistory.cpp b/src/openvic-simulation/history/CountryHistory.cpp
index cd682bd..04a5e09 100644
--- a/src/openvic-simulation/history/CountryHistory.cpp
+++ b/src/openvic-simulation/history/CountryHistory.cpp
@@ -5,342 +5,154 @@
using namespace OpenVic;
using namespace OpenVic::NodeTools;
-CountryHistory::CountryHistory(
- Culture const* new_primary_culture, std::vector<Culture const*>&& new_accepted_cultures, Religion const* new_religion,
- CountryParty const* new_ruling_party, Date new_last_election, decimal_map_t<Ideology const*>&& new_upper_house,
- Province const* new_capital, GovernmentType const* new_government_type, fixed_point_t new_plurality,
- NationalValue const* new_national_value, bool new_civilised, fixed_point_t new_prestige,
- std::vector<Reform const*>&& new_reforms, Deployment const* new_inital_oob
-) : primary_culture { new_primary_culture }, accepted_cultures { std::move(new_accepted_cultures) },
- religion { new_religion }, ruling_party { new_ruling_party }, last_election { new_last_election },
- upper_house { std::move(new_upper_house) }, capital { new_capital }, government_type { new_government_type },
- plurality { new_plurality }, national_value { new_national_value }, civilised { new_civilised },
- prestige { new_prestige }, reforms { std::move(new_reforms) }, inital_oob { new_inital_oob } {}
+CountryHistoryEntry::CountryHistoryEntry(Country const& new_country, Date new_date)
+ : HistoryEntry { new_date }, country { new_country } {}
-Culture const* CountryHistory::get_primary_culture() const {
- return primary_culture;
-}
-
-std::vector<Culture const*> const& CountryHistory::get_accepted_cultures() const {
- return accepted_cultures;
-}
-
-Religion const* CountryHistory::get_religion() const {
- return religion;
-}
-
-CountryParty const* CountryHistory::get_ruling_party() const {
- return ruling_party;
-}
-
-Date CountryHistory::get_last_election() const {
- return last_election;
-}
-
-decimal_map_t<Ideology const*> const& CountryHistory::get_upper_house() const {
- return upper_house;
-}
-
-Province const* CountryHistory::get_capital() const {
- return capital;
-}
-
-GovernmentType const* CountryHistory::get_government_type() const {
- return government_type;
-}
-
-fixed_point_t CountryHistory::get_plurality() const {
- return plurality;
-}
-
-NationalValue const* CountryHistory::get_national_value() const {
- return national_value;
-}
-
-bool CountryHistory::is_civilised() const {
- return civilised;
-}
-
-fixed_point_t CountryHistory::get_prestige() const {
- return prestige;
-}
-
-std::vector<Reform const*> const& CountryHistory::get_reforms() const {
- return reforms;
-}
-
-Deployment const* CountryHistory::get_inital_oob() const {
- return inital_oob;
-}
-
-bool CountryHistoryManager::add_country_history_entry(
- Country const* country, Date date, Culture const* primary_culture, std::vector<Culture const*>&& accepted_cultures,
- Religion const* religion, CountryParty const* ruling_party, Date last_election,
- decimal_map_t<Ideology const*>&& upper_house, Province const* capital, GovernmentType const* government_type,
- fixed_point_t plurality, NationalValue const* national_value, bool civilised, fixed_point_t prestige,
- std::vector<Reform const*>&& reforms, std::optional<Deployment const*> initial_oob, bool updated_accepted_cultures,
- bool updated_upper_house, bool updated_reforms
-) {
- if (locked) {
- Logger::error("Cannot add new history entry to country history registry: locked!");
- return false;
- }
-
- /* combine duplicate histories, priority to current (defined later) */
- country_history_map_t& country_registry = country_histories[country];
- const country_history_map_t::iterator existing_entry = country_registry.find(date);
-
- if (existing_entry != country_registry.end()) {
- if (primary_culture != nullptr) {
- existing_entry->second.primary_culture = primary_culture;
- }
- if (updated_accepted_cultures) {
- existing_entry->second.accepted_cultures = std::move(accepted_cultures);
- }
- if (religion != nullptr) {
- existing_entry->second.religion = religion;
- }
- if (ruling_party != nullptr) {
- existing_entry->second.ruling_party = ruling_party;
- }
- if (last_election != Date{}) {
- existing_entry->second.last_election = last_election;
- }
- if (updated_upper_house) {
- existing_entry->second.upper_house = std::move(upper_house);
- }
- if (capital != nullptr) {
- existing_entry->second.capital = capital;
- }
- if (government_type != nullptr) {
- existing_entry->second.government_type = government_type;
- }
- if (plurality >= 0) {
- existing_entry->second.plurality = plurality;
- }
- if (national_value != nullptr) {
- existing_entry->second.national_value = national_value;
- }
- if (civilised) {
- existing_entry->second.civilised = true;
- }
- if (prestige >= 0) {
- existing_entry->second.prestige = prestige;
- }
- if (updated_reforms) {
- existing_entry->second.reforms = std::move(reforms);
- }
- if (initial_oob) {
- existing_entry->second.inital_oob = *initial_oob;
- }
- } else {
- country_registry.emplace( date,
- CountryHistory {
- primary_culture, std::move(accepted_cultures), religion, ruling_party, last_election,
- std::move(upper_house), capital, government_type, plurality, national_value, civilised,
- prestige, std::move(reforms), std::move(*initial_oob)
- }
- );
- }
- return true;
-}
-
-void CountryHistoryManager::lock_country_histories() {
- for (const auto& entry : country_histories) {
- if (entry.second.size() == 0) {
- Logger::error(
- "Attempted to lock country histories - country ", entry.first->get_identifier(), " has no history entries!"
- );
- }
- }
- Logger::info("Locked country history registry after registering ", country_histories.size(), " items");
- locked = true;
-}
-
-bool CountryHistoryManager::is_locked() const {
- return locked;
-}
-
-CountryHistory const* CountryHistoryManager::get_country_history(Country const* country, Date entry) const {
- Date closest_entry;
- auto country_registry = country_histories.find(country);
-
- if (country_registry == country_histories.end()) {
- Logger::error("Attempted to access history of undefined country ", country->get_identifier());
- return nullptr;
- }
-
- for (const auto& current : country_registry->second) {
- if (current.first == entry) {
- return &current.second;
- }
- if (current.first > entry) {
- continue;
- }
- if (current.first > closest_entry && current.first < entry) {
- closest_entry = current.first;
- }
- }
+CountryHistoryMap::CountryHistoryMap(Country const& new_country) : country { new_country } {}
- auto entry_registry = country_registry->second.find(closest_entry);
- if (entry_registry != country_registry->second.end()) {
- return &entry_registry->second;
- }
- /* warned about lack of entries earlier, return nullptr */
- return nullptr;
-}
-
-inline CountryHistory const* CountryHistoryManager::get_country_history(Country const* country, Bookmark const* entry) const {
- return get_country_history(country, entry->get_date());
+std::unique_ptr<CountryHistoryEntry> CountryHistoryMap::_make_entry(Date date) const {
+ return std::unique_ptr<CountryHistoryEntry> { new CountryHistoryEntry { country, date } };
}
-inline bool CountryHistoryManager::_load_country_history_entry(
- GameManager& game_manager, Dataloader const& dataloader, Country const& country, Date date, ast::NodeCPtr root
+bool CountryHistoryMap::_load_history_entry(
+ GameManager const& game_manager, Dataloader const& dataloader, DeploymentManager& deployment_manager,
+ CountryHistoryEntry& entry, ast::NodeCPtr root
) {
PoliticsManager const& politics_manager = game_manager.get_politics_manager();
IssueManager const& issue_manager = politics_manager.get_issue_manager();
CultureManager const& culture_manager = game_manager.get_pop_manager().get_culture_manager();
- Province const* capital = nullptr;
- Culture const* primary_culture = nullptr;
- Religion const* religion = nullptr;
- GovernmentType const* government_type = nullptr;
- NationalValue const* national_value = nullptr;
- CountryParty const* ruling_party = nullptr;
- std::vector<Culture const*> accepted_cultures {};
- std::vector<Reform const*> reforms {};
- decimal_map_t<Ideology const*> upper_house {};
- fixed_point_t plurality = -1, prestige = -1;
- bool civilised = false;
- Date last_election {};
- std::optional<Deployment const*> initial_oob;
-
- bool updated_accepted_cultures = false, updated_upper_house = false, updated_reforms = false;
-
- bool ret = expect_dictionary_keys_and_default(
- [this, &issue_manager, &reforms, &updated_reforms, &country](std::string_view key, ast::NodeCPtr value) -> bool {
+ return expect_dictionary_keys_and_default(
+ [this, &game_manager, &dataloader, &deployment_manager, &issue_manager, &entry](
+ std::string_view key, ast::NodeCPtr value) -> bool {
ReformGroup const* reform_group = issue_manager.get_reform_group_by_identifier(key);
if (reform_group != nullptr) {
- updated_reforms = true;
- return issue_manager.expect_reform_identifier(
- [reform_group, &reforms, &country](Reform const& reform) -> bool {
- if (&reform.get_reform_group() != reform_group) {
- Logger::warning(
- "Listing ", reform.get_identifier(), " as belonging to the reform group ",
- reform_group->get_identifier(), " when it actually belongs to ",
- reform.get_reform_group().get_identifier()
- );
- }
- if (std::find(reforms.begin(), reforms.end(), &reform) != reforms.end()) {
- Logger::error(
- "Redefinition of reform ", reform.get_identifier(), " in history of ", country.get_identifier()
- );
- return false;
- }
- reforms.push_back(&reform);
- return true;
+ return issue_manager.expect_reform_identifier([&entry, reform_group](Reform const& reform) -> bool {
+ if (&reform.get_reform_group() != reform_group) {
+ Logger::warning(
+ "Listing ", reform.get_identifier(), " as belonging to the reform group ",
+ reform_group->get_identifier(), " when it actually belongs to ",
+ reform.get_reform_group().get_identifier(), " in history of ", entry.get_country().get_identifier()
+ );
+ }
+ if (std::find(entry.reforms.begin(), entry.reforms.end(), &reform) != entry.reforms.end()) {
+ Logger::error(
+ "Redefinition of reform ", reform.get_identifier(), " in history of ",
+ entry.get_country().get_identifier()
+ );
+ return false;
}
- )(value);
+ entry.reforms.push_back(&reform);
+ return true;
+ })(value);
}
// TODO: technologies & inventions
- return true;
+ return _load_history_sub_entry_callback(
+ game_manager, dataloader, deployment_manager, entry.get_date(), value, key, value, key_value_success_callback
+ );
},
/* we have to use a lambda, assign_variable_callback_pointer
* apparently doesn't play nice with const & non-const accessors */
// TODO - fix this issue (cause by provinces having non-const accessors)
"capital", ZERO_OR_ONE,
- game_manager.get_map().expect_province_identifier([&capital](Province const& province) -> bool {
- capital = &province;
- return true;
- }),
+ game_manager.get_map().expect_province_identifier(assign_variable_callback_pointer(entry.capital)),
"primary_culture", ZERO_OR_ONE,
- culture_manager.expect_culture_identifier(assign_variable_callback_pointer(primary_culture)),
- "culture", ZERO_OR_MORE,
- culture_manager.expect_culture_identifier(
- [&game_manager, &accepted_cultures, &updated_accepted_cultures](Culture const& culture) -> bool {
- updated_accepted_cultures = true;
- accepted_cultures.push_back(&culture);
+ culture_manager.expect_culture_identifier(assign_variable_callback_pointer(entry.primary_culture)),
+ "culture", ZERO_OR_MORE, culture_manager.expect_culture_identifier(
+ [&entry](Culture const& culture) -> bool {
+ entry.accepted_cultures.push_back(&culture);
+ return true;
+ }
+ ),
+ "religion", ZERO_OR_ONE, game_manager.get_pop_manager().get_religion_manager().expect_religion_identifier(
+ assign_variable_callback_pointer(entry.religion)
+ ),
+ "government", ZERO_OR_ONE, politics_manager.get_government_type_manager().expect_government_type_identifier(
+ assign_variable_callback_pointer(entry.government_type)
+ ),
+ "plurality", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(entry.plurality)),
+ "nationalvalue", ZERO_OR_ONE, politics_manager.get_national_value_manager().expect_national_value_identifier(
+ assign_variable_callback_pointer(entry.national_value)
+ ),
+ "civilized", ZERO_OR_ONE, expect_bool(assign_variable_callback(entry.civilised)),
+ "prestige", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(entry.prestige)),
+ "ruling_party", ZERO_OR_ONE, country.expect_party_identifier(assign_variable_callback_pointer(entry.ruling_party)),
+ "last_election", ZERO_OR_ONE, expect_date(assign_variable_callback(entry.last_election)),
+ "upper_house", ZERO_OR_ONE, politics_manager.get_ideology_manager().expect_ideology_dictionary(
+ [&entry](Ideology const& ideology, ast::NodeCPtr value) -> bool {
+ return expect_fixed_point([&entry, &ideology](fixed_point_t val) -> bool {
+ entry.upper_house[&ideology] = val;
return true;
+ })(value);
+ }
+ ),
+ "oob", ZERO_OR_ONE, expect_identifier_or_string(
+ [&game_manager, &deployment_manager, &dataloader, &entry](std::string_view path) -> bool {
+ Deployment const* deployment = nullptr;
+ const bool ret = deployment_manager.load_oob_file(game_manager, dataloader, path, deployment, false);
+ if (deployment != nullptr) {
+ entry.inital_oob = deployment;
}
- ),
- "religion", ZERO_OR_ONE,
- game_manager.get_pop_manager().get_religion_manager().expect_religion_identifier(
- assign_variable_callback_pointer(religion)
- ),
- "government", ZERO_OR_ONE,
- politics_manager.get_government_type_manager().expect_government_type_identifier(
- assign_variable_callback_pointer(government_type)
- ),
- "plurality", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(plurality)),
- "nationalvalue", ZERO_OR_ONE,
- politics_manager.get_national_value_manager().expect_national_value_identifier(
- assign_variable_callback_pointer(national_value)
- ),
- "civilized", ZERO_OR_ONE, expect_bool(assign_variable_callback(civilised)),
- "prestige", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(prestige)),
- "ruling_party", ZERO_OR_ONE, country.expect_party_identifier(assign_variable_callback_pointer(ruling_party)),
- "last_election", ZERO_OR_ONE, expect_date(assign_variable_callback(last_election)),
- "upper_house", ZERO_OR_ONE,
- politics_manager.get_ideology_manager().expect_ideology_dictionary(
- [&upper_house, &updated_upper_house](Ideology const& ideology, ast::NodeCPtr value) -> bool {
- return expect_fixed_point([&upper_house, &updated_upper_house, &ideology](fixed_point_t val) -> bool {
- if (val != 0) {
- upper_house[&ideology] += val;
- updated_upper_house = true;
- }
- return true;
- })(value);
- }
- ),
- "oob", ZERO_OR_ONE, expect_identifier_or_string([&game_manager, &dataloader, &initial_oob](std::string_view path) -> bool {
- if(!initial_oob.has_value())
- initial_oob = decltype(initial_oob)::value_type {};
- return game_manager.get_military_manager().get_deployment_manager().load_oob_file(
- game_manager, dataloader, path, *initial_oob, false
- );
- }),
+ return ret;
+ }
+ ),
"schools", ZERO_OR_ONE, success_callback, // TODO: technology school
"foreign_investment", ZERO_OR_ONE, success_callback // TODO: foreign investment
)(root);
+}
- ret &= add_country_history_entry(
- &country, date, primary_culture,
- std::move(accepted_cultures), religion, ruling_party, last_election, std::move(upper_house), capital, government_type,
- plurality, national_value, civilised, prestige, std::move(reforms), std::move(initial_oob), updated_accepted_cultures,
- updated_upper_house, updated_reforms
- );
- return ret;
+void CountryHistoryManager::lock_country_histories() {
+ Logger::info("Locked country history registry after registering ", country_histories.size(), " items");
+ locked = true;
+}
+
+bool CountryHistoryManager::is_locked() const {
+ return locked;
+}
+
+CountryHistoryMap const* CountryHistoryManager::get_country_history(Country const* country) const {
+ if (country == nullptr) {
+ Logger::error("Attempted to access history of null country");
+ return nullptr;
+ }
+ decltype(country_histories)::const_iterator country_registry = country_histories.find(country);
+ if (country_registry != country_histories.end()) {
+ return &country_registry->second;
+ } else {
+ Logger::error("Attempted to access history of country ", country->get_identifier(), " but none has been defined!");
+ return nullptr;
+ }
}
bool CountryHistoryManager::load_country_history_file(
GameManager& game_manager, Dataloader const& dataloader, Country const& country, ast::NodeCPtr root
) {
+ if (locked) {
+ Logger::error(
+ "Attempted to load country history file for ", country.get_identifier(),
+ " after country history registry was locked!"
+ );
+ return false;
+ }
+
if (country.is_dynamic_tag()) {
return true; /* as far as I can tell dynamic countries are hardcoded, broken, and unused */
}
- bool ret = _load_country_history_entry(
- game_manager, dataloader, country, game_manager.get_define_manager().get_start_date(), root
- );
-
- ret &= expect_dictionary([this, &game_manager, &dataloader, &country](std::string_view key, ast::NodeCPtr value) -> bool {
- bool is_date = false;
- Date entry = Date::from_string(key, &is_date, true);
- if (!is_date) {
- return true;
- }
-
- Date end_date = game_manager.get_define_manager().get_end_date();
- if (entry > end_date) {
- Logger::error(
- "History entry ", entry.to_string(), " of country ", country.get_identifier(),
- " defined after defined end date ", end_date.to_string()
- );
+ decltype(country_histories)::iterator it = country_histories.find(&country);
+ if (it == country_histories.end()) {
+ const std::pair<decltype(country_histories)::iterator, bool> result =
+ country_histories.emplace(&country, CountryHistoryMap { country });
+ if (result.second) {
+ it = result.first;
+ } else {
+ Logger::error("Failed to create country history map for country ", country.get_identifier());
return false;
}
+ }
+ CountryHistoryMap& country_history = it->second;
- return _load_country_history_entry(game_manager, dataloader, country, entry, value);
- })(root);
-
- return ret;
+ return country_history._load_history_file(
+ game_manager, dataloader, game_manager.get_military_manager().get_deployment_manager(), root
+ );
}
diff --git a/src/openvic-simulation/history/CountryHistory.hpp b/src/openvic-simulation/history/CountryHistory.hpp
index 3109d4f..ffb44c0 100644
--- a/src/openvic-simulation/history/CountryHistory.hpp
+++ b/src/openvic-simulation/history/CountryHistory.hpp
@@ -5,6 +5,7 @@
#include "openvic-simulation/country/Country.hpp"
#include "openvic-simulation/history/Bookmark.hpp"
+#include "openvic-simulation/history/HistoryMap.hpp"
#include "openvic-simulation/map/Province.hpp"
#include "openvic-simulation/military/Deployment.hpp"
#include "openvic-simulation/politics/Government.hpp"
@@ -17,86 +18,64 @@
#include "openvic-simulation/types/Date.hpp"
namespace OpenVic {
- struct CountryHistoryManager;
+ struct CountryHistoryMap;
- struct CountryHistory {
- friend struct CountryHistoryManager;
+ struct CountryHistoryEntry : HistoryEntry {
+ friend struct CountryHistoryMap;
private:
- Culture const* primary_culture;
- std::vector<Culture const*> accepted_cultures;
- Religion const* religion;
- CountryParty const* ruling_party;
- Date last_election;
- decimal_map_t<Ideology const*> upper_house;
- Province const* capital;
- GovernmentType const* government_type;
- fixed_point_t plurality;
- NationalValue const* national_value;
- bool civilised;
- fixed_point_t prestige;
- std::vector<Reform const*> reforms;
- Deployment const* inital_oob;
+ Country const& PROPERTY(country);
+
+ std::optional<Culture const*> PROPERTY(primary_culture);
+ std::vector<Culture const*> PROPERTY(accepted_cultures);
+ std::optional<Religion const*> PROPERTY(religion);
+ std::optional<CountryParty const*> PROPERTY(ruling_party);
+ std::optional<Date> PROPERTY(last_election);
+ decimal_map_t<Ideology const*> PROPERTY(upper_house);
+ std::optional<Province const*> PROPERTY(capital);
+ std::optional<GovernmentType const*> PROPERTY(government_type);
+ std::optional<fixed_point_t> PROPERTY(plurality);
+ std::optional<NationalValue const*> PROPERTY(national_value);
+ std::optional<bool> PROPERTY(civilised);
+ std::optional<fixed_point_t> PROPERTY(prestige);
+ std::vector<Reform const*> PROPERTY(reforms);
+ std::optional<Deployment const*> PROPERTY(inital_oob);
// TODO: technologies, tech schools, and inventions when PR#51 merged
// TODO: starting foreign investment
- CountryHistory(
- Culture const* new_primary_culture, std::vector<Culture const*>&& new_accepted_cultures,
- Religion const* new_religion, CountryParty const* new_ruling_party, Date new_last_election,
- decimal_map_t<Ideology const*>&& new_upper_house, Province const* new_capital,
- GovernmentType const* new_government_type, fixed_point_t new_plurality, NationalValue const* new_national_value,
- bool new_civilised, fixed_point_t new_prestige, std::vector<Reform const*>&& new_reforms,
- Deployment const* new_inital_oob
- );
+ CountryHistoryEntry(Country const& new_country, Date new_date);
+ };
- public:
- Culture const* get_primary_culture() const;
- std::vector<Culture const*> const& get_accepted_cultures() const;
- Religion const* get_religion() const;
- CountryParty const* get_ruling_party() const;
- Date get_last_election() const;
- decimal_map_t<Ideology const*> const& get_upper_house() const;
- Province const* get_capital() const;
- GovernmentType const* get_government_type() const;
- fixed_point_t get_plurality() const;
- NationalValue const* get_national_value() const;
- bool is_civilised() const;
- fixed_point_t get_prestige() const;
- std::vector<Reform const*> const& get_reforms() const;
- Deployment const* get_inital_oob() const;
+ struct CountryHistoryManager;
+
+ struct CountryHistoryMap : HistoryMap<CountryHistoryEntry, Dataloader const&, DeploymentManager&> {
+ friend struct CountryHistoryManager;
+
+ private:
+ Country const& PROPERTY(country);
+
+ protected:
+ CountryHistoryMap(Country const& new_country);
+
+ std::unique_ptr<CountryHistoryEntry> _make_entry(Date date) const override;
+ bool _load_history_entry(
+ GameManager const& game_manager, Dataloader const& dataloader, DeploymentManager& deployment_manager,
+ CountryHistoryEntry& entry, ast::NodeCPtr root
+ ) override;
};
struct CountryHistoryManager {
private:
- using country_history_map_t = std::map<Date, CountryHistory>;
- std::map<Country const*, country_history_map_t> country_histories;
+ std::map<Country const*, CountryHistoryMap> country_histories;
bool locked = false;
- inline bool _load_country_history_entry(
- GameManager& game_manager, Dataloader const& dataloader, Country const& country, Date date,
- ast::NodeCPtr root
- );
-
public:
- CountryHistoryManager() {}
-
- bool add_country_history_entry(
- Country const* country, Date date, Culture const* primary_culture, std::vector<Culture const*>&& accepted_cultures,
- Religion const* religion, CountryParty const* ruling_party, Date last_election,
- decimal_map_t<Ideology const*>&& upper_house, Province const* capital, GovernmentType const* government_type,
- fixed_point_t plurality, NationalValue const* national_value, bool civilised, fixed_point_t prestige,
- std::vector<Reform const*>&& reforms, std::optional<Deployment const*> initial_oob, bool updated_accepted_cultures,
- bool updated_upper_house, bool updated_reforms
- );
+ CountryHistoryManager() = default;
void lock_country_histories();
bool is_locked() const;
- /* Returns history of country at date, if date doesn't have an entry returns
- * closest entry before date. Return can be nullptr if an error occurs. */
- CountryHistory const* get_country_history(Country const* country, Date entry) const;
- /* Returns history of country at bookmark date. Return can be nullptr if an error occurs. */
- inline CountryHistory const* get_country_history(Country const* country, Bookmark const* entry) const;
+ CountryHistoryMap const* get_country_history(Country const* country) const;
bool load_country_history_file(
GameManager& game_manager, Dataloader const& dataloader, Country const& country, ast::NodeCPtr root
diff --git a/src/openvic-simulation/history/HistoryMap.cpp b/src/openvic-simulation/history/HistoryMap.cpp
new file mode 100644
index 0000000..b669208
--- /dev/null
+++ b/src/openvic-simulation/history/HistoryMap.cpp
@@ -0,0 +1,15 @@
+#include "HistoryMap.hpp"
+
+#include "openvic-simulation/GameManager.hpp"
+
+using namespace OpenVic;
+
+HistoryEntry::HistoryEntry(Date new_date) : date { new_date } {}
+
+Date OpenVic::_get_start_date(GameManager const& game_manager) {
+ return game_manager.get_define_manager().get_start_date();
+}
+
+Date OpenVic::_get_end_date(GameManager const& game_manager) {
+ return game_manager.get_define_manager().get_end_date();
+}
diff --git a/src/openvic-simulation/history/HistoryMap.hpp b/src/openvic-simulation/history/HistoryMap.hpp
new file mode 100644
index 0000000..64d886d
--- /dev/null
+++ b/src/openvic-simulation/history/HistoryMap.hpp
@@ -0,0 +1,110 @@
+#pragma once
+
+#include <map>
+#include <memory>
+
+#include "openvic-simulation/dataloader/NodeTools.hpp"
+#include "openvic-simulation/types/Date.hpp"
+
+namespace OpenVic {
+
+ struct HistoryEntry {
+ private:
+ Date PROPERTY(date);
+
+ protected:
+ HistoryEntry(Date new_date);
+ };
+
+ struct GameManager;
+
+ /* Helper functions to avoid cyclic dependency issues */
+ Date _get_start_date(GameManager const& game_manager);
+ Date _get_end_date(GameManager const& game_manager);
+
+ template<std::derived_from<HistoryEntry> _Entry, typename... Args>
+ struct HistoryMap {
+ using entry_type = _Entry;
+
+ private:
+ std::map<Date, std::unique_ptr<entry_type>> PROPERTY(entries);
+
+ bool _try_load_history_entry(GameManager const& game_manager, Args... args, Date date, ast::NodeCPtr root) {
+ typename decltype(entries)::iterator it = entries.find(date);
+ if (it == entries.end()) {
+ const std::pair<typename decltype(entries)::iterator, bool> result = entries.emplace(date, _make_entry(date));
+ if (result.second) {
+ it = result.first;
+ } else {
+ Logger::error("Failed to create history entry at date ", date);
+ return false;
+ }
+ }
+ return _load_history_entry(game_manager, args..., *it->second, root);
+ }
+
+ protected:
+ HistoryMap() = default;
+
+ virtual std::unique_ptr<entry_type> _make_entry(Date date) const = 0;
+
+ virtual bool _load_history_entry(
+ GameManager const& game_manager, Args... args, entry_type& entry, ast::NodeCPtr root
+ ) = 0;
+
+ bool _load_history_file(GameManager const& game_manager, Args... args, ast::NodeCPtr root) {
+ return _try_load_history_entry(game_manager, args..., _get_start_date(game_manager), root);
+ }
+
+ bool _load_history_sub_entry_callback(
+ GameManager const& game_manager, Args... args, Date date, ast::NodeCPtr root, std::string_view key,
+ ast::NodeCPtr value, NodeTools::key_value_callback_t default_callback = NodeTools::key_value_invalid_callback
+ ) {
+ /* Date blocks (loaded into the corresponding HistoryEntry) */
+ bool is_date = false;
+ const Date sub_date { Date::from_string(key, &is_date, true) };
+ if (is_date) {
+ if (sub_date <= date) {
+ Logger::error("History entry ", sub_date, " defined before parent entry date ", date);
+ return false;
+ }
+ const Date end_date = _get_end_date(game_manager);
+ if (sub_date > end_date) {
+ Logger::error("History entry ", sub_date, " defined after end date ", end_date);
+ return false;
+ }
+ if (_try_load_history_entry(game_manager, args..., sub_date, value)) {
+ return true;
+ } else {
+ Logger::error("Failed to load history entry at date ", sub_date);
+ return false;
+ }
+ }
+
+ return default_callback(key, value);
+ }
+
+ public:
+ /* Returns history entry at specific date, if date doesn't have an entry returns nullptr. */
+ entry_type const* get_entry(Date date) const {
+ typename decltype(entries)::const_iterator it = entries.find(date);
+ if (it != entries.end()) {
+ return it->second.get();
+ }
+ return nullptr;
+ }
+ /* Returns history entries up to date as an ordered list of entries. */
+ std::vector<entry_type const*> get_entries(Date end) const {
+ std::vector<entry_type const*> ret;
+ for (typename decltype(entries)::value_type const& entry : entries) {
+ if (entry.first <= end) {
+ ret.push_back(entry.second.get());
+ }
+ }
+ std::sort(ret.begin(), ret.end(), [](entry_type const* lhs, entry_type const* rhs) -> bool {
+ return lhs->get_date() < rhs->get_date();
+ });
+ return ret;
+ }
+ };
+}
diff --git a/src/openvic-simulation/history/ProvinceHistory.cpp b/src/openvic-simulation/history/ProvinceHistory.cpp
index 65e37e1..141d256 100644
--- a/src/openvic-simulation/history/ProvinceHistory.cpp
+++ b/src/openvic-simulation/history/ProvinceHistory.cpp
@@ -6,179 +6,17 @@
using namespace OpenVic;
using namespace OpenVic::NodeTools;
-ProvinceHistory::ProvinceHistory(
- Country const* new_owner, Country const* new_controller, Province::colony_status_t new_colonial, bool new_slave,
- std::vector<Country const*>&& new_cores, Good const* new_rgo, Province::life_rating_t new_life_rating,
- TerrainType const* new_terrain_type, building_level_map_t&& new_buildings,
- decimal_map_t<Ideology const*>&& new_party_loyalties
-) : owner { new_owner }, controller { new_controller }, colonial { new_colonial }, slave { new_slave },
- cores { std::move(new_cores) }, rgo { new_rgo }, life_rating { new_life_rating }, terrain_type { new_terrain_type },
- buildings { std::move(new_buildings) }, party_loyalties { std::move(new_party_loyalties) } {}
+ProvinceHistoryEntry::ProvinceHistoryEntry(Province const& new_province, Date new_date)
+ : HistoryEntry { new_date }, province { new_province } {}
-Country const* ProvinceHistory::get_owner() const {
- return owner;
-}
-
-Country const* ProvinceHistory::get_controller() const {
- return controller;
-}
-
-Province::colony_status_t ProvinceHistory::get_colony_status() const {
- return colonial;
-}
-
-bool ProvinceHistory::is_slave() const {
- return slave;
-}
-
-std::vector<Country const*> const& ProvinceHistory::get_cores() const {
- return cores;
-}
-
-bool ProvinceHistory::is_core_of(Country const* country) const {
- return std::find(cores.begin(), cores.end(), country) != cores.end();
-}
-
-Good const* ProvinceHistory::get_rgo() const {
- return rgo;
-}
+ProvinceHistoryMap::ProvinceHistoryMap(Province const& new_province) : province { new_province } {}
-Province::life_rating_t ProvinceHistory::get_life_rating() const {
- return life_rating;
+std::unique_ptr<ProvinceHistoryEntry> ProvinceHistoryMap::_make_entry(Date date) const {
+ return std::unique_ptr<ProvinceHistoryEntry> { new ProvinceHistoryEntry { province, date } };
}
-TerrainType const* ProvinceHistory::get_terrain_type() const {
- return terrain_type;
-}
-
-ProvinceHistory::building_level_map_t const& ProvinceHistory::get_buildings() const {
- return buildings;
-}
-
-decimal_map_t<Ideology const*> const& ProvinceHistory::get_party_loyalties() const {
- return party_loyalties;
-}
-
-bool ProvinceHistoryManager::add_province_history_entry(
- Province const* province, Date date, Country const* owner, Country const* controller,
- std::optional<Province::colony_status_t>&& colonial, std::optional<bool>&& slave, std::vector<Country const*>&& cores,
- std::vector<Country const*>&& remove_cores, Good const* rgo, std::optional<Province::life_rating_t>&& life_rating,
- TerrainType const* terrain_type, std::optional<ProvinceHistory::building_level_map_t>&& buildings,
- std::optional<decimal_map_t<Ideology const*>>&& party_loyalties
-) {
- if (locked) {
- Logger::error("Cannot add new history entry to province history registry: locked!");
- return false;
- }
-
- /* combine duplicate histories, priority to current (defined later) */
- auto& province_registry = province_histories[province];
- const auto existing_entry = province_registry.find(date);
-
- if (existing_entry != province_registry.end()) {
- if (owner != nullptr) {
- existing_entry->second.owner = owner;
- }
- if (controller != nullptr) {
- existing_entry->second.controller = controller;
- }
- if (rgo != nullptr) {
- existing_entry->second.rgo = rgo;
- }
- if (terrain_type != nullptr) {
- existing_entry->second.terrain_type = terrain_type;
- }
- if (colonial) {
- existing_entry->second.colonial = *colonial;
- }
- if (slave) {
- existing_entry->second.slave = *slave;
- }
- if (life_rating) {
- existing_entry->second.life_rating = *life_rating;
- }
- if (buildings) {
- existing_entry->second.buildings = std::move(*buildings);
- }
- if (party_loyalties) {
- existing_entry->second.party_loyalties = std::move(*party_loyalties);
- }
- // province history cores are additive
- existing_entry->second.cores.insert(existing_entry->second.cores.end(), cores.begin(), cores.end());
- for (Country const* which : remove_cores) {
- const auto core = std::find(cores.begin(), cores.end(), which);
- if (core == cores.end()) {
- Logger::error(
- "In history of province ", province->get_identifier(), " tried to remove nonexistant core of country: ",
- which->get_identifier(), " at date ", date.to_string()
- );
- return false;
- }
- existing_entry->second.cores.erase(core);
- }
- } else {
- province_registry.emplace(date, ProvinceHistory {
- owner, controller, *colonial, *slave, std::move(cores), rgo, *life_rating,
- terrain_type, std::move(*buildings), std::move(*party_loyalties)
- });
- }
- return true;
-}
-
-void ProvinceHistoryManager::lock_province_histories() {
- for (auto const& entry : province_histories) {
- if (entry.second.size() == 0) {
- Logger::error(
- "Attempted to lock province histories - province ", entry.first->get_identifier(), " has no history entries!"
- );
- }
- }
- Logger::info("Locked province history registry after registering ", province_histories.size(), " items");
- locked = true;
-}
-
-bool ProvinceHistoryManager::is_locked() const {
- return locked;
-}
-
-ProvinceHistory const* ProvinceHistoryManager::get_province_history(Province const* province, Date entry) const {
- Date closest_entry;
- auto province_registry = province_histories.find(province);
-
- if (province_registry == province_histories.end()) {
- Logger::error("Attempted to access history of undefined province ", province->get_identifier());
- return nullptr;
- }
-
- for (auto const& current : province_registry->second) {
- if (current.first == entry) {
- return &current.second;
- }
- if (current.first > entry) {
- continue;
- }
- if (current.first > closest_entry && current.first < entry) {
- closest_entry = current.first;
- }
- }
-
- auto entry_registry = province_registry->second.find(closest_entry);
- if (entry_registry != province_registry->second.end()) {
- return &entry_registry->second;
- }
- /* warned about lack of entries earlier, return nullptr */
- return nullptr;
-}
-
-inline ProvinceHistory const* ProvinceHistoryManager::get_province_history(
- Province const* province, Bookmark const* bookmark
-) const {
- return get_province_history(province, bookmark->get_date());
-}
-
-inline bool ProvinceHistoryManager::_load_province_history_entry(
- GameManager const& game_manager, Province const& province, Date date, ast::NodeCPtr root,
- bool is_base_entry
+bool ProvinceHistoryMap::_load_history_entry(
+ GameManager const& game_manager, ProvinceHistoryEntry& entry, ast::NodeCPtr root
) {
BuildingManager const& building_manager = game_manager.get_economy_manager().get_building_manager();
CountryManager const& country_manager = game_manager.get_country_manager();
@@ -186,77 +24,52 @@ inline bool ProvinceHistoryManager::_load_province_history_entry(
IdeologyManager const& ideology_manager = game_manager.get_politics_manager().get_ideology_manager();
TerrainTypeManager const& terrain_type_manager = game_manager.get_map().get_terrain_type_manager();
- Country const* owner = nullptr;
- Country const* controller = nullptr;
- std::vector<Country const*> cores {};
- std::vector<Country const*> remove_cores {};
- Good const* rgo = nullptr;
- std::optional<Province::colony_status_t> colonial;
- std::optional<Province::life_rating_t> life_rating;
- std::optional<bool> slave;
- TerrainType const* terrain_type = nullptr;
- std::optional<ProvinceHistory::building_level_map_t> buildings;
- std::optional<decimal_map_t<Ideology const*>> party_loyalties;
-
using enum Province::colony_status_t;
static const string_map_t<Province::colony_status_t> colony_status_map {
{ "0", STATE }, { "1", PROTECTORATE }, { "2", COLONY }
};
- bool ret = expect_dictionary_keys_and_default(
- [&building_manager, &buildings, date, is_base_entry](std::string_view key, ast::NodeCPtr value) -> bool {
+ return expect_dictionary_keys_and_default(
+ [this, &game_manager, &building_manager, &entry](
+ std::string_view key, ast::NodeCPtr value) -> bool {
// used for province buildings like forts or railroads
Building const* building = building_manager.get_building_by_identifier(key);
if (building != nullptr) {
- return expect_uint<Building::level_t>([&buildings, building](Building::level_t level) -> bool {
- if(!buildings.has_value())
- buildings = decltype(buildings)::value_type {};
- buildings->emplace(building, level);
+ return expect_uint<Building::level_t>([&entry, building](Building::level_t level) -> bool {
+ entry.buildings[building] = level;
return true;
})(value);
}
- /* Date blocks are skipped here (they get their own invocation of _load_province_history_entry) */
- bool is_date = false;
- const Date sub_date { Date::from_string(key, &is_date, true) };
- if (is_date) {
- if (is_base_entry) {
- return true;
- } else {
- Logger::error(
- "Province history nested multiple levels deep! ", sub_date, " is inside ", date,
- " (Any date blocks within a date block are ignored)"
- );
- return false;
- }
- }
-
- return key_value_invalid_callback(key, value);
+ return _load_history_sub_entry_callback(game_manager, entry.get_date(), value, key, value);
},
- "owner", ZERO_OR_ONE, country_manager.expect_country_identifier(assign_variable_callback_pointer(owner)),
- "controller", ZERO_OR_ONE, country_manager.expect_country_identifier(assign_variable_callback_pointer(controller)),
+ "owner", ZERO_OR_ONE,
+ country_manager.expect_country_identifier(assign_variable_callback_pointer(entry.owner)),
+ "controller", ZERO_OR_ONE,
+ country_manager.expect_country_identifier(assign_variable_callback_pointer(entry.controller)),
"add_core", ZERO_OR_MORE, country_manager.expect_country_identifier(
- [&cores](Country const& core) -> bool {
- cores.push_back(&core);
+ [&entry](Country const& core) -> bool {
+ entry.add_cores.push_back(&core);
return true;
}
),
"remove_core", ZERO_OR_MORE, country_manager.expect_country_identifier(
- [&remove_cores](Country const& core) -> bool {
- remove_cores.push_back(&core);
+ [&entry](Country const& core) -> bool {
+ entry.remove_cores.push_back(&core);
return true;
}
),
"colonial", ZERO_OR_ONE,
- expect_identifier(expect_mapped_string(colony_status_map, assign_variable_callback(colonial))),
- "colony", ZERO_OR_ONE, expect_identifier(expect_mapped_string(colony_status_map, assign_variable_callback(colonial))),
- "is_slave", ZERO_OR_ONE, expect_bool(assign_variable_callback(slave)),
- "trade_goods", ZERO_OR_ONE, good_manager.expect_good_identifier(assign_variable_callback_pointer(rgo)),
- "life_rating", ZERO_OR_ONE, expect_uint<Province::life_rating_t>(assign_variable_callback(life_rating)),
+ expect_identifier(expect_mapped_string(colony_status_map, assign_variable_callback(entry.colonial))),
+ "colony", ZERO_OR_ONE,
+ expect_identifier(expect_mapped_string(colony_status_map, assign_variable_callback(entry.colonial))),
+ "is_slave", ZERO_OR_ONE, expect_bool(assign_variable_callback(entry.slave)),
+ "trade_goods", ZERO_OR_ONE, good_manager.expect_good_identifier(assign_variable_callback_pointer(entry.rgo)),
+ "life_rating", ZERO_OR_ONE, expect_uint<Province::life_rating_t>(assign_variable_callback(entry.life_rating)),
"terrain", ZERO_OR_ONE, terrain_type_manager.expect_terrain_type_identifier(
- assign_variable_callback_pointer(terrain_type)
+ assign_variable_callback_pointer(entry.terrain_type)
),
- "party_loyalty", ZERO_OR_MORE, [&ideology_manager, &party_loyalties](ast::NodeCPtr node) -> bool {
+ "party_loyalty", ZERO_OR_MORE, [&ideology_manager, &entry](ast::NodeCPtr node) -> bool {
Ideology const* ideology = nullptr;
fixed_point_t amount = 0; // percent I do believe
@@ -266,12 +79,10 @@ inline bool ProvinceHistoryManager::_load_province_history_entry(
),
"loyalty_value", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(amount))
)(node);
- if(!party_loyalties.has_value())
- party_loyalties = decltype(party_loyalties)::value_type {};
- party_loyalties->emplace(ideology, amount);
+ entry.party_loyalties[ideology] = amount;
return ret;
},
- "state_building", ZERO_OR_MORE, [&building_manager, &buildings](ast::NodeCPtr node) -> bool {
+ "state_building", ZERO_OR_MORE, [&building_manager, &entry](ast::NodeCPtr node) -> bool {
Building const* building = nullptr;
uint8_t level = 0;
@@ -282,47 +93,79 @@ inline bool ProvinceHistoryManager::_load_province_history_entry(
),
"upgrade", ZERO_OR_ONE, success_callback // doesn't appear to have an effect
)(node);
- if(!buildings.has_value())
- buildings = decltype(buildings)::value_type {};
- buildings->emplace(building, level);
+ entry.buildings[building] = level;
return ret;
}
)(root);
+}
- ret &= add_province_history_entry(
- &province, date, owner, controller, std::move(colonial), std::move(slave), std::move(cores), std::move(remove_cores),
- rgo, std::move(life_rating), terrain_type, std::move(buildings), std::move(party_loyalties)
- );
- return ret;
+void ProvinceHistoryManager::lock_province_histories(Map const& map, bool detailed_errors) {
+ std::vector<bool> province_checklist(map.get_province_count());
+ for (decltype(province_histories)::value_type const& entry : province_histories) {
+ province_checklist[entry.first->get_index() - 1] = true;
+ }
+
+ size_t missing = 0;
+ for (size_t idx = 0; idx < province_checklist.size(); ++idx) {
+ if (!province_checklist[idx]) {
+ Province const& province = *map.get_province_by_index(idx + 1);
+ if (!province.get_water()) {
+ if (detailed_errors) {
+ Logger::warning("Province history missing for province: ", province.get_identifier());
+ }
+ missing++;
+ }
+ }
+ }
+ if (missing > 0) {
+ Logger::warning("Province history is missing for ", missing, " provinces");
+ }
+
+ Logger::info("Locked province history registry after registering ", province_histories.size(), " items");
+ locked = true;
+}
+
+bool ProvinceHistoryManager::is_locked() const {
+ return locked;
+}
+
+ProvinceHistoryMap const* ProvinceHistoryManager::get_province_history(Province const* province) const {
+ if (province == nullptr) {
+ Logger::error("Attempted to access history of null province");
+ return nullptr;
+ }
+ decltype(province_histories)::const_iterator province_registry = province_histories.find(province);
+ if (province_registry != province_histories.end()) {
+ return &province_registry->second;
+ } else {
+ Logger::error("Attempted to access history of province ", province->get_identifier(), " but none has been defined!");
+ return nullptr;
+ }
}
bool ProvinceHistoryManager::load_province_history_file(
GameManager const& game_manager, Province const& province, ast::NodeCPtr root
) {
- bool ret = _load_province_history_entry(
- game_manager, province, game_manager.get_define_manager().get_start_date(), root, true
- );
-
- ret &= expect_dictionary(
- [this, &game_manager, &province, end_date = game_manager.get_define_manager().get_end_date()](
- std::string_view key, ast::NodeCPtr value) -> bool {
- bool is_date = false;
- const Date entry = Date::from_string(key, &is_date, true);
- if (!is_date) {
- return true;
- }
-
- if (entry > end_date) {
- Logger::error(
- "History entry ", entry, " of province ", province.get_identifier(),
- " defined after defined end date ", end_date
- );
- return false;
- }
+ if (locked) {
+ Logger::error(
+ "Attempted to load province history file for ", province.get_identifier(),
+ " after province history registry was locked!"
+ );
+ return false;
+ }
- return _load_province_history_entry(game_manager, province, entry, value, false);
+ decltype(province_histories)::iterator it = province_histories.find(&province);
+ if (it == province_histories.end()) {
+ const std::pair<decltype(province_histories)::iterator, bool> result =
+ province_histories.emplace(&province, ProvinceHistoryMap { province });
+ if (result.second) {
+ it = result.first;
+ } else {
+ Logger::error("Failed to create province history map for province ", province.get_identifier());
+ return false;
}
- )(root);
+ }
+ ProvinceHistoryMap& province_history = it->second;
- return ret;
+ return province_history._load_history_file(game_manager, root);
}
diff --git a/src/openvic-simulation/history/ProvinceHistory.hpp b/src/openvic-simulation/history/ProvinceHistory.hpp
index fb90cc4..5a18723 100644
--- a/src/openvic-simulation/history/ProvinceHistory.hpp
+++ b/src/openvic-simulation/history/ProvinceHistory.hpp
@@ -8,84 +8,64 @@
#include "openvic-simulation/economy/Building.hpp"
#include "openvic-simulation/economy/Good.hpp"
#include "openvic-simulation/history/Bookmark.hpp"
+#include "openvic-simulation/history/HistoryMap.hpp"
#include "openvic-simulation/map/Province.hpp"
#include "openvic-simulation/map/TerrainType.hpp"
namespace OpenVic {
- struct ProvinceHistoryManager;
+ struct ProvinceHistoryMap;
- struct ProvinceHistory {
- friend struct ProvinceHistoryManager;
+ struct ProvinceHistoryEntry : HistoryEntry {
+ friend struct ProvinceHistoryMap;
using building_level_map_t = std::map<Building const*, Building::level_t>;
private:
- Country const* owner;
- Country const* controller;
- Province::colony_status_t colonial;
- bool slave;
- std::vector<Country const*> cores; // non-standard, maintains cores between entries
- Good const* rgo;
- Province::life_rating_t life_rating;
- TerrainType const* terrain_type;
- building_level_map_t buildings;
- decimal_map_t<Ideology const*> party_loyalties;
-
- ProvinceHistory(
- Country const* new_owner, Country const* new_controller, Province::colony_status_t new_colonial, bool new_slave,
- std::vector<Country const*>&& new_cores, Good const* new_rgo, Province::life_rating_t new_life_rating,
- TerrainType const* new_terrain_type, building_level_map_t&& new_buildings,
- decimal_map_t<Ideology const*>&& new_party_loyalties
- );
+ Province const& PROPERTY(province);
- public:
- Country const* get_owner() const;
- Country const* get_controller() const;
- Province::colony_status_t get_colony_status() const; // 0 = state, 1 = protectorate, 2 = colony
- bool is_slave() const;
- std::vector<Country const*> const& get_cores() const;
- bool is_core_of(Country const* country) const;
- Good const* get_rgo() const;
- Province::life_rating_t get_life_rating() const;
- TerrainType const* get_terrain_type() const;
- building_level_map_t const& get_buildings() const;
- decimal_map_t<Ideology const*> const& get_party_loyalties() const;
+ std::optional<Country const*> PROPERTY(owner);
+ std::optional<Country const*> PROPERTY(controller);
+ std::optional<Province::colony_status_t> PROPERTY(colonial);
+ std::optional<bool> PROPERTY(slave);
+ std::vector<Country const*> PROPERTY(add_cores);
+ std::vector<Country const*> PROPERTY(remove_cores);
+ std::optional<Good const*> PROPERTY(rgo);
+ std::optional<Province::life_rating_t> PROPERTY(life_rating);
+ std::optional<TerrainType const*> PROPERTY(terrain_type);
+ building_level_map_t PROPERTY(buildings);
+ decimal_map_t<Ideology const*> PROPERTY(party_loyalties);
+
+ ProvinceHistoryEntry(Province const& new_province, Date new_date);
+ };
+
+ struct ProvinceHistoryManager;
+
+ struct ProvinceHistoryMap : HistoryMap<ProvinceHistoryEntry> {
+ friend struct ProvinceHistoryManager;
+
+ private:
+ Province const& PROPERTY(province);
+
+ protected:
+ ProvinceHistoryMap(Province const& new_province);
+
+ std::unique_ptr<ProvinceHistoryEntry> _make_entry(Date date) const override;
+ bool _load_history_entry(GameManager const& game_manager, ProvinceHistoryEntry& entry, ast::NodeCPtr root) override;
};
struct ProvinceHistoryManager {
private:
- std::map<Province const*, std::map<Date, ProvinceHistory>> province_histories;
+ std::map<Province const*, ProvinceHistoryMap> PROPERTY(province_histories);
bool locked = false;
- inline bool _load_province_history_entry(
- GameManager const& game_manager, Province const& province, Date date, ast::NodeCPtr root,
- bool is_base_entry
- );
-
public:
- ProvinceHistoryManager() {}
-
- bool add_province_history_entry(
- Province const* province, Date date, Country const* owner, Country const* controller,
- std::optional<Province::colony_status_t>&& colonial, std::optional<bool>&& slave,
- std::vector<Country const*>&& cores, // additive to existing entries
- std::vector<Country const*>&& remove_cores, // existing cores that need to be removed
- Good const* rgo, std::optional<Province::life_rating_t>&& life_rating, TerrainType const* terrain_type,
- std::optional<ProvinceHistory::building_level_map_t>&& buildings,
- std::optional<decimal_map_t<Ideology const*>>&& party_loyalties
- );
-
- void lock_province_histories();
+ ProvinceHistoryManager() = default;
+
+ void lock_province_histories(Map const& map, bool detailed_errors);
bool is_locked() const;
- /* Returns history of province at date, if date doesn't have an entry returns closest entry before date.
- * Return can be nullptr if an error occurs. */
- ProvinceHistory const* get_province_history(Province const* province, Date entry) const;
- /* Returns history of province at bookmark date. Return can be nullptr if an error occurs. */
- inline ProvinceHistory const* get_province_history(Province const* province, Bookmark const* bookmark) const;
+ ProvinceHistoryMap const* get_province_history(Province const* province) const;
- bool load_province_history_file(
- GameManager const& game_manager, Province const& province, ast::NodeCPtr root
- );
+ bool load_province_history_file(GameManager const& game_manager, Province const& province, ast::NodeCPtr root);
};
} // namespace OpenVic