2018-11-14 23:18:02 +00:00
|
|
|
|
using Microsoft.Extensions.Logging;
|
2018-11-12 00:28:37 +00:00
|
|
|
|
using Roadie.Library;
|
|
|
|
|
using Roadie.Library.Caching;
|
|
|
|
|
using Roadie.Library.Configuration;
|
2019-11-17 14:10:17 +00:00
|
|
|
|
using Roadie.Library.Data.Context;
|
2018-11-12 00:28:37 +00:00
|
|
|
|
using Roadie.Library.Encoding;
|
|
|
|
|
using Roadie.Library.Models.Statistics;
|
|
|
|
|
using Roadie.Library.Utility;
|
|
|
|
|
using System;
|
2018-12-09 03:16:05 +00:00
|
|
|
|
using System.Collections.Generic;
|
2018-11-12 00:28:37 +00:00
|
|
|
|
using System.Diagnostics;
|
2018-12-09 03:16:05 +00:00
|
|
|
|
using System.Linq;
|
2018-11-12 00:28:37 +00:00
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
|
|
|
|
namespace Roadie.Api.Services
|
|
|
|
|
{
|
|
|
|
|
public class StatisticsService : ServiceBase, IStatisticsService
|
|
|
|
|
{
|
|
|
|
|
public StatisticsService(IRoadieSettings configuration,
|
2019-06-30 22:14:36 +00:00
|
|
|
|
IHttpEncoder httpEncoder,
|
|
|
|
|
IHttpContext httpContext,
|
2019-11-17 14:10:17 +00:00
|
|
|
|
IRoadieDbContext context,
|
2019-06-30 22:14:36 +00:00
|
|
|
|
ICacheManager cacheManager,
|
|
|
|
|
ILogger<StatisticsService> logger)
|
2018-11-12 00:28:37 +00:00
|
|
|
|
: base(configuration, httpEncoder, context, cacheManager, logger, httpContext)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-07 03:16:33 +00:00
|
|
|
|
public Task<OperationResult<LibraryStats>> LibraryStatistics()
|
2018-11-12 00:28:37 +00:00
|
|
|
|
{
|
|
|
|
|
LibraryStats result = null;
|
|
|
|
|
var sw = new Stopwatch();
|
|
|
|
|
sw.Start();
|
2019-03-17 02:24:46 +00:00
|
|
|
|
try
|
2018-11-12 00:28:37 +00:00
|
|
|
|
{
|
2019-07-04 15:50:31 +00:00
|
|
|
|
result = new LibraryStats
|
2019-03-17 02:24:46 +00:00
|
|
|
|
{
|
2019-07-04 15:50:31 +00:00
|
|
|
|
UserCount = DbContext.Users.Count(),
|
|
|
|
|
CollectionCount = DbContext.Collections.Count(),
|
2019-09-30 01:53:13 +00:00
|
|
|
|
PlaylistCount = DbContext.Playlists.Count(),
|
2019-07-04 15:50:31 +00:00
|
|
|
|
ArtistCount = DbContext.Artists.Count(),
|
|
|
|
|
LabelCount = DbContext.Labels.Count(),
|
|
|
|
|
ReleaseCount = DbContext.Releases.Count(),
|
|
|
|
|
ReleaseMediaCount = DbContext.ReleaseMedias.Count()
|
|
|
|
|
};
|
|
|
|
|
result.PlayedCount = DbContext.UserTracks.Sum(x => x.PlayedCount);
|
|
|
|
|
var tracks = DbContext.Tracks.Where(x => x.Hash != null);
|
|
|
|
|
result.TrackCount = tracks.Count();
|
|
|
|
|
result.TotalTrackDuration = tracks.Sum(x => (long?)x.Duration);
|
|
|
|
|
result.TotalTrackSize = tracks.Sum(x => (long?)x.FileSize);
|
2019-06-30 22:14:36 +00:00
|
|
|
|
var lastScan = DbContext.ScanHistories.OrderByDescending(x => x.CreatedDate).FirstOrDefault();
|
2019-07-04 15:50:31 +00:00
|
|
|
|
result.LastScan = lastScan?.CreatedDate;
|
2019-03-17 02:24:46 +00:00
|
|
|
|
sw.Stop();
|
2018-11-12 00:28:37 +00:00
|
|
|
|
}
|
2019-03-17 02:24:46 +00:00
|
|
|
|
catch (Exception ex)
|
2018-12-09 03:16:05 +00:00
|
|
|
|
{
|
2019-06-30 22:14:36 +00:00
|
|
|
|
Logger.LogError(ex);
|
2018-12-09 03:16:05 +00:00
|
|
|
|
}
|
2019-06-30 22:14:36 +00:00
|
|
|
|
|
2019-07-07 03:16:33 +00:00
|
|
|
|
return Task.FromResult(new OperationResult<LibraryStats>
|
2018-11-12 00:28:37 +00:00
|
|
|
|
{
|
|
|
|
|
OperationTime = sw.ElapsedMilliseconds,
|
2019-07-07 03:16:33 +00:00
|
|
|
|
IsSuccess = result != null,
|
2018-11-12 00:28:37 +00:00
|
|
|
|
Data = result
|
2019-07-07 03:16:33 +00:00
|
|
|
|
});
|
2018-11-12 00:28:37 +00:00
|
|
|
|
}
|
2019-01-08 22:40:26 +00:00
|
|
|
|
|
2019-11-17 20:02:19 +00:00
|
|
|
|
public Task<OperationResult<IEnumerable<DateAndCount>>> ArtistsByDate()
|
|
|
|
|
{
|
|
|
|
|
var sw = new Stopwatch();
|
|
|
|
|
sw.Start();
|
|
|
|
|
var result = new List<DateAndCount>();
|
|
|
|
|
var dateInfos = (from r in DbContext.Artists
|
|
|
|
|
orderby r.CreatedDate
|
|
|
|
|
select r.CreatedDate)
|
|
|
|
|
.ToArray()
|
|
|
|
|
.GroupBy(x => x.ToString("yyyy-MM-dd"))
|
|
|
|
|
.Select(x => new
|
|
|
|
|
{
|
|
|
|
|
date = x.Key,
|
|
|
|
|
count = x.Count()
|
|
|
|
|
});
|
|
|
|
|
foreach (var dateInfo in dateInfos)
|
|
|
|
|
{
|
|
|
|
|
result.Add(new DateAndCount
|
|
|
|
|
{
|
|
|
|
|
Date = dateInfo.date,
|
|
|
|
|
Count = dateInfo.count
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
sw.Stop();
|
|
|
|
|
return Task.FromResult(new OperationResult<IEnumerable<DateAndCount>>
|
|
|
|
|
{
|
|
|
|
|
OperationTime = sw.ElapsedMilliseconds,
|
|
|
|
|
IsSuccess = result != null,
|
|
|
|
|
Data = result
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-08 22:40:26 +00:00
|
|
|
|
public Task<OperationResult<IEnumerable<DateAndCount>>> ReleasesByDate()
|
|
|
|
|
{
|
|
|
|
|
var sw = new Stopwatch();
|
|
|
|
|
sw.Start();
|
|
|
|
|
var result = new List<DateAndCount>();
|
2019-07-04 15:50:31 +00:00
|
|
|
|
var dateInfos = (from r in DbContext.Releases
|
|
|
|
|
orderby r.CreatedDate
|
2019-08-03 22:59:20 +00:00
|
|
|
|
select r.CreatedDate)
|
|
|
|
|
.ToArray()
|
|
|
|
|
.GroupBy(x => x.ToString("yyyy-MM-dd"))
|
|
|
|
|
.Select(x => new
|
2019-07-04 15:50:31 +00:00
|
|
|
|
{
|
2019-08-03 22:59:20 +00:00
|
|
|
|
date = x.Key,
|
|
|
|
|
count = x.Count()
|
2019-07-04 15:50:31 +00:00
|
|
|
|
});
|
|
|
|
|
foreach (var dateInfo in dateInfos)
|
2019-01-08 22:40:26 +00:00
|
|
|
|
{
|
2019-07-04 15:50:31 +00:00
|
|
|
|
result.Add(new DateAndCount
|
2019-01-08 22:40:26 +00:00
|
|
|
|
{
|
2019-07-04 15:50:31 +00:00
|
|
|
|
Date = dateInfo.date,
|
|
|
|
|
Count = dateInfo.count
|
|
|
|
|
});
|
2019-01-08 22:40:26 +00:00
|
|
|
|
}
|
|
|
|
|
sw.Stop();
|
|
|
|
|
return Task.FromResult(new OperationResult<IEnumerable<DateAndCount>>
|
|
|
|
|
{
|
|
|
|
|
OperationTime = sw.ElapsedMilliseconds,
|
2019-07-04 15:50:31 +00:00
|
|
|
|
IsSuccess = result != null,
|
2019-01-08 22:40:26 +00:00
|
|
|
|
Data = result
|
|
|
|
|
});
|
|
|
|
|
}
|
2019-11-17 20:02:19 +00:00
|
|
|
|
|
|
|
|
|
public Task<OperationResult<IEnumerable<DateAndCount>>> SongsPlayedByUser()
|
|
|
|
|
{
|
|
|
|
|
var sw = new Stopwatch();
|
|
|
|
|
sw.Start();
|
|
|
|
|
var result = new List<DateAndCount>();
|
|
|
|
|
var dateInfos = (from r in DbContext.UserTracks
|
|
|
|
|
join u in DbContext.Users on r.UserId equals u.Id
|
|
|
|
|
select new { u.UserName, r.PlayedCount })
|
|
|
|
|
.ToArray()
|
|
|
|
|
.GroupBy(x => x.UserName)
|
|
|
|
|
.Select(x => new
|
|
|
|
|
{
|
|
|
|
|
username = x.Key,
|
|
|
|
|
count = x.Count()
|
|
|
|
|
});
|
|
|
|
|
foreach (var dateInfo in dateInfos)
|
|
|
|
|
{
|
|
|
|
|
result.Add(new DateAndCount
|
|
|
|
|
{
|
|
|
|
|
Date = dateInfo.username,
|
|
|
|
|
Count = dateInfo.count
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
sw.Stop();
|
|
|
|
|
return Task.FromResult(new OperationResult<IEnumerable<DateAndCount>>
|
|
|
|
|
{
|
|
|
|
|
OperationTime = sw.ElapsedMilliseconds,
|
|
|
|
|
IsSuccess = result != null,
|
|
|
|
|
Data = result
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Task<OperationResult<IEnumerable<DateAndCount>>> SongsPlayedByDate()
|
|
|
|
|
{
|
|
|
|
|
var sw = new Stopwatch();
|
|
|
|
|
sw.Start();
|
|
|
|
|
var result = new List<DateAndCount>();
|
|
|
|
|
var dateInfos = (from r in DbContext.UserTracks
|
|
|
|
|
orderby r.LastPlayed
|
|
|
|
|
select r.LastPlayed ?? r.CreatedDate)
|
|
|
|
|
.ToArray()
|
|
|
|
|
.GroupBy(x => x.ToString("yyyy-MM-dd"))
|
|
|
|
|
.Select(x => new
|
|
|
|
|
{
|
|
|
|
|
date = x.Key,
|
|
|
|
|
count = x.Count()
|
|
|
|
|
});
|
|
|
|
|
foreach (var dateInfo in dateInfos)
|
|
|
|
|
{
|
|
|
|
|
result.Add(new DateAndCount
|
|
|
|
|
{
|
|
|
|
|
Date = dateInfo.date,
|
|
|
|
|
Count = dateInfo.count
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
sw.Stop();
|
|
|
|
|
return Task.FromResult(new OperationResult<IEnumerable<DateAndCount>>
|
|
|
|
|
{
|
|
|
|
|
OperationTime = sw.ElapsedMilliseconds,
|
|
|
|
|
IsSuccess = result != null,
|
|
|
|
|
Data = result
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Task<OperationResult<IEnumerable<DateAndCount>>> ReleasesByDecade()
|
|
|
|
|
{
|
|
|
|
|
var sw = new Stopwatch();
|
|
|
|
|
sw.Start();
|
|
|
|
|
var result = new List<DateAndCount>();
|
|
|
|
|
var decadeInfos = (from r in DbContext.Releases
|
|
|
|
|
orderby r.ReleaseDate
|
|
|
|
|
select r.ReleaseDate ?? r.CreatedDate)
|
|
|
|
|
.ToArray()
|
|
|
|
|
.GroupBy(x => x.ToString("yyyy"))
|
|
|
|
|
.Select(x => new
|
|
|
|
|
{
|
|
|
|
|
year = SafeParser.ToNumber<int>(x.Key),
|
|
|
|
|
count = x.Count()
|
|
|
|
|
});
|
2020-01-28 03:44:13 +00:00
|
|
|
|
if (decadeInfos?.Any() == true)
|
2019-11-17 20:02:19 +00:00
|
|
|
|
{
|
2020-01-28 03:44:13 +00:00
|
|
|
|
const int decadeInterval = 10;
|
2019-11-20 22:49:49 +00:00
|
|
|
|
var startingDecade = (decadeInfos.Min(x => x.year) / 10) * 10;
|
|
|
|
|
var endingDecade = (decadeInfos.Max(x => x.year) / 10) * 10;
|
|
|
|
|
for (int decade = startingDecade; decade <= endingDecade; decade += decadeInterval)
|
2019-11-17 20:02:19 +00:00
|
|
|
|
{
|
2019-11-20 22:49:49 +00:00
|
|
|
|
var endOfDecade = decade + 9;
|
|
|
|
|
var count = decadeInfos.Where(x => x.year >= decade && x.year <= endOfDecade).Sum(x => x.count);
|
|
|
|
|
if (count > 0)
|
2019-11-17 20:02:19 +00:00
|
|
|
|
{
|
2019-11-20 22:49:49 +00:00
|
|
|
|
result.Add(new DateAndCount
|
|
|
|
|
{
|
|
|
|
|
Date = decade.ToString(),
|
|
|
|
|
Count = count
|
|
|
|
|
});
|
|
|
|
|
}
|
2019-11-17 20:02:19 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
sw.Stop();
|
|
|
|
|
return Task.FromResult(new OperationResult<IEnumerable<DateAndCount>>
|
|
|
|
|
{
|
|
|
|
|
OperationTime = sw.ElapsedMilliseconds,
|
|
|
|
|
IsSuccess = result != null,
|
|
|
|
|
Data = result
|
|
|
|
|
});
|
|
|
|
|
}
|
2018-11-12 00:28:37 +00:00
|
|
|
|
}
|
2018-11-14 23:18:02 +00:00
|
|
|
|
}
|