Refactor GridScheduleGenerator and related models for improved repeat slot handling
ci / build-backend (push) Successful in 1m17s
ci / build-frontend (push) Successful in 37s
ci / tests (push) Successful in 1m38s
ci / sonar (push) Successful in 3m44s

Updated the GridScheduleGenerator to utilize a new PlanningRepeatWindow structure for managing repeat slots, enhancing the logic for loading repeat units. The LoadRepeatUnitsAsync method was modified to accept a channel ID and repeat window, ensuring accurate retrieval of past entries. Additionally, the PlanningSlot record was updated to include the new RepeatWindow property, and the SchedulePlanner was adjusted to collect repeat units based on the updated logic. Enhanced unit tests to verify the correct behavior of repeat slot functionality, ensuring that overlaps and elastic start times are handled appropriately.
This commit is contained in:
Leonid Pershin
2026-07-29 08:34:03 +03:00
parent 46c0169dea
commit c67d1f7752
5 changed files with 143 additions and 17 deletions
@@ -341,6 +341,56 @@ public class SchedulePlannerTests
Assert.Contains(result.Warnings, w => w.Kind == PlanningWarningKind.RepeatSourceEmpty);
}
/// <summary>
/// Горизонт строится одним прогоном, поэтому источник повтора обычно ещё не в базе, а в этой же
/// ленте: вечерний фильм понедельника повторяют во вторник утром, и оба спланированы вместе.
/// </summary>
[Fact]
public void RepeatSlot_TakesSourceFromTheSameRun()
{
var evening = Slot(T0, 60, [Element(1, 60)]);
var morning = Slot(T0.AddHours(2), 60, []) with
{
SlotKind = SlotKind.Repeat,
RepeatWindow = new PlanningRepeatWindow(T0, T0.AddHours(1)),
};
var result = Run(Input([evening, morning], horizonHours: 4));
var source = result.Items.First(i => i.StartsAtUtc == T0);
Assert.Contains(
result.Items,
i => i.StartsAtUtc >= T0.AddHours(2) && i.MediaAssetId == source.MediaAssetId
);
Assert.DoesNotContain(
result.Warnings,
w => w.Kind == PlanningWarningKind.RepeatSourceEmpty
);
}
/// <summary>
/// Старты эластичные: фильм законно начинается раньше объявленного времени, и окно повтора
/// обязано ловить его по пересечению, а не по попаданию старта внутрь.
/// </summary>
[Fact]
public void RepeatSlot_CatchesUnitStartedBeforeWindow()
{
var evening = Slot(T0, 60, [Element(1, 60)]);
var morning = Slot(T0.AddHours(2), 60, []) with
{
SlotKind = SlotKind.Repeat,
RepeatWindow = new PlanningRepeatWindow(T0.AddMinutes(10), T0.AddMinutes(70)),
};
var result = Run(Input([evening, morning], horizonHours: 4));
var source = result.Items.First(i => i.StartsAtUtc == T0);
Assert.Contains(
result.Items,
i => i.StartsAtUtc >= T0.AddHours(2) && i.MediaAssetId == source.MediaAssetId
);
}
[Fact]
public void Trace_IsWrittenWithSlotAndStrategy()
{