Blog/Components/Pages/Rvrb.razor.cs 2.9 K · 78 lines · raw · history

1 using System.Globalization;
2 using Blog.Models;
3 using Blog.Services;
4 using Microsoft.AspNetCore.Components;
5 using Microsoft.Extensions.Options;
6
7 namespace Blog.Components.Pages;
8
9 public partial class Rvrb : ComponentBase
10 {
11 [Inject]
12 public required RvrbService Service { get; set; }
13
14 [Inject]
15 public required IOptions<RvrbOptions> Settings { get; set; }
16
17 private RvrbStatus Status { get; set; } = RvrbStatus.Unreachable("not read yet");
18
19 private RvrbSnapshot? Snapshot => Status.Snapshot;
20
21 private RvrbOptions Options => Settings.Value;
22
23 /// <summary>
24 /// How stale the snapshot is by the time it reaches the browser. Snapshots are cached and
25 /// shared, so the track that was 40 seconds in when it was taken is further along by now — this
26 /// is what lets the page pick the counter up where the bot left it.
27 /// </summary>
28 private TimeSpan Age => DateTimeOffset.UtcNow - Status.FetchedAt;
29
30 private string StatusLabel => Status switch
31 {
32 { Snapshot: null } => "offline",
33 { Snapshot.Live: null } => "up, not in the room",
34 _ => "up, in the room"
35 };
36
37 private string StatusClass => Status switch
38 {
39 { Snapshot: null } => "status-down",
40 { Snapshot.Live: null } => "status-idle",
41 _ => "status-up"
42 };
43
44 protected override async Task OnInitializedAsync()
45 {
46 Status = await Service.GetStatusAsync().ConfigureAwait(true);
47 await base.OnInitializedAsync().ConfigureAwait(true);
48 }
49
50 /// <summary>The hover label on a bar: which day it is, and what it counts.</summary>
51 private static string BarTitle(RvrbDay day) => $"{day.Date:yyyy-MM-dd}: {day.Plays} plays";
52
53 /// <summary>
54 /// The weekday under a bar, so a fortnight of counts reads as weeks rather than as a row of
55 /// numbers. Invariant rather than the request's culture: the rest of the page is in English,
56 /// and a per-visitor abbreviation would change how wide the column has to be.
57 /// </summary>
58 private static string DayLabel(RvrbDay day) => day.Date.ToString("ddd", CultureInfo.InvariantCulture);
59
60 /// <summary>
61 /// The same weekday as a single letter, for a chart too narrow to give each day three of them.
62 /// Ambiguous on its own — T is Tuesday or Thursday — but the column carries the full date in
63 /// its title, and the alternative at that width is a clipped abbreviation.
64 /// </summary>
65 private static string DayInitial(RvrbDay day) => DayLabel(day)[..1];
66
67 /// <summary>
68 /// A day's bar height as a percentage of the busiest day in the window, floored at something
69 /// visible so a day with one play doesn't render as nothing at all.
70 /// </summary>
71 private int BarHeight(int plays)
72 {
73 if (plays == 0) return 0;
74
75 var busiest = Snapshot?.PlaysPerDay.Max(day => day.Plays) ?? 0;
76 return busiest == 0 ? 0 : Math.Max(4, (int)Math.Round(plays * 100.0 / busiest));
77 }
78 }