66 lines
1.8 KiB
JavaScript
66 lines
1.8 KiB
JavaScript
export async function drawLineChart() {
|
|
const res = await fetch("/api/stats");
|
|
const data = await res.json();
|
|
|
|
const canvas = document.getElementById("scoreChart");
|
|
const ctx = canvas.getContext("2d");
|
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
|
|
const allDays = Array.from(new Set(
|
|
Object.values(data).flat().map(d => d.day)
|
|
)).sort();
|
|
|
|
const maxScore = Math.max(
|
|
...Object.values(data).flat().map(d => d.avg_score)
|
|
);
|
|
|
|
const padding = 50;
|
|
const chartW = canvas.width - padding * 2;
|
|
const chartH = canvas.height - padding * 2;
|
|
|
|
// Axes
|
|
ctx.strokeStyle = "#000";
|
|
ctx.beginPath();
|
|
ctx.moveTo(padding, padding);
|
|
ctx.lineTo(padding, canvas.height - padding);
|
|
ctx.lineTo(canvas.width - padding, canvas.height - padding);
|
|
ctx.stroke();
|
|
|
|
const colors = ["#007bff", "#28a745", "#dc3545", "#ffc107", "#6f42c1"];
|
|
let playerIndex = 0;
|
|
|
|
for (const [player, entries] of Object.entries(data)) {
|
|
ctx.strokeStyle = colors[playerIndex % colors.length];
|
|
ctx.beginPath();
|
|
|
|
entries.forEach((entry, i) => {
|
|
const x = padding + (i * (chartW / (allDays.length - 1)));
|
|
const y = canvas.height - padding - ((entry.avg_score / maxScore) * chartH);
|
|
|
|
if (i === 0) ctx.moveTo(x, y);
|
|
else ctx.lineTo(x, y);
|
|
|
|
// draw point
|
|
ctx.beginPath();
|
|
ctx.arc(x, y, 3, 0, 2 * Math.PI);
|
|
ctx.fillStyle = ctx.strokeStyle;
|
|
ctx.fill();
|
|
});
|
|
|
|
ctx.stroke();
|
|
|
|
// Legend
|
|
ctx.fillStyle = ctx.strokeStyle;
|
|
ctx.fillText(player, canvas.width - 100, padding + playerIndex * 20);
|
|
playerIndex++;
|
|
}
|
|
|
|
// X axis labels
|
|
ctx.fillStyle = "#000";
|
|
allDays.forEach((day, i) => {
|
|
const x = padding + (i * (chartW / (allDays.length - 1)));
|
|
ctx.fillText(day.slice(5), x - 10, canvas.height - padding + 15);
|
|
});
|
|
}
|
|
|