past page QOL

This commit is contained in:
Andy Pack 2022-11-19 11:47:23 +00:00
parent 20232f4abe
commit 99cb615161
Signed by: sarsoo
GPG Key ID: A55BA3536A5E0ED7
7 changed files with 120 additions and 19 deletions

View File

@ -1,6 +1,8 @@
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using IF.Lastfm.Core.Objects;
using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Selector.Cache; using Selector.Cache;
@ -49,6 +51,16 @@ namespace Selector.Web.Hubs
} }
private static IEnumerable<string> AlbumSuffixes = new[]
{
" (Deluxe)",
" (Deluxe Edition)",
" (Special)",
" (Special Edition)",
" (Expanded)",
" (Expanded Edition)",
};
public async Task OnSubmitted(PastParams param) public async Task OnSubmitted(PastParams param)
{ {
param.Track = string.IsNullOrWhiteSpace(param.Track) ? null : param.Track; param.Track = string.IsNullOrWhiteSpace(param.Track) ? null : param.Track;
@ -67,38 +79,49 @@ namespace Selector.Web.Hubs
to: to to: to
).ToArray(); ).ToArray();
Parallel.ForEach(listenQuery, (listen) =>
{
foreach (var suffix in AlbumSuffixes)
{
if (listen.AlbumName.EndsWith(suffix, StringComparison.OrdinalIgnoreCase))
{
listen.AlbumName = listen.AlbumName.Substring(0, listen.AlbumName.Length - suffix.Length);
}
}
});
var artistGrouped = listenQuery var artistGrouped = listenQuery
.GroupBy(x => x.ArtistName) .GroupBy(x => x.ArtistName.ToLowerInvariant())
.Select(x => (x.Key, x.Count())) .Select(x => (x.Key, x.Count()))
.OrderByDescending(x => x.Item2) .OrderByDescending(x => x.Item2)
.Take(20) .Take(pastOptions.Value.RankingCount)
.ToArray(); .ToArray();
var albumGrouped = listenQuery var albumGrouped = listenQuery
.GroupBy(x => (x.AlbumName, x.ArtistName)) .GroupBy(x => (x.AlbumName.ToLowerInvariant(), x.ArtistName.ToLowerInvariant()))
.Select(x => (x.Key, x.Count())) .Select(x => (x.Key, x.Count(), $"{x.FirstOrDefault()?.AlbumName} // {x.FirstOrDefault()?.ArtistName}"))
.OrderByDescending(x => x.Item2) .OrderByDescending(x => x.Item2)
.Take(20) .Take(pastOptions.Value.RankingCount)
.ToArray(); .ToArray();
var trackGrouped = listenQuery var trackGrouped = listenQuery
.GroupBy(x => (x.TrackName, x.ArtistName)) .GroupBy(x => (x.TrackName.ToLowerInvariant(), x.ArtistName.ToLowerInvariant()))
.Select(x => (x.Key, x.Count())) .Select(x => (x.Key, x.Count(), $"{x.FirstOrDefault()?.TrackName} // {x.FirstOrDefault()?.ArtistName}"))
.OrderByDescending(x => x.Item2) .OrderByDescending(x => x.Item2)
.Take(20) .Take(pastOptions.Value.RankingCount)
.ToArray(); .ToArray();
await Clients.Caller.OnRankResult(new() await Clients.Caller.OnRankResult(new()
{ {
TrackEntries = trackGrouped.Select(x => new ChartEntry() TrackEntries = trackGrouped.Select(x => new ChartEntry()
{ {
Name = $"{x.Key.TrackName} - {x.Key.ArtistName}", Name = x.Item3,
Value = x.Item2 Value = x.Item2
}).ToArray(), }).ToArray(),
AlbumEntries = albumGrouped.Select(x => new ChartEntry() AlbumEntries = albumGrouped.Select(x => new ChartEntry()
{ {
Name = $"{x.Key.AlbumName} - {x.Key.ArtistName}", Name = x.Item3,
Value = x.Item2 Value = x.Item2
}).ToArray(), }).ToArray(),

View File

@ -9,9 +9,9 @@
<div id="pastapp" class="app col-12"> <div id="pastapp" class="app col-12">
<div class="card" style="width: 100%"> <div class="card" style="width: 100%">
<div> <div>
<input v-model="track" class="form-input form-control" placeholder="Track" /> <input v-model="track" class="form-input form-control" placeholder="Track" v-on:keyup.enter="submit" />
<input v-model="album" class="form-input form-control" placeholder="Album" /> <input v-model="album" class="form-input form-control" placeholder="Album" v-on:keyup.enter="submit" />
<input v-model="artist" class="form-input form-control" placeholder="Artist" /> <input v-model="artist" class="form-input form-control" placeholder="Artist" v-on:keyup.enter="submit" />
</div> </div>
<div> <div>
<label for="from-picker">From</label> <label for="from-picker">From</label>
@ -27,7 +27,6 @@
<count-card :count="totalCount"></count-card> <count-card :count="totalCount"></count-card>
<play-count-chart-card :data_points="resampledSeries" <play-count-chart-card :data_points="resampledSeries"
:title="'Time Series'"
:chart_id="'time_series'" :chart_id="'time_series'"
:colour="'#ffffff'" :colour="'#ffffff'"
v-if="resampledSeries.length > 0"></play-count-chart-card> v-if="resampledSeries.length > 0"></play-count-chart-card>
@ -37,6 +36,11 @@
<rank-card :title="'Album'" :entries="albumEntries" v-if="albumEntries.length > 1"></rank-card> <rank-card :title="'Album'" :entries="albumEntries" v-if="albumEntries.length > 1"></rank-card>
<rank-card :title="'Artist'" :entries="artistEntries" v-if="artistEntries.length > 1"></rank-card> <rank-card :title="'Artist'" :entries="artistEntries" v-if="artistEntries.length > 1"></rank-card>
</div> </div>
<album-chart-card :data_points="mutatedAlbums"
:chart_id="'past'"
:colour="'#ffffff'"
v-if="albumEntries.length > 1"></album-chart-card>
</div> </div>
</div> </div>

View File

@ -52,7 +52,7 @@ export let PlayCountChartCard: Vue.Component = {
}, },
scales: { scales: {
yAxis: { yAxis: {
suggestedMin: 0 beginAtZero: true
}, },
xAxis: { xAxis: {
type: 'time', type: 'time',
@ -112,7 +112,7 @@ export let CombinedPlayCountChartCard: Vue.Component = {
}, },
scales: { scales: {
yAxis: { yAxis: {
suggestedMin: 0 beginAtZero: true
}, },
xAxis: { xAxis: {
type: 'time', type: 'time',

View File

@ -0,0 +1,48 @@
import * as Vue from "vue";
import { Chart, BarElement, BarController } from "chart.js";
import 'chartjs-adapter-luxon';
import { CountSample, RankEntry } from "scripts/HubInterfaces";
Chart.register(BarElement, BarController);
export let BarChartCard: Vue.Component = {
props: ['data_points', 'title', 'chart_id', 'link', 'earliest_date', 'latest_date', 'colour'],
data() {
return {
chartData: {
datasets: [{
data: this.data_points.map((e: RankEntry) => {
return {x: e.name, y: e.value};
}),
}]
}
}
},
computed: {
chartId() {
return "bar-chart-" + this.chart_id;
}
},
template:
`
<div class="chart-card card" style="width: 100%">
<h1>{{ title }}</h1>
<canvas :id="chartId"></canvas>
<lastfm-logo :link="link" v-if="link" />
</div>
`,
mounted() {
new Chart(`bar-chart-${this.chart_id}`, {
type: "bar",
data: this.chartData,
options: {
backgroundColor: 'white',
scales: {
y: {
beginAtZero: true
}
}
}
})
}
}

View File

@ -3,12 +3,21 @@ import * as Vue from "vue";
export let CountCard: Vue.Component = { export let CountCard: Vue.Component = {
props: ['count'], props: ['count'],
computed: { computed: {
formattedCount() {
if(this.count != null)
{
return this.count.toLocaleString()
}
else
{
return '0';
}
}
}, },
template: template:
` `
<div class="card"> <div class="card">
<h2>{{ count }}</h2> <h2>{{ formattedCount }}</h2>
</div> </div>
` `
} }

View File

@ -6,9 +6,11 @@ import { RankCard } from "./Past/RankCard";
import { CountCard } from "./Past/CountCard"; import { CountCard } from "./Past/CountCard";
import { PlayCountChartCard } from "./Now/PlayCountGraph"; import { PlayCountChartCard } from "./Now/PlayCountGraph";
import { LastFmLogoLink } from "./Now/LastFm"; import { LastFmLogoLink } from "./Now/LastFm";
import { BarChartCard } from "./Past/BarGraphCard";
const connection = new signalR.HubConnectionBuilder() const connection = new signalR.HubConnectionBuilder()
.withUrl("/pasthub") .withUrl("/pasthub")
.withAutomaticReconnect()
.build(); .build();
connection.start() connection.start()
@ -60,12 +62,26 @@ const app = Vue.createApp({
console.log(context); console.log(context);
this.trackEntries = [];
this.albumEntries = [];
this.artistEntries = [];
this.resampledSeries = [];
connection.invoke("OnSubmitted", context); connection.invoke("OnSubmitted", context);
} }
} },
computed: {
mutatedAlbums() {
return this.albumEntries.map((e: RankEntry) => {
e.name = e.name.split(' // ')[0];
return e;
});
}
},
}); });
app.component("play-count-chart-card", PlayCountChartCard); app.component("play-count-chart-card", PlayCountChartCard);
app.component("album-chart-card", BarChartCard);
app.component("rank-card", RankCard); app.component("rank-card", RankCard);
app.component("lastfm-logo", LastFmLogoLink); app.component("lastfm-logo", LastFmLogoLink);
app.component("count-card", CountCard); app.component("count-card", CountCard);

View File

@ -24,6 +24,7 @@ namespace Selector
public const string Key = "Past"; public const string Key = "Past";
public TimeSpan ResampleWindow { get; set; } = TimeSpan.FromDays(7); public TimeSpan ResampleWindow { get; set; } = TimeSpan.FromDays(7);
public int RankingCount { get; set; } = 20;
} }
} }