show threat rate in debug output

This commit is contained in:
2026-06-14 13:11:35 +02:00
parent 123c544423
commit 1ea1cc59fb
10 changed files with 217 additions and 11 deletions

View File

@@ -337,6 +337,85 @@ TEST_CASE("BuildingSystem: miner output buffer stalls when full", "[building]")
REQUIRE_FALSE(b->production.has_value());
}
// ---------------------------------------------------------------------------
// REQ-UI-DEBUG-OVERLAY production counts
// ---------------------------------------------------------------------------
TEST_CASE("BuildingSystem: productionBuildingCount excludes construction sites", "[building]")
{
const GameConfig cfg = loadConfig();
BeltSystem belts(cfg.world.beltSpeed_tps);
int stock = 0;
std::mt19937 rng(0);
BuildingId nextBuildingId = 1;
BuildingSystem bs(cfg, belts,
[&nextBuildingId]() { return nextBuildingId++; },
[&stock](int n) { stock += n; },
[](const std::string&, QVector2D, const std::optional<ShipLayoutConfig>&) {},
[](const std::string&) -> bool { return true; },
rng);
const BuildingId minerId = bs.place(BuildingType::Miner, QPoint(0, 0), Rotation::East, 0);
const BuildingId smelterId = bs.place(BuildingType::Smelter, QPoint(10, 0), Rotation::East, 0);
(void)smelterId;
Tick tick = 0;
// Both still under construction.
REQUIRE(bs.productionBuildingCount() == 0);
// The queue builds one at a time: miner (10s) completes at tick 300, then
// the smelter (15s) starts and completes at tick 300 + 450 = 750.
runTicks(bs, belts, static_cast<int>(secondsToTicks(10.0)) + 1, tick);
REQUIRE(bs.productionBuildingCount() == 1);
runTicks(bs, belts, static_cast<int>(secondsToTicks(15.0)), tick);
REQUIRE(bs.productionBuildingCount() == 2);
// Neither has a recipe selected, so neither has an active cycle.
REQUIRE(bs.activeProductionBuildingCount() == 0);
bs.setRecipe(minerId, "mine_iron_ore");
runTicks(bs, belts, 1, tick);
REQUIRE(bs.activeProductionBuildingCount() == 1);
}
TEST_CASE("BuildingSystem: activeProductionBuildingCount tracks production cycle state",
"[building]")
{
const GameConfig cfg = loadConfig();
BeltSystem belts(cfg.world.beltSpeed_tps);
int stock = 0;
std::mt19937 rng(0);
BuildingId nextBuildingId = 1;
BuildingSystem bs(cfg, belts,
[&nextBuildingId]() { return nextBuildingId++; },
[&stock](int n) { stock += n; },
[](const std::string&, QVector2D, const std::optional<ShipLayoutConfig>&) {},
[](const std::string&) -> bool { return true; },
rng);
const BuildingId id = bs.place(BuildingType::Miner, QPoint(0, 0), Rotation::East, 0);
bs.setRecipe(id, "mine_iron_ore");
Tick tick = 0;
// Not yet operational while under construction.
REQUIRE(bs.activeProductionBuildingCount() == 0);
// Construction completes at tick 300; cycle 1 starts the same tick (completesAt=330).
runTicks(bs, belts, static_cast<int>(secondsToTicks(10.0)) + 1, tick);
REQUIRE(bs.activeProductionBuildingCount() == 1);
// Run cycles 1 and 2 to completion (1s each); cycle 3 stalls once the
// output buffer (capacity 2) is full (REQ-MAT-OUTPUT-BUFFER).
runTicks(bs, belts, 2 * static_cast<int>(secondsToTicks(1.0)) + 1, tick);
const Building* b = bs.findBuilding(id);
REQUIRE(b != nullptr);
REQUIRE(static_cast<int>(b->outputBuffer.items.size()) == 2);
REQUIRE_FALSE(b->production.has_value());
REQUIRE(bs.activeProductionBuildingCount() == 0);
}
// ---------------------------------------------------------------------------
// Belt pull → input buffer
// ---------------------------------------------------------------------------