From 9b06879eecb8983a18ea39154bbe90fe488ae9af Mon Sep 17 00:00:00 2001 From: wvpm <24685035+wvpm@users.noreply.github.com> Date: Wed, 18 Sep 2024 17:47:10 +0200 Subject: Move production types to economy/production/ --- .../economy/ArtisanalProducer.cpp | 13 - .../economy/ArtisanalProducer.hpp | 24 -- src/openvic-simulation/economy/BuildingType.hpp | 5 +- src/openvic-simulation/economy/EconomyManager.hpp | 4 +- src/openvic-simulation/economy/FactoryProducer.cpp | 58 ---- src/openvic-simulation/economy/FactoryProducer.hpp | 61 ---- src/openvic-simulation/economy/ProductionType.cpp | 326 --------------------- src/openvic-simulation/economy/ProductionType.hpp | 121 -------- .../economy/ResourceGatheringOperation.cpp | 21 -- .../economy/ResourceGatheringOperation.hpp | 28 -- .../economy/production/ArtisanalProducer.cpp | 13 + .../economy/production/ArtisanalProducer.hpp | 22 ++ .../economy/production/FactoryProducer.cpp | 58 ++++ .../economy/production/FactoryProducer.hpp | 50 ++++ .../economy/production/ProductionType.cpp | 326 +++++++++++++++++++++ .../economy/production/ProductionType.hpp | 121 ++++++++ .../production/ResourceGatheringOperation.cpp | 21 ++ .../production/ResourceGatheringOperation.hpp | 25 ++ 18 files changed, 642 insertions(+), 655 deletions(-) delete mode 100644 src/openvic-simulation/economy/ArtisanalProducer.cpp delete mode 100644 src/openvic-simulation/economy/ArtisanalProducer.hpp delete mode 100644 src/openvic-simulation/economy/FactoryProducer.cpp delete mode 100644 src/openvic-simulation/economy/FactoryProducer.hpp delete mode 100644 src/openvic-simulation/economy/ProductionType.cpp delete mode 100644 src/openvic-simulation/economy/ProductionType.hpp delete mode 100644 src/openvic-simulation/economy/ResourceGatheringOperation.cpp delete mode 100644 src/openvic-simulation/economy/ResourceGatheringOperation.hpp create mode 100644 src/openvic-simulation/economy/production/ArtisanalProducer.cpp create mode 100644 src/openvic-simulation/economy/production/ArtisanalProducer.hpp create mode 100644 src/openvic-simulation/economy/production/FactoryProducer.cpp create mode 100644 src/openvic-simulation/economy/production/FactoryProducer.hpp create mode 100644 src/openvic-simulation/economy/production/ProductionType.cpp create mode 100644 src/openvic-simulation/economy/production/ProductionType.hpp create mode 100644 src/openvic-simulation/economy/production/ResourceGatheringOperation.cpp create mode 100644 src/openvic-simulation/economy/production/ResourceGatheringOperation.hpp (limited to 'src/openvic-simulation') diff --git a/src/openvic-simulation/economy/ArtisanalProducer.cpp b/src/openvic-simulation/economy/ArtisanalProducer.cpp deleted file mode 100644 index d5cc3d3..0000000 --- a/src/openvic-simulation/economy/ArtisanalProducer.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "ArtisanalProducer.hpp" - -using namespace OpenVic; - -ArtisanalProducer::ArtisanalProducer( - ProductionType const& new_production_type, - GoodDefinition::good_definition_map_t&& new_stockpile, - fixed_point_t new_current_production, - GoodDefinition::good_definition_map_t&& new_current_needs -) : production_type { new_production_type }, - stockpile { std::move(new_stockpile) }, - current_production { new_current_production }, - current_needs { std::move(new_current_needs) } {} diff --git a/src/openvic-simulation/economy/ArtisanalProducer.hpp b/src/openvic-simulation/economy/ArtisanalProducer.hpp deleted file mode 100644 index ed5b231..0000000 --- a/src/openvic-simulation/economy/ArtisanalProducer.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include "openvic-simulation/economy/GoodDefinition.hpp" -#include "openvic-simulation/economy/ProductionType.hpp" -#include "openvic-simulation/types/fixed_point/FixedPoint.hpp" -#include "openvic-simulation/utility/Getters.hpp" - -namespace OpenVic { - class ArtisanalProducer final { - private: - ProductionType const& PROPERTY(production_type); - GoodDefinition::good_definition_map_t PROPERTY(stockpile); - fixed_point_t PROPERTY(current_production); - GoodDefinition::good_definition_map_t PROPERTY(current_needs); - - public: - ArtisanalProducer( - ProductionType const& new_production_type, - GoodDefinition::good_definition_map_t&& new_stockpile, - fixed_point_t new_current_production, - GoodDefinition::good_definition_map_t&& new_current_needs - ); - }; -} diff --git a/src/openvic-simulation/economy/BuildingType.hpp b/src/openvic-simulation/economy/BuildingType.hpp index ab999cd..e28dd86 100644 --- a/src/openvic-simulation/economy/BuildingType.hpp +++ b/src/openvic-simulation/economy/BuildingType.hpp @@ -1,12 +1,13 @@ #pragma once -#include "openvic-simulation/misc/Modifier.hpp" #include "openvic-simulation/economy/GoodDefinition.hpp" -#include "openvic-simulation/economy/ProductionType.hpp" +#include "openvic-simulation/economy/production/ProductionType.hpp" +#include "openvic-simulation/misc/Modifier.hpp" #include "openvic-simulation/types/Date.hpp" #include "openvic-simulation/types/IdentifierRegistry.hpp" #include "openvic-simulation/types/fixed_point/FixedPoint.hpp" + namespace OpenVic { struct BuildingTypeManager; diff --git a/src/openvic-simulation/economy/EconomyManager.hpp b/src/openvic-simulation/economy/EconomyManager.hpp index 2464912..7f0520d 100644 --- a/src/openvic-simulation/economy/EconomyManager.hpp +++ b/src/openvic-simulation/economy/EconomyManager.hpp @@ -2,9 +2,11 @@ #include "openvic-simulation/economy/BuildingType.hpp" #include "openvic-simulation/economy/GoodDefinition.hpp" -#include "openvic-simulation/economy/ProductionType.hpp" +#include "openvic-simulation/economy/production/ProductionType.hpp" + #include "openvic-dataloader/v2script/Parser.hpp" + namespace OpenVic { struct EconomyManager { private: diff --git a/src/openvic-simulation/economy/FactoryProducer.cpp b/src/openvic-simulation/economy/FactoryProducer.cpp deleted file mode 100644 index 2ef9fa8..0000000 --- a/src/openvic-simulation/economy/FactoryProducer.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include "FactoryProducer.hpp" - -using namespace OpenVic; - -FactoryProducer::FactoryProducer( - ProductionType const& new_production_type, - fixed_point_t new_size_multiplier, - fixed_point_t new_revenue_yesterday, - fixed_point_t new_output_quantity_yesterday, - fixed_point_t new_unsold_quantity_yesterday, - ordered_map&& new_employees, - GoodDefinition::good_definition_map_t&& new_stockpile, - fixed_point_t new_budget, - fixed_point_t new_balance_yesterday, - fixed_point_t new_received_investments_yesterday, - fixed_point_t new_market_spendings_yesterday, - fixed_point_t new_paychecks_yesterday, - uint32_t new_unprofitable_days, - uint32_t new_subsidised_days, - uint32_t new_days_without_input, - uint8_t new_hiring_priority, - uint8_t new_profit_history_current, - daily_profit_history_t&& new_daily_profit_history -) : production_type { new_production_type }, - size_multiplier { new_size_multiplier }, - revenue_yesterday { new_revenue_yesterday }, - output_quantity_yesterday { new_output_quantity_yesterday }, - unsold_quantity_yesterday { new_unsold_quantity_yesterday }, - employees { std::move(new_employees) }, - stockpile { std::move(new_stockpile) }, - budget { new_budget }, - balance_yesterday { new_balance_yesterday }, - received_investments_yesterday { new_received_investments_yesterday }, - market_spendings_yesterday { new_market_spendings_yesterday }, - paychecks_yesterday { new_paychecks_yesterday }, - unprofitable_days { new_unprofitable_days }, - subsidised_days { new_subsidised_days }, - days_without_input { new_days_without_input }, - hiring_priority { new_hiring_priority }, - profit_history_current { new_profit_history_current }, - daily_profit_history { std::move(new_daily_profit_history) } {} - -FactoryProducer::FactoryProducer(ProductionType const& new_production_type, fixed_point_t new_size_multiplier) - : FactoryProducer { new_production_type, new_size_multiplier, 0, 0, 0, {}, {}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {} } {} - -fixed_point_t FactoryProducer::get_profitability_yesterday() const { - return daily_profit_history[profit_history_current]; -} - -fixed_point_t FactoryProducer::get_average_profitability_last_seven_days() const { - fixed_point_t sum = 0; - - for (int i = 0; i <= profit_history_current; i++) { - sum += daily_profit_history[i]; - } - - return sum / (1 + profit_history_current); -} diff --git a/src/openvic-simulation/economy/FactoryProducer.hpp b/src/openvic-simulation/economy/FactoryProducer.hpp deleted file mode 100644 index ee658a5..0000000 --- a/src/openvic-simulation/economy/FactoryProducer.hpp +++ /dev/null @@ -1,61 +0,0 @@ -#pragma once - -#include - -#include "openvic-simulation/economy/GoodDefinition.hpp" -#include "openvic-simulation/economy/ProductionType.hpp" -#include "openvic-simulation/types/fixed_point/FixedPoint.hpp" -#include "openvic-simulation/utility/Getters.hpp" - -namespace OpenVic { - class FactoryProducer final { - private: - static constexpr uint8_t DAYS_OF_HISTORY = 7; - using daily_profit_history_t = std::array; - - uint8_t PROPERTY(profit_history_current); - daily_profit_history_t PROPERTY(daily_profit_history); - ProductionType const& PROPERTY(production_type); - fixed_point_t PROPERTY(revenue_yesterday); - fixed_point_t PROPERTY(output_quantity_yesterday); - fixed_point_t PROPERTY(unsold_quantity_yesterday); - fixed_point_t PROPERTY(size_multiplier); - ordered_map PROPERTY(employees); - GoodDefinition::good_definition_map_t PROPERTY(stockpile); - fixed_point_t PROPERTY(budget); - fixed_point_t PROPERTY(balance_yesterday); - fixed_point_t PROPERTY(received_investments_yesterday); - fixed_point_t PROPERTY(market_spendings_yesterday); - fixed_point_t PROPERTY(paychecks_yesterday); - uint32_t PROPERTY(unprofitable_days); - uint32_t PROPERTY(subsidised_days); - uint32_t PROPERTY(days_without_input); - uint8_t PROPERTY_RW(hiring_priority); - - public: - FactoryProducer( - ProductionType const& new_production_type, - fixed_point_t new_size_multiplier, - fixed_point_t new_revenue_yesterday, - fixed_point_t new_output_quantity_yesterday, - fixed_point_t new_unsold_quantity_yesterday, - ordered_map&& new_employees, - GoodDefinition::good_definition_map_t&& new_stockpile, - fixed_point_t new_budget, - fixed_point_t new_balance_yesterday, - fixed_point_t new_received_investments_yesterday, - fixed_point_t new_market_spendings_yesterday, - fixed_point_t new_paychecks_yesterday, - uint32_t new_unprofitable_days, - uint32_t new_subsidised_days, - uint32_t new_days_without_input, - uint8_t new_hiring_priority, - uint8_t new_profit_history_current, - daily_profit_history_t&& new_daily_profit_history - ); - FactoryProducer(ProductionType const& new_production_type, fixed_point_t new_size_multiplier); - - fixed_point_t get_profitability_yesterday() const; - fixed_point_t get_average_profitability_last_seven_days() const; - }; -} diff --git a/src/openvic-simulation/economy/ProductionType.cpp b/src/openvic-simulation/economy/ProductionType.cpp deleted file mode 100644 index 65f3eba..0000000 --- a/src/openvic-simulation/economy/ProductionType.cpp +++ /dev/null @@ -1,326 +0,0 @@ -#include "ProductionType.hpp" - -#include - -using namespace OpenVic; -using namespace OpenVic::NodeTools; - -Job::Job( - PopType const* new_pop_type, - effect_t new_effect_type, - fixed_point_t new_effect_multiplier, - fixed_point_t new_desired_workforce_share -) : pop_type { new_pop_type }, - effect_type { new_effect_type }, - effect_multiplier { new_effect_multiplier }, - desired_workforce_share { new_desired_workforce_share } {} - -ProductionType::ProductionType( - std::string_view new_identifier, - std::optional new_owner, - std::vector&& new_jobs, - template_type_t new_template_type, - Pop::pop_size_t new_base_workforce_size, - GoodDefinition::good_definition_map_t&& new_input_goods, - GoodDefinition const* new_output_goods, - fixed_point_t new_base_output_quantity, - std::vector&& new_bonuses, - GoodDefinition::good_definition_map_t&& new_maintenance_requirements, - bool new_is_coastal, - bool new_is_farm, - bool new_is_mine -) : HasIdentifier { new_identifier }, - owner { new_owner }, - jobs { std::move(new_jobs) }, - template_type { new_template_type }, - base_workforce_size { new_base_workforce_size }, - input_goods { std::move(new_input_goods) }, - output_goods { new_output_goods }, - base_output_quantity { new_base_output_quantity }, - bonuses { std::move(new_bonuses) }, - maintenance_requirements { std::move(new_maintenance_requirements) }, - coastal { new_is_coastal }, - farm { new_is_farm }, - mine { new_is_mine } {} - -bool ProductionType::parse_scripts(DefinitionManager const& definition_manager) { - bool ret = true; - for (auto& [bonus_script, bonus_value] : bonuses) { - ret &= bonus_script.parse_script(false, definition_manager); - } - return ret; -} - -ProductionTypeManager::ProductionTypeManager() : rgo_owner_sprite { 0 } {} - -node_callback_t ProductionTypeManager::_expect_job( - GoodDefinitionManager const& good_definition_manager, PopManager const& pop_manager, callback_t callback -) { - return [this, &good_definition_manager, &pop_manager, callback](ast::NodeCPtr node) -> bool { - using enum Job::effect_t; - - std::string_view pop_type {}; - Job::effect_t effect_type {THROUGHPUT}; - fixed_point_t effect_multiplier = 1, desired_workforce_share = 1; - - static const string_map_t effect_map = { - { "input", INPUT }, { "output", OUTPUT }, { "throughput", THROUGHPUT } - }; - - bool res = expect_dictionary_keys( - "poptype", ONE_EXACTLY, expect_identifier(assign_variable_callback(pop_type)), - "effect", ONE_EXACTLY, expect_identifier(expect_mapped_string(effect_map, assign_variable_callback(effect_type))), - "effect_multiplier", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(effect_multiplier)), - "amount", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(desired_workforce_share)) - )(node); - - PopType const* found_pop_type = pop_manager.get_pop_type_by_identifier(pop_type); - return res & callback({ found_pop_type, effect_type, effect_multiplier, desired_workforce_share }); - }; -} - -node_callback_t ProductionTypeManager::_expect_job_list( - GoodDefinitionManager const& good_definition_manager, PopManager const& pop_manager, - callback_t&&> callback -) { - return [this, &good_definition_manager, &pop_manager, callback](ast::NodeCPtr node) -> bool { - std::vector jobs; - bool ret = expect_list(_expect_job(good_definition_manager, pop_manager, vector_callback(jobs)))(node); - ret &= callback(std::move(jobs)); - return ret; - }; -} - -bool ProductionTypeManager::add_production_type( - std::string_view identifier, - std::optional owner, - std::vector&& jobs, - ProductionType::template_type_t template_type, - Pop::pop_size_t base_workforce_size, - GoodDefinition::good_definition_map_t&& input_goods, - GoodDefinition const* output_goods, - fixed_point_t base_output_quantity, - std::vector&& bonuses, - GoodDefinition::good_definition_map_t&& maintenance_requirements, - bool is_coastal, - bool is_farm, - bool is_mine -) { - if (identifier.empty()) { - Logger::error("Invalid production type identifier - empty!"); - return false; - } - - if (base_workforce_size <= 0) { - Logger::error("Base workforce size ('workforce') for production type ", identifier, " was 0 or unset!"); - return false; - } - - if (base_output_quantity <= 0) { - Logger::error("Base output quantity ('value') for production type ", identifier, " was 0 or unset!"); - return false; - } - - if (output_goods == nullptr) { - Logger::error("Output good for production type ", identifier, " was null!"); - return false; - } - - using enum ProductionType::template_type_t; - - if (template_type == ARTISAN) { - if (owner.has_value()) { - Logger::warning( - "Artisanal production type ", identifier, " should not have an owner - it is being ignored." - ); - owner.reset(); - } - - if (!jobs.empty()) { - Logger::warning( - "Artisanal production type ", identifier, " should not have employees - ", jobs.size(), " are being ignored." - ); - jobs.clear(); - } - } else { - if (!owner.has_value()) { - Logger::error("Production type ", identifier, " is missing an owner."); - return false; - } - - if (owner->get_pop_type() == nullptr) { - Logger::error("Production type ", identifier, " owner has an invalid pop type."); - return false; - } - - if (jobs.empty()) { - Logger::error("Production type ", identifier, " lacks jobs ('employees')."); - return false; - } - - for (size_t i = 0; i < jobs.size(); i++) { - if (jobs[i].get_pop_type() == nullptr) { - Logger::error("Production type ", identifier, " has invalid pop type in employees[", i, "]."); - return false; - } - } - } - - const bool ret = production_types.add_item({ - identifier, owner, std::move(jobs), template_type, base_workforce_size, std::move(input_goods), output_goods, - base_output_quantity, std::move(bonuses), std::move(maintenance_requirements), is_coastal, is_farm, is_mine - }); - if (rgo_owner_sprite <= 0 && ret && template_type == RGO && owner.has_value() && owner->get_pop_type() != nullptr) { - /* Set rgo owner sprite to that of the first RGO owner we find. */ - rgo_owner_sprite = owner->get_pop_type()->get_sprite(); - } - return ret; -} - -bool ProductionTypeManager::load_production_types_file( - GoodDefinitionManager const& good_definition_manager, PopManager const& pop_manager, ovdl::v2script::Parser const& parser -) { - using namespace std::string_view_literals; - auto template_symbol = parser.find_intern("template"sv); - if (!template_symbol) { - Logger::error("template could not be interned."); - } - - size_t expected_types = 0; - - /* Pass #1: find and store template identifiers */ - ordered_set templates; - ordered_map template_target_map; - bool ret = expect_dictionary( - [this, &expected_types, &templates, &template_target_map, &template_symbol](std::string_view key, ast::NodeCPtr value) -> bool { - expected_types++; - - std::string_view template_id = ""; - bool found_template = false; - const bool ret = - expect_key(template_symbol, expect_identifier(assign_variable_callback(template_id)), &found_template)(value); - if (found_template) { - if (ret) { - templates.emplace(template_id); - template_target_map.emplace(key, template_id); - } else { - Logger::error("Failed get template identifier for ", key); - return false; - } - } - return true; - } - )(parser.get_file_node()); - - /* Pass #2: create and populate the template map */ - ordered_map template_node_map; - ret &= expect_dictionary( - [this, &expected_types, &templates, &template_node_map](std::string_view key, ast::NodeCPtr value) -> bool { - if (templates.contains(key)) { - template_node_map.emplace(key, value); - expected_types--; - } - return true; - } - )(parser.get_file_node()); - - /* Pass #3: actually load production types */ - reserve_more_production_types(expected_types); - ret &= expect_dictionary( - [this, &good_definition_manager, &pop_manager, &template_target_map, &template_node_map]( - std::string_view key, ast::NodeCPtr node) -> bool { - using enum ProductionType::template_type_t; - - if (template_node_map.contains(key)) { - return true; - } - - std::optional owner; - std::vector jobs; - ProductionType::template_type_t template_type { FACTORY }; - GoodDefinition const* output_goods = nullptr; - Pop::pop_size_t base_workforce_size = 0; - GoodDefinition::good_definition_map_t input_goods, maintenance_requirements; - fixed_point_t base_output_quantity = 0; - std::vector bonuses; - bool is_coastal = false, is_farm = false, is_mine = false; - - bool ret = true; - - static const string_map_t template_type_map = { - { "factory", FACTORY }, { "rgo", RGO }, { "artisan", ARTISAN } - }; - - auto parse_node = expect_dictionary_keys( - "template", ZERO_OR_ONE, success_callback, /* Already parsed using expect_key in Pass #1 above. */ - "bonus", ZERO_OR_MORE, [&bonuses](ast::NodeCPtr bonus_node) -> bool { - ConditionScript trigger { scope_t::STATE, scope_t::NO_SCOPE, scope_t::NO_SCOPE }; - fixed_point_t bonus_value {}; - const bool ret = expect_dictionary_keys( - "trigger", ONE_EXACTLY, trigger.expect_script(), - "value", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(bonus_value)) - )(bonus_node); - bonuses.emplace_back(std::move(trigger), bonus_value); - return ret; - }, - "owner", ZERO_OR_ONE, _expect_job(good_definition_manager, pop_manager, move_variable_callback(owner)), - "employees", ZERO_OR_ONE, _expect_job_list(good_definition_manager, pop_manager, move_variable_callback(jobs)), - "type", ZERO_OR_ONE, - expect_identifier(expect_mapped_string(template_type_map, assign_variable_callback(template_type))), - "workforce", ZERO_OR_ONE, expect_uint(assign_variable_callback(base_workforce_size)), - "input_goods", ZERO_OR_ONE, - good_definition_manager.expect_good_definition_decimal_map(move_variable_callback(input_goods)), - "output_goods", ZERO_OR_ONE, - good_definition_manager.expect_good_definition_identifier(assign_variable_callback_pointer(output_goods)), - "value", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(base_output_quantity)), - "efficiency", ZERO_OR_ONE, good_definition_manager.expect_good_definition_decimal_map( - move_variable_callback(maintenance_requirements) - ), - "is_coastal", ZERO_OR_ONE, expect_bool(assign_variable_callback(is_coastal)), - "farm", ZERO_OR_ONE, expect_bool(assign_variable_callback(is_farm)), - "mine", ZERO_OR_ONE, expect_bool(assign_variable_callback(is_mine)) - ); - - /* Check if this ProductionType has a template, and if so parse it. */ - { - const typename decltype(template_target_map)::const_iterator target_it = template_target_map.find(key); - if (target_it != template_target_map.end()) { - const std::string_view template_id = target_it->second; - const typename decltype(template_node_map)::const_iterator node_it = template_node_map.find(template_id); - if (node_it != template_node_map.end()) { - ret &= parse_node(node_it->second); - } else { - Logger::error("Missing template ", template_id, " for production type ", key, "!"); - ret = false; - } - } - } - - /* Parse the ProductionType's own entries, over those of its template if necessary. */ - ret &= parse_node(node); - - ret &= add_production_type( - key, owner, std::move(jobs), template_type, base_workforce_size, std::move(input_goods), output_goods, - base_output_quantity, std::move(bonuses), std::move(maintenance_requirements), is_coastal, is_farm, is_mine - ); - return ret; - } - )(parser.get_file_node()); - - production_types.lock(); - - if (rgo_owner_sprite <= 0) { - Logger::error("No RGO owner pop type sprite found!"); - ret = false; - } - - return ret; -} - -bool ProductionTypeManager::parse_scripts(DefinitionManager const& definition_manager) { - bool ret = true; - for (ProductionType& production_type : production_types.get_items()) { - ret &= production_type.parse_scripts(definition_manager); - } - return ret; -} diff --git a/src/openvic-simulation/economy/ProductionType.hpp b/src/openvic-simulation/economy/ProductionType.hpp deleted file mode 100644 index 5394938..0000000 --- a/src/openvic-simulation/economy/ProductionType.hpp +++ /dev/null @@ -1,121 +0,0 @@ -#pragma once - -#include - -#include "openvic-simulation/economy/GoodDefinition.hpp" -#include "openvic-simulation/pop/Pop.hpp" -#include "openvic-simulation/scripts/ConditionScript.hpp" -#include "openvic-simulation/types/IdentifierRegistry.hpp" -#include "openvic-simulation/types/fixed_point/FixedPoint.hpp" - -namespace OpenVic { - struct ProductionTypeManager; - - struct Job { - friend struct ProductionTypeManager; - - enum struct effect_t { INPUT, OUTPUT, THROUGHPUT }; - - private: - PopType const* PROPERTY(pop_type); - effect_t PROPERTY(effect_type); - fixed_point_t PROPERTY(effect_multiplier); - fixed_point_t PROPERTY(desired_workforce_share); - - Job( - PopType const* new_pop_type, - effect_t new_effect_type, - fixed_point_t new_effect_multiplier, - fixed_point_t new_desired_workforce_share - ); - - public: - Job() = default; - }; - - struct ProductionType : HasIdentifier { - friend struct ProductionTypeManager; - - enum struct template_type_t { FACTORY, RGO, ARTISAN }; - - using bonus_t = std::pair; - - private: - const std::optional PROPERTY(owner); - std::vector PROPERTY(jobs); - const template_type_t PROPERTY(template_type); - const Pop::pop_size_t PROPERTY(base_workforce_size); - - GoodDefinition::good_definition_map_t PROPERTY(input_goods); - GoodDefinition const* PROPERTY(output_goods); - const fixed_point_t PROPERTY(base_output_quantity); - std::vector PROPERTY(bonuses); - - GoodDefinition::good_definition_map_t PROPERTY(maintenance_requirements); - const bool PROPERTY_CUSTOM_PREFIX(coastal, is); - - const bool PROPERTY_CUSTOM_PREFIX(farm, is); - const bool PROPERTY_CUSTOM_PREFIX(mine, is); - - ProductionType( - std::string_view new_identifier, - std::optional new_owner, - std::vector&& new_jobs, - template_type_t new_template_type, - Pop::pop_size_t new_base_workforce_size, - GoodDefinition::good_definition_map_t&& new_input_goods, - GoodDefinition const* new_output_goods, - fixed_point_t new_base_output_quantity, - std::vector&& new_bonuses, - GoodDefinition::good_definition_map_t&& new_maintenance_requirements, - bool new_is_coastal, - bool new_is_farm, - bool new_is_mine - ); - - bool parse_scripts(DefinitionManager const& definition_manager); - - public: - ProductionType(ProductionType&&) = default; - }; - - struct ProductionTypeManager { - private: - IdentifierRegistry IDENTIFIER_REGISTRY(production_type); - PopType::sprite_t PROPERTY(rgo_owner_sprite); - - NodeTools::node_callback_t _expect_job( - GoodDefinitionManager const& good_definition_manager, PopManager const& pop_manager, - NodeTools::callback_t callback - ); - NodeTools::node_callback_t _expect_job_list( - GoodDefinitionManager const& good_definition_manager, PopManager const& pop_manager, - NodeTools::callback_t&&> callback - ); - - public: - ProductionTypeManager(); - - bool add_production_type( - std::string_view identifier, - std::optional owner, - std::vector&& employees, - ProductionType::template_type_t template_type, - Pop::pop_size_t workforce, - GoodDefinition::good_definition_map_t&& input_goods, - GoodDefinition const* output_goods, - fixed_point_t value, - std::vector&& bonuses, - GoodDefinition::good_definition_map_t&& maintenance_requirements, - bool coastal, - bool farm, - bool mine - ); - - bool load_production_types_file( - GoodDefinitionManager const& good_definition_manager, PopManager const& pop_manager, ovdl::v2script::Parser const& parser - ); - - bool parse_scripts(DefinitionManager const& definition_manager); - }; -} diff --git a/src/openvic-simulation/economy/ResourceGatheringOperation.cpp b/src/openvic-simulation/economy/ResourceGatheringOperation.cpp deleted file mode 100644 index 9bf6f49..0000000 --- a/src/openvic-simulation/economy/ResourceGatheringOperation.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "ResourceGatheringOperation.hpp" - -using namespace OpenVic; - -ResourceGatheringOperation::ResourceGatheringOperation( - ProductionType const& new_production_type, - fixed_point_t new_size_multiplier, - fixed_point_t new_revenue_yesterday, - fixed_point_t new_output_quantity_yesterday, - fixed_point_t new_unsold_quantity_yesterday, - ordered_map&& new_employees -) : production_type { new_production_type }, - revenue_yesterday { new_revenue_yesterday }, - output_quantity_yesterday { new_output_quantity_yesterday }, - unsold_quantity_yesterday { new_unsold_quantity_yesterday }, - size_multiplier { new_size_multiplier }, - employees { std::move(new_employees) } {} - -ResourceGatheringOperation::ResourceGatheringOperation( - ProductionType const& new_production_type, fixed_point_t new_size_multiplier -) : ResourceGatheringOperation { new_production_type, new_size_multiplier, 0, 0, 0, {} } {} diff --git a/src/openvic-simulation/economy/ResourceGatheringOperation.hpp b/src/openvic-simulation/economy/ResourceGatheringOperation.hpp deleted file mode 100644 index 73b4261..0000000 --- a/src/openvic-simulation/economy/ResourceGatheringOperation.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#include "openvic-simulation/economy/ProductionType.hpp" -#include "openvic-simulation/types/fixed_point/FixedPoint.hpp" -#include "openvic-simulation/utility/Getters.hpp" - -namespace OpenVic { - class ResourceGatheringOperation final { - private: - ProductionType const& PROPERTY(production_type); - fixed_point_t PROPERTY(revenue_yesterday); - fixed_point_t PROPERTY(output_quantity_yesterday); - fixed_point_t PROPERTY(unsold_quantity_yesterday); - fixed_point_t PROPERTY(size_multiplier); - ordered_map PROPERTY(employees); - - public: - ResourceGatheringOperation( - ProductionType const& new_production_type, - fixed_point_t new_size_multiplier, - fixed_point_t new_revenue_yesterday, - fixed_point_t new_output_quantity_yesterday, - fixed_point_t new_unsold_quantity_yesterday, - ordered_map&& new_employees - ); - ResourceGatheringOperation(ProductionType const& new_production_type, fixed_point_t new_size_multiplier); - }; -} diff --git a/src/openvic-simulation/economy/production/ArtisanalProducer.cpp b/src/openvic-simulation/economy/production/ArtisanalProducer.cpp new file mode 100644 index 0000000..d5cc3d3 --- /dev/null +++ b/src/openvic-simulation/economy/production/ArtisanalProducer.cpp @@ -0,0 +1,13 @@ +#include "ArtisanalProducer.hpp" + +using namespace OpenVic; + +ArtisanalProducer::ArtisanalProducer( + ProductionType const& new_production_type, + GoodDefinition::good_definition_map_t&& new_stockpile, + fixed_point_t new_current_production, + GoodDefinition::good_definition_map_t&& new_current_needs +) : production_type { new_production_type }, + stockpile { std::move(new_stockpile) }, + current_production { new_current_production }, + current_needs { std::move(new_current_needs) } {} diff --git a/src/openvic-simulation/economy/production/ArtisanalProducer.hpp b/src/openvic-simulation/economy/production/ArtisanalProducer.hpp new file mode 100644 index 0000000..e5c0b80 --- /dev/null +++ b/src/openvic-simulation/economy/production/ArtisanalProducer.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "openvic-simulation/economy/GoodDefinition.hpp" +#include "openvic-simulation/economy/production/ProductionType.hpp" +#include "openvic-simulation/types/fixed_point/FixedPoint.hpp" +#include "openvic-simulation/utility/Getters.hpp" + +namespace OpenVic { + class ArtisanalProducer final { + private: + ProductionType const& PROPERTY(production_type); + GoodDefinition::good_definition_map_t PROPERTY(stockpile); + fixed_point_t PROPERTY(current_production); + GoodDefinition::good_definition_map_t PROPERTY(current_needs); + + public: + ArtisanalProducer( + ProductionType const& new_production_type, GoodDefinition::good_definition_map_t&& new_stockpile, + fixed_point_t new_current_production, GoodDefinition::good_definition_map_t&& new_current_needs + ); + }; +} diff --git a/src/openvic-simulation/economy/production/FactoryProducer.cpp b/src/openvic-simulation/economy/production/FactoryProducer.cpp new file mode 100644 index 0000000..2ef9fa8 --- /dev/null +++ b/src/openvic-simulation/economy/production/FactoryProducer.cpp @@ -0,0 +1,58 @@ +#include "FactoryProducer.hpp" + +using namespace OpenVic; + +FactoryProducer::FactoryProducer( + ProductionType const& new_production_type, + fixed_point_t new_size_multiplier, + fixed_point_t new_revenue_yesterday, + fixed_point_t new_output_quantity_yesterday, + fixed_point_t new_unsold_quantity_yesterday, + ordered_map&& new_employees, + GoodDefinition::good_definition_map_t&& new_stockpile, + fixed_point_t new_budget, + fixed_point_t new_balance_yesterday, + fixed_point_t new_received_investments_yesterday, + fixed_point_t new_market_spendings_yesterday, + fixed_point_t new_paychecks_yesterday, + uint32_t new_unprofitable_days, + uint32_t new_subsidised_days, + uint32_t new_days_without_input, + uint8_t new_hiring_priority, + uint8_t new_profit_history_current, + daily_profit_history_t&& new_daily_profit_history +) : production_type { new_production_type }, + size_multiplier { new_size_multiplier }, + revenue_yesterday { new_revenue_yesterday }, + output_quantity_yesterday { new_output_quantity_yesterday }, + unsold_quantity_yesterday { new_unsold_quantity_yesterday }, + employees { std::move(new_employees) }, + stockpile { std::move(new_stockpile) }, + budget { new_budget }, + balance_yesterday { new_balance_yesterday }, + received_investments_yesterday { new_received_investments_yesterday }, + market_spendings_yesterday { new_market_spendings_yesterday }, + paychecks_yesterday { new_paychecks_yesterday }, + unprofitable_days { new_unprofitable_days }, + subsidised_days { new_subsidised_days }, + days_without_input { new_days_without_input }, + hiring_priority { new_hiring_priority }, + profit_history_current { new_profit_history_current }, + daily_profit_history { std::move(new_daily_profit_history) } {} + +FactoryProducer::FactoryProducer(ProductionType const& new_production_type, fixed_point_t new_size_multiplier) + : FactoryProducer { new_production_type, new_size_multiplier, 0, 0, 0, {}, {}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {} } {} + +fixed_point_t FactoryProducer::get_profitability_yesterday() const { + return daily_profit_history[profit_history_current]; +} + +fixed_point_t FactoryProducer::get_average_profitability_last_seven_days() const { + fixed_point_t sum = 0; + + for (int i = 0; i <= profit_history_current; i++) { + sum += daily_profit_history[i]; + } + + return sum / (1 + profit_history_current); +} diff --git a/src/openvic-simulation/economy/production/FactoryProducer.hpp b/src/openvic-simulation/economy/production/FactoryProducer.hpp new file mode 100644 index 0000000..54ddfb8 --- /dev/null +++ b/src/openvic-simulation/economy/production/FactoryProducer.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include + +#include "openvic-simulation/economy/GoodDefinition.hpp" +#include "openvic-simulation/economy/production/ProductionType.hpp" +#include "openvic-simulation/types/fixed_point/FixedPoint.hpp" +#include "openvic-simulation/utility/Getters.hpp" + +namespace OpenVic { + class FactoryProducer final { + private: + static constexpr uint8_t DAYS_OF_HISTORY = 7; + using daily_profit_history_t = std::array; + + uint8_t PROPERTY(profit_history_current); + daily_profit_history_t PROPERTY(daily_profit_history); + ProductionType const& PROPERTY(production_type); + fixed_point_t PROPERTY(revenue_yesterday); + fixed_point_t PROPERTY(output_quantity_yesterday); + fixed_point_t PROPERTY(unsold_quantity_yesterday); + fixed_point_t PROPERTY(size_multiplier); + ordered_map PROPERTY(employees); + GoodDefinition::good_definition_map_t PROPERTY(stockpile); + fixed_point_t PROPERTY(budget); + fixed_point_t PROPERTY(balance_yesterday); + fixed_point_t PROPERTY(received_investments_yesterday); + fixed_point_t PROPERTY(market_spendings_yesterday); + fixed_point_t PROPERTY(paychecks_yesterday); + uint32_t PROPERTY(unprofitable_days); + uint32_t PROPERTY(subsidised_days); + uint32_t PROPERTY(days_without_input); + uint8_t PROPERTY_RW(hiring_priority); + + public: + FactoryProducer( + ProductionType const& new_production_type, fixed_point_t new_size_multiplier, fixed_point_t new_revenue_yesterday, + fixed_point_t new_output_quantity_yesterday, fixed_point_t new_unsold_quantity_yesterday, + ordered_map&& new_employees, GoodDefinition::good_definition_map_t&& new_stockpile, + fixed_point_t new_budget, fixed_point_t new_balance_yesterday, fixed_point_t new_received_investments_yesterday, + fixed_point_t new_market_spendings_yesterday, fixed_point_t new_paychecks_yesterday, uint32_t new_unprofitable_days, + uint32_t new_subsidised_days, uint32_t new_days_without_input, uint8_t new_hiring_priority, + uint8_t new_profit_history_current, daily_profit_history_t&& new_daily_profit_history + ); + FactoryProducer(ProductionType const& new_production_type, fixed_point_t new_size_multiplier); + + fixed_point_t get_profitability_yesterday() const; + fixed_point_t get_average_profitability_last_seven_days() const; + }; +} diff --git a/src/openvic-simulation/economy/production/ProductionType.cpp b/src/openvic-simulation/economy/production/ProductionType.cpp new file mode 100644 index 0000000..65f3eba --- /dev/null +++ b/src/openvic-simulation/economy/production/ProductionType.cpp @@ -0,0 +1,326 @@ +#include "ProductionType.hpp" + +#include + +using namespace OpenVic; +using namespace OpenVic::NodeTools; + +Job::Job( + PopType const* new_pop_type, + effect_t new_effect_type, + fixed_point_t new_effect_multiplier, + fixed_point_t new_desired_workforce_share +) : pop_type { new_pop_type }, + effect_type { new_effect_type }, + effect_multiplier { new_effect_multiplier }, + desired_workforce_share { new_desired_workforce_share } {} + +ProductionType::ProductionType( + std::string_view new_identifier, + std::optional new_owner, + std::vector&& new_jobs, + template_type_t new_template_type, + Pop::pop_size_t new_base_workforce_size, + GoodDefinition::good_definition_map_t&& new_input_goods, + GoodDefinition const* new_output_goods, + fixed_point_t new_base_output_quantity, + std::vector&& new_bonuses, + GoodDefinition::good_definition_map_t&& new_maintenance_requirements, + bool new_is_coastal, + bool new_is_farm, + bool new_is_mine +) : HasIdentifier { new_identifier }, + owner { new_owner }, + jobs { std::move(new_jobs) }, + template_type { new_template_type }, + base_workforce_size { new_base_workforce_size }, + input_goods { std::move(new_input_goods) }, + output_goods { new_output_goods }, + base_output_quantity { new_base_output_quantity }, + bonuses { std::move(new_bonuses) }, + maintenance_requirements { std::move(new_maintenance_requirements) }, + coastal { new_is_coastal }, + farm { new_is_farm }, + mine { new_is_mine } {} + +bool ProductionType::parse_scripts(DefinitionManager const& definition_manager) { + bool ret = true; + for (auto& [bonus_script, bonus_value] : bonuses) { + ret &= bonus_script.parse_script(false, definition_manager); + } + return ret; +} + +ProductionTypeManager::ProductionTypeManager() : rgo_owner_sprite { 0 } {} + +node_callback_t ProductionTypeManager::_expect_job( + GoodDefinitionManager const& good_definition_manager, PopManager const& pop_manager, callback_t callback +) { + return [this, &good_definition_manager, &pop_manager, callback](ast::NodeCPtr node) -> bool { + using enum Job::effect_t; + + std::string_view pop_type {}; + Job::effect_t effect_type {THROUGHPUT}; + fixed_point_t effect_multiplier = 1, desired_workforce_share = 1; + + static const string_map_t effect_map = { + { "input", INPUT }, { "output", OUTPUT }, { "throughput", THROUGHPUT } + }; + + bool res = expect_dictionary_keys( + "poptype", ONE_EXACTLY, expect_identifier(assign_variable_callback(pop_type)), + "effect", ONE_EXACTLY, expect_identifier(expect_mapped_string(effect_map, assign_variable_callback(effect_type))), + "effect_multiplier", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(effect_multiplier)), + "amount", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(desired_workforce_share)) + )(node); + + PopType const* found_pop_type = pop_manager.get_pop_type_by_identifier(pop_type); + return res & callback({ found_pop_type, effect_type, effect_multiplier, desired_workforce_share }); + }; +} + +node_callback_t ProductionTypeManager::_expect_job_list( + GoodDefinitionManager const& good_definition_manager, PopManager const& pop_manager, + callback_t&&> callback +) { + return [this, &good_definition_manager, &pop_manager, callback](ast::NodeCPtr node) -> bool { + std::vector jobs; + bool ret = expect_list(_expect_job(good_definition_manager, pop_manager, vector_callback(jobs)))(node); + ret &= callback(std::move(jobs)); + return ret; + }; +} + +bool ProductionTypeManager::add_production_type( + std::string_view identifier, + std::optional owner, + std::vector&& jobs, + ProductionType::template_type_t template_type, + Pop::pop_size_t base_workforce_size, + GoodDefinition::good_definition_map_t&& input_goods, + GoodDefinition const* output_goods, + fixed_point_t base_output_quantity, + std::vector&& bonuses, + GoodDefinition::good_definition_map_t&& maintenance_requirements, + bool is_coastal, + bool is_farm, + bool is_mine +) { + if (identifier.empty()) { + Logger::error("Invalid production type identifier - empty!"); + return false; + } + + if (base_workforce_size <= 0) { + Logger::error("Base workforce size ('workforce') for production type ", identifier, " was 0 or unset!"); + return false; + } + + if (base_output_quantity <= 0) { + Logger::error("Base output quantity ('value') for production type ", identifier, " was 0 or unset!"); + return false; + } + + if (output_goods == nullptr) { + Logger::error("Output good for production type ", identifier, " was null!"); + return false; + } + + using enum ProductionType::template_type_t; + + if (template_type == ARTISAN) { + if (owner.has_value()) { + Logger::warning( + "Artisanal production type ", identifier, " should not have an owner - it is being ignored." + ); + owner.reset(); + } + + if (!jobs.empty()) { + Logger::warning( + "Artisanal production type ", identifier, " should not have employees - ", jobs.size(), " are being ignored." + ); + jobs.clear(); + } + } else { + if (!owner.has_value()) { + Logger::error("Production type ", identifier, " is missing an owner."); + return false; + } + + if (owner->get_pop_type() == nullptr) { + Logger::error("Production type ", identifier, " owner has an invalid pop type."); + return false; + } + + if (jobs.empty()) { + Logger::error("Production type ", identifier, " lacks jobs ('employees')."); + return false; + } + + for (size_t i = 0; i < jobs.size(); i++) { + if (jobs[i].get_pop_type() == nullptr) { + Logger::error("Production type ", identifier, " has invalid pop type in employees[", i, "]."); + return false; + } + } + } + + const bool ret = production_types.add_item({ + identifier, owner, std::move(jobs), template_type, base_workforce_size, std::move(input_goods), output_goods, + base_output_quantity, std::move(bonuses), std::move(maintenance_requirements), is_coastal, is_farm, is_mine + }); + if (rgo_owner_sprite <= 0 && ret && template_type == RGO && owner.has_value() && owner->get_pop_type() != nullptr) { + /* Set rgo owner sprite to that of the first RGO owner we find. */ + rgo_owner_sprite = owner->get_pop_type()->get_sprite(); + } + return ret; +} + +bool ProductionTypeManager::load_production_types_file( + GoodDefinitionManager const& good_definition_manager, PopManager const& pop_manager, ovdl::v2script::Parser const& parser +) { + using namespace std::string_view_literals; + auto template_symbol = parser.find_intern("template"sv); + if (!template_symbol) { + Logger::error("template could not be interned."); + } + + size_t expected_types = 0; + + /* Pass #1: find and store template identifiers */ + ordered_set templates; + ordered_map template_target_map; + bool ret = expect_dictionary( + [this, &expected_types, &templates, &template_target_map, &template_symbol](std::string_view key, ast::NodeCPtr value) -> bool { + expected_types++; + + std::string_view template_id = ""; + bool found_template = false; + const bool ret = + expect_key(template_symbol, expect_identifier(assign_variable_callback(template_id)), &found_template)(value); + if (found_template) { + if (ret) { + templates.emplace(template_id); + template_target_map.emplace(key, template_id); + } else { + Logger::error("Failed get template identifier for ", key); + return false; + } + } + return true; + } + )(parser.get_file_node()); + + /* Pass #2: create and populate the template map */ + ordered_map template_node_map; + ret &= expect_dictionary( + [this, &expected_types, &templates, &template_node_map](std::string_view key, ast::NodeCPtr value) -> bool { + if (templates.contains(key)) { + template_node_map.emplace(key, value); + expected_types--; + } + return true; + } + )(parser.get_file_node()); + + /* Pass #3: actually load production types */ + reserve_more_production_types(expected_types); + ret &= expect_dictionary( + [this, &good_definition_manager, &pop_manager, &template_target_map, &template_node_map]( + std::string_view key, ast::NodeCPtr node) -> bool { + using enum ProductionType::template_type_t; + + if (template_node_map.contains(key)) { + return true; + } + + std::optional owner; + std::vector jobs; + ProductionType::template_type_t template_type { FACTORY }; + GoodDefinition const* output_goods = nullptr; + Pop::pop_size_t base_workforce_size = 0; + GoodDefinition::good_definition_map_t input_goods, maintenance_requirements; + fixed_point_t base_output_quantity = 0; + std::vector bonuses; + bool is_coastal = false, is_farm = false, is_mine = false; + + bool ret = true; + + static const string_map_t template_type_map = { + { "factory", FACTORY }, { "rgo", RGO }, { "artisan", ARTISAN } + }; + + auto parse_node = expect_dictionary_keys( + "template", ZERO_OR_ONE, success_callback, /* Already parsed using expect_key in Pass #1 above. */ + "bonus", ZERO_OR_MORE, [&bonuses](ast::NodeCPtr bonus_node) -> bool { + ConditionScript trigger { scope_t::STATE, scope_t::NO_SCOPE, scope_t::NO_SCOPE }; + fixed_point_t bonus_value {}; + const bool ret = expect_dictionary_keys( + "trigger", ONE_EXACTLY, trigger.expect_script(), + "value", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(bonus_value)) + )(bonus_node); + bonuses.emplace_back(std::move(trigger), bonus_value); + return ret; + }, + "owner", ZERO_OR_ONE, _expect_job(good_definition_manager, pop_manager, move_variable_callback(owner)), + "employees", ZERO_OR_ONE, _expect_job_list(good_definition_manager, pop_manager, move_variable_callback(jobs)), + "type", ZERO_OR_ONE, + expect_identifier(expect_mapped_string(template_type_map, assign_variable_callback(template_type))), + "workforce", ZERO_OR_ONE, expect_uint(assign_variable_callback(base_workforce_size)), + "input_goods", ZERO_OR_ONE, + good_definition_manager.expect_good_definition_decimal_map(move_variable_callback(input_goods)), + "output_goods", ZERO_OR_ONE, + good_definition_manager.expect_good_definition_identifier(assign_variable_callback_pointer(output_goods)), + "value", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(base_output_quantity)), + "efficiency", ZERO_OR_ONE, good_definition_manager.expect_good_definition_decimal_map( + move_variable_callback(maintenance_requirements) + ), + "is_coastal", ZERO_OR_ONE, expect_bool(assign_variable_callback(is_coastal)), + "farm", ZERO_OR_ONE, expect_bool(assign_variable_callback(is_farm)), + "mine", ZERO_OR_ONE, expect_bool(assign_variable_callback(is_mine)) + ); + + /* Check if this ProductionType has a template, and if so parse it. */ + { + const typename decltype(template_target_map)::const_iterator target_it = template_target_map.find(key); + if (target_it != template_target_map.end()) { + const std::string_view template_id = target_it->second; + const typename decltype(template_node_map)::const_iterator node_it = template_node_map.find(template_id); + if (node_it != template_node_map.end()) { + ret &= parse_node(node_it->second); + } else { + Logger::error("Missing template ", template_id, " for production type ", key, "!"); + ret = false; + } + } + } + + /* Parse the ProductionType's own entries, over those of its template if necessary. */ + ret &= parse_node(node); + + ret &= add_production_type( + key, owner, std::move(jobs), template_type, base_workforce_size, std::move(input_goods), output_goods, + base_output_quantity, std::move(bonuses), std::move(maintenance_requirements), is_coastal, is_farm, is_mine + ); + return ret; + } + )(parser.get_file_node()); + + production_types.lock(); + + if (rgo_owner_sprite <= 0) { + Logger::error("No RGO owner pop type sprite found!"); + ret = false; + } + + return ret; +} + +bool ProductionTypeManager::parse_scripts(DefinitionManager const& definition_manager) { + bool ret = true; + for (ProductionType& production_type : production_types.get_items()) { + ret &= production_type.parse_scripts(definition_manager); + } + return ret; +} diff --git a/src/openvic-simulation/economy/production/ProductionType.hpp b/src/openvic-simulation/economy/production/ProductionType.hpp new file mode 100644 index 0000000..5394938 --- /dev/null +++ b/src/openvic-simulation/economy/production/ProductionType.hpp @@ -0,0 +1,121 @@ +#pragma once + +#include + +#include "openvic-simulation/economy/GoodDefinition.hpp" +#include "openvic-simulation/pop/Pop.hpp" +#include "openvic-simulation/scripts/ConditionScript.hpp" +#include "openvic-simulation/types/IdentifierRegistry.hpp" +#include "openvic-simulation/types/fixed_point/FixedPoint.hpp" + +namespace OpenVic { + struct ProductionTypeManager; + + struct Job { + friend struct ProductionTypeManager; + + enum struct effect_t { INPUT, OUTPUT, THROUGHPUT }; + + private: + PopType const* PROPERTY(pop_type); + effect_t PROPERTY(effect_type); + fixed_point_t PROPERTY(effect_multiplier); + fixed_point_t PROPERTY(desired_workforce_share); + + Job( + PopType const* new_pop_type, + effect_t new_effect_type, + fixed_point_t new_effect_multiplier, + fixed_point_t new_desired_workforce_share + ); + + public: + Job() = default; + }; + + struct ProductionType : HasIdentifier { + friend struct ProductionTypeManager; + + enum struct template_type_t { FACTORY, RGO, ARTISAN }; + + using bonus_t = std::pair; + + private: + const std::optional PROPERTY(owner); + std::vector PROPERTY(jobs); + const template_type_t PROPERTY(template_type); + const Pop::pop_size_t PROPERTY(base_workforce_size); + + GoodDefinition::good_definition_map_t PROPERTY(input_goods); + GoodDefinition const* PROPERTY(output_goods); + const fixed_point_t PROPERTY(base_output_quantity); + std::vector PROPERTY(bonuses); + + GoodDefinition::good_definition_map_t PROPERTY(maintenance_requirements); + const bool PROPERTY_CUSTOM_PREFIX(coastal, is); + + const bool PROPERTY_CUSTOM_PREFIX(farm, is); + const bool PROPERTY_CUSTOM_PREFIX(mine, is); + + ProductionType( + std::string_view new_identifier, + std::optional new_owner, + std::vector&& new_jobs, + template_type_t new_template_type, + Pop::pop_size_t new_base_workforce_size, + GoodDefinition::good_definition_map_t&& new_input_goods, + GoodDefinition const* new_output_goods, + fixed_point_t new_base_output_quantity, + std::vector&& new_bonuses, + GoodDefinition::good_definition_map_t&& new_maintenance_requirements, + bool new_is_coastal, + bool new_is_farm, + bool new_is_mine + ); + + bool parse_scripts(DefinitionManager const& definition_manager); + + public: + ProductionType(ProductionType&&) = default; + }; + + struct ProductionTypeManager { + private: + IdentifierRegistry IDENTIFIER_REGISTRY(production_type); + PopType::sprite_t PROPERTY(rgo_owner_sprite); + + NodeTools::node_callback_t _expect_job( + GoodDefinitionManager const& good_definition_manager, PopManager const& pop_manager, + NodeTools::callback_t callback + ); + NodeTools::node_callback_t _expect_job_list( + GoodDefinitionManager const& good_definition_manager, PopManager const& pop_manager, + NodeTools::callback_t&&> callback + ); + + public: + ProductionTypeManager(); + + bool add_production_type( + std::string_view identifier, + std::optional owner, + std::vector&& employees, + ProductionType::template_type_t template_type, + Pop::pop_size_t workforce, + GoodDefinition::good_definition_map_t&& input_goods, + GoodDefinition const* output_goods, + fixed_point_t value, + std::vector&& bonuses, + GoodDefinition::good_definition_map_t&& maintenance_requirements, + bool coastal, + bool farm, + bool mine + ); + + bool load_production_types_file( + GoodDefinitionManager const& good_definition_manager, PopManager const& pop_manager, ovdl::v2script::Parser const& parser + ); + + bool parse_scripts(DefinitionManager const& definition_manager); + }; +} diff --git a/src/openvic-simulation/economy/production/ResourceGatheringOperation.cpp b/src/openvic-simulation/economy/production/ResourceGatheringOperation.cpp new file mode 100644 index 0000000..9bf6f49 --- /dev/null +++ b/src/openvic-simulation/economy/production/ResourceGatheringOperation.cpp @@ -0,0 +1,21 @@ +#include "ResourceGatheringOperation.hpp" + +using namespace OpenVic; + +ResourceGatheringOperation::ResourceGatheringOperation( + ProductionType const& new_production_type, + fixed_point_t new_size_multiplier, + fixed_point_t new_revenue_yesterday, + fixed_point_t new_output_quantity_yesterday, + fixed_point_t new_unsold_quantity_yesterday, + ordered_map&& new_employees +) : production_type { new_production_type }, + revenue_yesterday { new_revenue_yesterday }, + output_quantity_yesterday { new_output_quantity_yesterday }, + unsold_quantity_yesterday { new_unsold_quantity_yesterday }, + size_multiplier { new_size_multiplier }, + employees { std::move(new_employees) } {} + +ResourceGatheringOperation::ResourceGatheringOperation( + ProductionType const& new_production_type, fixed_point_t new_size_multiplier +) : ResourceGatheringOperation { new_production_type, new_size_multiplier, 0, 0, 0, {} } {} diff --git a/src/openvic-simulation/economy/production/ResourceGatheringOperation.hpp b/src/openvic-simulation/economy/production/ResourceGatheringOperation.hpp new file mode 100644 index 0000000..d71c569 --- /dev/null +++ b/src/openvic-simulation/economy/production/ResourceGatheringOperation.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "openvic-simulation/economy/production/ProductionType.hpp" +#include "openvic-simulation/types/fixed_point/FixedPoint.hpp" +#include "openvic-simulation/utility/Getters.hpp" + +namespace OpenVic { + class ResourceGatheringOperation final { + private: + ProductionType const& PROPERTY(production_type); + fixed_point_t PROPERTY(revenue_yesterday); + fixed_point_t PROPERTY(output_quantity_yesterday); + fixed_point_t PROPERTY(unsold_quantity_yesterday); + fixed_point_t PROPERTY(size_multiplier); + ordered_map PROPERTY(employees); + + public: + ResourceGatheringOperation( + ProductionType const& new_production_type, fixed_point_t new_size_multiplier, fixed_point_t new_revenue_yesterday, + fixed_point_t new_output_quantity_yesterday, fixed_point_t new_unsold_quantity_yesterday, + ordered_map&& new_employees + ); + ResourceGatheringOperation(ProductionType const& new_production_type, fixed_point_t new_size_multiplier); + }; +} -- cgit v1.2.3-56-ga3b1