//using System; //using System.Collections.Generic; //using System.Linq; //using MoreLinq; //using Sony.Filtr.Contracts.Entities; //using Sony.Filtr.Core; //using Sony.Filtr.Core.Settings; //using Sony.Filtr.DistributedCaching; //using Sony.Core.Data; //using Artist = Spotifony.Core.Data.Artist; //using Track = Spotifony.Core.Data.Track; //namespace Sony.Filtr.PlaylistGeneration //{ // public class TrackSuggestionManager // { // private static TrackSuggestionManager _instance = new TrackSuggestionManager(); // public static TrackSuggestionManager Instance { get { return _instance; } } // public IEnumerable GetSuggestedTracks(Application application, string spotifyRegionCode, IEnumerable artists = null, IEnumerable similarArtists = null) // { // var tracksPerArtist = SettingsManager.Instance.GetIntSetting("numberOfTracksPerArtist", application); // var maxArtists = SettingsManager.Instance.GetIntSetting("numberOfArtists", application) * 2; // var sonyPercent = SettingsManager.Instance.GetIntSetting("sonyPercentage", application); // var cacheKey = GetCacheKey(application, spotifyRegionCode, artists, similarArtists, tracksPerArtist, maxArtists, sonyPercent); // List trackSuggestions = DistributedCacheHandler.Instance.Get(cacheKey) as List; // if (trackSuggestions != null) // return trackSuggestions; // var sonyArtistsNeeded = (int)Math.Ceiling((maxArtists * (sonyPercent / 100.0))); // trackSuggestions = new List(); // List allArtists = new List(); // if (artists != null) // { // allArtists.AddRange(artists.Select(a => new SimilarArtistMatch(a, 100))); // foreach (var artist in artists) // { // allArtists.AddRange(PlaylistGenerationManager.Instance.GetSimilarArtists(artist, 100)); // } // } // if (similarArtists != null) // { // allArtists.AddRange(similarArtists); // } // //TODO: If duplicate we should only keep the one with highest score // var artistsToUse = allArtists.Where(a => a != null && a.Artist != null).ToList(); // artistsToUse = IsNotBlackListed(application, artistsToUse).ToList(); // artistsToUse = artistsToUse.Distinct(new SimilarArtistEntityEqualer()).OrderByDescending(s => s.Match).ToList(); // var usedArtists = new List(); // var sonyArtist = artistsToUse.Where(a => a.Artist.IsSonyArtist).OrderByDescending(a => a.Match); // //We want the top similar artists but we must ensure we reach the sony percent // foreach (var artist in sonyArtist) // { // if (trackSuggestions.Count > sonyArtistsNeeded) // break; // var artistTracks = GetTopSonyTracks(artist, tracksPerArtist, spotifyRegionCode); // if (artistTracks.Any()) // { // trackSuggestions.Add(new TrackSuggestion() { Artist = artist, Tracks = artistTracks.ToList() }); // usedArtists.Add(artist.Artist); // } // } // //We have reached the necessary number of sony artist, we keep filling until we have as many as we need // var otherArtists = artistsToUse.Where(s => !usedArtists.Contains(s.Artist)).OrderByDescending(a => a.Match); // foreach (var artist in otherArtists) // { // if (trackSuggestions.Count >= maxArtists) // break; // var artistTracks = PlaylistGenerationManager.Instance.GetTopTracks(artist, tracksPerArtist, spotifyRegionCode); // if (artistTracks != null && artistTracks.Any()) // { // trackSuggestions.Add(new TrackSuggestion() { Artist = artist, Tracks = artistTracks.Take(tracksPerArtist).ToList() }); // } // } // trackSuggestions = trackSuggestions.OrderByDescending(t => t.Artist.Match).ToList(); // DistributedCacheHandler.Instance.Put(cacheKey, trackSuggestions, DateTime.Now.AddDays(1)); // return trackSuggestions; // } // public IEnumerable GetSuggestedTracks3(Application application, string spotifyRegionCode, IEnumerable artists = null, IEnumerable similarArtists = null, string genre = null) // { // var tracksPerArtist = SettingsManager.Instance.GetIntSetting("numberOfTracksPerArtist", application); // var maxArtists = SettingsManager.Instance.GetIntSetting("numberOfArtists", application) * 2; // var cacheKey = "New3" + GetCacheKey3(application, spotifyRegionCode, artists, similarArtists, tracksPerArtist, maxArtists); // List trackSuggestions = DistributedCacheHandler.Instance.Get(cacheKey) as List; // if (trackSuggestions != null) // return trackSuggestions; // trackSuggestions = new List(); // List allArtists = new List(); // if (artists != null) // { // allArtists.AddRange(artists.Select(a => new SimilarArtistMatch(a, 100))); // foreach (var artist in artists) // { // allArtists.AddRange(PlaylistGenerationManager.Instance.GetSimilarArtists(artist, 100)); // } // } // if (similarArtists != null) // { // allArtists.AddRange(similarArtists); // } // //TODO: If duplicate we should only keep the one with highest score // var artistsToUse = allArtists.Where(a => a != null && a.Artist != null); // artistsToUse = IsNotBlackListed(application, artistsToUse); // BoostSonyArtists2(artistsToUse); // artistsToUse = artistsToUse.Distinct(new SimilarArtistEntityEqualer()) // .OrderByDescending(s => s.Match) // .ThenByDescending(s => s.Artist.IsSonyArtist); // foreach (var artist in artistsToUse) // { // if (trackSuggestions.Count >= maxArtists) // break; // IEnumerable artistTracks; // if (artist.Artist.IsSonyArtist) // artistTracks = GetTopSonyTracks(artist, 100, spotifyRegionCode); // else // artistTracks = PlaylistGenerationManager.Instance.GetTopTracks(artist, 100, spotifyRegionCode); // if (genre != null) // { // //We only want tracks that have correct genre. // artistTracks = FilterGenre(artistTracks, genre); // } // if (artistTracks != null) // { // var tracksToAdd = artistTracks.Take(tracksPerArtist).ToList(); // if (tracksToAdd.Any()) // trackSuggestions.Add(new TrackSuggestion() { Artist = artist, Tracks = tracksToAdd }); // } // } // trackSuggestions = trackSuggestions.OrderByDescending(t => t.Artist.Match).ThenByDescending(t => t.Artist.Artist.IsSonyArtist).ToList(); // DistributedCacheHandler.Instance.Put(cacheKey, trackSuggestions, DateTime.Now.AddDays(1)); // return trackSuggestions; // } // public List GetSuggestedTracksForGenre(Genre genre, string regionCode) // { // var cacheKey = "GetSuggestedTracksForGenre:-" + genre.LastFMTag + " " + regionCode; // List trackSuggestions = DistributedCacheHandler.Instance.Get(cacheKey) as List; // if (trackSuggestions != null) // return trackSuggestions; // trackSuggestions = new List(); // var topTracks = PlaylistGenerationManager.Instance.GetTopTracksForTag(genre.LastFMTag); // //int index = 0; // var groupedTracks = topTracks.GroupBy(g => g.Item.ArtistName); // const int maxArtists = 500; // foreach (var artistGroup in groupedTracks) // { // if (trackSuggestions.Count >= maxArtists) // break; // var artistName = artistGroup.Key; // var artist = PlaylistGenerationManager.Instance.GetArtist(artistName); // if (artist == null) // continue; // var lastFmTracks = artistGroup.Select(t => t).ToList(); // var localTracks1 = PlaylistGenerationManager.Instance.GetTopTracks(artist, 100, regionCode); // if (localTracks1 == null) // continue; // var localTracks = localTracks1.ToList(); // localTracks = localTracks.Join(lastFmTracks, // localTrack => localTrack.Name.ToLower(), // lastFmTrack => lastFmTrack.Item.Name.ToLower(), // (localTrack, lastFmTrack) => new { LastFmTrack = lastFmTrack, LocalTrack = localTrack }) // .OrderByDescending(l => l.LocalTrack.IsSonyTrack).ThenBy(l => l.LastFmTrack.Weight) // .Select(l => l.LocalTrack).DistinctBy(t => t.Name).Take(3).ToList(); // if (localTracks.Any()) // { // var bestTrackRank = artistGroup.Min(a => a.Weight); // double matchValue = Math.Max(500 - bestTrackRank, 1); // if (localTracks.First().IsSonyTrack) // matchValue = matchValue * 2; // else if (artist.IsSonyArtist) // matchValue = matchValue * 1.2; // var trackSuggestion = new TrackSuggestion(); // trackSuggestion.Artist = new SimilarArtistMatch(artist, matchValue/10); // trackSuggestion.Match = matchValue/10; // trackSuggestion.Tracks = localTracks; // trackSuggestions.Add(trackSuggestion); // } // } // trackSuggestions = trackSuggestions.OrderByDescending(t => t.Match).Take(50).ToList(); // DistributedCacheHandler.Instance.Put(cacheKey, trackSuggestions); // return trackSuggestions; // } // private IEnumerable FilterGenre(IEnumerable artistTracks, string genre) // { // foreach (var track in artistTracks) // { // List genres = new List(); // try // { // genres = PlaylistGenerationManager.Instance.GetTrackGenres(track); // } // catch (Exception) // { // //TODO: How do we verify lastfm has the track in a better way? // } // if (genres.Contains(genre, StringComparer.InvariantCultureIgnoreCase)) // { // yield return track; // } // } // } // private void BoostSonyArtists(IEnumerable artistsToUse) // { // artistsToUse.Where(a=> a.Artist.IsSonyArtist).ToList().ForEach(a=> a.Match = BoostSonyMatchValue(a.Match)); // } // private void BoostSonyArtists2(IEnumerable artistsToUse) // { // artistsToUse.Where(a => a.Artist.IsSonyArtist).ToList().ForEach(a => a.Match = BoostSonyMatchValue2(a.Match)); // } // private double BoostSonyMatchValue(double p) // { // if (p >= 60) // return 100; // if (p >= 30) // return 99; // return p; // } // private double BoostSonyMatchValue2(double score) // { // return score*1.5; // } // private IEnumerable GetTopSonyTracks(SimilarArtistMatch artist, int tracksPerArtist, string spotifyRegionCode) // { // Dictionary orderedList = new Dictionary(); // var artistTracks = PlaylistGenerationManager.Instance.GetTopTracks(artist, 100, spotifyRegionCode); // int order = 1; // foreach (var track in artistTracks) // { // orderedList.Add(track, order); // order++; // } // var ordered = orderedList.OrderByDescending(t => t.Key.IsSonyTrack).ThenBy(t => t.Value); // var tracks = ordered.Take(tracksPerArtist).Select(t=> t.Key); // return tracks; // } // private IEnumerable IsNotBlackListed(Application app, IEnumerable artistsToUse) // { // var blacklistedArtists = SonyMusicManager.Instance.BlacklistManager.GetBlacklistedArtists(app); // var lookup = blacklistedArtists.ToLookup(b=> b.ArtistName.ToLower()); // return artistsToUse.Where(a => !lookup.Contains(a.Artist.Name.ToLower())); // } // private string GetCacheKey(Application application, string spotifyRegionCode, IEnumerable artists, IEnumerable similarArtists, int tracksPerArtist, int maxArtists, int sonyPercent = 0) // { // if (spotifyRegionCode == null) // spotifyRegionCode = "null"; // return string.Join("-", "GetSuggestedTracks", application.ID, spotifyRegionCode.ToLower(), GetArtistsCacheKey(artists), GetSimilarArtistsCacheKey(similarArtists), tracksPerArtist, maxArtists, sonyPercent); // } // private string GetCacheKey2(Application application, string spotifyRegionCode, IEnumerable artists, IEnumerable similarArtists, int tracksPerArtist, int maxArtists) // { // if (spotifyRegionCode == null) // spotifyRegionCode = "null"; // return string.Join("-", "GetSuggestedTracks-v2-", application.ID, spotifyRegionCode.ToLower(), GetArtistsCacheKey(artists), GetSimilarArtistsCacheKey(similarArtists), tracksPerArtist, maxArtists); // } // private string GetCacheKey3(Application application, string spotifyRegionCode, IEnumerable artists, IEnumerable similarArtists, int tracksPerArtist, int maxArtists) // { // if (spotifyRegionCode == null) // spotifyRegionCode = "null"; // return string.Join("-", "GetSuggestedTracks-v3-", application.ID, spotifyRegionCode.ToLower(), GetArtistsCacheKey(artists), GetSimilarArtistsCacheKey(similarArtists), tracksPerArtist, maxArtists); // } // private string GetSimilarArtistsCacheKey(IEnumerable artists) // { // if (artists == null || !artists.Any()) // return "-"; // return GetArtistsCacheKey(artists.Select(a=> a.Artist)); // } // private string GetArtistsCacheKey(IEnumerable artists) // { // if (artists == null || !artists.Any()) // return "-"; // return string.Join(":", artists.OrderBy(a => a.Name).Select(a => "a:" + a.Name.ToLower())); // } // //private static IEnumerable GetTrackBasedRecommendedArtists(IEnumerable tracks) // //{ // // List similarArtists = new List(); // // foreach (var track in tracks) // // { // // similarArtists.Add(new SimilarArtistMatch(PlaylistGenerationManager.Instance.GetArtist(track.ArtistName), 100)); // // var similarTracks = PlaylistGenerationManager.Instance.GetSimilarTracks(track); // // foreach (var similarTrack in similarTracks) // // { // // var artist = PlaylistGenerationManager.Instance.GetArtist(similarTrack.Item.ArtistName); // // similarArtists.Add(new SimilarArtistMatch(artist, similarTrack.Weight)); // // } // // } // // return similarArtists; // //} // //private IEnumerable GetPersonaTracks(Artist artist, Persona persona) // //{ // // if (persona != null) // // return persona.PromotedTracks.Where(t => t.ArtistName == artist.Name); // // return new List(); // //} // public class SimilarArtistEntityEqualer : IEqualityComparer // { // public bool Equals(SimilarArtistMatch x, SimilarArtistMatch y) // { // if (x == y) // return true; // if (x == null || y == null) // return false; // return (x.Artist.Name == x.Artist.Name); // } // public int GetHashCode(SimilarArtistMatch obj) // { // if (obj != null && obj.Artist != null && obj.Artist.Name != null) // return obj.Artist.Name.GetHashCode(); // return 0; // } // } // } //}