(function () { const dataEl = document.getElementById("chart-data"); const canvas = document.getElementById("temperatureChart"); if (!dataEl || !canvas) return; const series = JSON.parse(dataEl.textContent || "[]"); const colors = ["#166b5b", "#cf5a24", "#355c9a", "#7a4e9f", "#9a6235"]; const ctx = canvas.getContext("2d"); function resizeCanvas() { const ratio = window.devicePixelRatio || 1; const rect = canvas.getBoundingClientRect(); canvas.width = Math.max(320, Math.floor(rect.width * ratio)); canvas.height = Math.floor(360 * ratio); ctx.setTransform(ratio, 0, 0, ratio, 0, 0); } function draw() { resizeCanvas(); const width = canvas.clientWidth; const height = 360; const pad = { top: 24, right: 24, bottom: 44, left: 54 }; const plotW = width - pad.left - pad.right; const plotH = height - pad.top - pad.bottom; ctx.clearRect(0, 0, width, height); const points = series.flatMap((item) => item.points.map((point) => ({ ...point, date: new Date(point.time), })) ); if (!points.length) { ctx.fillStyle = "#64706b"; ctx.font = "16px system-ui, sans-serif"; ctx.fillText("Waiting for readings for today.", pad.left, pad.top + 40); return; } const minTime = Math.min(...points.map((point) => point.date.getTime())); const maxTime = Math.max(...points.map((point) => point.date.getTime())); const temps = points.map((point) => Number(point.temperature)); const minTemp = Math.floor(Math.min(...temps) - 1); const maxTemp = Math.ceil(Math.max(...temps) + 1); const timeSpan = Math.max(1, maxTime - minTime); const tempSpan = Math.max(1, maxTemp - minTemp); function xFor(date) { return pad.left + ((date.getTime() - minTime) / timeSpan) * plotW; } function yFor(temp) { return pad.top + plotH - ((temp - minTemp) / tempSpan) * plotH; } ctx.strokeStyle = "#dfe5df"; ctx.lineWidth = 1; ctx.fillStyle = "#64706b"; ctx.font = "12px system-ui, sans-serif"; for (let i = 0; i <= 4; i += 1) { const y = pad.top + (plotH / 4) * i; const temp = maxTemp - (tempSpan / 4) * i; ctx.beginPath(); ctx.moveTo(pad.left, y); ctx.lineTo(width - pad.right, y); ctx.stroke(); ctx.fillText(`${temp.toFixed(1)}C`, 8, y + 4); } series.forEach((item, index) => { const color = colors[index % colors.length]; const sorted = item.points .map((point) => ({ ...point, date: new Date(point.time) })) .sort((a, b) => a.date - b.date); ctx.strokeStyle = color; ctx.lineWidth = 3; ctx.beginPath(); sorted.forEach((point, pointIndex) => { const x = xFor(point.date); const y = yFor(Number(point.temperature)); if (pointIndex === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y); }); ctx.stroke(); sorted.forEach((point) => { ctx.fillStyle = color; ctx.beginPath(); ctx.arc(xFor(point.date), yFor(Number(point.temperature)), 3, 0, Math.PI * 2); ctx.fill(); }); }); const legendY = height - 18; series.forEach((item, index) => { const x = pad.left + index * 150; ctx.fillStyle = colors[index % colors.length]; ctx.fillRect(x, legendY - 9, 10, 10); ctx.fillStyle = "#1d2522"; ctx.font = "12px system-ui, sans-serif"; ctx.fillText(item.name, x + 16, legendY); }); } window.addEventListener("resize", draw); draw(); })();