Skip to content

Government salaries and social income #363

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions src/openvic-simulation/InstanceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,13 @@ InstanceManager::InstanceManager(
new_definition_manager.get_economy_manager().get_production_type_manager()
},
global_flags { "global" },
country_instance_manager { new_definition_manager.get_country_definition_manager() },
country_instance_manager {
new_definition_manager.get_country_definition_manager(),
new_definition_manager.get_modifier_manager().get_modifier_effect_cache(),
new_definition_manager.get_define_manager().get_country_defines(),
new_definition_manager.get_define_manager().get_pops_defines(),
new_definition_manager.get_pop_manager().get_pop_types()
},
unit_instance_manager {
new_definition_manager.get_pop_manager().get_culture_manager(),
new_definition_manager.get_military_manager().get_leader_trait_manager(),
Expand Down Expand Up @@ -88,15 +94,15 @@ void InstanceManager::update_gamestate() {
* SS-98, SS-101
*/
void InstanceManager::tick() {
country_instance_manager.country_manager_reset_before_tick();

today++;

Logger::info("Tick: ", today);

// Tick...
country_instance_manager.country_manager_tick_before_map(*this);
map_instance.map_tick();
country_instance_manager.country_manager_tick(*this);
country_instance_manager.country_manager_tick_after_map(*this);
unit_instance_manager.tick();
market_instance.execute_orders();

Expand Down
259 changes: 242 additions & 17 deletions src/openvic-simulation/country/CountryInstance.cpp

Large diffs are not rendered by default.

95 changes: 86 additions & 9 deletions src/openvic-simulation/country/CountryInstance.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <utility>
#include <vector>

#include "openvic-simulation/country/SharedCountryValues.hpp"
#include "openvic-simulation/modifier/ModifierSum.hpp"
#include "openvic-simulation/politics/Ideology.hpp"
#include "openvic-simulation/politics/Rule.hpp"
Expand Down Expand Up @@ -51,6 +52,8 @@ namespace OpenVic {
struct GameRulesManager;
struct CountryDefines;
struct EconomyDefines;
struct PopsDefines;
struct Pop;

static constexpr Timespan RECENT_WAR_LOSS_TIME_LIMIT = Timespan::from_years(5);

Expand Down Expand Up @@ -91,6 +94,7 @@ namespace OpenVic {

GameRulesManager const& game_rules_manager;
CountryDefines const& country_defines;
SharedCountryValues const& shared_country_values;

colour_t PROPERTY(colour); // Cached to avoid searching government overrides for every province
ProvinceInstance* PROPERTY_PTR(capital, nullptr);
Expand Down Expand Up @@ -131,21 +135,47 @@ namespace OpenVic {
// TODO - total amount of each good produced

/* Budget */
// TODO - cash stockpile change over last 30 days
moveable_atomic_fixed_point_t PROPERTY(cash_stockpile);
std::unique_ptr<std::mutex> taxable_income_mutex;
fixed_point_t PROPERTY(gold_income);
IndexedMap<PopType, fixed_point_t> PROPERTY(taxable_income_by_pop_type);
IndexedMap<Strata, fixed_point_t> PROPERTY(effective_tax_rate_by_strata);
IndexedMap<Strata, SliderValue> PROPERTY(tax_rate_slider_value_by_strata);

fixed_point_t PROPERTY(administrative_efficiency);
constexpr fixed_point_t get_corruption_cost_multiplier() const {
return 2 - administrative_efficiency;
}

//store per slider per good: desired, bought & cost
//store purchase record from last tick and prediction next tick
SliderValue PROPERTY(land_spending_slider_value);
SliderValue PROPERTY(naval_spending_slider_value);
SliderValue PROPERTY(construction_spending_slider_value);
SliderValue PROPERTY(education_spending_slider_value);

SliderValue PROPERTY(administration_spending_slider_value);
SliderValue PROPERTY(social_spending_slider_value);
fixed_point_t PROPERTY(actual_administration_spending);
fixed_point_t PROPERTY(projected_administration_spending_unscaled_by_slider);

SliderValue PROPERTY(education_spending_slider_value);
fixed_point_t PROPERTY(actual_education_spending);
fixed_point_t PROPERTY(projected_education_spending_unscaled_by_slider);

SliderValue PROPERTY(military_spending_slider_value);
fixed_point_t PROPERTY(actual_military_spending);
fixed_point_t PROPERTY(projected_military_spending_unscaled_by_slider);

SliderValue PROPERTY(social_spending_slider_value);
fixed_point_t PROPERTY(actual_social_spending);
fixed_point_t PROPERTY(projected_pensions_spending_unscaled_by_slider);
fixed_point_t PROPERTY(projected_unemployment_subsidies_spending_unscaled_by_slider);

SliderValue PROPERTY(tariff_rate_slider_value);
// TODO - cash stockpile change over last 30 days
//TODO actual & projected tariff income/expense

//TODO actual factory subsidies
//projected cost is UI only and lists the different factories

/* Technology */
IndexedMap<Technology, unlock_level_t> PROPERTY(technology_unlock_levels);
Expand Down Expand Up @@ -316,6 +346,7 @@ namespace OpenVic {
decltype(ship_type_unlock_levels)::keys_type const& ship_type_unlock_levels_keys,
decltype(tax_rate_slider_value_by_strata)::keys_type const& strata_keys,
GameRulesManager const& new_game_rules_manager,
SharedCountryValues const& new_shared_country_values,
GoodInstanceManager& new_good_instance_manager,
CountryDefines const& new_country_defines,
EconomyDefines const& new_economy_defines
Expand Down Expand Up @@ -523,7 +554,45 @@ namespace OpenVic {

private:
void _update_production(DefineManager const& define_manager);
void _update_budget(DefineManager const& define_manager, ModifierEffectCache const& modifier_effect_cache);
void _update_budget();

//base here means not scaled by slider or pop size
constexpr fixed_point_t calculate_administration_salary_base(
SharedPopTypeValues const& pop_type_values,
const fixed_point_t corruption_cost_multiplier
) const {
return pop_type_values.get_administration_salary_base() * corruption_cost_multiplier;
}
constexpr fixed_point_t calculate_education_salary_base(
SharedPopTypeValues const& pop_type_values,
const fixed_point_t corruption_cost_multiplier
) const {
return pop_type_values.get_education_salary_base() * corruption_cost_multiplier;
}
constexpr fixed_point_t calculate_military_salary_base(
SharedPopTypeValues const& pop_type_values,
const fixed_point_t corruption_cost_multiplier
) const {
return pop_type_values.get_military_salary_base() * corruption_cost_multiplier;
}
fixed_point_t calculate_pensions_base(
ModifierEffectCache const& modifier_effect_cache,
SharedPopTypeValues const& pop_type_values
) const;
fixed_point_t calculate_unemployment_subsidies_base(
ModifierEffectCache const& modifier_effect_cache,
SharedPopTypeValues const& pop_type_values
) const;
fixed_point_t calculate_minimum_wage_base(
ModifierEffectCache const& modifier_effect_cache,
SharedPopTypeValues const& pop_type_values
) const;
constexpr fixed_point_t calculate_social_income_variant_base(
SharedPopTypeValues const& pop_type_values
) const {
return administrative_efficiency * pop_type_values.get_social_income_variant_base();
}

// Expects current_research to be non-null
void _update_current_tech(InstanceManager const& instance_manager);
void _update_technology(InstanceManager const& instance_manager);
Expand All @@ -548,9 +617,9 @@ namespace OpenVic {
return modifier_sum.for_each_contributing_modifier(effect, std::move(callback));
}

void country_reset_before_tick();
void update_gamestate(InstanceManager& instance_manager);
void country_tick(InstanceManager& instance_manager);
void country_tick_before_map(InstanceManager& instance_manager);
void country_tick_after_map(InstanceManager& instance_manager);

good_data_t& get_good_data(GoodInstance const& good_instance);
good_data_t const& get_good_data(GoodInstance const& good_instance) const;
Expand All @@ -564,6 +633,7 @@ namespace OpenVic {
void report_input_consumption(ProductionType const& production_type, GoodDefinition const& good, const fixed_point_t quantity);
void report_input_demand(ProductionType const& production_type, GoodDefinition const& good, const fixed_point_t quantity);
void report_output(ProductionType const& production_type, const fixed_point_t quantity);
void request_salaries_and_welfare(Pop& pop) const;
};

struct CountryDefinitionManager;
Expand All @@ -574,6 +644,7 @@ namespace OpenVic {
CountryDefinitionManager const& PROPERTY(country_definition_manager);

IdentifierRegistry<CountryInstance> IDENTIFIER_REGISTRY(country_instance);
SharedCountryValues shared_country_values;

IndexedMap<CountryDefinition, CountryInstance*> PROPERTY(country_definition_to_instance_map);

Expand All @@ -588,7 +659,13 @@ namespace OpenVic {
void update_rankings(Date today, DefineManager const& define_manager);

public:
CountryInstanceManager(CountryDefinitionManager const& new_country_definition_manager);
CountryInstanceManager(
CountryDefinitionManager const& new_country_definition_manager,
ModifierEffectCache const& new_modifier_effect_cache,
CountryDefines const& new_country_defines,
PopsDefines const& new_pop_defines,
std::vector<PopType> const& pop_type_keys
);

IDENTIFIER_REGISTRY_NON_CONST_ACCESSORS(country_instance);

Expand Down Expand Up @@ -618,7 +695,7 @@ namespace OpenVic {

void update_modifier_sums(Date today, StaticModifierCache const& static_modifier_cache);
void update_gamestate(InstanceManager& instance_manager);
void country_manager_reset_before_tick();
void country_manager_tick(InstanceManager& instance_manager);
void country_manager_tick_before_map(InstanceManager& instance_manager);
void country_manager_tick_after_map(InstanceManager& instance_manager);
};
}
53 changes: 53 additions & 0 deletions src/openvic-simulation/country/SharedCountryValues.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#include "SharedCountryValues.hpp"

#include "openvic-simulation/defines/PopsDefines.hpp"
#include "openvic-simulation/economy/GoodInstance.hpp"
#include "openvic-simulation/pop/PopNeedsMacro.hpp"
#include "openvic-simulation/pop/PopType.hpp"
#include "openvic-simulation/types/IndexedMap.hpp"

using namespace OpenVic;

SharedCountryValues::SharedCountryValues(
ModifierEffectCache const& new_modifier_effect_cache,
CountryDefines const& new_country_defines,
PopsDefines const& new_pop_defines,
decltype(shared_pop_type_values)::keys_type const& pop_type_keys
) : modifier_effect_cache { new_modifier_effect_cache },
country_defines { new_country_defines },
pop_defines { new_pop_defines },
shared_pop_type_values { &pop_type_keys }
{}

void SharedCountryValues::update_costs(GoodInstanceManager const& good_instance_manager) {
for (auto [pop_type, value] : shared_pop_type_values) {
value.update_costs(pop_type, pop_defines, good_instance_manager);
}
}

void SharedPopTypeValues::update_costs(PopType const& pop_type, PopsDefines const& pop_defines, GoodInstanceManager const& good_instance_manager) {
administration_salary_base = education_salary_base = military_salary_base = fixed_point_t::_0();
using enum PopType::income_type_t;

#define UPDATE_NEED_COSTS(need_category) \
base_##need_category##_need_costs = fixed_point_t::_0(); \
for (auto const& [good_definition_ptr, quantity] : pop_type.get_##need_category##_needs()) { \
GoodInstance const& good_instance = good_instance_manager.get_good_instance_from_definition(*good_definition_ptr); \
base_##need_category##_need_costs += good_instance.get_price() * quantity; \
} \
base_##need_category##_need_costs *= pop_defines.get_base_goods_demand(); \
if ((pop_type.get_##need_category##_needs_income_types() & ADMINISTRATION) == ADMINISTRATION) { \
administration_salary_base += base_##need_category##_need_costs; \
} \
if ((pop_type.get_##need_category##_needs_income_types() & EDUCATION) == EDUCATION) { \
education_salary_base += base_##need_category##_need_costs; \
} \
if ((pop_type.get_##need_category##_needs_income_types() & MILITARY) == MILITARY) { \
military_salary_base += base_##need_category##_need_costs; \
}

DO_FOR_ALL_NEED_CATEGORIES(UPDATE_NEED_COSTS)
#undef UPDATE_NEED_COSTS
}

#undef DO_FOR_ALL_NEED_CATEGORIES
53 changes: 53 additions & 0 deletions src/openvic-simulation/country/SharedCountryValues.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#pragma once

#include "openvic-simulation/pop/PopNeedsMacro.hpp"
#include "openvic-simulation/types/IndexedMap.hpp"
#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
#include "openvic-simulation/utility/Getters.hpp"

namespace OpenVic {
struct CountryDefines;
struct GoodInstanceManager;
struct ModifierEffectCache;
struct PopsDefines;
struct PopType;

struct SharedPopTypeValues {
private:
#define NEED_COST_FIELD(need_category) \
fixed_point_t base_##need_category##_need_costs;
DO_FOR_ALL_NEED_CATEGORIES(NEED_COST_FIELD)
#undef NEED_COST_FIELD

fixed_point_t PROPERTY(administration_salary_base);
fixed_point_t PROPERTY(education_salary_base);
fixed_point_t PROPERTY(military_salary_base);

public:
void update_costs(PopType const& pop_type, PopsDefines const& pop_defines, GoodInstanceManager const& good_instance_manager);
constexpr fixed_point_t get_social_income_variant_base() const {
return 2 * base_life_need_costs;
}
};

struct SharedCountryValues {
private:
ModifierEffectCache const& PROPERTY(modifier_effect_cache);
CountryDefines const& PROPERTY(country_defines);
PopsDefines const& pop_defines;
IndexedMap<PopType, SharedPopTypeValues> PROPERTY(shared_pop_type_values);

public:
SharedCountryValues(
ModifierEffectCache const& new_modifier_effect_cache,
CountryDefines const& new_country_defines,
PopsDefines const& new_pop_defines,
decltype(shared_pop_type_values)::keys_type const& pop_type_keys
);
SharedCountryValues(SharedCountryValues&&) = default;

void update_costs(GoodInstanceManager const& good_instance_manager);
};
}

#undef DO_FOR_ALL_NEED_CATEGORIES
11 changes: 10 additions & 1 deletion src/openvic-simulation/dataloader/NodeTools.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,13 +128,22 @@ using namespace std::string_view_literals;

template<IsOrderedMap Map>
inline bool map_key_value_invalid_callback(Map const& key_map, std::string_view key, ast::NodeCPtr) {
Logger::error("Invalid dictionary key \"", key, "\" valid values are [",
Logger::error("Invalid dictionary key \"", key, "\". Valid values are [",
StringUtils::string_join(key_map),
"]"
);
return false;
}

template<IsOrderedMap Map>
inline bool map_key_value_ignore_invalid_callback(Map const& key_map, std::string_view key, ast::NodeCPtr) {
Logger::warning("Invalid dictionary key \"", key, "\" is ignored. Valid values are [",
StringUtils::string_join(key_map),
"]"
);
return true;
}

node_callback_t expect_identifier(callback_t<std::string_view> callback);
node_callback_t expect_string(callback_t<std::string_view> callback, bool allow_empty = false);
node_callback_t expect_identifier_or_string(callback_t<std::string_view> callback, bool allow_empty = false);
Expand Down
1 change: 1 addition & 0 deletions src/openvic-simulation/misc/GameRulesManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ namespace OpenVic {
bool PROPERTY_RW(use_simple_farm_mine_logic, false);
// if changed during a session, call on_use_exponential_price_changes_changed for each GoodInstance.
bool PROPERTY_RW(use_exponential_price_changes, false);
bool PROPERTY_RW(prevent_negative_administration_efficiency, false);
demand_category PROPERTY_RW(artisanal_input_demand_category, demand_category::None);
country_to_report_economy_t PROPERTY_RW(country_to_report_economy, country_to_report_economy_t::Owner);

Expand Down
Loading