-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
20 changed files
with
477 additions
and
50 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
121 changes: 114 additions & 7 deletions
121
src/openvic-simulation/economy/production/ArtisanalProducer.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,120 @@ | ||
#include "ArtisanalProducer.hpp" | ||
|
||
#include "openvic-simulation/economy/GoodDefinition.hpp" | ||
#include "openvic-simulation/economy/trading/BuyResult.hpp" | ||
#include "openvic-simulation/economy/trading/SellResult.hpp" | ||
#include "openvic-simulation/pop/Pop.hpp" | ||
#include "types/fixed_point/FixedPoint.hpp" | ||
|
||
using namespace OpenVic; | ||
|
||
ArtisanalProducer::ArtisanalProducer( | ||
ProductionType const& new_production_type, | ||
MarketInstance& new_market_instance, | ||
ModifierEffectCache const& new_modifier_effect_cache, | ||
Pop& new_pop, | ||
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) } {} | ||
ProductionType const& new_production_type, | ||
fixed_point_t new_current_production | ||
) : market_instance { new_market_instance }, | ||
modifier_effect_cache { new_modifier_effect_cache }, | ||
pop { new_pop }, | ||
stockpile { new_stockpile }, | ||
production_type { new_production_type }, | ||
current_production { new_current_production } | ||
{} | ||
|
||
void ArtisanalProducer::artisan_tick() { | ||
GoodDefinition::good_definition_map_t goods_to_buy_and_max_price { }; | ||
GoodDefinition::good_definition_map_t demand { }; | ||
fixed_point_t inputs_bought_scalar = fixed_point_t::_1(); | ||
if (production_type.get_input_goods().empty()) { | ||
inputs_bought_scalar = fixed_point_t::_1(); | ||
} else { | ||
GoodInstanceManager const& good_instance_manager = market_instance.get_good_instance_manager(); | ||
for (auto const& [input_good_ptr, base_desired_quantity] : production_type.get_input_goods()) { | ||
const fixed_point_t desired_quantity = demand[input_good_ptr] = base_desired_quantity * pop.get_size() / production_type.get_base_workforce_size(); | ||
if (desired_quantity == fixed_point_t::_0()) { | ||
continue; | ||
} | ||
inputs_bought_scalar = std::min(stockpile[input_good_ptr] / desired_quantity, inputs_bought_scalar); | ||
GoodInstance const& good = good_instance_manager.get_good_instance_from_definition(*input_good_ptr); | ||
goods_to_buy_and_max_price[input_good_ptr] = good.get_max_next_price(); | ||
} | ||
|
||
if (inputs_bought_scalar > fixed_point_t::_0()) { | ||
for (auto const& [input_good_ptr, base_desired_quantity] : production_type.get_input_goods()) { | ||
const fixed_point_t desired_quantity = demand[input_good_ptr]; | ||
stockpile[input_good_ptr] = std::max( | ||
fixed_point_t::_0(), | ||
stockpile[input_good_ptr] - desired_quantity * inputs_bought_scalar | ||
); | ||
|
||
if (stockpile[input_good_ptr] >= desired_quantity) { | ||
goods_to_buy_and_max_price.erase(input_good_ptr); | ||
} | ||
} | ||
} | ||
|
||
const fixed_point_t total_cash_to_spend = pop.get_cash(); | ||
if (total_cash_to_spend > 0 && !goods_to_buy_and_max_price.empty()) { | ||
fixed_point_t max_possible_satisfaction = fixed_point_t::_1(); | ||
|
||
bool at_or_below_optimum = false; | ||
while (!at_or_below_optimum) { | ||
at_or_below_optimum = true; | ||
fixed_point_t total_demand_value = fixed_point_t::_0(); | ||
fixed_point_t total_stockpile_value = fixed_point_t::_0(); | ||
for (auto const& [input_good_ptr, max_price] : goods_to_buy_and_max_price) { | ||
total_demand_value += max_price * demand[input_good_ptr]; | ||
total_stockpile_value += max_price * stockpile[input_good_ptr]; | ||
} | ||
|
||
max_possible_satisfaction = total_demand_value == fixed_point_t::_0() | ||
? fixed_point_t::_1() | ||
: std::min( | ||
fixed_point_t::_1(), | ||
(total_stockpile_value + total_cash_to_spend) / total_demand_value | ||
); | ||
|
||
for (auto const& [input_good_ptr, max_price] : goods_to_buy_and_max_price) { | ||
const fixed_point_t optimal_quantity = demand[input_good_ptr] * max_possible_satisfaction; | ||
if (stockpile[input_good_ptr] >= optimal_quantity) { | ||
goods_to_buy_and_max_price.erase(input_good_ptr); | ||
at_or_below_optimum = false; | ||
} | ||
} | ||
} | ||
|
||
for (auto const& [input_good_ptr, max_price] : goods_to_buy_and_max_price) { | ||
const fixed_point_t optimal_quantity = demand[input_good_ptr] * max_possible_satisfaction; | ||
const fixed_point_t max_quantity_to_buy = demand[input_good_ptr] - stockpile[input_good_ptr]; | ||
const fixed_point_t money_to_spend = optimal_quantity * max_price; | ||
pop.add_artisan_inputs_expense(money_to_spend); | ||
market_instance.place_buy_up_to_order({ | ||
*input_good_ptr, | ||
max_quantity_to_buy, | ||
money_to_spend, | ||
[this, input_good_ptr](const BuyResult buy_result) -> void { | ||
pop.add_artisan_inputs_expense(-buy_result.get_money_left()); | ||
stockpile[input_good_ptr] += buy_result.get_quantity_bought(); | ||
} | ||
}); | ||
} | ||
} | ||
} | ||
|
||
current_production = production_type.get_base_output_quantity() | ||
* inputs_bought_scalar | ||
* pop.get_size() / production_type.get_base_workforce_size(); | ||
|
||
GoodDefinition const& output_good = production_type.get_output_good(); | ||
if (current_production > 0) { | ||
market_instance.place_market_sell_order({ | ||
output_good, | ||
current_production, | ||
[this](const SellResult sell_result) -> void { | ||
pop.add_artisanal_income(sell_result.get_money_gained()); | ||
} | ||
}); | ||
} | ||
} |
20 changes: 15 additions & 5 deletions
20
src/openvic-simulation/economy/production/ArtisanalProducer.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,32 @@ | ||
#pragma once | ||
|
||
#include "openvic-simulation/economy/GoodDefinition.hpp" | ||
#include "openvic-simulation/economy/production/ProductionType.hpp" | ||
#include "openvic-simulation/economy/trading/MarketInstance.hpp" | ||
#include "openvic-simulation/modifier/ModifierEffectCache.hpp" | ||
#include "openvic-simulation/types/fixed_point/FixedPoint.hpp" | ||
#include "openvic-simulation/utility/Getters.hpp" | ||
|
||
namespace OpenVic { | ||
struct Pop; | ||
|
||
struct ArtisanalProducer { | ||
private: | ||
MarketInstance& market_instance; | ||
ModifierEffectCache const& modifier_effect_cache; | ||
Pop& pop; | ||
GoodDefinition::good_definition_map_t stockpile; | ||
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 | ||
MarketInstance& new_market_instance, | ||
ModifierEffectCache const& new_modifier_effect_cache, | ||
Pop& new_pop, | ||
GoodDefinition::good_definition_map_t&& new_stockpile, | ||
ProductionType const& new_production_type, | ||
fixed_point_t new_current_production | ||
); | ||
void artisan_tick(); | ||
}; | ||
} |
44 changes: 44 additions & 0 deletions
44
src/openvic-simulation/economy/production/ArtisanalProducerFactoryPattern.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
#include "ArtisanalProducerFactoryPattern.hpp" | ||
|
||
#include "openvic-simulation/economy/GoodInstance.hpp" | ||
|
||
using namespace OpenVic; | ||
|
||
ArtisanalProducerFactoryPattern::ArtisanalProducerFactoryPattern( | ||
MarketInstance& new_market_instance, | ||
ModifierEffectCache const& new_modifier_effect_cache, | ||
ProductionTypeManager const& new_production_type_manager | ||
) : market_instance { new_market_instance }, | ||
modifier_effect_cache { new_modifier_effect_cache }, | ||
production_type_manager { new_production_type_manager } | ||
{} | ||
|
||
std::unique_ptr<ArtisanalProducer> ArtisanalProducerFactoryPattern::CreateNewArtisanalProducer(Pop& pop) const { | ||
ProductionType const* random_artisanal_production_type = nullptr; | ||
|
||
for (ProductionType const& production_type : production_type_manager.get_production_types()) { | ||
if (production_type.get_template_type() == ProductionType::template_type_t::ARTISAN) { | ||
GoodInstance const& good_instance = market_instance.get_good_instance_manager().get_good_instance_from_definition( | ||
production_type.get_output_good() | ||
); | ||
if (!good_instance.get_is_available()) { | ||
continue; | ||
} | ||
random_artisanal_production_type = &production_type; | ||
break; //TODO actually randomise it instead of picking the first. | ||
} | ||
} | ||
|
||
if (random_artisanal_production_type == nullptr) { | ||
Logger::error("CreateNewArtisanalProducer was called but there are no artisanal production types."); | ||
} | ||
|
||
return std::make_unique<ArtisanalProducer>( | ||
market_instance, | ||
modifier_effect_cache, | ||
pop, | ||
GoodDefinition::good_definition_map_t{}, | ||
*random_artisanal_production_type, | ||
fixed_point_t::_0() | ||
); | ||
} |
28 changes: 28 additions & 0 deletions
28
src/openvic-simulation/economy/production/ArtisanalProducerFactoryPattern.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
#pragma once | ||
|
||
#include <memory> | ||
|
||
#include "openvic-simulation/economy/production/ArtisanalProducer.hpp" | ||
#include "openvic-simulation/economy/production/ProductionType.hpp" | ||
#include "openvic-simulation/economy/trading/MarketInstance.hpp" | ||
#include "openvic-simulation/modifier/ModifierEffectCache.hpp" | ||
|
||
namespace OpenVic { | ||
struct Pop; | ||
|
||
struct ArtisanalProducerFactoryPattern { | ||
private: | ||
MarketInstance& market_instance; | ||
ModifierEffectCache const& modifier_effect_cache; | ||
ProductionTypeManager const& production_type_manager; | ||
|
||
public: | ||
ArtisanalProducerFactoryPattern( | ||
MarketInstance& new_market_instance, | ||
ModifierEffectCache const& new_modifier_effect_cache, | ||
ProductionTypeManager const& new_production_type_manager | ||
); | ||
|
||
std::unique_ptr<ArtisanalProducer> CreateNewArtisanalProducer(Pop& pop) const; | ||
}; | ||
} |
Oops, something went wrong.