Spaces:
Running
Running
File size: 4,098 Bytes
0f00bbc | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | <script lang="ts">
import type { Match } from '$lib/types';
import { prettyMap } from '$lib/utils/format';
import { mapColorClasses } from '$lib/utils/map-colors';
import { cn } from '$lib/utils';
interface Props {
matches: Match[];
}
let { matches }: Props = $props();
const mapsDist = $derived.by(() => {
const counts = new Map<string, number>();
for (const m of matches) counts.set(m.map_name, (counts.get(m.map_name) ?? 0) + 1);
return Array.from(counts.entries())
.map(([name, count]) => ({ name, count }))
.sort((a, b) => b.count - a.count);
});
const totalMaps = $derived(mapsDist.reduce((s, m) => s + m.count, 0));
const maxCount = $derived(Math.max(1, ...mapsDist.map((m) => m.count)));
// Histogram of rounds-per-match — buckets of 4 rounds.
const roundsHist = $derived.by(() => {
const buckets = new Map<string, number>();
for (const m of matches) {
const r = m.rounds_played;
if (!r) continue;
// pinch into [start, start+3] buckets; e.g. 13-16, 17-20, etc.
const start = Math.floor((r - 1) / 4) * 4 + 1;
const key = `${start}-${start + 3}`;
buckets.set(key, (buckets.get(key) ?? 0) + 1);
}
return Array.from(buckets.entries())
.map(([range, count]) => ({ range, count, sortKey: Number(range.split('-')[0]) }))
.sort((a, b) => a.sortKey - b.sortKey);
});
const roundsMax = $derived(Math.max(1, ...roundsHist.map((b) => b.count)));
</script>
<section class="mx-auto mt-12 max-w-5xl">
<h2
class="text-center font-heading text-xs font-semibold tracking-[0.2em] text-muted-foreground uppercase"
>
Statistics
</h2>
<div class="mt-6 grid gap-4 lg:grid-cols-2">
<!-- Maps distribution -->
<div class="rounded-md border bg-card p-4">
<div class="mb-3 flex items-baseline justify-between gap-2">
<div>
<div class="font-heading text-sm font-semibold">Maps distribution</div>
<p class="text-[11px] text-muted-foreground">
Maps rendered per CS2 map ({totalMaps} total)
</p>
</div>
</div>
<div class="space-y-1">
{#each mapsDist as m (m.name)}
{@const pct = (m.count / maxCount) * 100}
{@const sharePct = totalMaps ? (m.count / totalMaps) * 100 : 0}
<div class="grid grid-cols-[5.5rem_1fr_3.5rem] items-center gap-2 text-xs">
<span
class={cn(
'truncate rounded-sm border px-1.5 py-0.5 text-center text-[10px] font-medium capitalize',
mapColorClasses(m.name)
)}
title={m.name}>{prettyMap(m.name)}</span
>
<div class="relative h-3 overflow-hidden rounded-sm bg-muted/40">
<div
class={cn('absolute inset-y-0 left-0 rounded-sm border-r', mapColorClasses(m.name))}
style="width: {pct}%"
></div>
</div>
<span class="text-right font-mono text-muted-foreground tabular-nums">
{m.count}<span class="ml-1 text-[10px] text-muted-foreground/60"
>{sharePct.toFixed(0)}%</span
>
</span>
</div>
{/each}
</div>
</div>
<!-- Rounds-per-match histogram -->
<div class="rounded-md border bg-card p-4">
<div class="mb-3">
<div class="font-heading text-sm font-semibold">Rounds per map</div>
<p class="text-[11px] text-muted-foreground">
How many maps fall into each round-count band (regulation = 24)
</p>
</div>
<!-- Two rows: bars (definite-height parent so the % heights resolve) + labels. -->
<div class="flex h-32 items-end gap-1.5">
{#each roundsHist as b (b.range)}
{@const h = Math.max(2, (b.count / roundsMax) * 100)}
<div
class="min-w-0 flex-1 rounded-sm bg-foreground/70 transition-colors hover:bg-foreground"
style="height: {h}%"
title={`${b.range} rounds: ${b.count} maps`}
></div>
{/each}
</div>
<div class="mt-1 flex gap-1.5">
{#each roundsHist as b (b.range)}
<div
class="min-w-0 flex-1 truncate text-center font-mono text-[10px] text-muted-foreground/80"
>
{b.range}
</div>
{/each}
</div>
<div class="mt-1 text-center text-[10px] text-muted-foreground/70">rounds played</div>
</div>
</div>
</section>
|