diff --git a/ErsatzTV.Core/Scheduling/YamlScheduling/Models/YamlPlayoutSchedule.cs b/ErsatzTV.Core/Scheduling/YamlScheduling/Models/YamlPlayoutSchedule.cs index 33ac51f6c..42f06c5bb 100644 --- a/ErsatzTV.Core/Scheduling/YamlScheduling/Models/YamlPlayoutSchedule.cs +++ b/ErsatzTV.Core/Scheduling/YamlScheduling/Models/YamlPlayoutSchedule.cs @@ -12,6 +12,11 @@ public class YamlPlayoutSchedule [YamlMember(Alias = "end_date", ApplyNamingConventions = false)] public string EndDate { get; set; } + /// + /// Priority for schedule matching. Higher values are checked first. Default is 0. + /// + public int Priority { get; set; } + public List Reset { get; set; } = []; public List Playout { get; set; } = []; diff --git a/ErsatzTV.Core/Scheduling/YamlScheduling/SequentialPlayoutBuilder.cs b/ErsatzTV.Core/Scheduling/YamlScheduling/SequentialPlayoutBuilder.cs index ee26a7acf..9149be9aa 100644 --- a/ErsatzTV.Core/Scheduling/YamlScheduling/SequentialPlayoutBuilder.cs +++ b/ErsatzTV.Core/Scheduling/YamlScheduling/SequentialPlayoutBuilder.cs @@ -202,8 +202,23 @@ public class SequentialPlayoutBuilder( cancellationToken); } + // load alternate schedules + // sort by priority, then by index + IOrderedEnumerable<(YamlPlayoutSchedule schedule, int index)> sortedSchedules = playoutDefinition.Schedules + .Select((schedule, index) => (schedule, index)) + .OrderByDescending(x => x.schedule.Priority) + .ThenBy(x => x.index); + + // parse once + var parsedSchedules = sortedSchedules + .Select((s, i) => new YamlPlayoutParsedSchedule(s.schedule, i)) + .ToList(); + // Determine which schedule to use based on the start date - Option maybeActiveSchedule = GetActiveSchedule(playoutDefinition, start); + Option maybeActiveSchedule = AlternateScheduleSelector + .GetScheduleForDate(parsedSchedules, start) + .Map(s => s.Schedule); + List resetInstructions = []; List playoutInstructions = []; @@ -305,7 +320,10 @@ public class SequentialPlayoutBuilder( while (context.CurrentTime < finish) { // Check if we've crossed into a different schedule - Option maybeNewSchedule = GetActiveSchedule(playoutDefinition, context.CurrentTime); + Option maybeNewSchedule = AlternateScheduleSelector + .GetScheduleForDate(parsedSchedules, context.CurrentTime) + .Map(s => s.Schedule); + if (currentSchedule != maybeNewSchedule) { string oldName = currentSchedule.Match(cs => string.IsNullOrWhiteSpace(cs.Name) ? "Unnamed" : cs.Name, () => "Default"); @@ -737,19 +755,4 @@ public class SequentialPlayoutBuilder( return result; } - - /// - /// Finds the active schedule for the given date, or returns None if no schedule matches. - /// Schedules are checked by definition order. - /// - private static Option GetActiveSchedule(YamlPlayoutDefinition definition, DateTimeOffset date) - { - if (definition.Schedules.Count == 0) - { - return Option.None; - } - - var parsedSchedules = definition.Schedules.Select((s, i) => new YamlPlayoutParsedSchedule(s, i)).ToList(); - return AlternateScheduleSelector.GetScheduleForDate(parsedSchedules, date).Map(s => s.Schedule); - } }