Skip to content

Commit 3bdc2d4

Browse files
committed
Add type-safe pop_sum_t for large value sums of pops
Refactor pop_size_t to be type-safe Move pop_size_t to population/PopSize.hpp Add equalable to Concepts.hpp Add expect_strong_typedef to NodeTools.hpp Add `&& equalable<ValueType, OtherValueType>` requirement to IndexedFlatMap's divide_assign_handle_zero
1 parent 55c064f commit 3bdc2d4

28 files changed

+324
-105
lines changed

src/openvic-simulation/core/template/Concepts.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,4 +223,9 @@ namespace OpenVic {
223223
concept mul_add_assignable = requires(Lhs& lhs, const A a, const B b) {
224224
{ lhs += a * b } -> std::same_as<Lhs&>;
225225
};
226+
227+
template<typename Lhs, typename Rhs = Lhs>
228+
concept equalable = requires(Lhs const& lhs, Rhs const& rhs) {
229+
{ lhs == rhs } -> std::convertible_to<bool>;
230+
};
226231
}

src/openvic-simulation/country/CountryInstance.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@
4242
#include "openvic-simulation/types/Date.hpp"
4343
#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
4444
#include "openvic-simulation/types/IndexedFlatMap.hpp"
45-
#include "openvic-simulation/types/PopSize.hpp"
45+
#include "openvic-simulation/population/PopSize.hpp"
46+
#include "openvic-simulation/population/PopSum.hpp"
4647
#include "openvic-simulation/types/UnitBranchType.hpp"
4748
#include "openvic-simulation/utility/Containers.hpp"
4849
#include "openvic-simulation/utility/Logger.hpp"
@@ -1340,8 +1341,8 @@ void CountryInstance::_update_budget() {
13401341
OpenVic immediately updates both.
13411342
*/
13421343

1343-
pop_size_t total_non_colonial_population = 0;
1344-
pop_size_t administrators = 0;
1344+
pop_sum_t total_non_colonial_population = 0;
1345+
pop_sum_t administrators = 0;
13451346
for (State const* const state_ptr : states) {
13461347
if (state_ptr == nullptr) {
13471348
continue;
@@ -1352,7 +1353,7 @@ void CountryInstance::_update_budget() {
13521353
continue;
13531354
}
13541355

1355-
IndexedFlatMap<PopType, pop_size_t> const& state_population_by_type = state.get_population_by_type();
1356+
IndexedFlatMap<PopType, pop_sum_t> const& state_population_by_type = state.get_population_by_type();
13561357

13571358
for (auto const& [pop_type, size] : state_population_by_type) {
13581359
if (pop_type.is_administrator) {
@@ -1365,13 +1366,13 @@ void CountryInstance::_update_budget() {
13651366
if (total_non_colonial_population == 0) {
13661367
administrative_efficiency_from_administrators.set(fixed_point_t::_1);
13671368
administrator_percentage.set(fixed_point_t::_0);
1368-
} else {
1369-
administrator_percentage.set(fixed_point_t::parse(administrators) / total_non_colonial_population);
1369+
} else {
1370+
administrator_percentage.set(fixed_point_t::parse(type_safe::get(administrators)) / type_safe::get(total_non_colonial_population));
13701371

1371-
const fixed_point_t desired_administrators = desired_administrator_percentage.get_untracked() * total_non_colonial_population;
1372+
const fixed_point_t desired_administrators = desired_administrator_percentage.get_untracked() * type_safe::get(total_non_colonial_population);
13721373
const fixed_point_t administrative_efficiency_from_administrators_unclamped = std::min(
13731374
fixed_point_t::mul_div(
1374-
administrators,
1375+
type_safe::get(administrators),
13751376
fixed_point_t::_1 + get_modifier_effect_value(*modifier_effect_cache.get_administrative_efficiency()),
13761377
desired_administrators
13771378
)
@@ -1397,7 +1398,7 @@ void CountryInstance::_update_budget() {
13971398
projected_education_spending_unscaled_by_slider_running_total += size * education_salary_base_by_pop_type.at(pop_type).get_untracked();
13981399
projected_military_spending_unscaled_by_slider_running_total += size * military_salary_base_by_pop_type.at(pop_type).get_untracked();
13991400
projected_pensions_spending_unscaled_by_slider_running_total += size * calculate_pensions_base(pop_type);
1400-
projected_unemployment_subsidies_spending_unscaled_by_slider_running_total += get_unemployed_pops_by_type(pop_type)
1401+
projected_unemployment_subsidies_spending_unscaled_by_slider_running_total += type_safe::get(get_unemployed_pops_by_type(pop_type))
14011402
* calculate_unemployment_subsidies_base(pop_type);
14021403
}
14031404

src/openvic-simulation/dataloader/NodeTools.hpp

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -199,21 +199,49 @@ using namespace std::string_view_literals;
199199
return expect_uint(callback, base);
200200
}
201201

202+
template<derived_from_specialization_of<type_safe::strong_typedef> T, typename AsT = type_safe::underlying_type<T>>
203+
NodeCallback auto expect_strong_typedef(callback_t<T>& callback, int base = 10) {
204+
if constexpr (std::unsigned_integral<AsT>) {
205+
return expect_uint64(
206+
[callback](uint64_t val) mutable -> bool {
207+
if (val <= static_cast<uint64_t>(std::numeric_limits<AsT>::max())) {
208+
return callback(T(val));
209+
}
210+
spdlog::error_s(
211+
"Invalid uint: {} (valid range: [0, {}])", val,
212+
static_cast<uint64_t>(std::numeric_limits<AsT>::max())
213+
);
214+
return false;
215+
},
216+
base
217+
);
218+
} else {
219+
return expect_int64(
220+
[callback](int64_t val) mutable -> bool {
221+
if (val >= static_cast<int64_t>(std::numeric_limits<AsT>::min()) &&
222+
val <= static_cast<int64_t>(std::numeric_limits<AsT>::max())) {
223+
return callback(T(val));
224+
}
225+
spdlog::error_s(
226+
"Invalid int: {} (valid range: [{}, {}])", val,
227+
static_cast<int64_t>(std::numeric_limits<AsT>::min()),
228+
static_cast<int64_t>(std::numeric_limits<AsT>::max())
229+
);
230+
return false;
231+
},
232+
base
233+
);
234+
}
235+
}
236+
template<derived_from_specialization_of<type_safe::strong_typedef> T, typename AsT = type_safe::underlying_type<T>>
237+
NodeCallback auto expect_strong_typedef(callback_t<T>&& callback, int base = 10) {
238+
return expect_strong_typedef<T, AsT>(callback, base);
239+
}
240+
202241
template<derived_from_specialization_of<type_safe::strong_typedef> T>
203242
requires std::unsigned_integral<type_safe::underlying_type<T>>
204243
NodeCallback auto expect_index(callback_t<T>& callback, int base = 10) {
205-
using underlying_type = type_safe::underlying_type<T>;
206-
207-
return expect_uint64([callback](uint64_t val) mutable -> bool {
208-
if (val <= static_cast<uint64_t>(std::numeric_limits<underlying_type>::max())) {
209-
return callback(T(val));
210-
}
211-
spdlog::error_s(
212-
"Invalid uint: {} (valid range: [0, {}])",
213-
val, static_cast<uint64_t>(std::numeric_limits<underlying_type>::max())
214-
);
215-
return false;
216-
}, base);
244+
return expect_strong_typedef<T>(callback, base);
217245
}
218246
template<derived_from_specialization_of<type_safe::strong_typedef> T>
219247
requires std::unsigned_integral<type_safe::underlying_type<T>>

src/openvic-simulation/defines/MilitaryDefines.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ node_callback_t MilitaryDefines::expect_defines() {
1515
"REINFORCE_SPEED", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(reinforce_speed)),
1616
"COMBAT_DIFFICULTY_IMPACT", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(combat_difficulty_impact)),
1717
"BASE_COMBAT_WIDTH", ONE_EXACTLY, expect_uint(assign_variable_callback(base_combat_width)),
18-
"POP_MIN_SIZE_FOR_REGIMENT", ONE_EXACTLY, expect_uint(assign_variable_callback(min_pop_size_for_regiment)),
19-
"POP_SIZE_PER_REGIMENT", ONE_EXACTLY, expect_uint(assign_variable_callback(pop_size_per_regiment)),
18+
"POP_MIN_SIZE_FOR_REGIMENT", ONE_EXACTLY, expect_strong_typedef<pop_size_t>(assign_variable_callback(min_pop_size_for_regiment)),
19+
"POP_SIZE_PER_REGIMENT", ONE_EXACTLY, expect_strong_typedef<pop_size_t>(assign_variable_callback(pop_size_per_regiment)),
2020
"SOLDIER_TO_POP_DAMAGE", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(soldier_to_pop_damage)),
2121
"LAND_SPEED_MODIFIER", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(land_speed_modifier)),
2222
"NAVAL_SPEED_MODIFIER", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(naval_speed_modifier)),

src/openvic-simulation/defines/MilitaryDefines.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#include "openvic-simulation/dataloader/NodeTools.hpp"
44
#include "openvic-simulation/types/Date.hpp"
55
#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
6-
#include "openvic-simulation/types/PopSize.hpp"
6+
#include "openvic-simulation/population/PopSize.hpp"
77
#include "openvic-simulation/utility/Getters.hpp"
88

99
namespace OpenVic {

src/openvic-simulation/defines/PopsDefines.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ node_callback_t PopsDefines::expect_defines() {
7575
"MOVEMENT_SUPPORT_UH_FACTOR", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(movement_support_uh_factor)),
7676
"REBEL_OCCUPATION_STRENGTH_BONUS", ONE_EXACTLY,
7777
expect_fixed_point(assign_variable_callback(rebel_occupation_strength_bonus)),
78-
"LARGE_POPULATION_LIMIT", ONE_EXACTLY, expect_uint(assign_variable_callback(large_population_limit)),
78+
"LARGE_POPULATION_LIMIT", ONE_EXACTLY, expect_strong_typedef<pop_sum_t>(assign_variable_callback(large_population_limit)),
7979
"LARGE_POPULATION_INFLUENCE_PENALTY_CHUNK", ONE_EXACTLY,
80-
expect_uint(assign_variable_callback(large_population_influence_penalty_chunk))
80+
expect_strong_typedef<pop_sum_t>(assign_variable_callback(large_population_influence_penalty_chunk))
8181
);
8282
}

src/openvic-simulation/defines/PopsDefines.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
#include "openvic-simulation/dataloader/NodeTools.hpp"
44
#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
5-
#include "openvic-simulation/types/PopSize.hpp"
5+
#include "openvic-simulation/population/PopSum.hpp"
66
#include "openvic-simulation/types/ProvinceLifeRating.hpp"
77
#include "openvic-simulation/utility/Getters.hpp"
88

@@ -71,8 +71,8 @@ namespace OpenVic {
7171
fixed_point_t PROPERTY(nationalist_movement_mil_cap);
7272
fixed_point_t PROPERTY(movement_support_uh_factor);
7373
fixed_point_t PROPERTY(rebel_occupation_strength_bonus);
74-
pop_size_t PROPERTY(large_population_limit, 0);
75-
pop_size_t PROPERTY(large_population_influence_penalty_chunk, 0);
74+
pop_sum_t PROPERTY(large_population_limit, 0);
75+
pop_sum_t PROPERTY(large_population_influence_penalty_chunk, 0);
7676

7777
PopsDefines();
7878

src/openvic-simulation/economy/production/ArtisanalProducer.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ void ArtisanalProducer::artisan_tick_handler::calculate_inputs(
7171
//throughput scalar, the minimum of stockpile / base_desired_quantity
7272
//inputs_bought_fraction uses base_desired_quantity as population size is cancelled in the production and input calculations.
7373
const pop_size_t pop_size = pop.get_size();
74-
fixed_point_t inputs_bought_numerator = pop_size,
75-
inputs_bought_denominator = production_type.base_workforce_size,
74+
fixed_point_t inputs_bought_numerator = type_safe::get(pop_size),
75+
inputs_bought_denominator = type_safe::get(production_type.base_workforce_size),
7676
inputs_bought_fraction_v = inputs_bought_numerator / inputs_bought_denominator;
7777

7878
distinct_goods_to_buy = 0;
@@ -478,7 +478,7 @@ std::optional<fixed_point_t> ArtisanalProducer::estimate_production_type_score(
478478
fixed_point_t ArtisanalProducer::calculate_production_type_score(
479479
const fixed_point_t revenue,
480480
const fixed_point_t costs,
481-
const pop_size_t workforce
481+
const pop_sum_t workforce
482482
) {
483483
if (costs >= revenue) {
484484
return 0;

src/openvic-simulation/economy/production/ArtisanalProducer.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
77
#include "openvic-simulation/types/fixed_point/FixedPointMap.hpp"
88
#include "openvic-simulation/types/fixed_point/Fraction.hpp"
9-
#include "openvic-simulation/types/PopSize.hpp"
109
#include "openvic-simulation/utility/Getters.hpp"
1110

1211
namespace OpenVic {
@@ -22,6 +21,8 @@ namespace OpenVic {
2221
struct ProductionType;
2322
struct ProvinceInstance;
2423
struct RandomU32;
24+
struct pop_size_t;
25+
struct pop_sum_t;
2526

2627
struct ArtisanalProducer {
2728
private:
@@ -47,7 +48,7 @@ namespace OpenVic {
4748
static fixed_point_t calculate_production_type_score(
4849
const fixed_point_t revenue,
4950
const fixed_point_t costs,
50-
const pop_size_t workforce
51+
const pop_sum_t workforce
5152
);
5253

5354
public:

src/openvic-simulation/economy/production/Employee.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#pragma once
22

33
#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
4-
#include "openvic-simulation/types/PopSize.hpp"
4+
#include "openvic-simulation/population/PopSize.hpp"
55

66
namespace OpenVic {
77
struct CountryInstance;

0 commit comments

Comments
 (0)