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));
    }
예제 #2
0
    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);
    }