Ejemplo n.º 1
0
        public List<Track> GeneratePlayList(List<Track> availableTracks,
            MixLibrary mixLibrary,
            List<Track> currentPlaylist,
            Direction direction,
            int approximateLength,
            AllowBearableMixStrategy allowBearable,
            MixStrategy strategy,
            UseExtendedMixes useExtendedMixes,
            Dictionary<string, Dictionary<string, Track>> excludedMixes,
            bool restrictArtistClumping,
            bool restrictGenreClumping,
            bool restrictTitleClumping,
            ContinueMix continueMix,
            KeyMixStrategy keyMixStrategy,
            int maxTracksToAdd)
        {
            if (strategy == MixStrategy.Working && currentPlaylist.Count == 0) return currentPlaylist;

            Track workingTrack = null;
            if (strategy == MixStrategy.Working)
            {
                direction = Direction.Any;
                workingTrack = currentPlaylist.Last();
            }

            GeneratePlayListStatus = "";
            MixLibrary = mixLibrary;

            AvailableTracks = availableTracks;

            if (strategy == MixStrategy.Working) AvailableTracks.RemoveAll(t => MixLibrary.GetMixOutCount(t) == 0);

            if (AvailableTracks.Count == 0) return currentPlaylist;

            var availableTrackDescriptions = GetDistinctTrackDescriptions(AvailableTracks);

            var trackCountLimit = int.MaxValue;
            if (approximateLength > 0 && approximateLength != int.MaxValue)
            {
                var currentLength = currentPlaylist.Sum(cp => cp.Length);
                var requiredLength = Convert.ToInt32((approximateLength*60) - currentLength);

                if (requiredLength <= 0) return new List<Track>();
                var averageLength = AvailableTracks.Average(t => t.Length);

                trackCountLimit = (requiredLength/Convert.ToInt32(averageLength)) + currentPlaylist.Count;

                if (trackCountLimit == currentPlaylist.Count) return new List<Track>();
            }

            if (maxTracksToAdd != int.MaxValue && trackCountLimit > currentPlaylist.Count + maxTracksToAdd)
            {
                trackCountLimit = currentPlaylist.Count + maxTracksToAdd;
            }

            if (strategy != MixStrategy.Unranked && strategy != MixStrategy.Working)
            {
                if (trackCountLimit > AvailableTracks.Count)
                {
                    trackCountLimit = AvailableTracks.Count;
                }
            }

            var initialPlaylistCount = currentPlaylist.Count;

            var currentPaths = new List<TrackPath>();
            if (currentPlaylist.Count == 0)
            {
                var trackPaths = AvailableTracks.Select(track => new TrackPath(track));
                foreach (var path in trackPaths)
                {
                    CalculateAverageRankForPath(path);
                    currentPaths.Add(path);
                }
            }
            else if (continueMix == ContinueMix.No)
            {
                var trackPaths = AvailableTracks
                    .Select(track => new List<Track>(currentPlaylist) {track})
                    .Select(playlist => new TrackPath(playlist));

                foreach (var path in trackPaths)
                {
                    CalculateAverageRankForPath(path);
                    currentPaths.Add(path);
                }
            }
            else
            {
                var path = new TrackPath(currentPlaylist);
                CalculateAverageRankForPath(path);
                currentPaths.Add(path);
            }

            _cancelGeneratePlayList = false;
            _stopGeneratePlayList = false;

            var nextPaths = new List<TrackPath>();
            while (!IsGenerationHalted())
            {
                ParallelHelper.ForEach(currentPaths, currentPath => GeneratePaths(direction,
                    allowBearable,
                    strategy,
                    useExtendedMixes,
                    excludedMixes,
                    restrictArtistClumping,
                    restrictGenreClumping,
                    restrictTitleClumping,
                    keyMixStrategy,
                    workingTrack,
                    availableTrackDescriptions,
                    nextPaths,
                    currentPath));

                if (IsGenerationHalted()) break;

                if (nextPaths.Count == 0) break;

                GeneratePlayListStatus =
                    $"Generated {nextPaths.Count} possible paths for {nextPaths[0].Tracks.Count} of {trackCountLimit} tracks.";

                var max = 50*Environment.ProcessorCount;

                if (nextPaths.Count > max)
                {
                    nextPaths = nextPaths
                        .OrderByDescending(t => t.AverageRank)
                        .Take(max)
                        .ToList();
                }

                currentPaths.Clear();
                currentPaths.AddRange(nextPaths);

                if (nextPaths[0].Tracks.Count >= trackCountLimit) break;
                nextPaths.Clear();
            }

            if (_cancelGeneratePlayList) return currentPlaylist;

            var resultPath = currentPaths
                .OrderByDescending(t => GetAverageTrackAndMixAndKeyRank(t.Tracks))
                .FirstOrDefault();

            if ((strategy == MixStrategy.BestMix || strategy == MixStrategy.Variety ||
                 strategy == MixStrategy.ExtraVariety)
                && resultPath != null
                && resultPath.Tracks.Count < trackCountLimit
                && resultPath.Tracks.Count > 0)
            {
                availableTrackDescriptions = GetDistinctTrackDescriptions(AvailableTracks);
                var excludeTrackDescriptions = GetDistinctTrackDescriptions(resultPath.Tracks);
                var currentTrack = resultPath.Tracks[resultPath.Tracks.Count - 1];
                var nextTrack =
                    GetBestMixTracks(currentTrack, resultPath.Tracks, allowBearable, availableTrackDescriptions,
                        excludeTrackDescriptions, restrictArtistClumping, restrictArtistClumping, restrictTitleClumping,
                        keyMixStrategy)
                        .OrderBy(t => GetAverageTrackAndMixAndKeyRank(currentTrack, t))
                        .FirstOrDefault();

                if (nextTrack != null) resultPath.Tracks.Add(nextTrack);
            }

            var resultTracks = (resultPath != null)
                ? resultPath.Tracks
                : new List<Track>();

            if (continueMix == ContinueMix.IfPossible && resultTracks.Count == initialPlaylistCount)
            {
                return GeneratePlayList(availableTracks,
                    mixLibrary,
                    currentPlaylist,
                    direction,
                    approximateLength,
                    allowBearable,
                    strategy,
                    useExtendedMixes,
                    excludedMixes,
                    restrictArtistClumping,
                    restrictGenreClumping,
                    restrictTitleClumping,
                    ContinueMix.No,
                    keyMixStrategy,
                    maxTracksToAdd);
            }

            return resultTracks;
        }