diff --git a/static/calendar.js b/static/calendar.js index 4a68271..07bcfa3 100644 --- a/static/calendar.js +++ b/static/calendar.js @@ -558,10 +558,24 @@ function renderTotals(visible) { } const total = buckets.reduce((n, b) => n + b[2], 0); - const pctText = (n) => { const p = 100 * n / total, r = Math.round(p); return n > 0 && r === 0 ? `${p.toFixed(1)}%` : `${r}%`; }; + // Per-group subtotals + membership, so a bar's share can be scoped to its own group. + const groupTotal = {}, groupCount = {}; + for (const b of buckets) { + groupTotal[b[3]] = (groupTotal[b[3]] || 0) + b[2]; + groupCount[b[3]] = (groupCount[b[3]] || 0) + 1; + } + // A multi-bar group (rain intensities on precip, streak lengths on dry streak) shows + // each bar's share *within that group* — matching the per-group bar heights. A lone + // opposing column (Dry on precip, Rain day on dry streak) stays a share of ALL shown + // days, since a group-relative percentage there would trivially read 100%. + const pctText = (n, group) => { + const d = groupCount[group] > 1 ? (groupTotal[group] || 1) : total; + const p = 100 * n / d, r = Math.round(p); + return n > 0 && r === 0 ? `${p.toFixed(1)}%` : `${r}%`; + }; // The strip prints either each category's share (default) or its raw day count, // toggled by the "Show count" checkbox rendered in the header (state: showCount). - const valText = (n) => !n ? "0" : (showCount ? n.toLocaleString() : pctText(n)); + const valText = (n, group) => !n ? "0" : (showCount ? n.toLocaleString() : pctText(n, group)); const head = wActive ? `${days.length.toLocaleString()} of ${visible.length.toLocaleString()} shown days match the weather filter — by ${title}:` : `${visible.length.toLocaleString()} days shown — by ${title}:`; @@ -592,9 +606,9 @@ function renderTotals(visible) { // Caption stacks the category name over its value; the name reserves two lines // so the value figures stay aligned across columns whether a name wraps or not. return `
` + + `title="${label} · ${pctText(n, group)} (${n})">` + `${label}` + - `${valText(n)}` + + `${valText(n, group)}` + `${line}
`; }).join(""); totEl.innerHTML = `${header}