From b2612ab1ca6afd6bd1b882353ab5f5c116e34689 Mon Sep 17 00:00:00 2001 From: Emi Griffith Date: Sun, 19 Jul 2026 12:10:24 -0700 Subject: [PATCH] Show rain in centimetres rather than millimetres on metric pages (#191) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precipitation on a °C page now reads "4.90 cm" where it read "49.0 mm". Both units keep two decimals. cm and inches are only 2.54x apart, so cm needs the same resolution inches have — at one decimal every light-rain day would collapse to 0.0 or 0.1 cm, and the source itself is hundredths of an inch. Ingest is untouched: climate.py still converts the upstream mm to inches, which remains the stored unit and the value carried in data-precip-in. Claude-Session: https://claude.ai/code/session_013dRZmX9D3JEntfMKWMTWZ8 --- static/app.js | 4 ++-- static/shared.js | 4 ++-- static/units.js | 19 ++++++++++--------- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/static/app.js b/static/app.js index 9d6704d..a2b41d7 100644 --- a/static/app.js +++ b/static/app.js @@ -188,8 +188,8 @@ async function runGrade() { const cTemp = fmtTemp; // active unit, bare degree const cHum = (v) => (v == null ? "—" : `${Math.round(v)}%`); // relative %, unit-invariant const cWind = (v) => (v == null ? "—" : `${Math.round(toWind(v))}`); -// fmtPrecip carries the precision: two decimals for inches, one for mm (0.04" and -// 1.0mm are the same amount, and "1.02 mm" would imply precision we don't have). +// fmtPrecip carries the precision — two decimals in either unit, since cm and +// inches are close enough in scale to need the same resolution. const cRain = (v) => (v == null ? "—" : v > 0 ? fmtPrecip(v, false) : "·"); // Monochrome inline icons (currentColor) so the UI chrome matches the dark theme diff --git a/static/shared.js b/static/shared.js index 0c221f5..e124d65 100644 --- a/static/shared.js +++ b/static/shared.js @@ -121,8 +121,8 @@ function fmtMetricVal(unit, v) { if (unit === "temp") return fmtTemp(v); if (unit === "humid") return fmtHumid(v); if (unit === "wind") return fmtWind(v); - // The tier bar is tight on width, so precip keeps the ″ glyph over " mm"/" in". - if (unit === "precip") return `${fmtPrecip(v, false)}${getUnit() === "C" ? "mm" : "″"}`; + // The tier bar is tight on width, so precip keeps the ″ glyph over " cm"/" in". + if (unit === "precip") return `${fmtPrecip(v, false)}${getUnit() === "C" ? "cm" : "″"}`; if (unit === "dsr") return `${Math.round(v)}d`; return `${Math.round(v)}`; } diff --git a/static/units.js b/static/units.js index 49ee291..aefa0f1 100644 --- a/static/units.js +++ b/static/units.js @@ -4,7 +4,7 @@ // `onUnitChange`, so stored and plotted values stay imperial and only the numbers // shown flip. // -// One flag drives all of them: picking °C also gives mm and km/h. A reader who +// One flag drives all of them: picking °C also gives cm and km/h. A reader who // wants Celsius wants the rest metric too, and a per-measure control would be // three toggles in a header that has room for one. The button still shows °F/°C // because temperature is what people look for. @@ -67,24 +67,25 @@ export function fmtDelta(dF, withLetter) { } // --- precipitation (stored in inches) ---------------------------------------- -const MM_PER_IN = 25.4; +const CM_PER_IN = 2.54; // Inches as a number in the active unit. -export function toPrecip(vIn) { return _unit === "C" ? vIn * MM_PER_IN : vIn; } +export function toPrecip(vIn) { return _unit === "C" ? vIn * CM_PER_IN : vIn; } -// Millimetres get one decimal and inches two: 0.04 in and 1.0 mm are the same -// amount, and rendering "1.02 mm" would imply a precision the source lacks. -// The suffix is " in"/" mm" to match what content.py renders server-side, so a +// Both units get two decimals. They are only 2.54x apart, so cm needs the same +// resolution inches have — at one decimal every light-rain day would collapse to +// 0.0 or 0.1 cm, and the source itself is hundredths of an inch. +// The suffix is " in"/" cm" to match what content.py renders server-side, so a // climate page's repaint reproduces the text it shipped with rather than swapping // the glyph. Compact surfaces (the tier bar) pass withUnit=false and add their own. export function fmtPrecip(vIn, withUnit = true) { if (vIn == null || isNaN(vIn)) return "—"; return _unit === "C" - ? `${(vIn * MM_PER_IN).toFixed(1)}${withUnit ? " mm" : ""}` + ? `${(vIn * CM_PER_IN).toFixed(2)}${withUnit ? " cm" : ""}` : `${vIn.toFixed(2)}${withUnit ? " in" : ""}`; } -export const precipUnit = () => (_unit === "C" ? "mm" : "in"); +export const precipUnit = () => (_unit === "C" ? "cm" : "in"); // --- wind (stored in mph) ---------------------------------------------------- const KMH_PER_MPH = 1.609344; @@ -116,7 +117,7 @@ export function onUnitChange(cb) { _unitCbs.push(cb); } // known. Runs on load and on every toggle, wherever units.js is imported. const UNIT_LABEL = { temp: () => `°${_unit}`, - precip: () => (_unit === "C" ? "mm" : "inches"), + precip: () => (_unit === "C" ? "cm" : "inches"), wind: () => windUnit(), humid: () => "g/m³", };