From 4c9c04753048af097b2cc2effd0916661db008bb Mon Sep 17 00:00:00 2001 From: Jason Dove <1695733+jasongdove@users.noreply.github.com> Date: Tue, 30 Jul 2024 18:21:24 -0500 Subject: [PATCH] add basic marathon content (#1842) --- .../YamlScheduling/EnumeratorCache.cs | 62 +++++++++++++++++++ .../Models/YamlPlayoutContentMarathonItem.cs | 19 ++++++ .../YamlScheduling/YamlPlayoutBuilder.cs | 1 + 3 files changed, 82 insertions(+) create mode 100644 ErsatzTV.Core/Scheduling/YamlScheduling/Models/YamlPlayoutContentMarathonItem.cs diff --git a/ErsatzTV.Core/Scheduling/YamlScheduling/EnumeratorCache.cs b/ErsatzTV.Core/Scheduling/YamlScheduling/EnumeratorCache.cs index 22103111..bc191704 100644 --- a/ErsatzTV.Core/Scheduling/YamlScheduling/EnumeratorCache.cs +++ b/ErsatzTV.Core/Scheduling/YamlScheduling/EnumeratorCache.cs @@ -79,6 +79,7 @@ public class EnumeratorCache(IMediaCollectionRepository mediaCollectionRepositor case YamlPlayoutContentMultiCollectionItem multiCollection: items = await mediaCollectionRepository.GetMultiCollectionItemsByName(multiCollection.MultiCollection); break; + // playlist is handled later } @@ -86,6 +87,43 @@ public class EnumeratorCache(IMediaCollectionRepository mediaCollectionRepositor var state = new CollectionEnumeratorState { Seed = context.Playout.Seed + index, Index = 0 }; + // marathon is a special case that needs to be handled on its own + if (content is YamlPlayoutContentMarathonItem marathon) + { + if (!Enum.TryParse(marathon.ItemOrder, true, out PlaybackOrder playbackOrder)) + { + playbackOrder = PlaybackOrder.Shuffle; + } + + var allMediaItems = new List(); + + // grab items from each show guid + foreach (string showGuid in marathon.Guids.Map(g => $"{g.Source}://{g.Value}")) + { + allMediaItems.AddRange(await mediaCollectionRepository.GetShowItemsByShowGuids([showGuid])); + } + + // TODO: support different group_by + + var groups = allMediaItems + .GroupBy(MediaItemKeyByShow) + .ToList(); + + Dictionary> itemMap = []; + + foreach (IGrouping group in groups) + { + PlaylistItem playlistItem = GroupToPlaylistItem(marathon, playbackOrder, group); + itemMap.Add(playlistItem, group.ToList()); + } + + return await PlaylistEnumerator.Create( + mediaCollectionRepository, + itemMap, + state, + cancellationToken); + } + // playlist is a special case that needs to be handled on its own if (content is YamlPlayoutContentPlaylistItem playlist) { @@ -121,4 +159,28 @@ public class EnumeratorCache(IMediaCollectionRepository mediaCollectionRepositor return Option.None; } + + private int MediaItemKeyByShow(MediaItem mediaItem) => + mediaItem switch + { + Episode e => e.Season?.ShowId ?? 0, + _ => 0 + }; + + private static PlaylistItem GroupToPlaylistItem( + YamlPlayoutContentMarathonItem marathon, + PlaybackOrder playbackOrder, + IGrouping group) => + new() + { + Index = group.Key, + + CollectionType = ProgramScheduleItemCollectionType.TelevisionShow, + MediaItemId = group.Key, + + PlayAll = marathon.PlayAllItems, + PlaybackOrder = playbackOrder, + + IncludeInProgramGuide = true + }; } diff --git a/ErsatzTV.Core/Scheduling/YamlScheduling/Models/YamlPlayoutContentMarathonItem.cs b/ErsatzTV.Core/Scheduling/YamlScheduling/Models/YamlPlayoutContentMarathonItem.cs new file mode 100644 index 00000000..153e5bf5 --- /dev/null +++ b/ErsatzTV.Core/Scheduling/YamlScheduling/Models/YamlPlayoutContentMarathonItem.cs @@ -0,0 +1,19 @@ +using YamlDotNet.Serialization; + +namespace ErsatzTV.Core.Scheduling.YamlScheduling.Models; + +public class YamlPlayoutContentMarathonItem : YamlPlayoutContentItem +{ + public string Marathon { get; set; } + + public List Guids { get; set; } = []; + + [YamlMember(Alias = "group_by", ApplyNamingConventions = false)] + public string GroupBy { get; set; } + + [YamlMember(Alias = "item_order", ApplyNamingConventions = false)] + public string ItemOrder { get; set; } + + [YamlMember(Alias = "play_all_items", ApplyNamingConventions = false)] + public bool PlayAllItems { get; set; } +} diff --git a/ErsatzTV.Core/Scheduling/YamlScheduling/YamlPlayoutBuilder.cs b/ErsatzTV.Core/Scheduling/YamlScheduling/YamlPlayoutBuilder.cs index acaff6eb..27147d39 100644 --- a/ErsatzTV.Core/Scheduling/YamlScheduling/YamlPlayoutBuilder.cs +++ b/ErsatzTV.Core/Scheduling/YamlScheduling/YamlPlayoutBuilder.cs @@ -281,6 +281,7 @@ public class YamlPlayoutBuilder( var contentKeyMappings = new Dictionary { { "collection", typeof(YamlPlayoutContentCollectionItem) }, + { "marathon", typeof(YamlPlayoutContentMarathonItem) }, { "multi_collection", typeof(YamlPlayoutContentMultiCollectionItem) }, { "playlist", typeof(YamlPlayoutContentPlaylistItem) }, { "search", typeof(YamlPlayoutContentSearchItem) },