Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/playground limits #46

Merged
merged 2 commits into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ public record SongsByChordsRequest : PagedRequestBase

public int MinRating { get; init; } = 70;

public int SongsPerPage { get; init; } = 100;

[JsonConverter(typeof(JsonStringEnumConverter))]
public SongsByChordsRequestOrdering Ordering { get; init; } = SongsByChordsRequestOrdering.ByRating;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,4 @@ public record SongsByHeaderRequest : PagedRequestBase
public required string Query { get; init; }

public int MinRating { get; init; } = 70;

public int SongsPerPage { get; init; } = 100;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ namespace HarmonyDB.Index.Api.Model.VExternal1;
public record PagedRequestBase
{
public int PageNumber { get; init; } = 1;
public int ItemsPerPage { get; init; } = 100;
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ public record LoopsRequest : PagedRequestBase

public RequestScaleFilter DetectedScaleFilter { get; init; } = RequestScaleFilter.Any;

public int LoopsPerPage { get; init; } = 100;

[JsonConverter(typeof(JsonStringEnumConverter))]
public LoopsRequestOrdering Ordering { get; init; } = LoopsRequestOrdering.SuccessionsDesc;
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ public record SongsRequest : PagedRequestBase
public SongsRequestCorrectDetectionFilter CorrectDetectionFilter { get; init; } = SongsRequestCorrectDetectionFilter.Any;

public SongsRequestKnownTonalityFilter KnownTonalityFilter { get; init; } = SongsRequestKnownTonalityFilter.Any;

public int SongsPerPage { get; init; } = 100;

[JsonConverter(typeof(JsonStringEnumConverter))]
public SongsRequestOrdering Ordering { get; init; } = SongsRequestOrdering.TonalityConfidenceDesc;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
? (h, coverage).OnceAsNullable()
: null)
.Where(x => x.HasValue)
.Select(x => x.Value)

Check warning on line 77 in HarmonyDB.Index/HarmonyDB.Index.Api/Functions/VExternal1/SongsByChords.cs

View workflow job for this annotation

GitHub Actions / build

