private IList <MediaItem> Shuffle(IEnumerable <GroupedMediaItem> list, CloneableRandom random) { GroupedMediaItem[] copy = list.ToArray(); int n = copy.Length; while (n > 1) { n--; int k = random.Next(n + 1); (copy[k], copy[n]) = (copy[n], copy[k]); } return(GroupedMediaItem.FlattenGroups(copy, _mediaItemCount)); }
public static List <GroupedMediaItem> GroupMediaItems(IList <MediaItem> mediaItems, bool treatCollectionsAsShows) { var episodes = mediaItems.OfType <Episode>().ToList(); // var showIds = episodes.Map(e => e.Season.ShowId).Distinct().ToList(); var groups = new List <GroupedMediaItem>(); GroupedMediaItem group = null; var showIds = new List <Option <int> >(); if (treatCollectionsAsShows) { showIds.Add(Option <int> .None); } else { showIds.AddRange(episodes.Map(e => Some(e.Season.ShowId)).Distinct()); } foreach (Option <int> showId in showIds) { var lastNumber = 0; void AddUngrouped(MediaItem item) { if (group != null && lastNumber != 0) { groups.Add(group); group = null; lastNumber = 0; } groups.Add(new GroupedMediaItem(item, null)); } IEnumerable <Episode> sortedEpisodes = showId.Match( id => episodes.Filter(e => e.Season.ShowId == id), () => episodes).OrderBy(identity, new ChronologicalMediaComparer()); foreach (Episode episode in sortedEpisodes) { Option <int> maybeNumber = FindPartNumber(episode); if (maybeNumber.IsSome) { int number = maybeNumber.ValueUnsafe(); if (number <= lastNumber && group != null) { groups.Add(group); group = null; lastNumber = 0; } if (number > lastNumber) { if (lastNumber == 0) { // start a new group group = new GroupedMediaItem(episode, null); lastNumber = number; } else if (number == lastNumber + 1) { if (group != null) { // add to current group List <MediaItem> additional = group.Additional ?? new List <MediaItem>(); additional.Add(episode); group = new GroupedMediaItem(group.First, additional); } else { // this should never happen throw new InvalidOperationException( $"Bad shuffle state; unexpected number {number} after {lastNumber} with no existing group"); } lastNumber = number; } else { AddUngrouped(episode); } } else { AddUngrouped(episode); } } else { AddUngrouped(episode); } } if (group != null && lastNumber != 0) { groups.Add(group); group = null; } } foreach (MediaItem notEpisode in mediaItems.Filter(i => i is not Episode)) { groups.Add(new GroupedMediaItem(notEpisode, null)); } return(groups); }