(() => { const source = document.getElementById('fitness-data'); const initial = JSON.parse(source.textContent); let refreshing = false; async function refresh() { if (document.hidden || refreshing) return; refreshing = true; try { const response = await fetch(source.dataset.url, {cache: 'no-store', headers: {Accept: 'application/json'}}); if (response.ok && response.headers.get('content-type')?.includes('application/json')) { const next = await response.json(); if (JSON.stringify(next.series) !== JSON.stringify(initial.series) || JSON.stringify(next.runs) !== JSON.stringify(initial.runs) || JSON.stringify(next.zones) !== JSON.stringify(initial.zones)) window.location.reload(); } } catch { /* Keep the current chart available while offline. */ } finally { refreshing = false; } } window.addEventListener('focus', refresh); document.addEventListener('visibilitychange', () => { if (!document.hidden) refresh(); }); window.setInterval(refresh, 300000); const canvas = document.getElementById('fitness-chart'); if (!canvas) return; const series = initial.series; const keys = ['fitness', 'fatigue', 'form']; const colors = ['#67cbb8', '#f48459', '#b8a1f0']; const chart = new Chart(canvas, { type: 'line', data: {labels: [], datasets: keys.map((key, i) => ({label: key[0].toUpperCase() + key.slice(1), data: [], borderColor: colors[i], pointRadius: 0, borderWidth: 2}))}, options: {responsive: true, maintainAspectRatio: false, interaction: {mode: 'index', intersect: false}, plugins: {legend: {labels: {color: '#eeeae4'}}, tooltip: {callbacks: {afterBody(items) { const row = visible[items[0].dataIndex]; return [row.missing ? `${row.missing} unscored run(s); known effort only` : `Daily effort: ${row.load.toFixed(1)}`, ...(row.provisional ? ['Provisional estimate'] : [])]; }}}}, scales: {x: {ticks: {maxTicksLimit: 8, color: '#9ba4a5'}, grid: {color: '#303638'}}, y: {ticks: {color: '#9ba4a5'}, grid: {color: '#303638'}}}} }); let visible = series; const range = document.getElementById('fitness-range'); function update() { visible = range.value === 'all' ? series : series.slice(-Number(range.value)); chart.data.labels = visible.map(row => row.day); keys.forEach((key, i) => {chart.data.datasets[i].data = visible.map(row => row[key]);}); chart.update(); } range.addEventListener('change', update); update(); })();