diff --git a/ECSAPI/ECS/src/world.cpp b/ECSAPI/ECS/src/world.cpp index c8b7229..964e281 100644 --- a/ECSAPI/ECS/src/world.cpp +++ b/ECSAPI/ECS/src/world.cpp @@ -41,7 +41,16 @@ entt::entity ee_ecs::world::spawn_enterprise( { entt::entity entity = this->registry.create(); - this->registry.emplace(entity, is_building, state); + this->registry.emplace( + entity, + is_building, + state, + + defaults.base_efficiency * defaults.factor_efficiency, + + defaults.base_efficiency, + defaults.factor_efficiency + ); this->registry.emplace( entity, @@ -54,7 +63,13 @@ entt::entity ee_ecs::world::spawn_enterprise( { case ee_economy::ACTION_TYPE::MINING: { - this->registry.emplace(entity, defaults.resource_target, defaults.base_efficiency_flat); + this->registry.emplace(entity, defaults.resource_target); + break; + } + + case ee_economy::ACTION_TYPE::DELIVERY: + { + this->registry.emplace(entity, defaults.resource_target); break; } diff --git a/ECSAPI/ECS/test/test_conf.hpp b/ECSAPI/ECS/test/test_conf.hpp index f35e9a0..a209e93 100644 --- a/ECSAPI/ECS/test/test_conf.hpp +++ b/ECSAPI/ECS/test/test_conf.hpp @@ -18,7 +18,7 @@ struct WorldBenchmark : testing::Test ee_economy::enterprise_defaults miner = { .container = {.capacity = 100.0}, .resource_target = ee_economy::RESOURCE_TYPE::GOLD, - .base_efficiency_flat = 1.0 + .base_efficiency = 1.0 }; world.spawn_enterprise(false, ee_economy::ACTION_TYPE::MINING, state, miner); diff --git a/ECSAPI/ECS/test/world.cpp b/ECSAPI/ECS/test/world.cpp index 0db137c..3fdb5b6 100644 --- a/ECSAPI/ECS/test/world.cpp +++ b/ECSAPI/ECS/test/world.cpp @@ -15,7 +15,7 @@ TEST(WorldTest, RegisterState) ee_economy::container registered_container = world.get_registry().get(state); ASSERT_EQ(registered_state.external_id, 10); - ASSERT_EQ(registered_container.content[ee_economy::RESOURCE_TYPE::COAL], 98.0); + ASSERT_DOUBLE_EQ(registered_container.content[ee_economy::RESOURCE_TYPE::COAL], 98.0); } TEST(WorldTest, RegisterStateDuplicate) @@ -29,7 +29,52 @@ TEST(WorldTest, RegisterStateDuplicate) }, std::invalid_argument); } -TEST(WorldTest, SpawnEnterprise) +TEST(WorldTest, SpawnMiner) { - ASSERT_TRUE(false); + ee_ecs::world world; + + entt::entity state = world.get_registry().create(); + world.get_registry().emplace(state, (short)0); + world.get_registry().emplace(state, 100.0); + + ee_economy::enterprise_defaults defaults = { + .container = {.capacity = 100.0 }, + .resource_target = ee_economy::RESOURCE_TYPE::COAL, + .base_efficiency = 1.0, + }; + + entt::entity enterprise = world.spawn_enterprise(false, ee_economy::ACTION_TYPE::MINING, state, defaults); + + ee_economy::enterprise registered_enterprise = world.get_registry().get(enterprise); + ee_economy::miner registered_action = world.get_registry().get(enterprise); + ee_economy::container registered_container = world.get_registry().get(enterprise); + + ASSERT_DOUBLE_EQ(registered_enterprise.base_efficiency, 1.0); + ASSERT_EQ(registered_action.resource, ee_economy::RESOURCE_TYPE::COAL); + ASSERT_DOUBLE_EQ(registered_container.capacity, 100.0); +} + +TEST(WorldTest, SpawnDeliverer) +{ + ee_ecs::world world; + + entt::entity state = world.get_registry().create(); + world.get_registry().emplace(state, (short)0); + world.get_registry().emplace(state, 100.0); + + ee_economy::enterprise_defaults defaults = { + .container = {.capacity = 100.0 }, + .resource_target = ee_economy::RESOURCE_TYPE::COAL, + .base_efficiency = 1.0, + }; + + entt::entity enterprise = world.spawn_enterprise(false, ee_economy::ACTION_TYPE::DELIVERY, state, defaults); + + ee_economy::enterprise registered_enterprise = world.get_registry().get(enterprise); + ee_economy::deliverer registered_action = world.get_registry().get(enterprise); + ee_economy::container registered_container = world.get_registry().get(enterprise); + + ASSERT_DOUBLE_EQ(registered_enterprise.base_efficiency, 1.0); + ASSERT_EQ(registered_action.resource, ee_economy::RESOURCE_TYPE::COAL); + ASSERT_DOUBLE_EQ(registered_container.capacity, 100.0); } \ No newline at end of file diff --git a/ECSAPI/Economy/CMakeLists.txt b/ECSAPI/Economy/CMakeLists.txt index 0bc19bf..c0cf4c3 100644 --- a/ECSAPI/Economy/CMakeLists.txt +++ b/ECSAPI/Economy/CMakeLists.txt @@ -3,10 +3,11 @@ # List sources set(HEADERS "economy.hpp" "defines.hpp" "enterprise_defaults.hpp" "systems.hpp") -set(HEADERS_COMPONENTS "container.hpp" "enterprise.hpp" "miner.hpp" "producer.hpp" "state.hpp" "tags.hpp") +set(HEADERS_COMPONENTS "container.hpp" "enterprise.hpp" "state.hpp" "tags.hpp" + "miner.hpp" "producer.hpp" "deliverer.hpp") set(SOURCES "Economy.cpp") -set(SOURCES_SYSTEMS "mining.cpp") +set(SOURCES_SYSTEMS "mining.cpp" "delivering.cpp") list(TRANSFORM HEADERS PREPEND "include/ee_economy/") list(TRANSFORM HEADERS_COMPONENTS PREPEND "include/ee_economy/components/") diff --git a/ECSAPI/Economy/include/ee_economy/components/container.hpp b/ECSAPI/Economy/include/ee_economy/components/container.hpp index 61df5f2..845006c 100644 --- a/ECSAPI/Economy/include/ee_economy/components/container.hpp +++ b/ECSAPI/Economy/include/ee_economy/components/container.hpp @@ -12,8 +12,8 @@ namespace ee_economy void add(RESOURCE_TYPE type, double delta) { - content[type] += delta; - total += delta; + this->content[type] += delta; + this->total += delta; } }; } \ No newline at end of file diff --git a/ECSAPI/Economy/include/ee_economy/components/deliverer.hpp b/ECSAPI/Economy/include/ee_economy/components/deliverer.hpp new file mode 100644 index 0000000..22b7441 --- /dev/null +++ b/ECSAPI/Economy/include/ee_economy/components/deliverer.hpp @@ -0,0 +1,20 @@ +#pragma once +#include +#include + +namespace ee_economy +{ + struct deliver_contract + { + entt::entity from; + entt::entity to; + double value = 0.0; + }; + + struct deliverer + { + RESOURCE_TYPE resource = RESOURCE_TYPE::NONE; + + std::vector contracts; + }; +} \ No newline at end of file diff --git a/ECSAPI/Economy/include/ee_economy/components/enterprise.hpp b/ECSAPI/Economy/include/ee_economy/components/enterprise.hpp index c06848d..4a8aa62 100644 --- a/ECSAPI/Economy/include/ee_economy/components/enterprise.hpp +++ b/ECSAPI/Economy/include/ee_economy/components/enterprise.hpp @@ -1,12 +1,48 @@ #pragma once #include +#include namespace ee_economy { struct enterprise { bool is_building = false; - entt::entity state; + + double efficiency = 0.; + double base_efficiency = 0.; + double factor_efficiency = 1.; + + std::vector links_from; + std::vector links_to; + + inline void update_efficiency() + { + this->efficiency = this->base_efficiency * this->factor_efficiency; + } + + void add_base_efficiency(double delta) + { + this->base_efficiency += delta; + update_efficiency(); + } + + void add_factor_efficiency(double delta) + { + this->factor_efficiency += delta; + update_efficiency(); + } + + void multiply_base_efficiency(double factor) + { + this->base_efficiency *= factor; + update_efficiency(); + } + + void multiply_factor_efficiency(double factor) + { + this->factor_efficiency *= factor; + update_efficiency(); + } }; } \ No newline at end of file diff --git a/ECSAPI/Economy/include/ee_economy/components/miner.hpp b/ECSAPI/Economy/include/ee_economy/components/miner.hpp index e7ffb58..c82a0c0 100644 --- a/ECSAPI/Economy/include/ee_economy/components/miner.hpp +++ b/ECSAPI/Economy/include/ee_economy/components/miner.hpp @@ -7,6 +7,5 @@ namespace ee_economy struct miner { RESOURCE_TYPE resource = RESOURCE_TYPE::NONE; - double value = 0.; }; } \ No newline at end of file diff --git a/ECSAPI/Economy/include/ee_economy/economy.hpp b/ECSAPI/Economy/include/ee_economy/economy.hpp index 891f7bb..3c19784 100644 --- a/ECSAPI/Economy/include/ee_economy/economy.hpp +++ b/ECSAPI/Economy/include/ee_economy/economy.hpp @@ -7,6 +7,8 @@ #include "components/tags.hpp" #include "components/state.hpp" #include "components/container.hpp" + #include "components/enterprise.hpp" #include "components/miner.hpp" -#include "components/producer.hpp" \ No newline at end of file +#include "components/producer.hpp" +#include "components/deliverer.hpp" \ No newline at end of file diff --git a/ECSAPI/Economy/include/ee_economy/enterprise_defaults.hpp b/ECSAPI/Economy/include/ee_economy/enterprise_defaults.hpp index 7d8abbe..326b5fd 100644 --- a/ECSAPI/Economy/include/ee_economy/enterprise_defaults.hpp +++ b/ECSAPI/Economy/include/ee_economy/enterprise_defaults.hpp @@ -8,7 +8,8 @@ namespace ee_economy { container container; - RESOURCE_TYPE resource_target; - double base_efficiency_flat; + RESOURCE_TYPE resource_target = RESOURCE_TYPE::NONE; + double base_efficiency = 0.0; + double factor_efficiency = 1.0; }; } \ No newline at end of file diff --git a/ECSAPI/Economy/include/ee_economy/systems.hpp b/ECSAPI/Economy/include/ee_economy/systems.hpp index 6d36b01..d0694b7 100644 --- a/ECSAPI/Economy/include/ee_economy/systems.hpp +++ b/ECSAPI/Economy/include/ee_economy/systems.hpp @@ -5,8 +5,8 @@ namespace ee_economy { void mining(entt::registry& registry); // void producing(entt::registry& registry); - // void delivering(entt::registry& registry); - // void containing(entt::registry& registry); + void delivering(entt::registry& registry); + // void storaging(entt::registry& registry); ? // void destructing(entt::registry& registry); // void building(entt::registry& registry); // void trading(entt::registry& registry); diff --git a/ECSAPI/Economy/src/systems/delivering.cpp b/ECSAPI/Economy/src/systems/delivering.cpp new file mode 100644 index 0000000..c5e7582 --- /dev/null +++ b/ECSAPI/Economy/src/systems/delivering.cpp @@ -0,0 +1,33 @@ +#include + +void ee_economy::delivering(entt::registry ®istry) +{ + auto deliverers = registry.view(); + + for (auto [entity, enterprise, deliverer]: deliverers.each()) + { + for (deliver_contract &contract: deliverer.contracts) + { + container &from_storage = registry.get(contract.from); + container &to_storage = registry.get(contract.to); + + double deliver_value = enterprise.efficiency; + if (contract.value < enterprise.efficiency) + deliver_value = contract.value; + if (to_storage.total + deliver_value > to_storage.capacity) + deliver_value = to_storage.capacity - to_storage.total; + if (deliver_value > from_storage.content[deliverer.resource]) + deliver_value = from_storage.content[deliverer.resource]; + if (deliver_value < 0.0) + deliver_value = 0.0; + + to_storage.add(deliverer.resource, deliver_value); + from_storage.add(deliverer.resource, -deliver_value); + contract.value -= deliver_value; + } + + std::erase_if(deliverer.contracts, [](const deliver_contract &contract) { + return contract.value <= 0.0; + }); + } +} \ No newline at end of file diff --git a/ECSAPI/Economy/src/systems/mining.cpp b/ECSAPI/Economy/src/systems/mining.cpp index d6c0dff..d67323e 100644 --- a/ECSAPI/Economy/src/systems/mining.cpp +++ b/ECSAPI/Economy/src/systems/mining.cpp @@ -8,10 +8,7 @@ void ee_economy::mining(entt::registry ®istry) { container& state = registry.get(enterprise.state); - if (!state.content.contains(miner.resource) || state.content[miner.resource] < TOLERANCE) - continue; - - double mined_value = miner.value; + double mined_value = enterprise.efficiency; if (local_storage.total + mined_value > local_storage.capacity) mined_value = local_storage.capacity - local_storage.total; if (mined_value > state.content[miner.resource]) diff --git a/ECSAPI/Economy/test/CMakeLists.txt b/ECSAPI/Economy/test/CMakeLists.txt index 1fefa7e..ba4edb4 100644 --- a/ECSAPI/Economy/test/CMakeLists.txt +++ b/ECSAPI/Economy/test/CMakeLists.txt @@ -1,6 +1,7 @@ # List sources -set(SOURCES "test_conf.hpp" "main.cpp" "systems/mining.cpp") +set(SOURCES "test_conf.hpp" "main.cpp" + "systems/mining.cpp" "systems/delivering.cpp") # Find dependencies @@ -16,6 +17,10 @@ target_link_libraries(economy_tests PRIVATE Economy::Economy) # Test +if (CMAKE_VERSION VERSION_GREATER 3.12) + set_property(TARGET economy_tests PROPERTY CXX_STANDARD 20) +endif() + if (WIN32) add_custom_command( TARGET economy_tests POST_BUILD diff --git a/ECSAPI/Economy/test/systems/delivering.cpp b/ECSAPI/Economy/test/systems/delivering.cpp new file mode 100644 index 0000000..fc2bac4 --- /dev/null +++ b/ECSAPI/Economy/test/systems/delivering.cpp @@ -0,0 +1,110 @@ +#include +#include +#include "../test_conf.hpp" + +TEST_F(SystemsTest, DeliverySingleNormal) +{ + // [Miner -> Storage] by Deliverer + + ee_economy::enterprise &deliverer_enterprise = registry.get(deliverer); + ee_economy::deliverer &deliverer_deliverer = registry.get(deliverer); + + deliverer_deliverer.resource = ee_economy::RESOURCE_TYPE::COAL; + deliverer_enterprise.add_base_efficiency(1.0); + deliverer_deliverer.contracts.push_back({.from = miner, .to = storage, .value = 10.0}); + + ee_economy::container &from_container = registry.get(miner); + ee_economy::container &to_container = registry.get(storage); + + from_container.capacity = 15.0; + from_container.add(ee_economy::RESOURCE_TYPE::COAL, 15.0); + + to_container.capacity = 15.0; + + ee_economy::delivering(registry); + + ASSERT_DOUBLE_EQ(from_container.total, 14.0); + ASSERT_DOUBLE_EQ(from_container.content[ee_economy::RESOURCE_TYPE::COAL], 14.0); + ASSERT_DOUBLE_EQ(to_container.total, 1.0); + ASSERT_DOUBLE_EQ(to_container.content[ee_economy::RESOURCE_TYPE::COAL], 1.0); +} + +TEST_F(SystemsTest, DeliverySingleEmpty) +{ + // [Miner -> Storage] by Deliverer + + ee_economy::enterprise &deliverer_enterprise = registry.get(deliverer); + ee_economy::deliverer &deliverer_deliverer = registry.get(deliverer); + + deliverer_deliverer.resource = ee_economy::RESOURCE_TYPE::COAL; + deliverer_enterprise.add_base_efficiency(1.0); + deliverer_deliverer.contracts.push_back({.from = miner, .to = storage, .value = 10.0}); + + ee_economy::container &from_container = registry.get(miner); + ee_economy::container &to_container = registry.get(storage); + + from_container.capacity = 15.0; + to_container.capacity = 15.0; + + ee_economy::delivering(registry); + + ASSERT_DOUBLE_EQ(from_container.total, 0.0); + ASSERT_DOUBLE_EQ(from_container.content[ee_economy::RESOURCE_TYPE::COAL], 0.0); + ASSERT_DOUBLE_EQ(to_container.total, 0.0); + ASSERT_DOUBLE_EQ(to_container.content[ee_economy::RESOURCE_TYPE::COAL], 0.0); +} + +TEST_F(SystemsTest, DeliverySinglePoor) +{ + // [Miner -> Storage] by Deliverer + + ee_economy::enterprise &deliverer_enterprise = registry.get(deliverer); + ee_economy::deliverer &deliverer_deliverer = registry.get(deliverer); + + deliverer_deliverer.resource = ee_economy::RESOURCE_TYPE::COAL; + deliverer_enterprise.add_base_efficiency(1.0); + deliverer_deliverer.contracts.push_back({.from = miner, .to = storage, .value = 10.0}); + + ee_economy::container &from_container = registry.get(miner); + ee_economy::container &to_container = registry.get(storage); + + from_container.capacity = 15.0; + from_container.add(ee_economy::RESOURCE_TYPE::COAL, 0.5); + + to_container.capacity = 15.0; + + ee_economy::delivering(registry); + + ASSERT_DOUBLE_EQ(from_container.total, 0.0); + ASSERT_DOUBLE_EQ(from_container.content[ee_economy::RESOURCE_TYPE::COAL], 0.0); + ASSERT_DOUBLE_EQ(to_container.total, 0.5); + ASSERT_DOUBLE_EQ(to_container.content[ee_economy::RESOURCE_TYPE::COAL], 0.5); +} + +TEST_F(SystemsTest, DeliverySingleFinishContract) +{ + // [Miner -> Storage] by Deliverer + + ee_economy::enterprise &deliverer_enterprise = registry.get(deliverer); + ee_economy::deliverer &deliverer_deliverer = registry.get(deliverer); + + deliverer_deliverer.resource = ee_economy::RESOURCE_TYPE::COAL; + deliverer_enterprise.add_base_efficiency(16.0); + deliverer_deliverer.contracts.push_back({.from = miner, .to = storage, .value = 10.0}); + + ee_economy::container &from_container = registry.get(miner); + ee_economy::container &to_container = registry.get(storage); + + from_container.capacity = 15.0; + from_container.add(ee_economy::RESOURCE_TYPE::COAL, 15.0); + + to_container.capacity = 15.0; + + ee_economy::delivering(registry); + + ASSERT_DOUBLE_EQ(from_container.total, 5.0); + ASSERT_DOUBLE_EQ(from_container.content[ee_economy::RESOURCE_TYPE::COAL], 5.0); + ASSERT_DOUBLE_EQ(to_container.total, 10.0); + ASSERT_DOUBLE_EQ(to_container.content[ee_economy::RESOURCE_TYPE::COAL], 10.0); + ASSERT_EQ(deliverer_deliverer.contracts.size(), 0); +} \ No newline at end of file diff --git a/ECSAPI/Economy/test/systems/mining.cpp b/ECSAPI/Economy/test/systems/mining.cpp index 4666331..7d223c3 100644 --- a/ECSAPI/Economy/test/systems/mining.cpp +++ b/ECSAPI/Economy/test/systems/mining.cpp @@ -6,6 +6,7 @@ TEST_F(SystemsTest, MiningNormal) { ee_economy::container &state_container = registry.get(state); ee_economy::container &miner_container = registry.get(miner); + ee_economy::enterprise &miner_enterprise = registry.get(miner); ee_economy::miner &miner_miner = registry.get(miner); state_container.capacity = 15.0; @@ -13,7 +14,7 @@ TEST_F(SystemsTest, MiningNormal) miner_container.capacity = 5.0; miner_miner.resource = ee_economy::RESOURCE_TYPE::COAL; - miner_miner.value = 0.1; + miner_enterprise.add_base_efficiency(0.1); ee_economy::mining(registry); @@ -27,13 +28,14 @@ TEST_F(SystemsTest, MiningEmptyState) { ee_economy::container &state_container = registry.get(state); ee_economy::container &miner_container = registry.get(miner); + ee_economy::enterprise &miner_enterprise = registry.get(miner); ee_economy::miner &miner_miner = registry.get(miner); state_container.capacity = 15.0; miner_container.capacity = 5.0; miner_miner.resource = ee_economy::RESOURCE_TYPE::COAL; - miner_miner.value = 0.1; + miner_enterprise.add_base_efficiency(0.1); ee_economy::mining(registry); @@ -47,6 +49,7 @@ TEST_F(SystemsTest, MiningPoorState) { ee_economy::container &state_container = registry.get(state); ee_economy::container &miner_container = registry.get(miner); + ee_economy::enterprise &miner_enterprise = registry.get(miner); ee_economy::miner &miner_miner = registry.get(miner); state_container.capacity = 15.0; @@ -54,7 +57,7 @@ TEST_F(SystemsTest, MiningPoorState) miner_container.capacity = 5.0; miner_miner.resource = ee_economy::RESOURCE_TYPE::COAL; - miner_miner.value = 0.1; + miner_enterprise.add_base_efficiency(0.1); ee_economy::mining(registry); @@ -68,6 +71,7 @@ TEST_F(SystemsTest, MiningReachCap) { ee_economy::container &state_container = registry.get(state); ee_economy::container &miner_container = registry.get(miner); + ee_economy::enterprise &miner_enterprise = registry.get(miner); ee_economy::miner &miner_miner = registry.get(miner); state_container.capacity = 15.0; @@ -75,7 +79,7 @@ TEST_F(SystemsTest, MiningReachCap) miner_container.capacity = 0.05; miner_miner.resource = ee_economy::RESOURCE_TYPE::COAL; - miner_miner.value = 0.1; + miner_enterprise.add_base_efficiency(0.1); ee_economy::mining(registry); diff --git a/ECSAPI/Economy/test/test_conf.hpp b/ECSAPI/Economy/test/test_conf.hpp index 9b3a453..33e172f 100644 --- a/ECSAPI/Economy/test/test_conf.hpp +++ b/ECSAPI/Economy/test/test_conf.hpp @@ -11,6 +11,8 @@ struct SystemsTest : testing::Test entt::entity state; entt::entity miner; + entt::entity storage; + entt::entity deliverer; void SetUp() { @@ -24,6 +26,17 @@ struct SystemsTest : testing::Test registry.emplace(miner, false, state); registry.emplace(miner); registry.emplace(miner); + + // Create storage enterprise + storage = registry.create(); + registry.emplace(storage, false, state); + registry.emplace(storage); + + // Create delivering enterprise + deliverer = registry.create(); + registry.emplace(deliverer, false, state); + registry.emplace(deliverer); + registry.emplace(deliverer); } void TearDown()