From 5f090b9d9650daccc92c0130a3e29d68f4a4f4a5 Mon Sep 17 00:00:00 2001 From: Andreas Wrede Date: Mon, 1 Jun 2026 07:59:54 -0400 Subject: [PATCH] feat: auto-scale CPU history graph Y axis MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Y axis now fits the actual data range with 10% padding rather than fixed 0-100%. Grid lines use nice tick steps (1/2/5/10 × magnitude). Co-Authored-By: Claude Sonnet 4.6 --- hbd/server/templates/plugins.html | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/hbd/server/templates/plugins.html b/hbd/server/templates/plugins.html index 5129cec..507711f 100644 --- a/hbd/server/templates/plugins.html +++ b/hbd/server/templates/plugins.html @@ -975,7 +975,16 @@ const tMin = pts[0].t, tMax = pts[pts.length - 1].t; const tRange = tMax - tMin || 1; const x = t => PAD.left + ((t - tMin) / tRange) * cW; - const y = v => PAD.top + cH - (Math.min(v, 100) / 100) * cH; + + // Auto-scale Y axis with 10% padding, clamped to [0, 100] + const vMin = Math.min(...pts.map(p => p.v)); + const vMax = Math.max(...pts.map(p => p.v)); + const vRange = vMax - vMin || 1; + const vPad = Math.max(vRange * 0.1, 1); + const yLow = Math.max(0, vMin - vPad); + const yHigh = Math.min(100, vMax + vPad); + const yRange = yHigh - yLow || 1; + const y = v => PAD.top + cH - ((v - yLow) / yRange) * cH; // Build polyline points and filled area path const linePoints = pts.map(p => `${x(p.t).toFixed(1)},${y(p.v).toFixed(1)}`).join(' '); @@ -983,17 +992,22 @@ pts.map(p => `L${x(p.t).toFixed(1)},${y(p.v).toFixed(1)}`).join(' ') + ` L${x(pts[pts.length-1].t).toFixed(1)},${(PAD.top + cH).toFixed(1)} Z`; - // Color based on latest value + // Color based on latest absolute CPU % const latest = pts[pts.length - 1].v; const strokeColor = latest > 90 ? '#e53935' : latest > 70 ? '#fb8c00' : '#43a047'; const fillColor = latest > 90 ? '#ffcdd2' : latest > 70 ? '#ffe0b2' : '#c8e6c9'; - // Y-axis grid lines at 25, 50, 75, 100 + // Compute nice tick step for ~3-5 grid lines + const rawStep = yRange / 4; + const mag = Math.pow(10, Math.floor(Math.log10(rawStep || 1))); + const niceStep = [1, 2, 5, 10].map(f => f * mag).find(s => yRange / s <= 5) || mag * 10; + const tickStart = Math.ceil(yLow / niceStep) * niceStep; let gridLines = ''; - for (const pct of [25, 50, 75, 100]) { - const yy = y(pct).toFixed(1); + for (let v = tickStart; v <= yHigh + 0.001; v += niceStep) { + const yy = y(v).toFixed(1); + const label = Number.isInteger(v) ? v : v.toFixed(1); gridLines += ``; - gridLines += `${pct}`; + gridLines += `${label}`; } // X-axis time labels