Added rank to release.

This commit is contained in:
Steven Hildreth 2019-01-21 18:04:58 -06:00
parent b6c18c6245
commit bf0000cffa
10 changed files with 160 additions and 58 deletions

View file

@ -110,6 +110,9 @@ namespace Roadie.Library.Data
[MaxLength(65535)]
public string URLs { get; set; }
[Column("rank")]
public decimal? Rank { get; set; }
public Release()
{
this.Rating = 0;

View file

@ -53,6 +53,7 @@ namespace Roadie.Library.Models.Releases
public string Profile { get; set; }
public short? Rating { get; set; }
public decimal? Rank { get; set; }
[Required]
public DateTime ReleaseDate { get; set; }

View file

@ -19,6 +19,7 @@ namespace Roadie.Library.Models.Releases
public LibraryStatus? LibraryStatus { get; set; }
public IEnumerable<ReleaseMediaList> Media { get; set; }
public short? Rating { get; set; }
public decimal? Rank { get; set; }
public string ReleaseDate
{
@ -104,6 +105,7 @@ namespace Roadie.Library.Models.Releases
LibraryStatus = release.LibraryStatus,
MediaCount = release.MediaCount,
Rating = release.Rating,
Rank = release.Rank,
ReleaseDateDateTime = release.ReleaseDate,
ReleasePlayUrl = $"{ baseUrl }/play/release/{ release.RoadieId}",
Status = release.Status,

View file

@ -294,11 +294,39 @@ namespace Roadie.Api.Services
};
}
public async Task<OperationResult<bool>> ScanAllCollections(ApplicationUser user, bool isReadOnly = false, bool doPurgeFirst = true)
{
var sw = new Stopwatch();
sw.Start();
var errors = new List<Exception>();
var collections = this.DbContext.Collections.Where(x => x.IsLocked ?? false == false).ToArray();
foreach(var collection in collections)
{
var result = await this.ScanCollection(user, collection.RoadieId, isReadOnly, doPurgeFirst);
if(!result.IsSuccess)
{
errors.AddRange(result.Errors);
}
}
sw.Stop();
this.Logger.LogInformation(string.Format("ScanAllCollections, By User `{0}`", user));
return new OperationResult<bool>
{
IsSuccess = !errors.Any(),
Data = true,
OperationTime = sw.ElapsedMilliseconds,
Errors = errors
};
}
public async Task<OperationResult<bool>> ScanCollection(ApplicationUser user, Guid collectionId, bool isReadOnly = false, bool doPurgeFirst = true)
{
var sw = new Stopwatch();
sw.Start();
CollectionRelease[] crs = new CollectionRelease[0];
var result = new List<PositionAristRelease>();
var errors = new List<Exception>();
var collection = this.DbContext.Collections.FirstOrDefault(x => x.RoadieId == collectionId);
@ -311,7 +339,7 @@ namespace Roadie.Api.Services
{
if (doPurgeFirst)
{
var crs = this.DbContext.CollectionReleases.Where(x => x.CollectionId == collection.Id).ToArray();
crs = this.DbContext.CollectionReleases.Where(x => x.CollectionId == collection.Id).ToArray();
this.DbContext.CollectionReleases.RemoveRange(crs);
await this.DbContext.SaveChangesAsync();
}
@ -394,6 +422,12 @@ namespace Roadie.Api.Services
collection.Status = Statuses.Complete;
}
await this.DbContext.SaveChangesAsync();
foreach (var cr in crs)
{
await this.UpdateReleaseRank(cr.ReleaseId);
}
this.CacheManager.ClearRegion(collection.CacheRegion);
}
}
@ -447,6 +481,7 @@ namespace Roadie.Api.Services
try
{
var result = await this.ReleaseFactory.ScanReleaseFolder(release.RoadieId, this.Configuration.LibraryFolder, isReadOnly, release);
await this.UpdateReleaseRank(release.Id);
this.CacheManager.ClearRegion(release.CacheRegion);
}
catch (Exception ex)

View file

@ -16,14 +16,16 @@ namespace Roadie.Api.Services
Task<OperationResult<bool>> DoInitialSetup(ApplicationUser user, UserManager<ApplicationUser> userManager);
Task<OperationResult<bool>> ScanAllCollections(ApplicationUser user, bool isReadOnly = false, bool doPurgeFirst = true);
Task<OperationResult<bool>> ScanArtist(ApplicationUser user, Guid artistId, bool isReadOnly = false);
Task<OperationResult<bool>> ScanCollection(ApplicationUser user, Guid collectionId, bool isReadOnly = false, bool doPurgeFirst = true);
Task<OperationResult<bool>> ScanInboundFolder(ApplicationUser user, bool isReadOnly = false);
Task<OperationResult<bool>> ScanLibraryFolder(ApplicationUser user, bool isReadOnly = false);
Task<OperationResult<bool>> ScanRelease(ApplicationUser user, Guid releaseId, bool isReadOnly = false);
Task<OperationResult<bool>> ScanCollection(ApplicationUser user, Guid collectionId, bool isReadOnly = false, bool doPurgeFirst = true);
}
}

