96 lines
2.5 KiB
JavaScript
96 lines
2.5 KiB
JavaScript
(() => {
|
|
"use strict";
|
|
|
|
function escapeHtml(value) {
|
|
return String(value ?? "").replace(/[&<>"']/g, (ch) => ({
|
|
"&": "&",
|
|
"<": "<",
|
|
">": ">",
|
|
'"': """,
|
|
"'": "'",
|
|
}[ch]));
|
|
}
|
|
|
|
function fmtNumber(value) {
|
|
const n = Number(value || 0);
|
|
return Number.isFinite(n) ? n.toLocaleString() : "0";
|
|
}
|
|
|
|
function statusText(row) {
|
|
if (row.Alive === false || row.alive === false) return "Dead";
|
|
return "Alive";
|
|
}
|
|
|
|
function fitName(value, width) {
|
|
const s = String(value || "—").trimEnd();
|
|
if (s.length <= width) return s.padEnd(width, " ");
|
|
return s.slice(0, Math.max(0, width - 1)) + "…";
|
|
}
|
|
|
|
function fitPoints(value, width) {
|
|
return `${fmtNumber(value)} pts`.padStart(width, " ");
|
|
}
|
|
|
|
async function loadHomeHardcoreLeaderboard() {
|
|
const list = document.querySelector("#home-hardcore-leaderboard-body");
|
|
if (!list) return;
|
|
|
|
const cacheBucket = Math.floor(Date.now() / 300000);
|
|
const urls = [
|
|
`/generated/hardcore-leaderboard-points.json?v=${cacheBucket}`,
|
|
"/hardcore/leaderboard/points",
|
|
];
|
|
|
|
let rows = null;
|
|
let lastError = null;
|
|
|
|
for (const url of urls) {
|
|
try {
|
|
const res = await fetch(url, { credentials: "same-origin" });
|
|
if (!res.ok) {
|
|
lastError = new Error(`${url}: HTTP ${res.status}`);
|
|
continue;
|
|
}
|
|
|
|
const data = await res.json();
|
|
rows = Array.isArray(data) ? data : (data.rows || []);
|
|
break;
|
|
} catch (err) {
|
|
lastError = err;
|
|
}
|
|
}
|
|
|
|
if (!rows) {
|
|
list.innerHTML = `<li><span class="rank">!</span><span>${escapeHtml(lastError?.message || "Unable to load.")}</span></li>`;
|
|
return;
|
|
}
|
|
|
|
const top = rows.slice(0, 5);
|
|
|
|
if (!top.length) {
|
|
list.innerHTML = `<li><span class="rank">1.</span><span>—</span></li>`;
|
|
return;
|
|
}
|
|
|
|
list.innerHTML = top.map((row, idx) => {
|
|
const rank = idx + 1;
|
|
const name = row.PlayerName || row.CharacterName || row.character_name || "—";
|
|
const points = row.Points ?? row.TotalPoints ?? 0;
|
|
const status = statusText(row);
|
|
|
|
const line = `${fitName(name, 12)} ${fitPoints(points, 7)} ${status}`;
|
|
|
|
return `<li>
|
|
<span class="rank">${rank}.</span>
|
|
<span class="home-hardcore-line">${escapeHtml(line)}</span>
|
|
</li>`;
|
|
}).join("");
|
|
}
|
|
|
|
if (document.readyState === "loading") {
|
|
document.addEventListener("DOMContentLoaded", loadHomeHardcoreLeaderboard);
|
|
} else {
|
|
loadHomeHardcoreLeaderboard();
|
|
}
|
|
})();
|