Enhance channel management: add support for preferred weight multipliers and preferred hours in channel shows, update related data models and API endpoints, and implement validation for new properties. Refactor scheduling logic to utilize preferred hours for weight adjustments during show planning.

This commit is contained in:
Leonid Pershin
2026-07-25 18:44:28 +03:00
parent 358adbff21
commit 8718e8b6bf
36 changed files with 2921 additions and 97 deletions
@@ -8,9 +8,17 @@ public sealed record PlannerShow(
BlockMode BlockMode,
int BlockValue,
IReadOnlyList<Guid> EpisodeAssetIds,
int NextEpisodeIndex
int NextEpisodeIndex,
IReadOnlyList<PlannerHourWindow>? PreferredHours = null,
int PreferredWeightMultiplier = 1
);
/// <summary>Окно предпочтительных часов [StartHour, EndHour) суток (UTC) для планировщика.</summary>
public sealed record PlannerHourWindow(int StartHour, int EndHour)
{
public bool Contains(int hour) => hour >= StartHour && hour < EndHour;
}
/// <summary>Override в терминах планировщика: окно + режим + шоу с весами.</summary>
public sealed record PlannerOverride(
DateTimeOffset StartsAtUtc,
@@ -25,23 +33,28 @@ public sealed record PlannerOverrideShow(Guid ShowId, int Weight);
/// Политика ТВ-заставок на переходах. Планировщик из подходящих подблоков (<see cref="Variants"/>,
/// фильтр по <see cref="PlannerBumperVariant.Trigger"/> и контексту перехода) выбирает один по стратегии
/// <see cref="Selection"/> и резервирует слот длины его блока. Ассет подставляет оркестратор.
/// <see cref="ShowChangeChance"/>/<see cref="EpisodeChangeChance"/> — вероятность самого появления
/// заставки на смене шоу / между блоками одного шоу (0..1).
/// </summary>
public sealed record PlannerBumperConfig(
bool Enabled,
TimeSpan MinInterval,
BumperSelection Selection,
IReadOnlyList<PlannerBumperVariant> Variants
IReadOnlyList<PlannerBumperVariant> Variants,
double ShowChangeChance = 1.0,
double EpisodeChangeChance = 1.0
);
/// <summary>
/// Подблок заставки в терминах планировщика: id варианта + id родительского блока (стиль/звук) +
/// длительность слота (кратна сегменту) + правило показа.
/// длительность слота (кратна сегменту) + правило показа + вес (для <see cref="BumperSelection.WeightedRandom"/>).
/// </summary>
public sealed record PlannerBumperVariant(
Guid VariantId,
Guid TemplateId,
TimeSpan Duration,
BumperTrigger Trigger
BumperTrigger Trigger,
int Weight = 1
);
/// <summary>Полный вход планировщика для одного прогона по каналу.</summary>