diff --git a/Assets/Scripts/Modules/Population/PopulationService.cs b/Assets/Scripts/Modules/Population/PopulationService.cs index 11e48d6..6282d68 100644 --- a/Assets/Scripts/Modules/Population/PopulationService.cs +++ b/Assets/Scripts/Modules/Population/PopulationService.cs @@ -243,6 +243,10 @@ public sealed class PopulationService : IPopulation, ISaveParticipant { // Часы ушли назад (сброс отладочной перемотки, перевод часов на телефоне). Метку НЕ двигаем назад: // это время уже посчитано, и когда часы снова дойдут до него, оно не начислится второй раз (04.11). + // Но сообщить «расчёт дошёл до сейчас» нужно: время до сейчас тоже уже посчитано, и стройки, у которых оно + // вышло, завершаются. Иначе после «Сбросить перемотку» все стройки висели на 00:00, пока реальное время + // не догонит перемотку (05.11). Ресурсы здесь не начисляются + SimulatedUntil(unixNow); return; } if (elapsed == 0) { SimulatedUntil(unixNow); return; } diff --git a/Assets/Scripts/Modules/Tests/ProductionTests.cs b/Assets/Scripts/Modules/Tests/ProductionTests.cs index 847641a..3afd0ca 100644 --- a/Assets/Scripts/Modules/Tests/ProductionTests.cs +++ b/Assets/Scripts/Modules/Tests/ProductionTests.cs @@ -292,6 +292,27 @@ public class ProductionTests Assert.AreEqual(130 / 60f * 60 + 110 / 60f * 66, wood, 0.01f, "с ближайшего шага расчёта после конца стройки"); } + [Test] + public void Tick_ClockWentBack_StillReportsSimulatedTime_NoResources() + { + // «+1 час», потом «Сбросить перемотку»: часы ушли назад. Стройка, у которой время вышло, должна завершиться + // (событие о расчёте приходит), а ресурсы за уже посчитанный час второй раз не начисляются (05.11) + economy.Set(ResourceType.Food, 100000); + economy.Set(ResourceType.Wood, 0); + production.SetBuildings(Buildings((WorkJob.Woodcutter, 1))); + population.SetWorkers(WorkJob.Woodcutter, 30); + population.Tick(T0); + population.Tick(T0 + Hour); + float wood = economy.Get(ResourceType.Wood); + + long reported = 0; + EventBus.Subscribe(e => reported = e.UnixNow); + population.Tick(T0 + 60); + + Assert.AreEqual(T0 + 60, reported, "расчёт сообщает, до какого момента дошло время -- стройки завершаются"); + Assert.AreEqual(wood, economy.Get(ResourceType.Wood), 0.01f, "за уже посчитанное время ресурсов не прибавилось"); + } + [Test] public void Tick_SameMomentTwice_NoExtraResources() { diff --git a/Docs/Modules/Population.md b/Docs/Modules/Population.md index 757e4f6..7e50760 100644 --- a/Docs/Modules/Population.md +++ b/Docs/Modules/Population.md @@ -112,6 +112,7 @@ | Дата | Кто | Что | | --- | --- | --- | +| 05.11.2026 | Claude (Саша) | Часы назад (после «+1 час» и «Сбросить перемотку»): `Tick` всё равно публикует `GameTimeSimulatedEvent` на текущий момент — стройки, у которых время вышло, завершаются (раньше висели на «Стройка 00:00», пока реальное время не догонит перемотку). Ресурсы за уже посчитанное время по-прежнему не начисляются. Тест `Tick_ClockWentBack_StillReportsSimulatedTime_NoResources`. | | 04.11.2026 | Claude (Валдемар) | Решения 04.11 (офлайн по временным меткам): событие `GameTimeSimulatedEvent` на каждом шаге расчёта и в конце `Tick` — стройка, закончившаяся офлайн, вступает в силу в свой момент, добыча с момента завершения. Часы назад: метка последнего расчёта не уходит назад — закрыто повторное начисление. Тесты в `ProductionTests` (офлайн-стройка, повторный Tick, загрузка), обновлён тест про часы назад. Побочный эффект: после «DEV +10 часов» и перезапуска расчёт стоит, пока реальное время не догонит перемотку. | | 04.11.2026 | Claude (Саша) | Пропавшие без вести (решения 01.11, п. 5) занимают места в населении (`Soldiers` включает `IArmy.MissingTotal`), но не едят. | | 04.11.2026 | Claude (Саша) | Решения по отчёту Саши от 01.11, п. 4: воины едят по норме типа — пехота 0,15, лучники 0,20, кавалерия 0,15, осадные 0,15 в час (`PopulationRules.FoodPerTroopTypePerHour`, `EconomyConfig.population.foodPerTroopTypePerHour`); раненые — полную норму своего типа, даже ожидая койку (`IArmy.GetAllTroops`). Новобранцы — по `foodPerSoldierPerHour`. Без таблицы — как раньше (тесты Населения не менялись). Час — тот же, что у остальной еды (переход еды на игровые часы — открытый вопрос). |