diff --git a/public/index.css b/public/index.css
index 5cd2865..18b5386 100644
--- a/public/index.css
+++ b/public/index.css
@@ -2,7 +2,7 @@
body {
background-color: #262626;
- margin: 20px;
+ margin: 1vw;
color: #ffffff;
overflow: clip;
font-family:Work Sans,sans-serif;
@@ -14,29 +14,24 @@ body {
justify-content: space-between;
}
-#title {
- max-width: 500px;
-}
-
-
/* --- Left column --- */
.song {
position: relative;
}
#song-image {
- width: 500px;
- height: 500px;
- border-radius: 20px;
+ width: 25vw;
+ height: 25vw;
+ border-radius: 1vw;
}
#song-diff {
- font-size: 2rem;
- padding: 16px;
- min-width: 80px;
- height: 40px;
- border-radius: 20px;
- border: 1px solid black;
+ font-size: 3vh;
+ padding: 0.8vw;
+ min-width: 5vw;
+ height: 2vw;
+ border-radius: 1vw;
+ border: 0.02vw solid black;
position: absolute;
top: 0;
@@ -46,7 +41,7 @@ body {
text-align: center;
}
-#song-diff.stale {
+#song-diff.stale, #song-diff.new {
background-color: gray;
}
@@ -58,6 +53,16 @@ body {
background-color: red;
}
+.current-column {
+ font-size: 2.25vh;
+}
+
+.current-column h1 {
+ margin-bottom: 0;
+}
+.current-column h2 {
+ margin: 0;
+}
/* --- Middle column --- */
.left-divide {
@@ -66,18 +71,17 @@ body {
}
.song-stats {
- margin-left: 100px;
+ margin-left: 2vw;
}
-.artist-info p {
- margin: 0;
- padding: 0;
+.artist-info {
+ font-size: 2.25vh;
}
/* --- Right column --- */
#queue {
- width: 700px;
+ width: 35vw;
}
.queue-item {
@@ -86,18 +90,21 @@ body {
}
.queue-item .song-title {
- font-size: 2rem;
- margin-left: 20px;
+ font-size: 3vh;
+ margin-left: 1vw;
}
.queue-item .song-artist {
- font-size: 1.5rem;
- margin-left: 20px;
+ font-size: 2.25vh;
+ margin-left: 1vw;
color: #ccc;
}
.queue-item .song-time {
- text-align: right;
- margin-right: 10px;
- font-size: 1.5rem;
+ margin-right: 0.5vw;
+ font-size: 2.25vh;
+
+ justify-content: right;
+ display: flex;
+ gap: 1.5vw;
}
.queue-right-wrapper {
width: 100%;
@@ -109,10 +116,17 @@ body {
}
.queue-image {
- height: 100px;
- width: 100px;
+ height: 5vw;
+ width: 5vw;
}
.queue-item.playing {
background-color: #1a1a1a;
}
+
+.song-diff.queue-risen {
+ color: green;
+}
+.song-diff.queue-fallen {
+ color: red;
+}
diff --git a/public/index.html b/public/index.html
index d23d7de..ad82501 100644
--- a/public/index.html
+++ b/public/index.html
@@ -15,16 +15,15 @@
-
-
-
-
+
+
+
Trivia
diff --git a/public/index.js b/public/index.js
index ea53c0e..178bccc 100644
--- a/public/index.js
+++ b/public/index.js
@@ -1,10 +1,14 @@
window.onload = async (e) => {
- const res = await (await fetch("https://www.nporadio2.nl/api/charts/npo-radio-2-top-2000-van-2025-12-25", {})).json();
+ 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;
@@ -30,8 +34,7 @@ function update(curr) {
diff.classList = curr.position.type;
document.querySelector("#title").innerText = curr.track.title;
- document.querySelector("#artist").innerText = curr.track.artist;
- document.querySelector("#position").innerText = `Nummer ${curr.position.current}`;
+ document.querySelector("#artist").innerText = `${curr.track.artist} (#${curr.position.current})`;
getGraph(curr.track.artist, curr.track.title);
queue(curr.position.current);
@@ -41,19 +44,68 @@ function update(curr) {
async function getGraph(artist, title) {
const res = await (await fetch(`/graph/${artist.replace("?", "")}/${title}`, {})).json();
- const width = 500;
- const labelSpace = 50;
- const barWidth = (width - labelSpace) / res.length;
- const height = 500;
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);
- for (let i = 0; i <= 2000; i += 200) {
- const fraction = (i / 2000) * 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";
@@ -62,27 +114,39 @@ async function getGraph(artist, title) {
ctx.lineTo(width, fraction);
ctx.stroke();
- ctx.font = "20px sans-serif";
+ ctx.font = "40px sans-serif";
ctx.fillStyle = "#808080";
ctx.fillText(i.toString(), 0, fraction);
}
- for (let i = 0; i < res.length; i++) {
- const position = res[i].position;
- const fraction = (position / 2000) * height;
+ // 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.fillRect(barWidth * i, 0, barWidth, position / 10)
ctx.beginPath();
- ctx.fillStyle = "white";
- ctx.arc(labelSpace + barWidth * i + 10, fraction, 2.5, 0, 2*Math.PI);
- ctx.fill();
+ 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) * height;
- const nextFraction = (next / 2000) * height;
+ const currFraction = (curr / 2000) * graphHeight;
+ const nextFraction = (next / 2000) * graphHeight;
// ctx.fillRect(barWidth * i, 0, barWidth, position / 10)
ctx.beginPath();
@@ -102,14 +166,17 @@ function queue(currPos) {
queueEl.innerHTML = "";
for (const song of upcoming.reverse()) {
- const broadcastDT = new Date(song.broadcastUnixTime - offset * 1000);
+ const broadcastDT = new Date(song.broadcastUnixTime + offset * 1000);
queueEl.innerHTML += `
${song.track.title}
${song.track.artist}
-
${broadcastDT.getHours().toString().padStart(2, "0")}:${broadcastDT.getMinutes().toString().padStart(2, "0")}
+
+ ${song.position.label}
+ ${broadcastDT.getHours().toString().padStart(2, "0")}:${broadcastDT.getMinutes().toString().padStart(2, "0")}
+
`
@@ -132,12 +199,12 @@ async function getTrivia(curr) {
if (artistsSongs[0].position == curr.position.current) {
document.querySelector("#trivia-first").innerText = `Dit is het hoogste nummer van ${curr.track.artist} in de lijst.`;
} else {
- document.querySelector("#trivia-first").innerText = `Het hoogste nummer van ${curr.track.artist} is ${artistsSongs[0].title}.`;
+ document.querySelector("#trivia-first").innerText = `Het hoogste nummer van ${curr.track.artist} is ${artistsSongs[0].title} (#${artistsSongs[0].position}).`;
}
if (artistsSongs.at(-1).position == curr.position.current) {
document.querySelector("#trivia-last").innerText = `Dit is het laagste nummer van ${curr.track.artist} in de lijst.`;
} else {
- document.querySelector("#trivia-last").innerText = `Het laagste nummer van ${curr.track.artist} is ${artistsSongs.at(-1).title}.`;
+ document.querySelector("#trivia-last").innerText = `Het laagste nummer van ${curr.track.artist} is ${artistsSongs.at(-1).title} (#${artistsSongs.at(-1).position}).`;
}
}
diff --git a/server.js b/server.js
index d0e82bb..c50df4a 100644
--- a/server.js
+++ b/server.js
@@ -10,6 +10,665 @@ app.get("/", (req, res) => {
res.sendFile(path.resolve('./index.html'))
})
+app.get('/ranking', async (req, res) => {
+ // const ranking = await (await fetch("https://www.nporadio2.nl/api/charts/npo-radio-2-top-2000-van-2025-12-25", {})).json();
+
+ res.send({
+ "chartDate": "2025-12-25 00:00:00",
+ "editionIsActive": true,
+ "downloadUrls": {
+ "excelUrl": "https://cms-assets.nporadio.nl/npoRadio2/TOP2000-2025.xls?v=1765830938",
+ "pdfUrl": "https://cms-assets.nporadio.nl/npoRadio2/NPO-Radio-2-Top-2000-2025.pdf?v=1765831780"
+ },
+ "positions": [
+ {
+ "broadcastTime": "2025-12-27T15:08:15+01:00",
+ "broadcastTimeFormatted": "zaterdag 27 dec 2025 15:00 - 16:00 uur",
+ "broadcastUnixTime": 1766844495000,
+ "id": "6f4ca036-438f-4932-b048-04cf12995060",
+ "position": {
+ "current": 1201,
+ "label": "-68",
+ "previous": 1133,
+ "type": "fallen"
+ },
+ "totalPositions": 1,
+ "track": {
+ "artist": "Snowy White",
+ "coverUrl": "https://npo-artistdb.b-cdn.net/images/e8b0c345-b123-4a84-a472-29298d4dc7ed__Bird-Of-Paradise.jpg?aspect_ratio=501%3A500&width=500&height=500",
+ "detailUrl": "/muziek/nummers/6f4ca036-438f-4932-b048-04cf12995060/bird-of-paradise",
+ "historyUrl": "/top2000/statistieken/door-de-jaren-heen/snowy-white/bird-of-paradise",
+ "id": "6f4ca036-438f-4932-b048-04cf12995060",
+ "isAvailable": true,
+ "previewUrl": "https://p.scdn.co/mp3-preview/4bedf26f99d7c5d2072f301ca852a9375398d867?cid=e10971e8edab41f8b0986464de19b8f3",
+ "title": "Bird Of Paradise"
+ }
+ },
+ {
+ "broadcastTime": "2025-12-27T15:05:00+01:00",
+ "broadcastTimeFormatted": "zaterdag 27 dec 2025 15:00 - 16:00 uur",
+ "broadcastUnixTime": 1766844300000,
+ "id": "a7ef1907-c656-4bd2-8fbd-248add9c1222",
+ "position": {
+ "current": 1202,
+ "label": "-79",
+ "previous": 1123,
+ "type": "fallen"
+ },
+ "totalPositions": 1,
+ "track": {
+ "artist": "Crosby, Stills, Nash & Young",
+ "coverUrl": "https://npo-artistdb.b-cdn.net/images/db03712e-7235-45ef-8371-f1ed5afc4e71__Teach-Your-Children.jpg?aspect_ratio=501%3A500&width=500&height=500",
+ "detailUrl": "/muziek/nummers/a7ef1907-c656-4bd2-8fbd-248add9c1222/teach-your-children",
+ "historyUrl": "/top2000/statistieken/door-de-jaren-heen/crosby-stills-nash-young/teach-your-children",
+ "id": "a7ef1907-c656-4bd2-8fbd-248add9c1222",
+ "isAvailable": true,
+ "previewUrl": "https://p.scdn.co/mp3-preview/a4b0d977cac5cf760933592681cb865231133142?cid=e10971e8edab41f8b0986464de19b8f3",
+ "title": "Teach Your Children"
+ }
+ },
+ {
+ "broadcastTime": "2025-12-27T14:51:52+01:00",
+ "broadcastTimeFormatted": "zaterdag 27 dec 2025 14:00 - 15:00 uur",
+ "broadcastUnixTime": 1766843512000,
+ "id": "4db20c37-c402-45c2-b90d-8cab3a8fd593",
+ "position": {
+ "current": 1203,
+ "label": "-137",
+ "previous": 1066,
+ "type": "fallen"
+ },
+ "totalPositions": 1,
+ "track": {
+ "artist": "Beth Hart & Joe Bonamassa",
+ "coverUrl": "https://npo-artistdb.b-cdn.net/images/18f83c48-a15f-440c-b85f-5b8bcf051d48__I-ll-Take-Care-Of-You.jpg?aspect_ratio=501%3A500&width=500&height=500",
+ "detailUrl": "/muziek/nummers/4db20c37-c402-45c2-b90d-8cab3a8fd593/ill-take-care-of-you",
+ "historyUrl": "/top2000/statistieken/door-de-jaren-heen/beth-hart-joe-bonamassa/ill-take-care-of-you-albumversie",
+ "id": "4db20c37-c402-45c2-b90d-8cab3a8fd593",
+ "isAvailable": true,
+ "previewUrl": null,
+ "title": "I'll Take Care Of You (Albumversie)"
+ }
+ },
+ {
+ "broadcastTime": "2025-12-27T14:47:50+01:00",
+ "broadcastTimeFormatted": "zaterdag 27 dec 2025 14:00 - 15:00 uur",
+ "broadcastUnixTime": 1766843270000,
+ "id": "e88bbf6c-a39a-4334-9575-039077721319",
+ "position": {
+ "current": 1204,
+ "label": "-55",
+ "previous": 1149,
+ "type": "fallen"
+ },
+ "totalPositions": 1,
+ "track": {
+ "artist": "Kaleo",
+ "coverUrl": "https://npo-artistdb.b-cdn.net/images/be57f7e6-f541-471d-88e1-cda0cfd54550__Kaleo-0.jpg?aspect_ratio=501%3A500&width=500&height=500",
+ "detailUrl": "/muziek/nummers/e88bbf6c-a39a-4334-9575-039077721319/way-down-we-go",
+ "historyUrl": "/top2000/statistieken/door-de-jaren-heen/kaleo/way-down-we-go",
+ "id": "e88bbf6c-a39a-4334-9575-039077721319",
+ "isAvailable": true,
+ "previewUrl": "https://p.scdn.co/mp3-preview/d98c7057adac754607c1a2ab8c72113c3e7a2338?cid=e10971e8edab41f8b0986464de19b8f3",
+ "title": "Way Down We Go"
+ }
+ },
+ {
+ "broadcastTime": "2025-12-27T14:41:31+01:00",
+ "broadcastTimeFormatted": "zaterdag 27 dec 2025 14:00 - 15:00 uur",
+ "broadcastUnixTime": 1766842891000,
+ "id": "184d9d04-27e2-46e0-b42f-8db9599dc4e9",
+ "position": {
+ "current": 1205,
+ "label": "+483",
+ "previous": 1688,
+ "type": "risen"
+ },
+ "totalPositions": 1,
+ "track": {
+ "artist": "Michael Jackson",
+ "coverUrl": "https://npo-artistdb.b-cdn.net/images/47fd63a8-800b-45f8-afa6-1b00a330c535__Don-t-Stop-til-You-Get-Enough.jpg?aspect_ratio=501%3A500&width=500&height=500",
+ "detailUrl": "/muziek/nummers/184d9d04-27e2-46e0-b42f-8db9599dc4e9/dont-stop-til-you-get-enough",
+ "historyUrl": "/top2000/statistieken/door-de-jaren-heen/michael-jackson/dont-stop-til-you-get-enough-albumversie",
+ "id": "184d9d04-27e2-46e0-b42f-8db9599dc4e9",
+ "isAvailable": true,
+ "previewUrl": null,
+ "title": "Don't Stop 'Til You Get Enough (Albumversie)"
+ }
+ },
+ {
+ "broadcastTime": "2025-12-27T14:37:20+01:00",
+ "broadcastTimeFormatted": "zaterdag 27 dec 2025 14:00 - 15:00 uur",
+ "broadcastUnixTime": 1766842640000,
+ "id": "01978d13-e960-73d9-ac0f-10889762874d",
+ "position": {
+ "current": 1206,
+ "label": "-10",
+ "previous": 1196,
+ "type": "fallen"
+ },
+ "totalPositions": 1,
+ "track": {
+ "artist": "Rammstein",
+ "coverUrl": "https://npo-artistdb.b-cdn.net/images/a6bf6875-56bb-448b-b4e4-b7ec4cfa1749__AMERIKA.jpg?aspect_ratio=501%3A500&width=500&height=500",
+ "detailUrl": "/muziek/nummers/01978d13-e960-73d9-ac0f-10889762874d/amerika",
+ "historyUrl": "/top2000/statistieken/door-de-jaren-heen/rammstein/amerika",
+ "id": "01978d13-e960-73d9-ac0f-10889762874d",
+ "isAvailable": true,
+ "previewUrl": null,
+ "title": "Amerika"
+ }
+ },
+ {
+ "broadcastTime": "2025-12-27T14:31:49+01:00",
+ "broadcastTimeFormatted": "zaterdag 27 dec 2025 14:00 - 15:00 uur",
+ "broadcastUnixTime": 1766842309000,
+ "id": "6677b744-b8c5-4095-870f-732488e9d7f6",
+ "position": {
+ "current": 1207,
+ "label": "-92",
+ "previous": 1115,
+ "type": "fallen"
+ },
+ "totalPositions": 1,
+ "track": {
+ "artist": "Carole King",
+ "coverUrl": "https://npo-artistdb.b-cdn.net/images/48a6fc6c-406f-4ecb-903a-664816c8332a__You-ve-Got-A-Friend.jpg?aspect_ratio=501%3A500&width=500&height=500",
+ "detailUrl": "/muziek/nummers/6677b744-b8c5-4095-870f-732488e9d7f6/youve-got-a-friend",
+ "historyUrl": "/top2000/statistieken/door-de-jaren-heen/carole-king/youve-got-a-friend",
+ "id": "6677b744-b8c5-4095-870f-732488e9d7f6",
+ "isAvailable": true,
+ "previewUrl": "https://assets.stemtool.npox.nl/audio/382/c-624e2d14d6f182bc79083a372e277ded-6.mp3?v=1725881570",
+ "title": "You've Got A Friend"
+ }
+ },
+ {
+ "broadcastTime": "2025-12-27T14:27:45+01:00",
+ "broadcastTimeFormatted": "zaterdag 27 dec 2025 14:00 - 15:00 uur",
+ "broadcastUnixTime": 1766842065000,
+ "id": "2be29add-afef-447c-af86-41bc90b47f3c",
+ "position": {
+ "current": 1208,
+ "label": "+321",
+ "previous": 1529,
+ "type": "risen"
+ },
+ "totalPositions": 1,
+ "track": {
+ "artist": "Normaal",
+ "coverUrl": "https://npo-artistdb.b-cdn.net/images/8dc9855f-f807-4731-9f01-49fa5b19186a__ikbun.jpg?aspect_ratio=501%3A500&width=500&height=500",
+ "detailUrl": "/muziek/nummers/2be29add-afef-447c-af86-41bc90b47f3c/ik-bun-moar-een-eenvoudige-boerenlul",
+ "historyUrl": "/top2000/statistieken/door-de-jaren-heen/normaal/ik-bun-moar-een-eenvoudige-boerenlul",
+ "id": "2be29add-afef-447c-af86-41bc90b47f3c",
+ "isAvailable": true,
+ "previewUrl": "https://p.scdn.co/mp3-preview/3b532e7f39c38b02ce0804d177173c94a9c16458?cid=19f7f13455664bcab5373cb63d176694",
+ "title": "Ik Bun Moar Een Eenvoudige Boerenlul"
+ }
+ },
+ {
+ "broadcastTime": "2025-12-27T14:23:19+01:00",
+ "broadcastTimeFormatted": "zaterdag 27 dec 2025 14:00 - 15:00 uur",
+ "broadcastUnixTime": 1766841799000,
+ "id": "ed0818ac-2c6d-4cf6-983a-9125d18c871b",
+ "position": {
+ "current": 1209,
+ "label": "-132",
+ "previous": 1077,
+ "type": "fallen"
+ },
+ "totalPositions": 1,
+ "track": {
+ "artist": "Temple Of The Dog",
+ "coverUrl": "https://npo-artistdb.b-cdn.net/images/8785ddb5-fde6-4382-877d-61192b18ea53__Hunger-Strike.jpg?aspect_ratio=501%3A500&width=500&height=500",
+ "detailUrl": "/muziek/nummers/ed0818ac-2c6d-4cf6-983a-9125d18c871b/hunger-strike",
+ "historyUrl": "/top2000/statistieken/door-de-jaren-heen/temple-of-the-dog/hunger-strike",
+ "id": "ed0818ac-2c6d-4cf6-983a-9125d18c871b",
+ "isAvailable": true,
+ "previewUrl": "https://assets.stemtool.npox.nl/audio/7420/c-d2f6dbf57ba43a2ce6a880d01e0924cb-4.mp3?v=1726670780",
+ "title": "Hunger Strike"
+ }
+ },
+ {
+ "broadcastTime": "2025-12-27T14:19:31+01:00",
+ "broadcastTimeFormatted": "zaterdag 27 dec 2025 14:00 - 15:00 uur",
+ "broadcastUnixTime": 1766841571000,
+ "id": "0197396d-e247-702b-9e36-76524e91b54f",
+ "position": {
+ "current": 1210,
+ "label": "-314",
+ "previous": 896,
+ "type": "fallen"
+ },
+ "totalPositions": 1,
+ "track": {
+ "artist": "Red Hot Chili Peppers",
+ "coverUrl": "https://npo-artistdb.b-cdn.net/images/7a409ed7-4ab2-4ea1-a307-7e7081f2a012__Road-Trippin.jpg?aspect_ratio=501%3A500&width=500&height=500",
+ "detailUrl": "/muziek/nummers/0197396d-e247-702b-9e36-76524e91b54f/road-trippin",
+ "historyUrl": "/top2000/statistieken/door-de-jaren-heen/red-hot-chili-peppers/road-trippin",
+ "id": "0197396d-e247-702b-9e36-76524e91b54f",
+ "isAvailable": true,
+ "previewUrl": null,
+ "title": "Road Trippin'"
+ }
+ },
+ {
+ "broadcastTime": "2025-12-27T14:15:17+01:00",
+ "broadcastTimeFormatted": "zaterdag 27 dec 2025 14:00 - 15:00 uur",
+ "broadcastUnixTime": 1766841317000,
+ "id": "085923f8-8e0b-4764-8077-49efde92b2c8",
+ "position": {
+ "current": 1211,
+ "label": "-186",
+ "previous": 1025,
+ "type": "fallen"
+ },
+ "totalPositions": 1,
+ "track": {
+ "artist": "Depeche Mode",
+ "coverUrl": "https://npo-artistdb.b-cdn.net/images/03c66f3f-4cea-4921-8cc8-0bae5493bb55__Just-Can-t-Get-Enough.jpg?aspect_ratio=501%3A500&width=500&height=500",
+ "detailUrl": "/muziek/nummers/085923f8-8e0b-4764-8077-49efde92b2c8/just-cant-get-enough",
+ "historyUrl": "/top2000/statistieken/door-de-jaren-heen/depeche-mode/just-cant-get-enough-live",
+ "id": "085923f8-8e0b-4764-8077-49efde92b2c8",
+ "isAvailable": true,
+ "previewUrl": null,
+ "title": "Just Can't Get Enough (Live)"
+ }
+ },
+ {
+ "broadcastTime": "2025-12-27T14:09:41+01:00",
+ "broadcastTimeFormatted": "zaterdag 27 dec 2025 14:00 - 15:00 uur",
+ "broadcastUnixTime": 1766840981000,
+ "id": "703dd67b-c81b-48cd-9faf-cfcfece72f43",
+ "position": {
+ "current": 1212,
+ "label": "-84",
+ "previous": 1128,
+ "type": "fallen"
+ },
+ "totalPositions": 1,
+ "track": {
+ "artist": "Paul McCartney & Wings",
+ "coverUrl": "https://npo-artistdb.b-cdn.net/images/eca307ce-aa89-4252-a586-9b5a0b6cba6a__Band-On-The-Run.jpg?aspect_ratio=501%3A500&width=500&height=500",
+ "detailUrl": "/muziek/nummers/703dd67b-c81b-48cd-9faf-cfcfece72f43/band-on-the-run",
+ "historyUrl": "/top2000/statistieken/door-de-jaren-heen/paul-mccartney-wings/band-on-the-run",
+ "id": "703dd67b-c81b-48cd-9faf-cfcfece72f43",
+ "isAvailable": true,
+ "previewUrl": "https://assets.stemtool.npox.nl/audio/3223/c-673f51dffb08f804ba20f033a68a36cc-6.mp3?v=1725882494",
+ "title": "Band On The Run"
+ }
+ },
+ {
+ "broadcastTime": "2025-12-27T14:05:00+01:00",
+ "broadcastTimeFormatted": "zaterdag 27 dec 2025 14:00 - 15:00 uur",
+ "broadcastUnixTime": 1766840700000,
+ "id": "744695e9-65c3-4952-ad4e-aa1303194809",
+ "position": {
+ "current": 1213,
+ "label": "+206",
+ "previous": 1419,
+ "type": "risen"
+ },
+ "totalPositions": 1,
+ "track": {
+ "artist": "Live",
+ "coverUrl": "https://npo-artistdb.b-cdn.net/images/069b9569-749b-4d1d-842f-b7ffa830e890__The-Dolphin-s-Cry.jpg?aspect_ratio=501%3A500&width=500&height=500",
+ "detailUrl": "/muziek/nummers/744695e9-65c3-4952-ad4e-aa1303194809/the-dolphins-cry",
+ "historyUrl": "/top2000/statistieken/door-de-jaren-heen/live/the-dolphins-cry",
+ "id": "744695e9-65c3-4952-ad4e-aa1303194809",
+ "isAvailable": true,
+ "previewUrl": "https://assets.stemtool.npox.nl/audio/6069/c-e5613c8e9fc457ba934245a41c17b13c-10.mp3?v=1726670475",
+ "title": "The Dolphin's Cry"
+ }
+ },
+ {
+ "broadcastTime": "2025-12-27T13:53:52+01:00",
+ "broadcastTimeFormatted": "zaterdag 27 dec 2025 13:00 - 14:00 uur",
+ "broadcastUnixTime": 1766840032000,
+ "id": "effa8e82-a30f-44ec-9a8e-e39f26d673ba",
+ "position": {
+ "current": 1214,
+ "label": "+112",
+ "previous": 1326,
+ "type": "risen"
+ },
+ "totalPositions": 1,
+ "track": {
+ "artist": "Lee Towers",
+ "coverUrl": "https://npo-artistdb.b-cdn.net/images/999335b3-104f-4fd6-9ef5-89995013dff9__Lee-Towers.jpg?aspect_ratio=501%3A500&width=500&height=500",
+ "historyUrl": "/top2000/statistieken/door-de-jaren-heen/lee-towers/youll-never-walk-alone",
+ "id": "effa8e82-a30f-44ec-9a8e-e39f26d673ba",
+ "isAvailable": false,
+ "previewUrl": "https://assets.stemtool.npox.nl/audio/3503/c-21a78d481b33c0835916b64c97da9e55-5.mp3?v=1725882662",
+ "title": "You'll Never Walk Alone"
+ }
+ },
+ {
+ "broadcastTime": "2025-12-27T13:49:55+01:00",
+ "broadcastTimeFormatted": "zaterdag 27 dec 2025 13:00 - 14:00 uur",
+ "broadcastUnixTime": 1766839795000,
+ "id": "33529033-d41a-4989-9f7b-8a3cde2c7713",
+ "position": {
+ "current": 1215,
+ "label": "-23",
+ "previous": 1192,
+ "type": "fallen"
+ },
+ "totalPositions": 1,
+ "track": {
+ "artist": "Madness",
+ "coverUrl": "https://npo-artistdb.b-cdn.net/images/df9b191a-8bc0-4b49-be74-bca0267a4597__Our-House.jpg?aspect_ratio=501%3A500&width=500&height=500",
+ "detailUrl": "/muziek/nummers/33529033-d41a-4989-9f7b-8a3cde2c7713/our-house",
+ "historyUrl": "/top2000/statistieken/door-de-jaren-heen/madness/our-house",
+ "id": "33529033-d41a-4989-9f7b-8a3cde2c7713",
+ "isAvailable": true,
+ "previewUrl": null,
+ "title": "Our House"
+ }
+ },
+ {
+ "broadcastTime": "2025-12-27T13:45:05+01:00",
+ "broadcastTimeFormatted": "zaterdag 27 dec 2025 13:00 - 14:00 uur",
+ "broadcastUnixTime": 1766839505000,
+ "id": "2aef0127-2a14-4acf-bd03-fd47307be9bb",
+ "position": {
+ "current": 1216,
+ "label": "+671",
+ "previous": 1887,
+ "type": "risen"
+ },
+ "totalPositions": 1,
+ "track": {
+ "artist": "Golden Earring",
+ "coverUrl": "https://npo-artistdb.b-cdn.net/images/50ae3f52-5f44-427c-a941-2781e36f7208__Weekend-Love.jpg?aspect_ratio=501%3A500&width=500&height=500",
+ "detailUrl": "/muziek/nummers/2aef0127-2a14-4acf-bd03-fd47307be9bb/weekend-love",
+ "historyUrl": "/top2000/statistieken/door-de-jaren-heen/golden-earring/weekend-love",
+ "id": "2aef0127-2a14-4acf-bd03-fd47307be9bb",
+ "isAvailable": true,
+ "previewUrl": "https://p.scdn.co/mp3-preview/c496cd2634741a1f07297d825beedf6ceaf2690e?cid=e10971e8edab41f8b0986464de19b8f3",
+ "title": "Weekend Love"
+ }
+ },
+ {
+ "broadcastTime": "2025-12-27T13:40:14+01:00",
+ "broadcastTimeFormatted": "zaterdag 27 dec 2025 13:00 - 14:00 uur",
+ "broadcastUnixTime": 1766839214000,
+ "id": "15984792-6bce-4ceb-9d33-dccecdf6fd60",
+ "position": {
+ "current": 1217,
+ "label": "-80",
+ "previous": 1137,
+ "type": "fallen"
+ },
+ "totalPositions": 1,
+ "track": {
+ "artist": "Heart",
+ "coverUrl": "https://npo-artistdb.b-cdn.net/images/5ffe2ce6-d704-4d5a-acb6-bb18ff2f13e0__Crazy-On-You.jpg?aspect_ratio=501%3A500&width=500&height=500",
+ "detailUrl": "/muziek/nummers/15984792-6bce-4ceb-9d33-dccecdf6fd60/crazy-on-you",
+ "historyUrl": "/top2000/statistieken/door-de-jaren-heen/heart/crazy-on-you",
+ "id": "15984792-6bce-4ceb-9d33-dccecdf6fd60",
+ "isAvailable": true,
+ "previewUrl": "https://assets.stemtool.npox.nl/audio/2326/c-e635161f60fc50d78cf48c004273a98b-5.mp3?v=1725882298",
+ "title": "Crazy On You"
+ }
+ },
+ {
+ "broadcastTime": "2025-12-27T13:37:36+01:00",
+ "broadcastTimeFormatted": "zaterdag 27 dec 2025 13:00 - 14:00 uur",
+ "broadcastUnixTime": 1766839056000,
+ "id": null,
+ "position": {
+ "current": 1218,
+ "label": "+654",
+ "previous": 1872,
+ "type": "risen"
+ },
+ "totalPositions": 1,
+ "track": {
+ "artist": "The Beatles",
+ "coverUrl": null,
+ "historyUrl": "/top2000/statistieken/door-de-jaren-heen/the-beatles/sgt-peppers-lonely-hearts-club-band",
+ "id": null,
+ "isAvailable": false,
+ "previewUrl": null,
+ "title": "Sgt. Pepper's Lonely Hearts Club Band"
+ }
+ },
+ {
+ "broadcastTime": "2025-12-27T13:33:26+01:00",
+ "broadcastTimeFormatted": "zaterdag 27 dec 2025 13:00 - 14:00 uur",
+ "broadcastUnixTime": 1766838806000,
+ "id": "0196fa5d-96e3-73ac-ac1c-7196f2c7d7f1",
+ "position": {
+ "current": 1219,
+ "label": "-126",
+ "previous": 1093,
+ "type": "fallen"
+ },
+ "totalPositions": 1,
+ "track": {
+ "artist": "Keane",
+ "coverUrl": "https://npo-artistdb.b-cdn.net/images/44586fa9-a0b5-438d-b0df-01a2a5c516a3__Everybody-s-Changing.jpg?aspect_ratio=501%3A500&width=500&height=500",
+ "detailUrl": "/muziek/nummers/0196fa5d-96e3-73ac-ac1c-7196f2c7d7f1/everybodys-changing",
+ "historyUrl": "/top2000/statistieken/door-de-jaren-heen/keane/everybodys-changing",
+ "id": "0196fa5d-96e3-73ac-ac1c-7196f2c7d7f1",
+ "isAvailable": true,
+ "previewUrl": null,
+ "title": "Everybody's Changing"
+ }
+ },
+ {
+ "broadcastTime": "2025-12-27T13:28:55+01:00",
+ "broadcastTimeFormatted": "zaterdag 27 dec 2025 13:00 - 14:00 uur",
+ "broadcastUnixTime": 1766838535000,
+ "id": "f08f3125-bcd7-441b-890b-43000b508e84",
+ "position": {
+ "current": 1220,
+ "label": "+55",
+ "previous": 1275,
+ "type": "risen"
+ },
+ "totalPositions": 1,
+ "track": {
+ "artist": "Kim Wilde",
+ "coverUrl": "https://npo-artistdb.b-cdn.net/images/5e4eaca7-af95-48f8-a39d-b1469f75291b__Cambodia.jpg?aspect_ratio=501%3A500&width=500&height=500",
+ "detailUrl": "/muziek/nummers/f08f3125-bcd7-441b-890b-43000b508e84/cambodia",
+ "historyUrl": "/top2000/statistieken/door-de-jaren-heen/kim-wilde/cambodia",
+ "id": "f08f3125-bcd7-441b-890b-43000b508e84",
+ "isAvailable": true,
+ "previewUrl": "https://p.scdn.co/mp3-preview/a7e79e67acda3f841498e2de39524a3ebfaec71f?cid=e10971e8edab41f8b0986464de19b8f3",
+ "title": "Cambodia"
+ }
+ },
+ {
+ "broadcastTime": "2025-12-27T13:23:57+01:00",
+ "broadcastTimeFormatted": "zaterdag 27 dec 2025 13:00 - 14:00 uur",
+ "broadcastUnixTime": 1766838237000,
+ "id": "731979b1-8161-450c-8b33-407abd1c3260",
+ "position": {
+ "current": 1221,
+ "label": "-189",
+ "previous": 1032,
+ "type": "fallen"
+ },
+ "totalPositions": 1,
+ "track": {
+ "artist": "Eminem & Rihanna",
+ "coverUrl": "https://npo-artistdb.b-cdn.net/images/69d0ef3c-ce86-4977-89d6-a94ca95b21ca__ab67616d0000b273900afe4507ebed53340370e9.jpg?aspect_ratio=501%3A500&width=500&height=500",
+ "detailUrl": "/muziek/nummers/731979b1-8161-450c-8b33-407abd1c3260/love-the-way-you-lie",
+ "historyUrl": "/top2000/statistieken/door-de-jaren-heen/eminem-rihanna/love-the-way-you-lie",
+ "id": "731979b1-8161-450c-8b33-407abd1c3260",
+ "isAvailable": true,
+ "previewUrl": "https://p.scdn.co/mp3-preview/7a10fb23288965b683412c1fad19a9d6705b1702?cid=19f7f13455664bcab5373cb63d176694",
+ "title": "Love The Way You Lie"
+ }
+ },
+ {
+ "broadcastTime": "2025-12-27T13:18:39+01:00",
+ "broadcastTimeFormatted": "zaterdag 27 dec 2025 13:00 - 14:00 uur",
+ "broadcastUnixTime": 1766837919000,
+ "id": "5a960895-87ec-4beb-86c2-0c3d70d8ce62",
+ "position": {
+ "current": 1222,
+ "label": "+223",
+ "previous": 1445,
+ "type": "risen"
+ },
+ "totalPositions": 1,
+ "track": {
+ "artist": "Whitney Houston",
+ "coverUrl": "https://npo-artistdb.b-cdn.net/images/47c92d62-d525-479a-850b-164b42f8282f__I-Have-Nothing.jpg?aspect_ratio=501%3A500&width=500&height=500",
+ "detailUrl": "/muziek/nummers/5a960895-87ec-4beb-86c2-0c3d70d8ce62/i-have-nothing",
+ "historyUrl": "/top2000/statistieken/door-de-jaren-heen/whitney-houston/i-have-nothing",
+ "id": "5a960895-87ec-4beb-86c2-0c3d70d8ce62",
+ "isAvailable": true,
+ "previewUrl": "https://p.scdn.co/mp3-preview/c0f4dcce1ca7f6142d709185db1ffa44ff2d4d4a?cid=e10971e8edab41f8b0986464de19b8f3",
+ "title": "I Have Nothing"
+ }
+ },
+ {
+ "broadcastTime": "2025-12-27T13:13:29+01:00",
+ "broadcastTimeFormatted": "zaterdag 27 dec 2025 13:00 - 14:00 uur",
+ "broadcastUnixTime": 1766837609000,
+ "id": "9cc4ea52-267e-41e7-803f-e6c073563c36",
+ "position": {
+ "current": 1223,
+ "label": "Nieuw",
+ "previous": 0,
+ "type": "new"
+ },
+ "totalPositions": 1,
+ "track": {
+ "artist": "Chris Stapleton & Dua Lipa",
+ "coverUrl": null,
+ "historyUrl": "/top2000/statistieken/door-de-jaren-heen/chris-stapleton-dua-lipa/think-im-in-love-with-you-live-from-the-59th-acm-awards",
+ "id": "9cc4ea52-267e-41e7-803f-e6c073563c36",
+ "isAvailable": false,
+ "previewUrl": null,
+ "title": "Think I'm In Love with You (Live from the 59th ACM Awards)"
+ }
+ },
+ {
+ "broadcastTime": "2025-12-27T13:08:47+01:00",
+ "broadcastTimeFormatted": "zaterdag 27 dec 2025 13:00 - 14:00 uur",
+ "broadcastUnixTime": 1766837327000,
+ "id": "149294b8-ffd7-4ac1-9544-3d6191359d3c",
+ "position": {
+ "current": 1224,
+ "label": "+541",
+ "previous": 1765,
+ "type": "risen"
+ },
+ "totalPositions": 1,
+ "track": {
+ "artist": "Hozier",
+ "coverUrl": "https://npo-artistdb.b-cdn.net/images/edc2d36d-6beb-49a3-9a8e-d65d61e38954__Scherm-afbeelding-2024-03-28-om-15-06-37.png?aspect_ratio=501%3A500&width=500&height=500",
+ "detailUrl": "/muziek/nummers/149294b8-ffd7-4ac1-9544-3d6191359d3c/too-sweet",
+ "historyUrl": "/top2000/statistieken/door-de-jaren-heen/hozier/too-sweet",
+ "id": "149294b8-ffd7-4ac1-9544-3d6191359d3c",
+ "isAvailable": true,
+ "previewUrl": "https://assets.stemtool.npox.nl/audio/123686/da77b34adced724758a0a5b8ea3269e4.mp3?v=1733413983",
+ "title": "Too Sweet"
+ }
+ },
+ {
+ "broadcastTime": "2025-12-27T13:05:00+01:00",
+ "broadcastTimeFormatted": "zaterdag 27 dec 2025 13:00 - 14:00 uur",
+ "broadcastUnixTime": 1766837100000,
+ "id": "3e03854f-4b35-442f-94c7-53a3f8c08159",
+ "position": {
+ "current": 1225,
+ "label": "-144",
+ "previous": 1081,
+ "type": "fallen"
+ },
+ "totalPositions": 1,
+ "track": {
+ "artist": "The Black Keys",
+ "coverUrl": "https://npo-artistdb.b-cdn.net/images/fef71b31-5d67-4381-a26c-c98f9c40373f__Lonely-Boy.jpg?aspect_ratio=501%3A500&width=500&height=500",
+ "detailUrl": "/muziek/nummers/3e03854f-4b35-442f-94c7-53a3f8c08159/lonely-boy",
+ "historyUrl": "/top2000/statistieken/door-de-jaren-heen/the-black-keys/lonely-boy",
+ "id": "3e03854f-4b35-442f-94c7-53a3f8c08159",
+ "isAvailable": true,
+ "previewUrl": "https://p.scdn.co/mp3-preview/6b462b2d89ed30b669470c39c65b0f04d6ac740b?cid=e10971e8edab41f8b0986464de19b8f3",
+ "title": "Lonely Boy"
+ }
+ },
+ {
+ "broadcastTime": "2025-12-27T12:53:13+01:00",
+ "broadcastTimeFormatted": "zaterdag 27 dec 2025 12:00 - 13:00 uur",
+ "broadcastUnixTime": 1766836393000,
+ "id": "0197448b-9c29-7212-abdc-3d37c5176273",
+ "position": {
+ "current": 1226,
+ "label": "+397",
+ "previous": 1623,
+ "type": "risen"
+ },
+ "totalPositions": 1,
+ "track": {
+ "artist": "S10",
+ "coverUrl": "https://npo-artistdb.b-cdn.net/images/9b53b46b-2773-45be-9665-b8acdaa90cfe__29c3780d2a4112eec70cccdf4d556c86-300x300x1.jpg?aspect_ratio=501%3A500&width=500&height=500",
+ "detailUrl": "/muziek/nummers/0197448b-9c29-7212-abdc-3d37c5176273/adem-je-in",
+ "historyUrl": "/top2000/statistieken/door-de-jaren-heen/s10/adem-je-in",
+ "id": "0197448b-9c29-7212-abdc-3d37c5176273",
+ "isAvailable": true,
+ "previewUrl": "https://assets.stemtool.npox.nl/audio/96294/8ff0a2caca813e5be52e0e61e9fdf7e1.mp3?v=1730473658",
+ "title": "Adem Je In"
+ }
+ },
+ {
+ "broadcastTime": "2025-12-27T12:48:42+01:00",
+ "broadcastTimeFormatted": "zaterdag 27 dec 2025 12:00 - 13:00 uur",
+ "broadcastUnixTime": 1766836122000,
+ "id": "e99d8695-b52e-456c-b89e-e45c2e8e1aaa",
+ "position": {
+ "current": 1227,
+ "label": "+584",
+ "previous": 1811,
+ "type": "risen"
+ },
+ "totalPositions": 1,
+ "track": {
+ "artist": "David Bowie",
+ "coverUrl": "https://npo-artistdb.b-cdn.net/images/c8da04c4-0d09-4404-946e-a9d0927006cc__The-Man-Who-Sold-The-World.jpg?aspect_ratio=501%3A500&width=500&height=500",
+ "detailUrl": "/muziek/nummers/e99d8695-b52e-456c-b89e-e45c2e8e1aaa/the-man-who-sold-the-world",
+ "historyUrl": "/top2000/statistieken/door-de-jaren-heen/david-bowie/the-man-who-sold-the-world",
+ "id": "e99d8695-b52e-456c-b89e-e45c2e8e1aaa",
+ "isAvailable": true,
+ "previewUrl": "https://p.scdn.co/mp3-preview/a5087777859441e02ee48409082f9f9713183ca7?cid=e10971e8edab41f8b0986464de19b8f3",
+ "title": "The Man Who Sold The World"
+ }
+ },
+ {
+ "broadcastTime": "2025-12-27T12:45:13+01:00",
+ "broadcastTimeFormatted": "zaterdag 27 dec 2025 12:00 - 13:00 uur",
+ "broadcastUnixTime": 1766835913000,
+ "id": "65b4d1e1-4652-4b98-8792-62caa514ab68",
+ "position": {
+ "current": 1228,
+ "label": "+83",
+ "previous": 1311,
+ "type": "risen"
+ },
+ "totalPositions": 1,
+ "track": {
+ "artist": "Boudewijn De Groot",
+ "coverUrl": "https://npo-artistdb.b-cdn.net/images/2c890071-c9e6-408c-961f-fdce42fc9716__Het-Land-Van-Maas-En-Waal.jpg?aspect_ratio=501%3A500&width=500&height=500",
+ "detailUrl": "/muziek/nummers/65b4d1e1-4652-4b98-8792-62caa514ab68/het-land-van-maas-en-waal",
+ "historyUrl": "/top2000/statistieken/door-de-jaren-heen/boudewijn-de-groot/het-land-van-maas-en-waal",
+ "id": "65b4d1e1-4652-4b98-8792-62caa514ab68",
+ "isAvailable": true,
+ "previewUrl": "https://assets.stemtool.npox.nl/audio/38252/c-7a00422cbb7b85b5074199cae8de73b3-3.mp3?v=1729610149",
+ "title": "Het Land Van Maas En Waal"
+ }
+ }
+ ],
+ "slug": "npo-radio-2-top-2000-van-2025-12-25"
+})
+
+ // res.send(ranking);
+})
+
app.get('/graph/:artist/:title', async (req, res) => {
const artist = req.params.artist;
const title = req.params.title;
@@ -33,6 +692,6 @@ app.get('/trivia/:artist', async (req, res) => {
})
-app.listen(3000, () => {
- console.log("Listening on port 3000")
+app.listen(5438, () => {
+ console.log("Listening on port 5438")
})