From a261c2fe473f8aab4e95fa2909d27e22838e6942 Mon Sep 17 00:00:00 2001 From: Theodore Song Date: Tue, 7 Jul 2026 15:41:09 -0400 Subject: [PATCH] Add dated return chart axes --- index.html | 45 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/index.html b/index.html index f6c94ed..c07c92a 100644 --- a/index.html +++ b/index.html @@ -1172,6 +1172,24 @@ function renderChartRanges(){ document.querySelectorAll(".rangebtn").forEach(btn=>btn.onclick=()=>{localStorage.setItem(CHART_RANGE_KEY,btn.dataset.range);renderAll();}); } const snapTime=(s)=>new Date(s.timestamp||`${s.date}T12:00:00Z`).getTime(); +function chartDateLabel(t,compact=false){ + const d=new Date(t); + if(isNaN(d))return ""; + const sameYear=d.getUTCFullYear()===new Date().getUTCFullYear(); + return d.toLocaleDateString("en-US",compact + ? {month:"short",day:"numeric"} + : (sameYear?{month:"short",day:"numeric"}:{month:"short",day:"numeric",year:"2-digit"})); +} +function chartTicks(times,maxTicks=5){ + if(!times.length)return []; + if(times.length===1)return [{i:0,t:times[0]}]; + const count=Math.min(maxTicks,times.length),seen=new Set(),ticks=[]; + for(let n=0;nr.id===chartRange())||CHART_RANGES[0]; if(!range.days)return times; @@ -1188,7 +1206,7 @@ function drawCombo(svgId,legendId){ const allTimes=rangeFilteredTimes([...new Set(series.flatMap(s=>s.snaps.map(snapTime)))].sort((a,b)=>a-b)); const svg=$(svgId); if(!svg)return; if(!allTimes.length){svg.innerHTML="";if($(legendId))$(legendId).innerHTML=`No history yet — click "Run cycle".`;return;} - const W=600,H=240,pad=14; const vals=[0]; + const W=600,H=240,padL=42,padR=18,padT=18,padB=38; const vals=[0]; const lines=series.map(s=>{ let last=0,idx=0; const pts=allTimes.map(t=>{ @@ -1203,10 +1221,27 @@ function drawCombo(svgId,legendId){ const avgPts=allTimes.map((_,i)=>+(lines.reduce((sum,l)=>sum+l.pts[i],0)/Math.max(1,lines.length)).toFixed(2)); vals.push(...avgPts); const min=Math.min(...vals,0),max=Math.max(...vals,0),span=(max-min)||1; - const x=i=>allTimes.length===1?W/2:pad+(i/(allTimes.length-1))*(W-2*pad); - const y=v=>H-pad-((v-min)/span)*(H-2*pad); + const x=i=>allTimes.length===1?(padL+(W-padR))/2:padL+(i/(allTimes.length-1))*(W-padL-padR); + const y=v=>H-padB-((v-min)/span)*(H-padT-padB); + const yTicks=[...new Set([min,(min+max)/2,max].map(v=>+v.toFixed(1)))]; const zeroY=y(0).toFixed(1); - let inner=``; + let inner=` + + + + `; + inner+=``; + for(const v of yTicks){ + const yy=y(v).toFixed(1); + inner+=``; + inner+=`${fmtPct(v)}`; + } + inner+=``; + for(const tick of chartTicks(allTimes,5)){ + const xx=x(tick.i).toFixed(1); + inner+=``; + inner+=`${chartDateLabel(tick.t,true)}`; + } for(const ln of lines){ const d=ln.pts.map((v,i)=>`${i===0?"M":"L"}${x(i).toFixed(1)},${y(v).toFixed(1)}`).join(" "); const dot=allTimes.length===1?``:""; @@ -1214,6 +1249,8 @@ function drawCombo(svgId,legendId){ } const avgD=avgPts.map((v,i)=>`${i===0?"M":"L"}${x(i).toFixed(1)},${y(v).toFixed(1)}`).join(" "); inner+=``; + inner+=`${chartDateLabel(allTimes[0])}`; + inner+=`${chartDateLabel(allTimes[allTimes.length-1])}`; svg.innerHTML=inner; if($(legendId)){ const b=board();const avg=b.reduce((s,r)=>s+r.ret,0)/b.length;