Delivering and tests

- Deliverer component added
- Delivering system added
- Delivery tests
- Spawn enterprises tests (miner and deliverer)
- Base, factor and total efficiency of enterprise added
- Value of resource mined per tick moved from miner to enterprise efficiency
This commit is contained in:
legatt 2025-07-08 19:01:31 +03:00
parent 74042175f8
commit bbf45e832c
17 changed files with 307 additions and 26 deletions

View File

@ -41,7 +41,16 @@ entt::entity ee_ecs::world::spawn_enterprise(
{
entt::entity entity = this->registry.create();
this->registry.emplace<ee_economy::enterprise>(entity, is_building, state);
this->registry.emplace<ee_economy::enterprise>(
entity,
is_building,
state,
defaults.base_efficiency * defaults.factor_efficiency,
defaults.base_efficiency,
defaults.factor_efficiency
);
this->registry.emplace<ee_economy::container>(
entity,
@ -54,7 +63,13 @@ entt::entity ee_ecs::world::spawn_enterprise(
{
case ee_economy::ACTION_TYPE::MINING:
{
this->registry.emplace<ee_economy::miner>(entity, defaults.resource_target, defaults.base_efficiency_flat);
this->registry.emplace<ee_economy::miner>(entity, defaults.resource_target);
break;
}
case ee_economy::ACTION_TYPE::DELIVERY:
{
this->registry.emplace<ee_economy::deliverer>(entity, defaults.resource_target);
break;
}

View File

@ -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);

View File

@ -15,7 +15,7 @@ TEST(WorldTest, RegisterState)
ee_economy::container registered_container = world.get_registry().get<ee_economy::container>(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<ee_economy::state>(state, (short)0);
world.get_registry().emplace<ee_economy::container>(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<ee_economy::enterprise>(enterprise);
ee_economy::miner registered_action = world.get_registry().get<ee_economy::miner>(enterprise);
ee_economy::container registered_container = world.get_registry().get<ee_economy::container>(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<ee_economy::state>(state, (short)0);
world.get_registry().emplace<ee_economy::container>(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<ee_economy::enterprise>(enterprise);
ee_economy::deliverer registered_action = world.get_registry().get<ee_economy::deliverer>(enterprise);
ee_economy::container registered_container = world.get_registry().get<ee_economy::container>(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);
}

View File

@ -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/")

View File

@ -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;
}
};
}

View File

@ -0,0 +1,20 @@
#pragma once
#include <ee_economy/economy.hpp>
#include <vector>
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<deliver_contract> contracts;
};
}

View File

@ -1,12 +1,48 @@
#pragma once
#include <entt/entt.hpp>
#include <vector>
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<entt::entity> links_from;
std::vector<entt::entity> 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();
}
};
}

View File

@ -7,6 +7,5 @@ namespace ee_economy
struct miner
{
RESOURCE_TYPE resource = RESOURCE_TYPE::NONE;
double value = 0.;
};
}

View File

@ -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"
#include "components/deliverer.hpp"

View File

@ -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;
};
}

View File

@ -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);

View File

@ -0,0 +1,33 @@
#include <ee_economy/economy.hpp>
void ee_economy::delivering(entt::registry &registry)
{
auto deliverers = registry.view<enterprise, deliverer>();
for (auto [entity, enterprise, deliverer]: deliverers.each())
{
for (deliver_contract &contract: deliverer.contracts)
{
container &from_storage = registry.get<container>(contract.from);
container &to_storage = registry.get<container>(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;
});
}
}

View File

@ -8,10 +8,7 @@ void ee_economy::mining(entt::registry &registry)
{
container& state = registry.get<container>(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])

View File

@ -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

View File

@ -0,0 +1,110 @@
#include <gtest/gtest.h>
#include <ee_economy/economy.hpp>
#include "../test_conf.hpp"
TEST_F(SystemsTest, DeliverySingleNormal)
{
// [Miner -> Storage] by Deliverer
ee_economy::enterprise &deliverer_enterprise = registry.get<ee_economy::enterprise>(deliverer);
ee_economy::deliverer &deliverer_deliverer = registry.get<ee_economy::deliverer>(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<ee_economy::container>(miner);
ee_economy::container &to_container = registry.get<ee_economy::container>(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<ee_economy::enterprise>(deliverer);
ee_economy::deliverer &deliverer_deliverer = registry.get<ee_economy::deliverer>(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<ee_economy::container>(miner);
ee_economy::container &to_container = registry.get<ee_economy::container>(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<ee_economy::enterprise>(deliverer);
ee_economy::deliverer &deliverer_deliverer = registry.get<ee_economy::deliverer>(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<ee_economy::container>(miner);
ee_economy::container &to_container = registry.get<ee_economy::container>(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<ee_economy::enterprise>(deliverer);
ee_economy::deliverer &deliverer_deliverer = registry.get<ee_economy::deliverer>(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<ee_economy::container>(miner);
ee_economy::container &to_container = registry.get<ee_economy::container>(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);
}

View File

@ -6,6 +6,7 @@ TEST_F(SystemsTest, MiningNormal)
{
ee_economy::container &state_container = registry.get<ee_economy::container>(state);
ee_economy::container &miner_container = registry.get<ee_economy::container>(miner);
ee_economy::enterprise &miner_enterprise = registry.get<ee_economy::enterprise>(miner);
ee_economy::miner &miner_miner = registry.get<ee_economy::miner>(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<ee_economy::container>(state);
ee_economy::container &miner_container = registry.get<ee_economy::container>(miner);
ee_economy::enterprise &miner_enterprise = registry.get<ee_economy::enterprise>(miner);
ee_economy::miner &miner_miner = registry.get<ee_economy::miner>(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<ee_economy::container>(state);
ee_economy::container &miner_container = registry.get<ee_economy::container>(miner);
ee_economy::enterprise &miner_enterprise = registry.get<ee_economy::enterprise>(miner);
ee_economy::miner &miner_miner = registry.get<ee_economy::miner>(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<ee_economy::container>(state);
ee_economy::container &miner_container = registry.get<ee_economy::container>(miner);
ee_economy::enterprise &miner_enterprise = registry.get<ee_economy::enterprise>(miner);
ee_economy::miner &miner_miner = registry.get<ee_economy::miner>(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);

View File

@ -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<ee_economy::enterprise>(miner, false, state);
registry.emplace<ee_economy::miner>(miner);
registry.emplace<ee_economy::container>(miner);
// Create storage enterprise
storage = registry.create();
registry.emplace<ee_economy::enterprise>(storage, false, state);
registry.emplace<ee_economy::container>(storage);
// Create delivering enterprise
deliverer = registry.create();
registry.emplace<ee_economy::enterprise>(deliverer, false, state);
registry.emplace<ee_economy::deliverer>(deliverer);
registry.emplace<ee_economy::container>(deliverer);
}
void TearDown()