using System.Text.Json; using System.Text.Json.Serialization; namespace TeleWave.Application.Programming.Templates; /// Как слот выбирает элемент группы. public enum SlotStrategyType { /// Элементы группы по порядку позиций. Sequential = 0, /// Случайный элемент, не показанный последние N дней. RandomWithCooldown = 1, /// Всегда один и тот же элемент. Fixed = 2, } /// Что делать, когда остывание отсекло всех кандидатов. public enum CooldownFallback { /// Взять элемент, не игравший дольше всех. OldestFirst = 0, /// Проигнорировать остывание на этот выход. IgnoreCooldown = 1, } /// /// Стратегия выбора элемента внутри слота. Отвечает только за выбор элемента: единицы внутри элемента /// всегда идут по порядку от курсора — сериал не должен прыгать по сериям. /// /// Размер блока живёт на слоте отдельно и ортогонален стратегии: любую можно скомбинировать /// с «одна единица», «четыре подряд» или «пока не наберётся два часа». /// public sealed record SlotStrategy( SlotStrategyType Type = SlotStrategyType.Sequential, /// Начинать группу заново, дойдя до конца (иначе слот останавливается). bool RestartOnEnd = true, /// Дней остывания для . int CooldownDays = 0, CooldownFallback Fallback = CooldownFallback.OldestFirst, /// Закреплённый элемент для . Guid? FixedElementId = null ) { private static readonly JsonSerializerOptions Options = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, Converters = { new JsonStringEnumConverter() }, }; public string ToJson() => JsonSerializer.Serialize(this, Options); /// Разбирает сохранённую стратегию. Повреждённый JSON — как отсутствие стратегии: /// слот получит поведение по умолчанию, а не уронит генерацию всего канала. public static SlotStrategy? FromJson(string? json) { if (string.IsNullOrWhiteSpace(json)) return null; try { return JsonSerializer.Deserialize(json, Options); } catch (JsonException) { return null; } } }