Files
TeleWave/backend/src/TeleWave.Domain/Broadcast/Scheduling/SchedulePlannerModels.cs
T

82 lines
3.4 KiB
C#

namespace TeleWave.Domain.Broadcast.Scheduling;
/// <summary>Шоу канала, подготовленное для планировщика: только готовые серии, с курсором.</summary>
public sealed record PlannerShow(
Guid ChannelShowId,
Guid ShowId,
int Weight,
BlockMode BlockMode,
int BlockValue,
IReadOnlyList<Guid> EpisodeAssetIds,
int NextEpisodeIndex
);
/// <summary>Override в терминах планировщика: окно + режим + шоу с весами.</summary>
public sealed record PlannerOverride(
DateTimeOffset StartsAtUtc,
DateTimeOffset EndsAtUtc,
OverrideMode Mode,
IReadOnlyList<PlannerOverrideShow> Shows
);
public sealed record PlannerOverrideShow(Guid ShowId, int Weight);
/// <summary>
/// Политика ТВ-заставок на переходах. Планировщик выбирает блок (<see cref="Templates"/>) по
/// стратегии <see cref="Selection"/> и резервирует слот его длины (<see cref="PlannerBumperTemplate.Duration"/>,
/// уже выровнена генератором на сегмент). Конкретный отрендеренный ассет подставляет оркестратор
/// по паре шоу + выбранному блоку.
/// </summary>
public sealed record PlannerBumperConfig(
bool Enabled,
bool OnlyBetweenDifferentShows,
TimeSpan MinInterval,
BumperSelection Selection,
IReadOnlyList<PlannerBumperTemplate> Templates
);
/// <summary>Блок заставки в терминах планировщика: id + длительность слота (кратна сегменту).</summary>
public sealed record PlannerBumperTemplate(Guid TemplateId, TimeSpan Duration);
/// <summary>Полный вход планировщика для одного прогона по каналу.</summary>
public sealed record PlannerInput(
Guid ChannelId,
AdInsertion AdInsertion,
int AdsPerBreak,
int NextAdIndex,
IReadOnlyList<PlannerShow> Shows,
IReadOnlyList<Guid> AdPool,
IReadOnlyDictionary<Guid, TimeSpan> Durations,
IReadOnlyList<PlannerOverride> Overrides,
DateTimeOffset StartTime,
DateTimeOffset HorizonEnd,
PlannerBumperConfig? Bumpers = null,
int NextBumperIndex = 0
);
/// <summary>
/// Одна запланированная запись (ещё не доменная сущность). Для заставок (<see cref="Kind"/> ==
/// <see cref="ScheduleEntryKind.Bumper"/>) <see cref="MediaAssetId"/> пуст — его подставит
/// оркестратор после рендера по паре (<see cref="FromShowId"/> → <see cref="ToShowId"/>) и выбранному
/// блоку (<see cref="BumperTemplateId"/>).
/// </summary>
public sealed record PlannedEntry(
Guid MediaAssetId,
ScheduleEntryKind Kind,
DateTimeOffset StartsAtUtc,
DateTimeOffset EndsAtUtc,
Guid? ShowId,
int? EpisodeIndex,
Guid? FromShowId = null,
Guid? ToShowId = null,
Guid? BumperTemplateId = null
);
/// <summary>Результат прогона: новые записи + обновлённые курсоры (серий по каждому ChannelShow, рекламы, заставок).</summary>
public sealed record PlannerResult(
IReadOnlyList<PlannedEntry> Entries,
IReadOnlyDictionary<Guid, int> NextEpisodeIndexByChannelShow,
int NextAdIndex,
int NextBumperIndex
);