diff --git a/.github/workflows/sync-leaderboard.yml b/.github/workflows/sync-leaderboard.yml index c2ca5952..44b0e87c 100644 --- a/.github/workflows/sync-leaderboard.yml +++ b/.github/workflows/sync-leaderboard.yml @@ -55,6 +55,7 @@ jobs: # 2. Run sync export DATA_DIR=db-repo + export DATA_REPO_TOKEN=${{ secrets.DATA_REPO_TOKEN }} node scripts/sync-leaderboard.js # 3. Stage changes (everything except users.json) diff --git a/frontend/leaderboard.html b/frontend/leaderboard.html index 242c6f83..0119ac10 100644 --- a/frontend/leaderboard.html +++ b/frontend/leaderboard.html @@ -11,6 +11,25 @@ rel="stylesheet" /> + @@ -332,6 +351,16 @@

Leaderboard

`; renderLeaderboard(filteredData); } + function getRankChangeTag(rankChange) { + if (!rankChange) return ""; + if (rankChange === "NEW") + return `[new]`; + if (rankChange === "=") + return `[==]`; + if (rankChange.startsWith("+")) + return `[${rankChange}]`; + return `[${rankChange}]`; + } function getRankTag(rank) { switch (rank) { case 1: @@ -391,7 +420,7 @@

Leaderboard

row.className = "leaderboard-row"; row.innerHTML = `
${rank}
-
${tag}${user.name}
+
${tag}${user.name}${getRankChangeTag(user.rankChange)}
${user.id} Leaderboard
-
${tag}${user.name}
+
${tag}${user.name}${getRankChangeTag(user.rankChange)}
${user.id} { + previousRanks[user.id] = idx + 1; + }); + } + + currentSorted.forEach((user, idx) => { + const currentRank = idx + 1; + + if (previousRanks[user.id] === undefined) { + user.rankChange = "NEW"; + } else { + const delta = previousRanks[user.id] - currentRank; + if (delta > 0) user.rankChange = `+${delta}`; + else if (delta < 0) user.rankChange = `${delta}`; + else user.rankChange = "="; + } + }); +} + (async () => { const DATA_DIR = process.env.DATA_DIR || path.join(__dirname, "..", "data"); console.log(`Using data directory: ${DATA_DIR}`); @@ -87,6 +153,7 @@ function getFileName(daysAgo) { overallData.sort((a, b) => b.score - a.score); console.log("Writing sorted daily data to overall file..."); const overallFilepath = path.join(DATA_DIR, "overall.json"); + await computeRankChanges(overallData, "overall.json"); try { fs.writeFileSync( overallFilepath, @@ -144,6 +211,7 @@ function getFileName(daysAgo) { console.log("Writing sorted daily data to daily.json..."); const dailyFilepath = path.join(DATA_DIR, "daily.json"); + await computeRankChanges(dailyData, "daily.json"); try { fs.writeFileSync(dailyFilepath, JSON.stringify(dailyData, null, 2), "utf8"); console.log("Daily data saved successfully"); @@ -199,6 +267,7 @@ function getFileName(daysAgo) { console.log("Writing sorted weekly data to weekly.json..."); const weeklyFilepath = path.join(DATA_DIR, "weekly.json"); + await computeRankChanges(weeklyData, "weekly.json"); try { fs.writeFileSync( weeklyFilepath, @@ -258,6 +327,7 @@ function getFileName(daysAgo) { console.log("Writing sorted monthly data to monthly.json..."); const monthlyFilepath = path.join(DATA_DIR, "monthly.json"); + await computeRankChanges(monthlyData, "monthly.json"); try { fs.writeFileSync( monthlyFilepath,