Compare commits
No commits in common. "leaderboard" and "main" have entirely different histories.
leaderboar
...
main
@ -213,67 +213,3 @@ p {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Table styles leaderboard */
|
|
||||||
.leaderboard-table {
|
|
||||||
border-collapse: collapse;
|
|
||||||
width: 100%;
|
|
||||||
background: #ffffff;
|
|
||||||
border-radius: 10px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.leaderboard-table th,
|
|
||||||
.leaderboard-table td {
|
|
||||||
padding: 8px;
|
|
||||||
text-align: left;
|
|
||||||
border-bottom: 1px solid #ddd;
|
|
||||||
}
|
|
||||||
|
|
||||||
.leaderboard-table thead th {
|
|
||||||
background: #1b1b2f;
|
|
||||||
color: #ffffff;
|
|
||||||
font-weight: 600;
|
|
||||||
letter-spacing: 0.02em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.leaderboard-table tbody tr {
|
|
||||||
transition: background-color 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.leaderboard-table tbody tr:nth-child(even) {
|
|
||||||
background-color: #f7f9fc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.leaderboard-table tbody tr:hover {
|
|
||||||
background-color: #dbe6f7;
|
|
||||||
}
|
|
||||||
|
|
||||||
.leaderboard-table tbody tr.leaderboard-row-current-user,
|
|
||||||
.leaderboard-table tbody tr.leaderboard-row-current-user:nth-child(even),
|
|
||||||
.leaderboard-table tbody tr.leaderboard-row-current-user:hover {
|
|
||||||
background-color: #dff3df;
|
|
||||||
}
|
|
||||||
|
|
||||||
.leaderboard-table tbody tr.leaderboard-row-current-user td {
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.leaderboard-table tbody tr.leaderboard-row-gap td {
|
|
||||||
border-bottom: none;
|
|
||||||
padding: 0;
|
|
||||||
height: 16px;
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.leaderboard-table tbody tr.leaderboard-row-gap:hover,
|
|
||||||
.leaderboard-table tbody tr.leaderboard-row-gap:hover td {
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.leaderboard-table tbody tr.leaderboard-row-current-user-extra td {
|
|
||||||
border-top: 2px solid #b8dfb8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.leaderboard-table tbody tr:last-child td {
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
@ -58,7 +58,6 @@
|
|||||||
<script src="assets/src/service/score-service.js"></script>
|
<script src="assets/src/service/score-service.js"></script>
|
||||||
<script src="assets/src/service/leaderboard-service.js"></script>
|
<script src="assets/src/service/leaderboard-service.js"></script>
|
||||||
<script src="js/login.js"></script>
|
<script src="js/login.js"></script>
|
||||||
<script src="js/leaderboard.js"></script>
|
|
||||||
<!--Navigation Script -->
|
<!--Navigation Script -->
|
||||||
<script src="js/navigation.js"></script>
|
<script src="js/navigation.js"></script>
|
||||||
|
|
||||||
|
|||||||
@ -1,164 +0,0 @@
|
|||||||
// 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 = `
|
|
||||||
<td>${getDisplayedRank(entry, index)}</td>
|
|
||||||
<td>${entry.username ?? "-"}</td>
|
|
||||||
<td>${formatTime(entry.time)} min</td>
|
|
||||||
<td>${entry.score ?? "-"}</td>
|
|
||||||
`;
|
|
||||||
|
|
||||||
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 = '<td colspan="4"></td>';
|
|
||||||
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 = `
|
|
||||||
<td>${getDisplayedRank(extraUserEntry, 0)}</td>
|
|
||||||
<td>${extraUserEntry.username ?? "-"}</td>
|
|
||||||
<td>${formatTime(extraUserEntry.time)} min</td>
|
|
||||||
<td>${extraUserEntry.score ?? "-"}</td>
|
|
||||||
`;
|
|
||||||
|
|
||||||
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([]);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
@ -23,9 +23,6 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
if (page === "login" && typeof window.initLoginPage === "function") {
|
if (page === "login" && typeof window.initLoginPage === "function") {
|
||||||
window.initLoginPage();
|
window.initLoginPage();
|
||||||
}
|
}
|
||||||
if (page === "leaderboard" && typeof window.initLeaderboardPage === "function") {
|
|
||||||
window.initLeaderboardPage();
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.error("Fehler beim Laden von " + page + ":", error);
|
console.error("Fehler beim Laden von " + page + ":", error);
|
||||||
|
|||||||
@ -1,19 +1,5 @@
|
|||||||
<!-- Hauptbereich der Rangliste -->
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h2 class="mb-3">Leaderboard</h2>
|
<h2 class="mb-3">Leaderboard</h2>
|
||||||
|
|
||||||
<!-- Tabellarische Darstellung der besten Eintraege -->
|
<p class="mt-2">Hier kannst du die besten Spieler und ihre Scores sehen.</p>
|
||||||
<table class="leaderboard-table">
|
|
||||||
<thead>
|
|
||||||
<!-- Spalten fuer Rang, Nutzer, Zeit und Punkte -->
|
|
||||||
<tr>
|
|
||||||
<th>Rank</th>
|
|
||||||
<th>User</th>
|
|
||||||
<th>time</th>
|
|
||||||
<th>Score</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<!-- Wird zur Laufzeit durch js/leaderboard.js befuellt -->
|
|
||||||
<tbody id="leaderboard-body"></tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user