// Gemeinsame Ranglisten-Logik fuer Server (index.js) und CLI (admin.js). // Zwei Ansichten aus derselben Datei: Allzeit-Top-5 + Heute-Top-10. import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs'; import { dirname, join } from 'node:path'; import { fileURLToPath } from 'node:url'; const __dirname = dirname(fileURLToPath(import.meta.url)); const DATA_DIR = join(__dirname, '..', 'data'); export const LEADERBOARD_FILE = join(DATA_DIR, 'leaderboard.json'); const ALLTIME_COUNT = 5; const TODAY_COUNT = 10; const KEEP_ALLTIME = 100; // Datei klein halten export function readLeaderboard() { try { if (!existsSync(LEADERBOARD_FILE)) return []; const data = JSON.parse(readFileSync(LEADERBOARD_FILE, 'utf8')); return Array.isArray(data) ? data : []; } catch (err) { console.warn('[leaderboard] Datei unlesbar:', err.message); return []; } } export function writeLeaderboard(list) { if (!existsSync(DATA_DIR)) mkdirSync(DATA_DIR, { recursive: true }); writeFileSync(LEADERBOARD_FILE, JSON.stringify(list, null, 2)); } export function topN(list, n) { return [...list].sort((a, b) => b.score - a.score).slice(0, n); } // Server-lokaler Tages-Schluessel (YYYY-M-D) function dayKey(d) { return `${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}`; } export function isToday(entry) { return entry && entry.at && dayKey(new Date(entry.at)) === dayKey(new Date()); } // Zwei Ranglisten aus derselben Liste export function buildBoards(list) { return { allTime: topN(list, ALLTIME_COUNT), today: topN(list.filter(isToday), TODAY_COUNT), }; } // Score eintragen -> aktualisierte Boards. Behaelt Allzeit-Top-100 + alle heutigen Eintraege. export function addScore(name, score) { const list = readLeaderboard(); list.push({ name, score, at: new Date().toISOString() }); const keep = topN(list, KEEP_ALLTIME); const keepSet = new Set(keep); for (const e of list) if (isToday(e) && !keepSet.has(e)) keep.push(e); writeLeaderboard(keep); return buildBoards(keep); } // --- Verwaltung (CLI) --- // Loescht alle Eintraege eines Spielers (Name case-insensitiv exakt). Gibt Anzahl zurueck. export function deletePlayer(name) { const target = String(name || '').trim().toLowerCase(); if (!target) return 0; const list = readLeaderboard(); const kept = list.filter((e) => String(e.name || '').trim().toLowerCase() !== target); writeLeaderboard(kept); return list.length - kept.length; } // Leert die gesamte Rangliste. Gibt Anzahl geloeschter Eintraege zurueck. export function clearAll() { const n = readLeaderboard().length; writeLeaderboard([]); return n; } // Entfernt nur die heutigen Eintraege. Gibt Anzahl zurueck. export function clearToday() { const list = readLeaderboard(); const kept = list.filter((e) => !isToday(e)); writeLeaderboard(kept); return list.length - kept.length; }