public async Task <IReadOnlyCollection <AdvisedPlaylist> > Advise(IEnumerable <DiscModel> discs, int requiredAdvisesCount, CancellationToken cancellationToken)
        {
            Memo ??= await sessionDataService.GetData <PlaylistAdviserMemo>(PlaylistAdviserDataKey, cancellationToken) ?? CreateDefaultMemo();

            var playbacksMemo = Memo;

            var adviseGroups  = (await discGrouper.GroupLibraryDiscs(discs, cancellationToken)).ToList();
            var playbacksInfo = new PlaybacksInfo(adviseGroups);

            var highlyRatedSongsAdvises = await highlyRatedSongsAdviser.Advise(adviseGroups, playbacksInfo, cancellationToken);

            var favoriteAdviseGroupAdvises = await favoriteAdviseGroupsAdviser.Advise(adviseGroups, playbacksInfo, cancellationToken);

            var rankedAdvises = await rankBasedAdviser.Advise(adviseGroups, playbacksInfo, cancellationToken);

            var playlistQueue = new CompositeAdvisedPlaylistQueue(highlyRatedSongsAdvises, favoriteAdviseGroupAdvises, rankedAdvises);

            var advisedPlaylists = new List <AdvisedPlaylist>(requiredAdvisesCount);

            var knownAdviseSets = new HashSet <string>();

            while (advisedPlaylists.Count < requiredAdvisesCount)
            {
                var currentAdvise = GetNextAdvisedPlaylist(playbacksMemo, playlistQueue);
                if (currentAdvise == null)
                {
                    break;
                }

                var adviseSet = currentAdvise.AdviseSet;
                if (adviseSet != null)
                {
                    if (knownAdviseSets.Contains(adviseSet.Id))
                    {
                        continue;
                    }

                    knownAdviseSets.Add(adviseSet.Id);
                }

                advisedPlaylists.Add(currentAdvise);
                playbacksMemo = playbacksMemo.RegisterPlayback(currentAdvise);
            }

            return(advisedPlaylists);
        }
        public async Task <IReadOnlyCollection <AdvisedPlaylist> > Advise(IEnumerable <AdviseGroupContent> adviseGroups, PlaybacksInfo playbacksInfo, CancellationToken cancellationToken)
        {
            var adviseGroupsList = adviseGroups.ToList();

            var adviseSetToAdviseGroupMap = adviseGroupsList
                                            .SelectMany(adviseGroup => adviseGroup.AdviseSets.Select(adviseSet => (adviseGroup, adviseSet)))
                                            .ToDictionary(x => x.adviseSet.Id, x => x.adviseGroup);

            var advisedPlaylists = await rankBasedAdviser.Advise(adviseGroupsList, playbacksInfo, cancellationToken);

            return(advisedPlaylists.Select(x => x.AdviseSet)
                   .GroupBy(x => adviseSetToAdviseGroupMap[x.Id], new AdviseGroupContentEqualityComparer())
                   .Where(g => g.Key.IsFavorite)
                   .OrderByDescending(g => playbacksInfo.GetPlaybacksPassed(g.Key))
                   .Select(g => g.First())
                   .Select(AdvisedPlaylist.ForAdviseSetFromFavoriteAdviseGroup)
                   .ToList());
        }