feat(statistics): tabbed sections, honest gaps, smoothing overlay
Rework /statistics from one eight-chart scroll into four tabs behind a
sticky left rail that hangs in the page gutter from 2xl up. Only the
active panel mounts, and each card builds its canvas when it scrolls
into view.
Missing days are no longer drawn as straight lines. Every series is
aligned onto a shared daily grid derived from the days the crawler
actually observed: counts zero-fill (nobody listed a server that day),
prices break (there is no price to plot), and a collection outage breaks
every series at once.
Price charts gain a 7-day centered moving average over a receded raw
line, toggled from the rail. The average is null-preserving, so it never
bridges a gap. Chart.js bezier tension drops to 0 — the moving average
is the honest version of what tension was faking.
Series colours come from a fixed CVD-checked palette indexed by position
instead of Math.random() per render, which was repainting every chart on
each data update.
Fix four defects in the key metrics along the way:
- Per-unit price minima were set by fixed-price listings, whose
nvme_drives holds the configurator's *menu* rather than one machine's
drives (33 TB across eight entries, identical under two CPUs). One
such row decided the whole day. Excluding them moves the NVMe minimum
from €1.14/TB to €6.30/TB and NVMe-vs-HDD from 1.1x to 6.2x.
- The trend arrow never moved: FontAwesomeIcon does not swap its SVG
when the icon prop changes, so the tile kept the down arrow it mounted
with while showing a red "+4.08% rising".
- "Lowest price" was min(cheapest AMD, cheapest Intel), which can never
return a listing whose cpu_vendor is neither ("Intel®", "2x").
- The price index cannot exceed 1.0 by construction, so a subtitle
reading "Values > 1.0 = higher prices" described an unreachable state.
Drop the AMD-vs-Intel tile (it divided two unrelated machines) and
replace "ECC Premium" with an absolute best €/GB, since the old delta
measured RAM capacity, not error correction.
Also collapses the 37 per-datacenter queries into one grouped query per
country, and streams each result into state as it lands rather than in
three blocking batches.
feat(statistics): tabbed sections, honest gaps, smoothing overlay
Rework /statistics from one eight-chart scroll into four tabs behind a
sticky left rail that hangs in the page gutter from 2xl up. Only the
active panel mounts, and each card builds its canvas when it scrolls
into view.
Missing days are no longer drawn as straight lines. Every series is
aligned onto a shared daily grid derived from the days the crawler
actually observed: counts zero-fill (nobody listed a server that day),
prices break (there is no price to plot), and a collection outage breaks
every series at once.
Price charts gain a 7-day centered moving average over a receded raw
line, toggled from the rail. The average is null-preserving, so it never
bridges a gap. Chart.js bezier tension drops to 0 — the moving average
is the honest version of what tension was faking.
Series colours come from a fixed CVD-checked palette indexed by position
instead of Math.random() per render, which was repainting every chart on
each data update.
Fix four defects in the key metrics along the way:
- Per-unit price minima were set by fixed-price listings, whose
nvme_drives holds the configurator's *menu* rather than one machine's
drives (33 TB across eight entries, identical under two CPUs). One
such row decided the whole day. Excluding them moves the NVMe minimum
from €1.14/TB to €6.30/TB and NVMe-vs-HDD from 1.1x to 6.2x.
- The trend arrow never moved: FontAwesomeIcon does not swap its SVG
when the icon prop changes, so the tile kept the down arrow it mounted
with while showing a red "+4.08% rising".
- "Lowest price" was min(cheapest AMD, cheapest Intel), which can never
return a listing whose cpu_vendor is neither ("Intel®", "2x").
- The price index cannot exceed 1.0 by construction, so a subtitle
reading "Values > 1.0 = higher prices" described an unreachable state.
Drop the AMD-vs-Intel tile (it divided two unrelated machines) and
replace "ECC Premium" with an absolute best €/GB, since the old delta
measured RAM capacity, not error correction.
Also collapses the 37 per-datacenter queries into one grouped query per
country, and streams each result into state as it lands rather than in
three blocking batches.