View file

@ -254,6 +254,7 @@ namespace Roadie.Api.Services
LibraryStatus = r.LibraryStatus,
MediaCount = r.MediaCount,
Rating = r.Rating,
Rank = r.Rank,
ReleaseDateDateTime = r.ReleaseDate,
ReleasePlayUrl = $"{ this.HttpContext.BaseUrl }/play/release/{ r.RoadieId}",
Status = r.Status,
@ -470,6 +471,58 @@ namespace Roadie.Api.Services
});
}
public async Task<OperationResult<bool>> MergeReleases(User user, Guid releaseToMergeId, Guid releaseToMergeIntoId, bool addAsMedia)
{
var sw = new Stopwatch();
sw.Start();
var errors = new List<Exception>();
var releaseToMerge = this.DbContext.Releases
.Include(x => x.Artist)
.Include(x => x.Genres)
.Include("Genres.Genre")
.Include(x => x.Medias)
.Include("Medias.Tracks")
.Include("Medias.Tracks.TrackArtist")
.FirstOrDefault(x => x.RoadieId == releaseToMergeId);
if (releaseToMerge == null)
{
this.Logger.LogWarning("MergeReleases Unknown Release [{0}]", releaseToMergeId);
return new OperationResult<bool>(true, string.Format("Release Not Found [{0}]", releaseToMergeId));
}
var releaseToMergeInfo = this.DbContext.Releases
.Include(x => x.Artist)
.Include(x => x.Genres)
.Include("Genres.Genre")
.Include(x => x.Medias)
.Include("Medias.Tracks")
.Include("Medias.Tracks.TrackArtist")
.FirstOrDefault(x => x.RoadieId == releaseToMergeIntoId);
if (releaseToMergeInfo == null)
{
this.Logger.LogWarning("MergeReleases Unknown Release [{0}]", releaseToMergeIntoId);
return new OperationResult<bool>(true, string.Format("Release Not Found [{0}]", releaseToMergeIntoId));
}
try
{
await this.ReleaseFactory.MergeReleases(releaseToMerge, releaseToMergeInfo, addAsMedia);
}
catch (Exception ex)
{
this.Logger.LogError(ex);
errors.Add(ex);
}
sw.Stop();
this.Logger.LogInformation("MergeReleases Release `{0}` Merged Into Release `{1}`, By User `{2}`", releaseToMerge, releaseToMergeInfo, user);
return new OperationResult<bool>
{
IsSuccess = !errors.Any(),
Data = !errors.Any(),
OperationTime = sw.ElapsedMilliseconds,
Errors = errors
};
}
public Task<FileOperationResult<byte[]>> ReleaseZipped(User roadieUser, Guid id)
{
var release = this.GetRelease(id);
@ -671,59 +724,6 @@ namespace Roadie.Api.Services
};
}
public async Task<OperationResult<bool>> MergeReleases(User user, Guid releaseToMergeId, Guid releaseToMergeIntoId, bool addAsMedia)
{
var sw = new Stopwatch();
sw.Start();
var errors = new List<Exception>();
var releaseToMerge = this.DbContext.Releases
.Include(x => x.Artist)
.Include(x => x.Genres)
.Include("Genres.Genre")
.Include(x => x.Medias)
.Include("Medias.Tracks")
.Include("Medias.Tracks.TrackArtist")
.FirstOrDefault(x => x.RoadieId == releaseToMergeId);
if (releaseToMerge == null)
{
this.Logger.LogWarning("MergeReleases Unknown Release [{0}]", releaseToMergeId);
return new OperationResult<bool>(true, string.Format("Release Not Found [{0}]", releaseToMergeId));
}
var releaseToMergeInfo = this.DbContext.Releases
.Include(x => x.Artist)
.Include(x => x.Genres)
.Include("Genres.Genre")
.Include(x => x.Medias)
.Include("Medias.Tracks")
.Include("Medias.Tracks.TrackArtist")
.FirstOrDefault(x => x.RoadieId == releaseToMergeIntoId);
if (releaseToMergeInfo == null)
{
this.Logger.LogWarning("MergeReleases Unknown Release [{0}]", releaseToMergeIntoId);
return new OperationResult<bool>(true, string.Format("Release Not Found [{0}]", releaseToMergeIntoId));
}
try
{
await this.ReleaseFactory.MergeReleases(releaseToMerge, releaseToMergeInfo, addAsMedia);
}
catch (Exception ex)
{
this.Logger.LogError(ex);
errors.Add(ex);
}
sw.Stop();
this.Logger.LogInformation("MergeReleases Release `{0}` Merged Into Release `{1}`, By User `{2}`", releaseToMerge, releaseToMergeInfo, user);
return new OperationResult<bool>
{
IsSuccess = !errors.Any(),
Data = !errors.Any(),
OperationTime = sw.ElapsedMilliseconds,
Errors = errors
};
}
public async Task<OperationResult<Library.Models.Image>> UploadReleaseImage(User user, Guid id, IFormFile file)
{
var bytes = new byte[0];

View file

@ -420,7 +420,7 @@ namespace Roadie.Api.Services
}
release.LastUpdated = now;
await this.DbContext.SaveChangesAsync();
await this.UpdateReleaseRank(release.Id);
this.CacheManager.ClearRegion(user.CacheRegion);
this.CacheManager.ClearRegion(release.CacheRegion);
this.CacheManager.ClearRegion(release.Artist.CacheRegion);
@ -475,6 +475,7 @@ namespace Roadie.Api.Services
}
track.LastUpdated = now;
await this.DbContext.SaveChangesAsync();
await this.UpdateReleaseRank(track.ReleaseMedia.Release.Id);
this.CacheManager.ClearRegion(user.CacheRegion);
this.CacheManager.ClearRegion(track.CacheRegion);
@ -811,6 +812,11 @@ namespace Roadie.Api.Services
var release = this.DbContext.Releases.FirstOrDefault(x => x.Id == releaseId);
if (release != null)
{
release.PlayedCount = (from t in this.DbContext.Tracks
join rm in this.DbContext.ReleaseMedias on t.ReleaseMediaId equals rm.Id
where rm.ReleaseId == releaseId
where t.PlayedCount.HasValue
select t).Sum(x => x.PlayedCount);
release.Duration = (from t in this.DbContext.Tracks
join rm in this.DbContext.ReleaseMedias on t.ReleaseMediaId equals rm.Id
where rm.ReleaseId == releaseId
@ -820,6 +826,46 @@ namespace Roadie.Api.Services
}
}
/// <summary>
/// Update Relase Rank
/// Release Rank Calculation = Average of Track User Ratings + (User Rating of Release / Release Track Count) + Collection Rank Value
/// </summary>
protected async Task UpdateReleaseRank(int releaseId)
{
var release = this.DbContext.Releases.FirstOrDefault(x => x.Id == releaseId);
if (release != null)
{
var releaseTrackAverage = (from t in this.DbContext.Tracks
join rm in this.DbContext.ReleaseMedias on t.ReleaseMediaId equals rm.Id
join ut in this.DbContext.UserTracks on t.Id equals ut.TrackId
where rm.ReleaseId == releaseId
select (double?)ut.Rating).ToArray().Average(x => x);
var releaseUserRatingRank = release.Rating > 0 ? (decimal?)release.Rating / (decimal?)release.TrackCount : 0;
var collectionsWithRelease = (from c in this.DbContext.Collections
join cr in this.DbContext.CollectionReleases on c.Id equals cr.CollectionId
where cr.ReleaseId == release.Id
select new
{
c.CollectionCount,
cr.ListNumber
});
decimal releaseCollectionRank = 0;
foreach (var collectionWithRelease in collectionsWithRelease)
{
var rank = (decimal)((collectionWithRelease.CollectionCount * .01) - ((collectionWithRelease.ListNumber - 1) * .01));
releaseCollectionRank += rank;
}
release.Rank = SafeParser.ToNumber<decimal>(releaseTrackAverage) + releaseUserRatingRank + releaseCollectionRank;
await this.DbContext.SaveChangesAsync();
this.CacheManager.ClearRegion(release.CacheRegion);
}
}
private Image MakeImage(Guid id, string type, int? width, int? height, string caption = null, bool includeCachebuster = false)
{
if (width.HasValue && height.HasValue && (width.Value != this.Configuration.ThumbnailImageSize.Width || height.Value != this.Configuration.ThumbnailImageSize.Height))

View file

@ -324,6 +324,7 @@ namespace Roadie.Api.Services
LibraryStatus = r.LibraryStatus,
MediaCount = r.MediaCount,
Rating = r.Rating,
Rank = r.Rank,
ReleaseDateDateTime = r.ReleaseDate,
ReleasePlayUrl = $"{ this.HttpContext.BaseUrl }/play/release/{ r.RoadieId}",
Status = r.Status,

View file

@ -84,6 +84,18 @@ namespace Roadie.Api.Controllers
return Ok(result);
}
[HttpPost("scan/collection/rescanall")]
[ProducesResponseType(200)]
public async Task<IActionResult> ScanAllCollections()
{
var result = await this.AdminService.ScanAllCollections(await this.UserManager.GetUserAsync(User));
if (!result.IsSuccess)
{
return StatusCode((int)HttpStatusCode.InternalServerError);
}
return Ok(result);
}
[HttpPost("scan/collection/{id}")]
[ProducesResponseType(200)]
public async Task<IActionResult> ScanCollection(Guid id)

View file

@ -3,7 +3,7 @@
"Roadie.Api": {
"commandName": "Project",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
"ASPNETCORE_ENVIRONMENT": "Production"
},
"applicationUrl": "http://localhost:5123/"
}