use percentile instead of linear scale from max

This commit is contained in:
Davide Scaini
2026-03-29 11:26:58 +02:00
parent 5647e52865
commit d9ddae57ba
2 changed files with 68 additions and 6 deletions
+12 -5
View File
@@ -76,8 +76,16 @@
])
);
// Auto-scale: max daily km across all dates in filtered data
$: maxDailyKm = Math.max(...[...byDate.values()].map(v => v / 1000), 1);
// Sorted daily distances for percentile-based intensity scaling
$: sortedDaily = [...byDate.values()].sort((a, b) => a - b);
$: maxDailyKm = (sortedDaily[sortedDaily.length - 1] ?? 0) / 1000 || 1;
function pctRank(value: number, sorted: number[]): number {
if (!sorted.length) return 0;
let lo = 0, hi = sorted.length;
while (lo < hi) { const mid = (lo + hi) >> 1; if (sorted[mid] <= value) lo = mid + 1; else hi = mid; }
return lo / sorted.length;
}
// ── Totals ────────────────────────────────────────────────────────────────
$: totalsByYear = (() => {
@@ -117,8 +125,7 @@
for (const [date, sportMap] of byDateBySport) {
const total = byDate.get(date) ?? 0;
if (total === 0) { m.set(date, '#27272a'); continue; }
const km = total / 1000;
const intensity = Math.min(0.12 + (km / maxDailyKm) * 0.88, 1.0);
const intensity = 0.12 + pctRank(total, sortedDaily) * 0.88;
let tr = 0, tg = 0, tb = 0;
for (const [sp, dist] of sportMap) {
const w = dist / total;
@@ -280,7 +287,7 @@
{#each legendSwatches as c}
<div class="w-[10px] h-[10px] rounded-[2px]" style="background:{c}" />
{/each}
<span class="text-xs text-zinc-500 ml-1">More ({Math.round(maxDailyKm)} km max)</span>
<span class="text-xs text-zinc-500 ml-1">More (percentile · max {Math.round(maxDailyKm)} km)</span>
</div>
{#if sportsInData.length > 1}
<div class="flex items-center gap-2 ml-2">