// Formatiert Sekunden als m:ss. Bei ungültigem Wert wird ein Platzhalter angezeigt. function formatTime(seconds) { if (typeof seconds !== "number" || Number.isNaN(seconds)) { return "-"; } const minutes = Math.floor(seconds / 60); const remainingSeconds = Math.floor(seconds % 60); return `${minutes}:${String(remainingSeconds).padStart(2, "0")}`; } // Liefert den aktuellen Login-Kontext, falls Auth global verfügbar ist. function getLoggedInAuth() { if (!window.AppAuth || typeof window.AppAuth.getAuth !== "function") { return null; } const auth = window.AppAuth.getAuth(); if (!auth || !auth.username) { return null; } return auth; } // Vereinheitlicht Benutzernamen für robuste Vergleiche (z. B. Groß-/Kleinschreibung). function normalizeUsername(username) { return String(username ?? "").trim().toLowerCase(); } function getLoggedInUsername() { const auth = getLoggedInAuth(); if (!auth) { return null; } return normalizeUsername(auth.username); } // Nutzt den vom Backend gelieferten Rang, fallback auf die aktuelle Listenposition. function getDisplayedRank(entry, index) { const place = Number(entry?.place); if (!Number.isNaN(place) && place > 0) { return place; } return index + 1; } // Bestes Ergebnis: höchste Punktzahl, bei Gleichstand die geringere Zeit. function getBestScoreEntry(entries) { return entries .slice() .sort((a, b) => { const scoreA = Number(a.score ?? 0); const scoreB = Number(b.score ?? 0); if (scoreB !== scoreA) { return scoreB - scoreA; } const timeA = Number(a.time ?? Number.MAX_SAFE_INTEGER); const timeB = Number(b.time ?? Number.MAX_SAFE_INTEGER); return timeA - timeB; })[0] ?? null; } async function getCurrentUserLeaderboardEntry(username) { if (!window.ScoreService || !username) { return null; } const scoreService = new window.ScoreService(window.config); const result = await scoreService.getScoreByName(username); if (!result.ok || !Array.isArray(result.body) || result.body.length === 0) { return null; } return getBestScoreEntry(result.body); } // Rendert die Top-Liste und markiert den eingeloggten Nutzer visuell. function renderLeaderboard(entries, extraUserEntry = null) { const tableBody = document.getElementById("leaderboard-body"); if (!tableBody) { return; } const loggedInUsername = getLoggedInUsername(); tableBody.innerHTML = ""; entries.forEach((entry, index) => { const row = document.createElement("tr"); const rowUsername = normalizeUsername(entry.username); if (loggedInUsername && rowUsername === loggedInUsername) { row.classList.add("leaderboard-row-current-user"); } row.innerHTML = ` ${getDisplayedRank(entry, index)} ${entry.username ?? "-"} ${formatTime(entry.time)} min ${entry.score ?? "-"} `; tableBody.appendChild(row); }); if (extraUserEntry) { // Trennt Top-10 und eigenen Eintrag optisch, wenn der Nutzer nicht in den Top-10 ist. const spacerRow = document.createElement("tr"); spacerRow.classList.add("leaderboard-row-gap"); spacerRow.innerHTML = ''; tableBody.appendChild(spacerRow); const userRow = document.createElement("tr"); userRow.classList.add("leaderboard-row-current-user"); userRow.classList.add("leaderboard-row-current-user-extra"); userRow.innerHTML = ` ${getDisplayedRank(extraUserEntry, 0)} ${extraUserEntry.username ?? "-"} ${formatTime(extraUserEntry.time)} min ${extraUserEntry.score ?? "-"} `; tableBody.appendChild(userRow); } } async function loadTopTenLeaderboard() { const leaderboardService = new window.LeaderboardService(window.config); const result = await leaderboardService.getLeaderboard(0, 10); if (!result.ok || !Array.isArray(result.body)) { renderLeaderboard([]); return; } const auth = getLoggedInAuth(); let extraUserEntry = null; if (auth && auth.username) { const loggedInUsername = normalizeUsername(auth.username); // Falls der Nutzer nicht in den Top-10 erscheint, wird sein bestes Ergebnis separat gezeigt. const isInTopTen = result.body.some( (entry) => normalizeUsername(entry.username) === loggedInUsername, ); if (!isInTopTen) { extraUserEntry = await getCurrentUserLeaderboardEntry(auth.username); } } renderLeaderboard(result.body, extraUserEntry); } window.initLeaderboardPage = function initLeaderboardPage() { loadTopTenLeaderboard().catch((error) => { console.error("Fehler beim Laden des Leaderboards:", error); renderLeaderboard([]); }); };