using System; using System.Linq; using System.Threading.Tasks; using MoreLinq; using Nancy; using Nancy.LightningCache.Extensions; using Sony.Filtr.Applications; using Sony.Filtr.Contracts.Entities; using Sony.Filtr.Core.Buzz; using Sony.Filtr.Core.EditorialPlaylists; using Sony.Filtr.Tasks; namespace Sony.Filtr.AdminAPI.Modules.Stats { public class StatsModule : BaseModule { private readonly EditorialPlaylistManager _editorialPlaylistManager; private readonly ApplicationInstanceManager _applicationInstanceManager; public StatsModule(EditorialPlaylistManager editorialPlaylistManager, EditorialPlaylistStatsManager editorialPlaylistStatsManager, BuzzManager buzzManager, ApplicationInstanceManager applicationInstanceManager, ScheduledTaskManager scheduledTaskManager) : base(applicationInstanceManager) { _editorialPlaylistManager = editorialPlaylistManager; _applicationInstanceManager = applicationInstanceManager; //Get["GetGenericStats", "/{countryCode}/stats"] = parameters => Response.AsJson(GetStats(CurrentApplication, statisticsManager, TimePeriod.AllTime)); //Get["GetGenericStatsWeek", "/{countryCode}/stats/week"] = parameters => Response.AsJson(GetStats(CurrentApplication, statisticsManager, TimePeriod.LastWeek)); //Get["GetGenericStatsDay", "/{countryCode}/stats/day"] = parameters => Response.AsJson(GetStats(CurrentApplication, statisticsManager, TimePeriod.Today)); //Get["GetGenericStatsMonth", "/{countryCode}/stats/month"] = parameters => Response.AsJson(GetStats(CurrentApplication, statisticsManager, TimePeriod.LastMonth)); Get["GetTopPlaylistStats", "/stats/topPlaylists", true] = async (parameters, cx) => (await GetTopPlaylistsAsync(null)).AsCacheable(DateTime.Now.AddHours(1)); Get["GetTopPlaylistsStatsMarket", "/{countryCode}/stats/topPlaylists", true] = async (parameters, cx) => (await GetTopPlaylistsAsync(CurrentApplication)).AsCacheable(DateTime.Now.AddHours(1)); Get["GetTopGrowingPlaylistStats", "/stats/topGrowingPlaylists", true] = async (parameters, cx) => (await GetGrowingPlaylistsAsync(Request, null)).AsCacheable(DateTime.Now.AddHours(1)); Get["GetTopGrowingPlaylistStatsMarket", "/{countryCode}/stats/topGrowingPlaylists", true] = async (parameters, cx) => (await GetGrowingPlaylistsAsync(Request, CurrentApplication)).AsCacheable(DateTime.Now.AddHours(1)); Get["GetTopDecreasingPlaylists", "/stats/topDecreasingPlaylists", true] = async (parameters, cx) => (await GetDecreasingPlaylistsAsync(Request, null)).AsCacheable(DateTime.Now.AddHours(1)); Get["GetTopDecreasingPlaylistsMarket", "/{countryCode}/stats/topDecreasingPlaylists", true] = async (parameters, cx) => (await GetDecreasingPlaylistsAsync(Request, CurrentApplication)).AsCacheable(DateTime.Now.AddHours(1)); Get["GetTopBuzzAccounts", "/stats/topBuzzAccounts"] = parameters => GetTopBuzzCompanies(buzzManager, null); Get["GetTopBuzzAccountsMarket", "/{countryCode}/stats/topBuzzAccounts"] = parameters => GetTopBuzzCompanies(buzzManager, CurrentApplication); Get["GetTopPlaylistCountryStats", "/stats/country", true] = async (parameters, cx) => (await GetPlaylistCountryOverviewAsync(editorialPlaylistManager, editorialPlaylistStatsManager)) .AsCacheable(DateTime.Now.AddHours(1)); Get["GetMarketOverviewStats", "/stats/market", true] = async (parameters, cx) => (await GetPlaylistMarketOverviewAsync(editorialPlaylistManager, editorialPlaylistStatsManager)) .AsCacheable(DateTime.Now.AddHours(1)); Get["GetMarketCountryOverviewStats", "/stats/marketCountry", true] = async (parameters, cx) => (await GetPlaylistMarketCountryOverviewAsync(editorialPlaylistManager, editorialPlaylistStatsManager)) .AsCacheable(DateTime.Now.AddHours(1)); } private async Task GetPlaylistMarketCountryOverviewAsync(EditorialPlaylistManager editorialPlaylistManager, EditorialPlaylistStatsManager editorialPlaylistStatsManager) { var playlists = await editorialPlaylistManager.GetLightweightEditorialPlaylistsAsync(null, onlyActive: false); var stats = await editorialPlaylistStatsManager.GetPlaylistStatsAsync(playlists); var applications = _applicationInstanceManager.GetApplications().ToDictionary(a => a.ID, b => b); var groupedStats = stats.GroupBy(p => p.Playlist.ApplicationID).Select(a=> new { //Playlist = a.ToList(), PlaylistWithCountryCode = a.Where(p => p.Playlist.CountryCode != null && p.Playlist.CountryCode.Equals(applications[a.Key].SpotifyRegionCode, StringComparison.InvariantCultureIgnoreCase)), Application = applications[a.Key] }); var viewModels = groupedStats.Select(a => new { MarketName = a.Application.Name, CountryCode = a.Application.SpotifyRegionCode, PlaylistCount = a.PlaylistWithCountryCode.Count(), Followers = a.PlaylistWithCountryCode.Sum(withStats => withStats.LatestSubscribers), AverageFollowers = a.PlaylistWithCountryCode.Any() ? a.PlaylistWithCountryCode.Average(withStats => withStats.LatestSubscribers) : 0, DailyChange = a.PlaylistWithCountryCode.Sum(withStats => withStats.LatestSubscribers) - a.PlaylistWithCountryCode.Sum(withStats => withStats.SecondLatestSubscribers) }); return Response.AsJson(viewModels); } private async Task GetPlaylistMarketOverviewAsync(EditorialPlaylistManager editorialPlaylistManager, EditorialPlaylistStatsManager editorialPlaylistStatsManager) { var playlists = await editorialPlaylistManager.GetEditorialPlaylistsAsync(null, onlyActive: false); var stats = await editorialPlaylistStatsManager.GetPlaylistStatsAsync(playlists); var applications = _applicationInstanceManager.GetApplications().ToDictionary(a => a.ID, b => b); var groupedStats = stats.GroupBy(p => p.Playlist.ApplicationID); var viewModels = groupedStats.Select(p => new { MarketName = (applications.ContainsKey(p.Key)) ? applications[p.Key].Name : string.Empty, CountryCode = (applications.ContainsKey(p.Key)) ? applications[p.Key].SpotifyRegionCode : string.Empty, PlaylistCount = p.Count(), Followers = p.Sum(withStats => withStats.LatestSubscribers), AverageFollowers = p.Any() ? p.Average(withStats => withStats.LatestSubscribers) : 0, DailyChange = p.Sum(withStats => withStats.LatestSubscribers) - p.Sum(withStats => withStats.SecondLatestSubscribers) }); return Response.AsJson(viewModels); } private async Task GetPlaylistCountryOverviewAsync(EditorialPlaylistManager editorialPlaylistManager, EditorialPlaylistStatsManager editorialPlaylistStatsManager) { var playlists = await editorialPlaylistManager.GetEditorialPlaylistsAsync(null, onlyActive: false); var applications = _applicationInstanceManager.GetApplications().Where(a => a.SpotifyRegionCode != null).GroupBy(a => a.SpotifyRegionCode).ToDictionary(a => a.Key, b => b.First()); var groupedPlaylists = await editorialPlaylistManager.GetPlaylistAttributesAsync(playlists); var groupedStats = groupedPlaylists.DistinctBy(s => s.EditorialPlaylist.SpotifyLinkUri).GroupBy(p => p.EditorialPlaylist.CountryCode); var viewModels = groupedStats.Select(p => new { MarketName = (p.Key != null && applications.ContainsKey(p.Key)) ? applications[p.Key].Name : string.Empty, CountryCode = p.Key, PlaylistCount = p.Count(), Followers = p.Sum(withStats => withStats.Attributes.Followers), AverageFollowers = p.Any() ? p.Average(withStats => withStats.Attributes.Followers) : 0, DailyChange = p.Sum(withStats => withStats.Attributes.Followers) - p.Sum(withStats => withStats.Attributes.LastFollowers) }); return Response.AsJson(viewModels); } private Response GetTopBuzzCompanies(BuzzManager buzzManager, Application application) { var buzzCompanies = buzzManager.GetTopBuzzCompanies(); var market = _applicationInstanceManager.GetApplications().ToDictionary(a => a.ID); var viewModels = buzzCompanies.Where(a=> application == null || a.Key.ApplicationID == application.ID) .Select(b => new { Name = b.Key.Name, Market = market[b.Key.ApplicationID].Name, Subscribers = b.Value }); return Response.AsJson(viewModels); } private async Task GetDecreasingPlaylistsAsync(Request request, Application application) { //var daySpan = 1; //if (request.Query.timeSpan != null) //{ // int? timeSpanDays = request.Query.timeSpan; // if (timeSpanDays.HasValue) // daySpan = timeSpanDays.Value; //} var playlists = await _editorialPlaylistManager.GetEditorialPlaylistsAsync(application, onlyActive: false, lightWeight: true); var groupedPlaylists = await _editorialPlaylistManager.GetPlaylistAttributesAsync(playlists); var topPlaylists = groupedPlaylists .Where(p => p.Attributes.LastFollowers.HasValue && p.Attributes.LastFollowers > 0 && p.Attributes.Followers.HasValue && p.Attributes.Followers > 0) .OrderBy(p => p.Attributes.Followers - p.Attributes.LastFollowers) .DistinctBy(p => p.EditorialPlaylist.SpotifyLink).Take(10); var viewModels = topPlaylists.Select(p => new { Name = p.EditorialPlaylist.Name, Subscribers = p.Attributes.Followers, Followers = p.Attributes.Followers, LastFollowers = p.Attributes.LastFollowers, FollowerChange7 = p.Attributes.FollowerChange7, FollowerChange15 = p.Attributes.FollowerChange15, FollowerChange30 = p.Attributes.FollowerChange30, p.EditorialPlaylist.SpotifyLink.Uri, p.EditorialPlaylist.CountryCode, Decrease = Math.Abs(p.Attributes.Followers.Value - p.Attributes.LastFollowers.Value) }); //var viewModels = topPlaylists.Select(p => // new // { // p.Playlist.Name, // Subscribers = p.LatestSubscribers, // Trend = p.Stats.ToDictionary(k => k.Date, v => v.Subscribers), // p.Playlist.SpotifyLink.Uri, // p.Playlist.CountryCode, // Decrease = Math.Abs(GetDifference(p, daySpan)) // }); return Response.AsJson(viewModels); } private async Task GetGrowingPlaylistsAsync(Request request, Application application) { //var daySpan = 1; //if (request.Query.timeSpan != null) //{ // int? timeSpanDays = request.Query.timeSpan; // if (timeSpanDays.HasValue) // daySpan = timeSpanDays.Value; //} var playlists = await _editorialPlaylistManager.GetEditorialPlaylistsAsync(application, onlyActive: false, lightWeight: true); var groupedPlaylists = await _editorialPlaylistManager.GetPlaylistAttributesAsync(playlists); var topPlaylists = groupedPlaylists .Where(p => p.Attributes.LastFollowers.HasValue && p.Attributes.LastFollowers > 0 && p.Attributes.Followers.HasValue && p.Attributes.Followers > 0) .OrderByDescending(p => p.Attributes.Followers - p.Attributes.LastFollowers) .DistinctBy(p => p.EditorialPlaylist.SpotifyLink) .Take(10); var viewModels = topPlaylists.Select(p => new { Name = p.EditorialPlaylist.Name, Subscribers = p.Attributes.Followers, Followers = p.Attributes.Followers, LastFollowers = p.Attributes.LastFollowers, FollowerChange7 = p.Attributes.FollowerChange7, FollowerChange15 = p.Attributes.FollowerChange15, FollowerChange30 = p.Attributes.FollowerChange30, p.EditorialPlaylist.SpotifyLink.Uri, p.EditorialPlaylist.CountryCode, Increase = p.Attributes.Followers - p.Attributes.LastFollowers }); return Response.AsJson(viewModels); } private async Task GetTopPlaylistsAsync(Application application) { var playlists = await _editorialPlaylistManager.GetEditorialPlaylistsAsync(application, onlyActive: false, lightWeight: true); var groupedPlaylists = await _editorialPlaylistManager.GetPlaylistAttributesAsync(playlists); var topPlaylists = groupedPlaylists.OrderByDescending(p => p.Attributes.Followers).DistinctBy(p => p.EditorialPlaylist.SpotifyLink).Take(10); var viewModels = topPlaylists.Select(p => new { Name = p.EditorialPlaylist.Name, Subscribers = p.Attributes.Followers, Followers = p.Attributes.Followers, LastFollowers = p.Attributes.LastFollowers, FollowerChange7 = p.Attributes.FollowerChange7, FollowerChange15 = p.Attributes.FollowerChange15, FollowerChange30 = p.Attributes.FollowerChange30, p.EditorialPlaylist.SpotifyLink.Uri, p.EditorialPlaylist.CountryCode }); return Response.AsJson(viewModels); } //private StatisticsViewModel GetStats(Application app, StatisticsManager statisticsManager, TimePeriod timePeriod) //{ // var stats = new StatisticsViewModel(); // stats.TopRequestedArtists = statisticsManager.GetTopRequestedArtist(app, timePeriod); // stats.TopRequestedTags = statisticsManager.GetTopRequestedTag(app, timePeriod); // stats.TopPersonas = statisticsManager.GetTopPersona(app, timePeriod); // stats.TopRecommendedArtists = statisticsManager.GetTopRecommendArtists(app, timePeriod); // stats.TopRecommendedTracks = statisticsManager.GetTopRecommendedTracks(app, timePeriod); // stats.NumSavedPlaylistsGlobal = statisticsManager.GetSavedPlaylistNum(null, timePeriod); // stats.NumSavedPlaylists = statisticsManager.GetSavedPlaylistNum(app, timePeriod); // stats.NumGeneratedPlaylistsGlobal = statisticsManager.GetGeneratedPlaylistNum(null, timePeriod); // stats.NumGeneratedPlaylists = statisticsManager.GetGeneratedPlaylistNum(app, timePeriod); // return stats; //} } public class PlaylistWithAttribute { public Contracts.Entities.EditorialPlaylist Playlist { get; set; } public EditorialPlaylistAttributes Attributes { get; set; } } }