From a8cf22e43e6b118b214265b6ed40c0dd57ca0f11 Mon Sep 17 00:00:00 2001 From: Jason Dove <1695733+jasongdove@users.noreply.github.com> Date: Tue, 30 Jul 2024 19:24:56 -0500 Subject: [PATCH] group marathon by season (#1843) --- .../YamlScheduling/EnumeratorCache.cs | 58 +--------- .../YamlPlayoutMarathonHelper.cs | 108 ++++++++++++++++++ 2 files changed, 110 insertions(+), 56 deletions(-) create mode 100644 ErsatzTV.Core/Scheduling/YamlScheduling/YamlPlayoutMarathonHelper.cs diff --git a/ErsatzTV.Core/Scheduling/YamlScheduling/EnumeratorCache.cs b/ErsatzTV.Core/Scheduling/YamlScheduling/EnumeratorCache.cs index bc191704..6c980ca6 100644 --- a/ErsatzTV.Core/Scheduling/YamlScheduling/EnumeratorCache.cs +++ b/ErsatzTV.Core/Scheduling/YamlScheduling/EnumeratorCache.cs @@ -90,38 +90,8 @@ public class EnumeratorCache(IMediaCollectionRepository mediaCollectionRepositor // 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); + var helper = new YamlPlayoutMarathonHelper(mediaCollectionRepository); + return await helper.GetEnumerator(marathon, state, cancellationToken); } // playlist is a special case that needs to be handled on its own @@ -159,28 +129,4 @@ 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/YamlPlayoutMarathonHelper.cs b/ErsatzTV.Core/Scheduling/YamlScheduling/YamlPlayoutMarathonHelper.cs new file mode 100644 index 00000000..4e3269f0 --- /dev/null +++ b/ErsatzTV.Core/Scheduling/YamlScheduling/YamlPlayoutMarathonHelper.cs @@ -0,0 +1,108 @@ +using ErsatzTV.Core.Domain; +using ErsatzTV.Core.Interfaces.Repositories; +using ErsatzTV.Core.Interfaces.Scheduling; +using ErsatzTV.Core.Scheduling.YamlScheduling.Models; + +namespace ErsatzTV.Core.Scheduling.YamlScheduling; + +public class YamlPlayoutMarathonHelper(IMediaCollectionRepository mediaCollectionRepository) +{ + public async Task> GetEnumerator( + YamlPlayoutContentMarathonItem marathon, + CollectionEnumeratorState state, + CancellationToken cancellationToken) + { + 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])); + } + + List> groups = []; + + // group by show + if (string.Equals(marathon.GroupBy, "show", StringComparison.OrdinalIgnoreCase)) + { + groups.AddRange(allMediaItems.GroupBy(MediaItemKeyByShow)); + } + // group by season + else if (string.Equals(marathon.GroupBy, "season", StringComparison.OrdinalIgnoreCase)) + { + groups.AddRange(allMediaItems.GroupBy(MediaItemKeyBySeason)); + } + + Dictionary> itemMap = []; + + for (var index = 0; index < groups.Count; index++) + { + IGrouping group = groups[index]; + PlaylistItem playlistItem = GroupToPlaylistItem(index, marathon, playbackOrder, group); + itemMap.Add(playlistItem, group.ToList()); + } + + return await PlaylistEnumerator.Create( + mediaCollectionRepository, + itemMap, + state, + cancellationToken); + } + + private static GroupKey MediaItemKeyByShow(MediaItem mediaItem) => + mediaItem switch + { + Episode e => new GroupKey( + ProgramScheduleItemCollectionType.TelevisionShow, + null, + null, + null, + e.Season?.ShowId ?? 0), + _ => new GroupKey(ProgramScheduleItemCollectionType.TelevisionShow, null, null, null, 0) + }; + + private static GroupKey MediaItemKeyBySeason(MediaItem mediaItem) => + mediaItem switch + { + Episode e => new GroupKey( + ProgramScheduleItemCollectionType.TelevisionSeason, + null, + null, + null, + e.SeasonId), + _ => new GroupKey(ProgramScheduleItemCollectionType.TelevisionSeason, null, null, null, 0) + }; + + private static PlaylistItem GroupToPlaylistItem( + int index, + YamlPlayoutContentMarathonItem marathon, + PlaybackOrder playbackOrder, + IGrouping group) => + new() + { + Index = index, + + CollectionType = group.Key.CollectionType, + CollectionId = group.Key.CollectionId, + MultiCollectionId = group.Key.MultiCollectionId, + SmartCollectionId = group.Key.SmartCollectionId, + MediaItemId = group.Key.MediaItemId, + + PlayAll = marathon.PlayAllItems, + PlaybackOrder = playbackOrder, + + IncludeInProgramGuide = true + }; + + private record GroupKey( + ProgramScheduleItemCollectionType CollectionType, + int? CollectionId, + int? MultiCollectionId, + int? SmartCollectionId, + int? MediaItemId); +}