aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation/economy/production
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvic-simulation/economy/production')
-rw-r--r--src/openvic-simulation/economy/production/ArtisanalProducer.cpp13
-rw-r--r--src/openvic-simulation/economy/production/ArtisanalProducer.hpp22
-rw-r--r--src/openvic-simulation/economy/production/FactoryProducer.cpp58
-rw-r--r--src/openvic-simulation/economy/production/FactoryProducer.hpp50
-rw-r--r--src/openvic-simulation/economy/production/ProductionType.cpp326
-rw-r--r--src/openvic-simulation/economy/production/ProductionType.hpp121
-rw-r--r--src/openvic-simulation/economy/production/ResourceGatheringOperation.cpp21
-rw-r--r--src/openvic-simulation/economy/production/ResourceGatheringOperation.hpp25
8 files changed, 636 insertions, 0 deletions
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<Pop*, Pop::pop_size_t>&& 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 <cstdint>
+
+#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<fixed_point_t, DAYS_OF_HISTORY>;
+
+ 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<Pop*, Pop::pop_size_t> 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<Pop*, Pop::pop_size_t>&& 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 <openvic-dataloader/v2script/Parser.hpp>
+
+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<Job> new_owner,
+ std::vector<Job>&& 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<bonus_t>&& 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<Job&&> 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<Job::effect_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<std::vector<Job>&&> callback
+) {
+ return [this, &good_definition_manager, &pop_manager, callback](ast::NodeCPtr node) -> bool {
+ std::vector<Job> 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<Job> owner,
+ std::vector<Job>&& 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<ProductionType::bonus_t>&& 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<std::string_view> templates;
+ ordered_map<std::string_view, std::string_view> 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<std::string_view, ast::NodeCPtr> 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<Job> owner;
+ std::vector<Job> 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<ProductionType::bonus_t> bonuses;
+ bool is_coastal = false, is_farm = false, is_mine = false;
+
+ bool ret = true;
+
+ static const string_map_t<ProductionType::template_type_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 <openvic-dataloader/v2script/Parser.hpp>
+
+#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<ConditionScript, fixed_point_t>;
+
+ private:
+ const std::optional<Job> PROPERTY(owner);
+ std::vector<Job> 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<bonus_t> 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<Job> new_owner,
+ std::vector<Job>&& 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<bonus_t>&& 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<ProductionType> 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<Job&&> callback
+ );
+ NodeTools::node_callback_t _expect_job_list(
+ GoodDefinitionManager const& good_definition_manager, PopManager const& pop_manager,
+ NodeTools::callback_t<std::vector<Job>&&> callback
+ );
+
+ public:
+ ProductionTypeManager();
+
+ bool add_production_type(
+ std::string_view identifier,
+ std::optional<Job> owner,
+ std::vector<Job>&& 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<ProductionType::bonus_t>&& 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<Pop*, Pop::pop_size_t>&& 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<Pop*, Pop::pop_size_t> 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<Pop*, Pop::pop_size_t>&& new_employees
+ );
+ ResourceGatheringOperation(ProductionType const& new_production_type, fixed_point_t new_size_multiplier);
+ };
+}