Files
MVP1/Assets/Scripts/Modules/Tests/ProductionTests.cs
T

197 lines
8.4 KiB
C#
Raw Normal View History

using System.Collections.Generic;
using NUnit.Framework;
// Тесты добычи через рабочих (этап 3) и лимитов склада (этап 1).
// Запуск: Window -> General -> Test Runner -> EditMode -> Run All.
// Проверка из дизайн-документа: сбалансированный город даёт 90 еды, 50 дерева, 22.5 камня и 15 металла в час.
public class ProductionTests
{
const long T0 = 1_800_000_000;
const long Hour = 3600;
PopulationTests.FakeEconomy economy;
ArmyService army;
PopulationService population;
ProductionService production;
[SetUp]
public void SetUp()
{
GameServices.Clear();
EventBus.Clear();
SaveRegistry.Clear();
GameClock.ResetOffset();
economy = new PopulationTests.FakeEconomy();
army = new ArmyService();
population = new PopulationService(new PopulationRules());
production = new ProductionService(new ProductionRules());
GameServices.Register<IEconomy>(economy);
GameServices.Register<ISettlement>(new PopulationTests.FakeSettlement { TownHallLevel = 1 });
GameServices.Register<IArmy>(army);
GameServices.Register<IPopulation>(population);
GameServices.Register<IProduction>(production);
army.AddTroops(0, 30);
population.Tick(T0);
}
// По одному зданию 1 уровня на каждую профессию, кроме золота (нужно 2 фермы для 45 фермеров)
static List<KeyValuePair<WorkJob, int>> Buildings(params (WorkJob job, int level)[] list)
{
var result = new List<KeyValuePair<WorkJob, int>>();
foreach (var b in list) result.Add(new KeyValuePair<WorkJob, int>(b.job, b.level));
return result;
}
[Test]
public void BalancedCity_Gives90Food_50Wood_22_5Stone_15Iron()
{
production.SetBuildings(Buildings((WorkJob.Farmer, 1), (WorkJob.Farmer, 1), (WorkJob.Woodcutter, 1),
(WorkJob.Stonecutter, 1), (WorkJob.MinerIron, 1)));
population.SetWorkers(WorkJob.Farmer, 45);
population.SetWorkers(WorkJob.Woodcutter, 25);
population.SetWorkers(WorkJob.Stonecutter, 15);
population.SetWorkers(WorkJob.MinerIron, 15);
Assert.AreEqual(90f, production.RatePerHour(ResourceType.Food), 0.001f);
Assert.AreEqual(50f, production.RatePerHour(ResourceType.Wood), 0.001f);
Assert.AreEqual(22.5f, production.RatePerHour(ResourceType.Stone), 0.001f);
Assert.AreEqual(15f, production.RatePerHour(ResourceType.Iron), 0.001f);
Assert.AreEqual(100, population.Workers);
Assert.AreEqual(20, population.FreeWorkers);
}
[Test]
public void OneHour_AddsProduction_AndFoodIsNetOfEating()
{
economy.Set(ResourceType.Food, 100);
production.SetBuildings(Buildings((WorkJob.Farmer, 1), (WorkJob.Farmer, 1), (WorkJob.Woodcutter, 1)));
population.SetWorkers(WorkJob.Farmer, 45);
population.SetWorkers(WorkJob.Woodcutter, 25);
population.Tick(T0 + Hour);
Assert.AreEqual(100 + 90 - 33, economy.Get(ResourceType.Food), 0.01, "+90 добыли, -33 съели");
Assert.AreEqual(50, economy.Get(ResourceType.Wood), 0.01);
}
[Test]
public void ProductionComesBeforeEating_NoFalseStarvationOffline()
{
economy.Set(ResourceType.Food, 0); // склад пуст, но фермы кормят город
production.SetBuildings(Buildings((WorkJob.Farmer, 1), (WorkJob.Farmer, 1)));
population.SetWorkers(WorkJob.Farmer, 45);
population.Tick(T0 + 10 * Hour);
Assert.IsFalse(population.IsStarving, "сначала добыли, потом съели");
Assert.AreEqual((90 - 33) * 10, economy.Get(ResourceType.Food), 1.0);
}
[Test]
public void Workers_LimitedBySlots_AndByFreeWorkers()
{
production.SetBuildings(Buildings((WorkJob.Woodcutter, 1))); // 30 мест
Assert.AreEqual(30, population.SetWorkers(WorkJob.Woodcutter, 50), "больше мест не поставить");
production.SetBuildings(Buildings((WorkJob.Woodcutter, 1), (WorkJob.Farmer, 1), (WorkJob.Farmer, 1),
(WorkJob.Farmer, 1), (WorkJob.Farmer, 1)));
Assert.AreEqual(90, population.SetWorkers(WorkJob.Farmer, 120), "свободных осталось 90 из 120");
Assert.AreEqual(0, population.FreeWorkers);
}
[Test]
public void NoBuilding_NoWorkers()
{
Assert.AreEqual(0, population.SetWorkers(WorkJob.MinerGold, 10), "нет Золотого рудника -- нет мест");
Assert.AreEqual(0f, production.RatePerHour(ResourceType.Gold));
}
[Test]
public void HigherLevel_MoreSlots_AndEfficiency()
{
production.SetBuildings(Buildings((WorkJob.Woodcutter, 3))); // 30 + 2×10 мест, норма ×1.2
Assert.AreEqual(50, production.Slots(WorkJob.Woodcutter));
Assert.AreEqual(1.2f, production.Efficiency(WorkJob.Woodcutter), 0.0001f);
population.SetWorkers(WorkJob.Woodcutter, 50);
Assert.AreEqual(50 * 2 * 1.2f, production.RatePerHour(ResourceType.Wood), 0.001f);
}
[Test]
public void StorageCap_OverflowIsLost()
{
economy.SetCapacity(ResourceType.Wood, 1000);
economy.Set(ResourceType.Wood, 990);
production.SetBuildings(Buildings((WorkJob.Woodcutter, 1)));
population.SetWorkers(WorkJob.Woodcutter, 30); // 60 в час
population.Tick(T0 + Hour);
Assert.AreEqual(1000, economy.Get(ResourceType.Wood), 0.0001, "склад полон -- лишнее пропало");
}
[Test]
public void AutoFillAll_SpreadsWorkersEvenly()
{
production.SetBuildings(Buildings((WorkJob.Woodcutter, 1), (WorkJob.Farmer, 1), (WorkJob.Stonecutter, 1)));
population.AutoFillAll();
Assert.AreEqual(30, population.GetWorkers(WorkJob.Woodcutter));
Assert.AreEqual(30, population.GetWorkers(WorkJob.Farmer));
Assert.AreEqual(30, population.GetWorkers(WorkJob.Stonecutter));
Assert.AreEqual(30, population.FreeWorkers);
Assert.IsTrue(population.JobsInitialized);
}
[Test]
public void AutoFill_NewBuilding_TakesFreeWorkers()
{
production.SetBuildings(Buildings((WorkJob.Farmer, 1)));
Assert.AreEqual(30, population.AutoFill(WorkJob.Farmer));
production.SetBuildings(Buildings((WorkJob.Farmer, 1), (WorkJob.Farmer, 1)));
Assert.AreEqual(30, population.AutoFill(WorkJob.Farmer), "вторая ферма -- ещё 30");
Assert.AreEqual(60, population.GetWorkers(WorkJob.Farmer));
}
[Test]
public void FewerSlots_ClampJobs_RemovesExtraWorkers()
{
production.SetBuildings(Buildings((WorkJob.Farmer, 1), (WorkJob.Farmer, 1)));
population.SetWorkers(WorkJob.Farmer, 60);
production.SetBuildings(Buildings((WorkJob.Farmer, 1)));
population.ClampJobs();
Assert.AreEqual(30, population.GetWorkers(WorkJob.Farmer));
Assert.AreEqual(90, population.FreeWorkers);
}
[Test]
public void ManySmallTicks_EqualOneBigTick_WithProduction()
{
economy.Set(ResourceType.Food, 500);
production.SetBuildings(Buildings((WorkJob.Farmer, 1), (WorkJob.Woodcutter, 1)));
population.SetWorkers(WorkJob.Farmer, 30);
population.SetWorkers(WorkJob.Woodcutter, 30);
for (long t = T0 + 2; t <= T0 + 5 * Hour; t += 2) population.Tick(t);
float foodA = economy.Get(ResourceType.Food), woodA = economy.Get(ResourceType.Wood);
SetUp();
economy.Set(ResourceType.Food, 500);
production.SetBuildings(Buildings((WorkJob.Farmer, 1), (WorkJob.Woodcutter, 1)));
population.SetWorkers(WorkJob.Farmer, 30);
population.SetWorkers(WorkJob.Woodcutter, 30);
population.Tick(T0 + 5 * Hour);
Assert.AreEqual(foodA, economy.Get(ResourceType.Food), 1.0);
Assert.AreEqual(woodA, economy.Get(ResourceType.Wood), 1.0);
Assert.AreEqual(300, woodA, 1.0, "30 лесорубов × 2 × 5 часов");
}
[Test]
public void SaveAndRestore_KeepsSlots()
{
production.SetBuildings(Buildings((WorkJob.Stonecutter, 2)));
var copy = new ProductionService(new ProductionRules());
copy.Restore(production.Capture());
Assert.AreEqual(40, copy.Slots(WorkJob.Stonecutter));
Assert.AreEqual(1.1f, copy.Efficiency(WorkJob.Stonecutter), 0.0001f);
}
}