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);
        }
        private AdvisedPlaylist GetNextAdvisedPlaylist(PlaylistAdviserMemo playbacksMemo, CompositeAdvisedPlaylistQueue playlistQueue)
        {
            if (playbacksMemo.PlaybacksSinceHighlyRatedSongsPlaylist + 1 >= settings.HighlyRatedSongsAdviser.PlaybacksBetweenHighlyRatedSongs &&
                playlistQueue.TryDequeueHighlyRatedSongsAdvise(out var currentAdvise))
            {
                return(currentAdvise);
            }

            if (playbacksMemo.PlaybacksSinceFavoriteAdviseGroup + 1 >= settings.PlaybacksBetweenFavoriteAdviseGroups &&
                playlistQueue.TryDequeueFavoriteAdviseGroupAdvise(out currentAdvise))
            {
                return(currentAdvise);
            }

            return(playlistQueue.TryDequeueRankedAdvise(out currentAdvise) ? currentAdvise : null);
        }