Nullable value type may be null.
.Where(x => x.coverage >= request.MinCoverage && x.h.Rating >= request.MinRating)
.OrderByDescending<(IndexHeader h, float coverage), int>(request.Ordering switch
{
Expand All @@ -90,14 +90,14 @@

return new()
{
Songs = results.Skip((request.PageNumber - 1) * request.SongsPerPage).Take(request.SongsPerPage).Select(x => new SongsByChordsResponseSong
Songs = results.Skip((request.PageNumber - 1) * request.ItemsPerPage).Take(request.ItemsPerPage).Select(x => new SongsByChordsResponseSong
{
Header = x.h,
Coverage = x.coverage,
PredictedTonalityIndex = tonalitiesCache.Songs.GetValueOrDefault(x.h.ExternalId)?.TonalityProbabilities.ToLinear().GetPredictedTonality().ToIndex(),
}).ToList(),
Total = results.Count,
TotalPages = results.Count / request.SongsPerPage + (results.Count % request.SongsPerPage == 0 ? 0 : 1),
TotalPages = results.Count / request.ItemsPerPage + (results.Count % request.ItemsPerPage == 0 ? 0 : 1),
CurrentPageNumber = request.PageNumber,
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,12 @@ protected override async Task<SongsByHeaderResponse> Execute(SongsByHeaderReques
return new()
{
Songs = results
.Skip((request.PageNumber - 1) * request.SongsPerPage)
.Take(request.SongsPerPage)
.Skip((request.PageNumber - 1) * request.ItemsPerPage)
.Take(request.ItemsPerPage)
.Select(x => new SongsByHeaderResponseSong(x, tonalitiesCache.Songs.GetValueOrDefault(x.ExternalId)?.TonalityProbabilities.ToLinear().GetPredictedTonality().ToIndex()))
.ToList(),
Total = results.Count,
TotalPages = results.Count / request.SongsPerPage + (results.Count % request.SongsPerPage == 0 ? 0 : 1),
TotalPages = results.Count / request.ItemsPerPage + (results.Count % request.ItemsPerPage == 0 ? 0 : 1),
CurrentPageNumber = request.PageNumber,
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,9 @@ protected override async Task<LoopsResponse> Execute(LoopsRequest request)
return new()
{
Total = loops.Count,
TotalPages = loops.Count / request.LoopsPerPage + (loops.Count % request.LoopsPerPage == 0 ? 0 : 1),
TotalPages = loops.Count / request.ItemsPerPage + (loops.Count % request.ItemsPerPage == 0 ? 0 : 1),
CurrentPageNumber = request.PageNumber,
Loops = orderedLoops.Skip((request.PageNumber - 1) * request.LoopsPerPage).Take(request.LoopsPerPage).ToList(),
Loops = orderedLoops.Skip((request.PageNumber - 1) * request.ItemsPerPage).Take(request.ItemsPerPage).ToList(),
Distributions = new()
{
TotalSongs = loops.GetPercentiles(x => x.TotalSongs),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,9 @@ protected override async Task<SongsResponse> Execute(SongsRequest request)
return new()
{
Total = songs.Count,
TotalPages = songs.Count / request.SongsPerPage + (songs.Count % request.SongsPerPage == 0 ? 0 : 1),
TotalPages = songs.Count / request.ItemsPerPage + (songs.Count % request.ItemsPerPage == 0 ? 0 : 1),
CurrentPageNumber = request.PageNumber,
Songs = orderedSongs.Skip((request.PageNumber - 1) * request.SongsPerPage).Take(request.SongsPerPage).ToList(),
Songs = orderedSongs.Skip((request.PageNumber - 1) * request.ItemsPerPage).Take(request.ItemsPerPage).ToList(),
Distributions = new()
{
Rating = songs.GetPercentiles(x => x.IndexHeader.Rating),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@
using HarmonyDB.Index.Analysis.Models.CompactV1;
using Microsoft.AspNetCore.Localization;
using HarmonyDB.Index.Api.Model.VExternal1;
using HarmonyDB.Index.Api.Model.VExternal1.Main;
using HarmonyDB.Index.Api.Model.VExternal1.Tonalities;
using HarmonyDB.Playground.Web.Models.Home;
using HarmonyDB.Playground.Web.Services;
using OneShelf.Common.Api.Common;

namespace HarmonyDB.Playground.Web.Controllers;
Expand All @@ -33,8 +35,9 @@ public class HomeController : PlaygroundControllerBase
private readonly ChordDataParser _chordDataParser;
private readonly InputParser _inputParser;
private readonly ProgressionsVisualizer _progressionsVisualizer;
private readonly Limiter _limiter;

public HomeController(ILogger<HomeController> logger, IndexApiClient indexApiClient, SourceApiClient sourceApiClient, ProgressionsSearch progressionsSearch, ProgressionsBuilder progressionsBuilder, ChordDataParser chordDataParser, InputParser inputParser, ProgressionsVisualizer progressionsVisualizer, IndexExtractor indexExtractor)
public HomeController(ILogger<HomeController> logger, IndexApiClient indexApiClient, SourceApiClient sourceApiClient, ProgressionsSearch progressionsSearch, ProgressionsBuilder progressionsBuilder, ChordDataParser chordDataParser, InputParser inputParser, ProgressionsVisualizer progressionsVisualizer, IndexExtractor indexExtractor, Limiter limiter)
{
_logger = logger;
_indexApiClient = indexApiClient;
Expand All @@ -45,6 +48,7 @@ public HomeController(ILogger<HomeController> logger, IndexApiClient indexApiCli
_inputParser = inputParser;
_progressionsVisualizer = progressionsVisualizer;
_indexExtractor = indexExtractor;
_limiter = limiter;
}

public IActionResult MyIp()
Expand Down Expand Up @@ -157,7 +161,9 @@ public async Task<IActionResult> SongsByChords([FromQuery]SongsByChordsModel son
ViewBag.Trace = new ApiTraceBag();
}

ViewBag.Response = await _indexApiClient.SongsByChords(songsByChordsModel, ViewBag.Trace);
var response = await _indexApiClient.SongsByChords(songsByChordsModel, ViewBag.Trace);
ViewBag.Response = response;
ViewBag.Limit = _limiter.CheckLimit(songsByChordsModel, response, Limiter.MaxSongs);
}

songsByChordsModel.JustForm = false;
Expand All @@ -183,7 +189,9 @@ public async Task<IActionResult> SongsByHeader([FromQuery]SongsByHeaderModel son
ViewBag.Trace = new ApiTraceBag();
}

ViewBag.Response = await _indexApiClient.SongsByHeader(songsByHeaderModel, ViewBag.Trace);
var response = await _indexApiClient.SongsByHeader(songsByHeaderModel, ViewBag.Trace);
ViewBag.Response = response;
ViewBag.Limit = _limiter.CheckLimit(songsByHeaderModel, response, Limiter.MaxSongs);
}

songsByHeaderModel.JustForm = false;
Expand All @@ -208,7 +216,9 @@ public async Task<IActionResult> Loops([FromQuery] LoopsModel loopsModel)
ViewBag.Trace = new ApiTraceBag();
}

ViewBag.Response = await _indexApiClient.TonalitiesLoops(loopsModel, ViewBag.Trace);
var response = await _indexApiClient.TonalitiesLoops(loopsModel, ViewBag.Trace);
ViewBag.Response = response;
ViewBag.Limit = _limiter.CheckLimit(loopsModel, response, Limiter.MaxProgressions);
}

loopsModel.JustForm = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,22 @@
using HarmonyDB.Index.Api.Model.VExternal1;
using HarmonyDB.Playground.Web.Models.Tonalities;
using OneShelf.Common.Api.Common;
using HarmonyDB.Playground.Web.Models.Home;
using HarmonyDB.Playground.Web.Services;

namespace HarmonyDB.Playground.Web.Controllers;

public class TonalitiesController : PlaygroundControllerBase
{
private readonly ILogger<TonalitiesController> _logger;
private readonly IndexApiClient _indexApiClient;
private readonly Limiter _limiter;

public TonalitiesController(ILogger<TonalitiesController> logger, IndexApiClient indexApiClient)
public TonalitiesController(ILogger<TonalitiesController> logger, IndexApiClient indexApiClient, Limiter limiter)
{
_logger = logger;
_indexApiClient = indexApiClient;
_limiter = limiter;
}

public IActionResult Index()
Expand All @@ -53,7 +57,9 @@ public async Task<IActionResult> Loops(StructureLoopsModel model)
ViewBag.Trace = new ApiTraceBag();
}

ViewBag.Response = await _indexApiClient.TonalitiesLoops(model, ViewBag.Trace);
var response = await _indexApiClient.TonalitiesLoops(model, ViewBag.Trace);
ViewBag.Response = response;
ViewBag.Limit = _limiter.CheckLimit(model, response, Limiter.MaxProgressions);
}

model.JustForm = false;
Expand All @@ -78,7 +84,9 @@ public async Task<IActionResult> Songs(StructureSongsModel model)
ViewBag.Trace = new ApiTraceBag();
}

ViewBag.Response = await _indexApiClient.TonalitiesSongs(model, ViewBag.Trace);
var response = await _indexApiClient.TonalitiesSongs(model, ViewBag.Trace);
ViewBag.Response = response;
ViewBag.Limit = _limiter.CheckLimit(model, response, Limiter.MaxSongs);
}

model.JustForm = false;
Expand Down
2 changes: 2 additions & 0 deletions HarmonyDB.Playground/HarmonyDB.Playground.Web/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using HarmonyDB.Index.Analysis;
using HarmonyDB.Index.Api.Client;
using HarmonyDB.Playground.Web.Models;
using HarmonyDB.Playground.Web.Services;
using HarmonyDB.Source.Api.Client;
using Microsoft.AspNetCore.Localization.Routing;
using Microsoft.AspNetCore.Mvc;
Expand All @@ -26,6 +27,7 @@ public static void Main(string[] args)
.AddIndexApiClient(builder.Configuration)
.AddSourceApiClient(builder.Configuration)
.AddIndexAnalysis()
.AddScoped<Limiter>()
.Configure<PlaygroundOptions>(o => builder.Configuration.GetSection(nameof(PlaygroundOptions)).Bind(o));

const string defaultCulture = "en";
Expand Down
27 changes: 27 additions & 0 deletions HarmonyDB.Playground/HarmonyDB.Playground.Web/Services/Limiter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using HarmonyDB.Index.Api.Model.VExternal1;

namespace HarmonyDB.Playground.Web.Services;

public class Limiter
{
public const int MaxSongs = 300;
public const int MaxProgressions = 200;

public int? CheckLimit(PagedRequestBase request, PagedResponseBase response, int limit)
{
var fromIndex = (request.PageNumber - 1) * request.ItemsPerPage;
var toIndex = request.PageNumber * request.ItemsPerPage - 1;

if (toIndex < limit)
{
return null;
}

if (fromIndex >= response.Total - limit)
{
return null;
}

return limit;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
@ViewLocalizer["Min total successions"]: @Html.TextBoxFor(x => x.MinTotalSuccessions)
</p>
<p>
@ViewLocalizer["Loops Per Page"]: @Html.TextBoxFor(x => x.LoopsPerPage)
@ViewLocalizer["Loops Per Page"]: @Html.TextBoxFor(x => x.ItemsPerPage)
</p>
<p>
@ViewLocalizer["Scale"]:
Expand All @@ -66,8 +66,14 @@

@await Html.PartialAsync("Paging", Model)

<table class="table table-bordered table-sm">
<thead>
@if (ViewBag.Limit != null)
{
@await Html.PartialAsync("Limit", (int)ViewBag.Limit)
}
else
{
<table class="table table-bordered table-sm">
<thead>
<tr class="fw-bold">
<td>@ViewLocalizer["Progression"]</td>
<td>@ViewLocalizer["Degrees"]</td>
Expand All @@ -78,27 +84,28 @@
<td class="my-vertical">@ViewLocalizer["Total Occurrences"]</td>
<td class="my-vertical">@ViewLocalizer["Total Successions"]</td>
</tr>
</thead>
@foreach (var loop in response.Loops)
{
var predicted = loop.Probabilities.GetPredictedTonality();
var secondPredicted = loop.Probabilities.GetSecondPredictedTonality(out var secondConfidence);
<tr>
<td>@Html.ActionLink(loop.Normalized.GetTitle(predicted), "SongsByChords", new SongsByChordsModel { Query = loop.Normalized.GetTitle(predicted, true), JustForm = true })</td>
<td>@loop.Normalized.GetFunctionsTitle(predicted)</td>
<td class="fw-bold">@predicted.ToLoopTonalityTitle(predicted)</td>
<td class="text-end">@loop.Probabilities.TonalityConfidence().ToString("P0")</td>
<td class="fw-bold">@secondPredicted.ToLoopTonalityTitle(predicted)</td>
<td class="text-end">@secondConfidence.ToString("P0")</td>
<td>@loop.Normalized.GetTitle(secondPredicted)</td>
<td>@loop.Normalized.GetFunctionsTitle(secondPredicted)</td>
<td class="text-end">@loop.Length</td>
<td class="text-end">@loop.TotalSongs.ToString("N0")</td>
<td class="text-end">@loop.TotalOccurrences.ToString("N0")</td>
<td class="text-end">@loop.TotalSuccessions.ToString("N0")</td>
</tr>
}
</table>
</thead>
@foreach (var loop in response.Loops)
{
var predicted = loop.Probabilities.GetPredictedTonality();
var secondPredicted = loop.Probabilities.GetSecondPredictedTonality(out var secondConfidence);
<tr>
<td>@Html.ActionLink(loop.Normalized.GetTitle(predicted), "SongsByChords", new SongsByChordsModel { Query = loop.Normalized.GetTitle(predicted, true), JustForm = true })</td>
<td>@loop.Normalized.GetFunctionsTitle(predicted)</td>
<td class="fw-bold">@predicted.ToLoopTonalityTitle(predicted)</td>
<td class="text-end">@loop.Probabilities.TonalityConfidence().ToString("P0")</td>
<td class="fw-bold">@secondPredicted.ToLoopTonalityTitle(predicted)</td>
<td class="text-end">@secondConfidence.ToString("P0")</td>
<td>@loop.Normalized.GetTitle(secondPredicted)</td>
<td>@loop.Normalized.GetFunctionsTitle(secondPredicted)</td>
<td class="text-end">@loop.Length</td>
<td class="text-end">@loop.TotalSongs.ToString("N0")</td>
<td class="text-end">@loop.TotalOccurrences.ToString("N0")</td>
<td class="text-end">@loop.TotalSuccessions.ToString("N0")</td>
</tr>
}
</table>
}

@await Html.PartialAsync("Paging", Model)
}
Expand Down
Loading
Loading