using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using MoreLinq; using Sony.Filtr.Buzz; using Sony.Filtr.Contracts.Definitions; using Sony.Filtr.Contracts.Entities; using Sony.Filtr.Core.SonyMusic; using Sony.Filtr.Core.SpotifyBrowse; using Sony.Filtr.Core.SpotifyRegion; using Sony.Filtr.Playlists.Spotify; using Sony.Filtr.Playlists.Spotify.Model; using Sony.Filtr.SpotifyWebAPI.Model; using Sony.Filtr.Utility.Extensions; using Sony.Filtr.Core.EditorialPlaylists; using Sony.Filtr.SpotifyWebAPI; namespace Sony.Filtr.Worker.Onetime { public class ExportSonyPercentagesOverTimeByUpc { private readonly SpotifyPlaylistManager _spotifyPlaylistManager; private readonly SpotifyBrowseManager _spotifyBrowseManager; private readonly SonyMusicManager _sonyMusicManager; private readonly SpotifyRegionManager _spotifyRegionManager; private readonly BuzzAccountManager _buzzAccountManager; private readonly EditorialPlaylistManager _editorialPlaylistManager; private readonly SpotifyPlaylistHistoricTrackListManager _historicTrackListManager; private readonly SpotifyWebApi _spotifyWebApi; private ConcurrentDictionary _albumIsSony = new ConcurrentDictionary(); private ConcurrentDictionary _trackIsSony = new ConcurrentDictionary(); private string _market = "nl"; public ExportSonyPercentagesOverTimeByUpc(SpotifyPlaylistManager spotifyPlaylistManager, SpotifyBrowseManager spotifyBrowseManager, SonyMusicManager sonyMusicManager, SpotifyRegionManager spotifyRegionManager, BuzzAccountManager buzzAccountManager, EditorialPlaylistManager editorialPlaylistManager, SpotifyPlaylistHistoricTrackListManager historicTrackListManager, SpotifyWebApi spotifyWebApi) { _spotifyPlaylistManager = spotifyPlaylistManager; _spotifyBrowseManager = spotifyBrowseManager; _sonyMusicManager = sonyMusicManager; _spotifyRegionManager = spotifyRegionManager; _buzzAccountManager = buzzAccountManager; _editorialPlaylistManager = editorialPlaylistManager; _historicTrackListManager = historicTrackListManager; _spotifyWebApi = spotifyWebApi; } public async Task ExecuteAsync() { var playlistUsers = new List() { "spotify_netherlands", "spotlight_netherlands", "spotify_netherlands_social" }; List playlists = new List(); foreach(var playlistUser in playlistUsers) { var userPlaylists = _spotifyPlaylistManager.GetPlaylistsForUser(playlistUser); playlists.AddRange(userPlaylists); } ConcurrentBag results = new ConcurrentBag(); var totalPlaylists = playlists.Count; await playlists.ItemIndex().ForEachAsync(5, async playlistIndexItem => { try { var playlist = playlistIndexItem.Item; Console.WriteLine($"{playlist.PlaylistUri}. {playlistIndexItem.Index} / {totalPlaylists}"); var fromDate = new DateTime(2016, 4, 1); var toDate = new DateTime(2017, 3, 31); foreach (var date in EachDay(fromDate, toDate)) { var dateString = date.ToString("d", CultureInfo.GetCultureInfo("sv-SE")); try { var trackList = await _historicTrackListManager.GetHistoricTrackListAsync(playlist.PlaylistUri, dateString); var result = new TempResult() { Date = date, PlaylistUri = playlist.PlaylistUri, Name = playlist.Name, Tracks = trackList.Count, SonyPercentage = Math.Round(await CalculatePercentageAsync(trackList)) }; //Console.WriteLine(string.Join(", ", result.PlaylistUri, result.Date, result.Name, result.Tracks, result.SonyPercentage)); results.Add(result); } catch(Exception e) { Console.WriteLine(e); //throw; } } } catch(Exception e) { Console.WriteLine("Error for " + playlistIndexItem.Item.PlaylistUri + ":" + e); //throw; } }); FileInfo file = new FileInfo("SonyPercentage-Playlist.csv"); using(var fileStream = file.OpenWrite()) { fileStream.Write(Encoding.UTF8.GetPreamble(), 0, Encoding.UTF8.GetPreamble().Length); using(var fileWriter = new StreamWriter(fileStream)) { fileWriter.WriteLine(string.Join(";", "Uri", "Name", "Date", "Tracks", "WorldwideSonyPercentage")); foreach(var result in results) { await fileWriter.WriteLineAsync($"{result.PlaylistUri};{result.Name};{result.Date.ToShortDateString()};{result.Tracks};{result.SonyPercentage}"); } } } } private async Task CalculatePercentageAsync(List trackList) { if (!trackList.Any()) { return 0; } var tracksThatNeedLookup = trackList.Select(t => t.TrackId).Where(t => !_trackIsSony.ContainsKey(t)).ToList(); if (tracksThatNeedLookup.Any()) { var spotifyTracks = await _spotifyWebApi.GetAllTracksAsync(tracksThatNeedLookup, _market); var albumIds = spotifyTracks.FilterNull().Select(p => p.album?.id).FilterNull().Distinct().ToList(); var albumSony = await GetAlbumIsSonyAsync(albumIds); foreach (var spotifyTrack in spotifyTracks.FilterNull()) { if (spotifyTrack.album?.id != null) { _trackIsSony.TryAdd(spotifyTrack.linked_from?.id ?? spotifyTrack.id, albumSony.Contains(spotifyTrack.album.id)); } } } int trackcount = trackList.Count; int sonyTracks = trackList.Count(t => _trackIsSony.GetValueOrDefault(t.TrackId)); var percentage = ((1.0 * sonyTracks) / trackcount) * 100; return percentage; } private async Task> GetAlbumIsSonyAsync(List albumIds) { List isSony = albumIds.Where(a => _albumIsSony.ContainsKey(a) && _albumIsSony[a]).ToList(); var albumIdsNeedLookup = albumIds.Where(a => !_albumIsSony.ContainsKey(a)).ToList(); if (albumIdsNeedLookup.Any()) { var albums = await _spotifyWebApi.GetAllAlbumInfoAsync(albumIdsNeedLookup, _market); var upcs = albums.Select(a => a.external_ids?.upc).FilterNull().Distinct().ToList(); var isSonyUpc = await _sonyMusicManager.IsSonyAlbumAsync(upcs, _market); foreach(var album in albums) { if (isSonyUpc.Contains(album.external_ids?.upc)) { _albumIsSony.TryAdd(album.id, true); isSony.Add(album.id); } else { _albumIsSony.TryAdd(album.id, false); } } } return isSony.ToHashSet(); } private IEnumerable EachDay(DateTime from, DateTime thru) { for (var day = from.Date; day.Date <= thru.Date; day = day.AddDays(1)) yield return day; } private class TempResult { public string PlaylistUri { get; set; } public string Name { get; set; } public DateTime Date { get; set; } public int Tracks { get; set; } public double SonyPercentage { get; set; } } } }