window.onload = async (e) => { const res = await (await fetch("/ranking", {})).json(); window.ranking = res.positions; const offset = +window.location.search.slice(1); window.offset = offset; const canvas = document.querySelector('#graph'); canvas.width = 0.35 * window.innerWidth; canvas.height = 0.50 * window.innerHeight; const now = Date.now() - offset * 1000; const curr = window.ranking.find(it => it.broadcastUnixTime < now); var current = curr.position.current; update(curr) setInterval(() => { const now = Date.now() - offset * 1000; const curr = window.ranking.find(it => it.broadcastUnixTime < now); if (curr.position.current != current) { current = curr.position.current; update(curr); } }, 1000); }; function update(curr) { console.log("Updating"); document.querySelector("#song-image").src = curr.track.coverUrl; const diff = document.querySelector("#song-diff"); diff.innerText = curr.position.label; diff.classList = curr.position.type; document.querySelector("#title").innerText = curr.track.title; document.querySelector("#artist").innerText = `${curr.track.artist} (#${curr.position.current})`; getGraph(curr.track.artist, curr.track.title); queue(curr.position.current); getTrivia(curr) } async function getGraph(artist, title) { const res = await (await fetch(`/graph/${artist.replace("?", "")}/${title}`, {})).json(); const cv = document.querySelector("#graph"); const ctx = cv.getContext('2d'); const width = cv.width; const labelSpace = 100; const barWidth = (width - labelSpace) / res.length; const height = cv.height; const graphHeight = height - 60; ctx.clearRect(0, 0, width, height); // Dots let minPos = 2001; let maxPos = -1; let minYear = undefined; let maxYear = undefined; for (let i = 0; i < res.length; i++) { const position = res[i].position; if (position != undefined) { if (position < minPos) { minPos = position; minYear = i; } if (position > maxPos) { maxPos = position; maxYear = i; } } const fraction = (position / 2000) * graphHeight; ctx.beginPath(); ctx.fillStyle = "white"; ctx.arc(labelSpace + barWidth * i + 10, fraction, 2.5, 0, 2*Math.PI); ctx.fill(); } // Min and Max lines for (let p of [minPos, maxPos]) { const fraction = (p / 2000) * graphHeight; ctx.beginPath(); ctx.strokeStyle = "#808080"; ctx.lineWidth = 1; ctx.moveTo(labelSpace, fraction); ctx.lineTo(width, fraction); ctx.stroke(); ctx.font = "40px sans-serif"; ctx.fillStyle = "#808080"; ctx.fillText(p.toString(), 0, fraction); } // Y axis for (let i = 200; i <= 2000; i += 200) { const fraction = (i / 2000) * graphHeight; const lineDist = 70; if (Math.abs(i-minPos) <= lineDist || Math.abs(i-maxPos) <= lineDist) { continue; } ctx.beginPath(); ctx.strokeStyle = "#808080"; ctx.lineWidth = 1; ctx.moveTo(labelSpace, fraction); ctx.lineTo(width, fraction); ctx.stroke(); ctx.font = "40px sans-serif"; ctx.fillStyle = "#808080"; ctx.fillText(i.toString(), 0, fraction); } // X axis const startYear = 1999; const endYear = 2025; const years = endYear-startYear+1; for (let i of [...new Set([res.findIndex(it => it.position != undefined), minYear, maxYear])]) { const fraction = 10 + labelSpace + (i * (width - labelSpace)) / (years); console.log(fraction) let year = (100 + i - 1) % 100; ctx.beginPath(); ctx.strokeStyle = "#808080"; ctx.lineWidth = 1; ctx.moveTo(fraction, 0); ctx.lineTo(fraction, graphHeight); ctx.stroke(); ctx.font = "40px sans-serif"; ctx.fillStyle = "#808080"; ctx.fillText(year.toString(), fraction-3, height-10); } // Line plot for (let i = 0; i < res.length-1; i++) { const curr = res[i].position; const next = res[i+1].position; const currFraction = (curr / 2000) * graphHeight; const nextFraction = (next / 2000) * graphHeight; // ctx.fillRect(barWidth * i, 0, barWidth, position / 10) ctx.beginPath(); ctx.strokeStyle = "white"; ctx.lineWidth = 5; ctx.lineCap = "round"; ctx.moveTo(labelSpace + barWidth * i + 10, currFraction); ctx.lineTo(labelSpace + barWidth * (i+1) + 10, nextFraction); ctx.stroke(); } } function queue(currPos) { const upcoming = window.ranking.filter(it => currPos - it.position.current < 10 && currPos - it.position.current >= -1) const queueEl = document.querySelector('#queue') queueEl.innerHTML = ""; for (const song of upcoming.reverse()) { const broadcastDT = new Date(song.broadcastUnixTime + offset * 1000); queueEl.innerHTML += `
${song.track.title}
${song.track.artist}
${song.position.label} ${broadcastDT.getHours().toString().padStart(2, "0")}:${broadcastDT.getMinutes().toString().padStart(2, "0")}