From 8e6cf51dca715fa06da2c68d1d9510b34959e1ea Mon Sep 17 00:00:00 2001 From: Ryan Enns Date: Mon, 26 May 2025 19:19:55 -0400 Subject: [PATCH 1/2] stop using strings as date formats --- app/Http/Controllers/HomePageController.php | 9 ++-- resources/js/Composables/useApiClient.ts | 6 ++- resources/js/Pages/HomePage.vue | 57 +++++++++++---------- resources/js/Types/core.ts | 2 +- 4 files changed, 39 insertions(+), 35 deletions(-) diff --git a/app/Http/Controllers/HomePageController.php b/app/Http/Controllers/HomePageController.php index 8aed5dc..c1c3106 100644 --- a/app/Http/Controllers/HomePageController.php +++ b/app/Http/Controllers/HomePageController.php @@ -4,7 +4,6 @@ use App\Models\EloSnapshot; use App\Models\Player; -use Carbon\Carbon; use Illuminate\Support\Facades\DB; use Inertia\Inertia; use Inertia\Response; @@ -57,22 +56,22 @@ public function __invoke(): Response return Inertia::render('HomePage', [ 'solo_snapshots' => $soloRangeSnapshots->map(fn($snapshot) => [ - 'date' => Carbon::parse($snapshot->date)->format('Y-m-d'), + 'date' => $snapshot->date, 'buckets' => json_decode($snapshot->buckets, true), 'n' => $snapshot->n, ])->toArray(), 'team_snapshots' => $teamRangeSnapshots->map(fn($snapshot) => [ - 'date' => Carbon::parse($snapshot->date)->format('Y-m-d'), + 'date' => $snapshot->date, 'buckets' => json_decode($snapshot->buckets, true), 'n' => $snapshot->n, ])->toArray(), 'solo_percentile_snapshots' => $soloPercentileSnapshots->map(fn($snapshot) => [ - 'date' => Carbon::parse($snapshot->date)->format('Y-m-d'), + 'date' => $snapshot->date, 'buckets' => json_decode($snapshot->buckets, true), 'n' => $snapshot->n, ])->toArray(), 'team_percentile_snapshots' => $teamPercentileSnapshots->map(fn($snapshot) => [ - 'date' => Carbon::parse($snapshot->date)->format('Y-m-d'), + 'date' => $snapshot->date, 'buckets' => json_decode($snapshot->buckets, true), 'n' => $snapshot->n, ])->toArray(), diff --git a/resources/js/Composables/useApiClient.ts b/resources/js/Composables/useApiClient.ts index 9cb672a..beb98a2 100644 --- a/resources/js/Composables/useApiClient.ts +++ b/resources/js/Composables/useApiClient.ts @@ -55,9 +55,11 @@ export function useApiClient() { }; const getSnapshotForDate = async ( - date: string, + date: Date, ): Promise => { - const response = await fetch(`/snapshots?date=${date}`); + const response = await fetch( + `/snapshots?date=${date.toISOString().split("T")[0]}`, + ); if (!response.ok) { return { diff --git a/resources/js/Pages/HomePage.vue b/resources/js/Pages/HomePage.vue index 9c2bf4b..2d5d1b8 100644 --- a/resources/js/Pages/HomePage.vue +++ b/resources/js/Pages/HomePage.vue @@ -117,8 +117,8 @@ interface Props { team_snapshots: Snapshot[]; solo_percentile_snapshots: Snapshot[]; team_percentile_snapshots: Snapshot[]; - range_dates: string[]; - percentile_dates: string[]; + range_dates: Date[]; + percentile_dates: Date[]; leaderboard: Player[]; } const props = defineProps(); @@ -205,62 +205,56 @@ const soloSnapshots = ref(props.solo_snapshots); const teamSnapshots = ref(props.team_snapshots); const availableDates = computed(() => { - const soloDates = props.solo_snapshots.map((s) => s.date); - const teamDates = props.team_snapshots.map((s) => s.date); + const soloDates = props.solo_snapshots.map((s) => new Date(s.date)); + const teamDates = props.team_snapshots.map((s) => new Date(s.date)); return [...new Set([...soloDates, ...teamDates])].sort().reverse(); }); const availableDatesObjects = computed(() => { return selectedGraphType.value === "elo_range" - ? props.range_dates.map(parseLocalDate) - : props.percentile_dates.map(parseLocalDate); + ? props.range_dates + : props.percentile_dates; }); -const selectedDate = ref( - availableDates.value[0] - ? parseLocalDate(availableDates.value[0]) - : new Date(), -); - -function parseLocalDate(dateStr: string) { - const [year, month, day] = dateStr.split("-").map(Number); - - return new Date(year, month - 1, day); -} +const selectedDate = ref(availableDates.value[0] ?? new Date()); -const formatDate = (date: Date) => date.toISOString().split("T")[0]; +const iso = (d: string) => new Date(d).toISOString(); const currentSoloRangeSnapshot = computed(() => - soloSnapshots.value.find((s) => s.date === formatDate(selectedDate.value)), + soloSnapshots.value.find( + (s) => iso(s.date) === selectedDate.value.toISOString(), + ), ); const currentTeamRangeSnapshot = computed(() => - teamSnapshots.value.find((s) => s.date === formatDate(selectedDate.value)), + teamSnapshots.value.find( + (s) => iso(s.date) === selectedDate.value.toISOString(), + ), ); const currentSoloPercentileSnapshot = computed(() => props.solo_percentile_snapshots.find( - (s) => s.date === formatDate(selectedDate.value), + (s) => iso(s.date) === selectedDate.value.toISOString(), ), ); const currentTeamPercentileSnapshot = computed(() => props.team_percentile_snapshots.find( - (s) => s.date === formatDate(selectedDate.value), + (s) => iso(s.date) === selectedDate.value.toISOString(), ), ); watch(selectedDate, async () => { if ( soloSnapshots.value.find( - (s) => s.date === formatDate(selectedDate.value), + (s) => iso(s.date) === selectedDate.value.toISOString(), ) && teamSnapshots.value.find( - (s) => s.date === formatDate(selectedDate.value), + (s) => iso(s.date) === selectedDate.value.toISOString(), ) ) { return; } - const snapshots = await getSnapshotForDate(formatDate(selectedDate.value)); + const snapshots = await getSnapshotForDate(selectedDate.value); if (snapshots.error !== undefined) { return; @@ -274,11 +268,16 @@ const { renderRangeChart, renderPercentileChart } = useRatingChart(); const updateCharts = () => { if (selectedGraphType.value === "elo_range") { - if (!props.range_dates.includes(formatDate(selectedDate.value))) { + if ( + !props.range_dates + .map(iso) + .includes(selectedDate.value.toISOString()) + ) { selectedDate.value = new Date( props.range_dates[props.range_dates.length - 1], ); } + renderRangeChart( soloChartCanvas, currentSoloRangeSnapshot.value, @@ -295,7 +294,11 @@ const updateCharts = () => { } if (selectedGraphType.value === "percentile") { - if (!props.percentile_dates.includes(formatDate(selectedDate.value))) { + if ( + !props.percentile_dates + .map(iso) + .includes(selectedDate.value.toISOString()) + ) { selectedDate.value = new Date( props.percentile_dates[props.percentile_dates.length - 1], ); diff --git a/resources/js/Types/core.ts b/resources/js/Types/core.ts index 2b7a8d0..69bf7fc 100644 --- a/resources/js/Types/core.ts +++ b/resources/js/Types/core.ts @@ -58,7 +58,7 @@ export interface RatingChange { } export interface Snapshot { - date: string; + date: Date; buckets: { [range: string]: number; }; From 29be2ce8d569dafb96762f7074289375e5ff8c41 Mon Sep 17 00:00:00 2001 From: Ryan Enns Date: Mon, 26 May 2025 19:42:00 -0400 Subject: [PATCH 2/2] wip --- app/Http/Controllers/HomePageController.php | 2 +- resources/js/Pages/HomePage.vue | 13 +++++++------ resources/js/Types/core.ts | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/app/Http/Controllers/HomePageController.php b/app/Http/Controllers/HomePageController.php index c1c3106..3203e4a 100644 --- a/app/Http/Controllers/HomePageController.php +++ b/app/Http/Controllers/HomePageController.php @@ -10,7 +10,7 @@ class HomePageController extends Controller { - const MAX_SNAPSHOTS = 14; + const MAX_SNAPSHOTS = 1; public function __invoke(): Response { diff --git a/resources/js/Pages/HomePage.vue b/resources/js/Pages/HomePage.vue index 2d5d1b8..3dfb8c7 100644 --- a/resources/js/Pages/HomePage.vue +++ b/resources/js/Pages/HomePage.vue @@ -117,10 +117,11 @@ interface Props { team_snapshots: Snapshot[]; solo_percentile_snapshots: Snapshot[]; team_percentile_snapshots: Snapshot[]; - range_dates: Date[]; - percentile_dates: Date[]; + range_dates: string[]; + percentile_dates: string[]; leaderboard: Player[]; } + const props = defineProps(); const { getRateableHistory, getSnapshotForDate } = useApiClient(); @@ -213,13 +214,13 @@ const availableDates = computed(() => { const availableDatesObjects = computed(() => { return selectedGraphType.value === "elo_range" - ? props.range_dates - : props.percentile_dates; + ? props.range_dates.map(d => new Date(d)) + : props.percentile_dates.map(d => new Date(d)); }); -const selectedDate = ref(availableDates.value[0] ?? new Date()); +const iso = (date: string) => new Date(date).toISOString(); -const iso = (d: string) => new Date(d).toISOString(); +const selectedDate = ref(availableDates.value[0] ?? new Date()); const currentSoloRangeSnapshot = computed(() => soloSnapshots.value.find( diff --git a/resources/js/Types/core.ts b/resources/js/Types/core.ts index 69bf7fc..2b7a8d0 100644 --- a/resources/js/Types/core.ts +++ b/resources/js/Types/core.ts @@ -58,7 +58,7 @@ export interface RatingChange { } export interface Snapshot { - date: Date; + date: string; buckets: { [range: string]: number; };