Treffer-Toleranz, 2 Ranglisten, Anti-Cheat, CLI-Modi & Icons
- Treffer-Toleranz: Ziel wird geometrisch + bevorzugt getroffen, auch wenn verdeckt - Zwei Ranglisten: Hall of Fame (Allzeit-Top-5) + Heute (Top-10) - Anti-Cheat: server-autoritative Sessions (start/hit), Score = Server-Zahl, Mindestabstand gegen Auto-Klicker, Deckelung nach Spielzeit; Score ohne Session -> 400 - CLI (server/admin.js): list / delete <name> / clear-today / clear-all - Zwei Betriebsmodi per CLI (live, ohne Neustart): public (/ = Spiel) und private (/ gesperrt, Spiel unter geheimem /pfad) + "not allowed to play"-Seite - Board-Icons von Emojis auf echte SVG-Icons, Board heisst "Hall of Fame" Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
87
server/admin.js
Normal file
87
server/admin.js
Normal file
@@ -0,0 +1,87 @@
|
||||
// Rangliste per Kommandozeile verwalten.
|
||||
// Aufruf: node server/admin.js <befehl> [argument]
|
||||
// (oder ueber npm: npm run lb -- <befehl> [argument])
|
||||
//
|
||||
// Befehle:
|
||||
// list zeigt beide Ranglisten (Allzeit + Heute)
|
||||
// delete "<name>" loescht ALLE Eintraege eines Spielers (Name exakt, Gross/Klein egal)
|
||||
// clear-today loescht nur die heutigen Eintraege
|
||||
// clear-all loescht die komplette Rangliste
|
||||
|
||||
import { readLeaderboard, buildBoards, deletePlayer, clearAll, clearToday } from './leaderboardStore.js';
|
||||
import { getMode, setMode } from './modeStore.js';
|
||||
|
||||
const [, , cmd, ...rest] = process.argv;
|
||||
const arg = rest.join(' ').trim();
|
||||
|
||||
function printBoards() {
|
||||
const { allTime, today } = buildBoards(readLeaderboard());
|
||||
const fmt = (list) =>
|
||||
list.length
|
||||
? list.map((e, i) => ` ${String(i + 1).padStart(2)}. ${e.name} — ${e.score}`).join('\n')
|
||||
: ' (leer)';
|
||||
console.log('\n🏆 Allzeit (Top 5)\n' + fmt(allTime));
|
||||
console.log('\n📅 Heute (Top 10)\n' + fmt(today) + '\n');
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case 'list':
|
||||
printBoards();
|
||||
break;
|
||||
|
||||
case 'delete': {
|
||||
if (!arg) {
|
||||
console.error('Bitte einen Namen angeben: node server/admin.js delete "Name"');
|
||||
process.exit(1);
|
||||
}
|
||||
const n = deletePlayer(arg);
|
||||
console.log(n > 0 ? `✅ ${n} Eintrag/Eintraege von "${arg}" geloescht.` : `Keine Eintraege für "${arg}" gefunden.`);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'clear-today': {
|
||||
const n = clearToday();
|
||||
console.log(`✅ ${n} heutige Eintrag/Eintraege geloescht.`);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'clear-all': {
|
||||
const n = clearAll();
|
||||
console.log(`✅ Rangliste geleert (${n} Eintraege entfernt).`);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'mode': {
|
||||
const sub = (rest[0] || '').toLowerCase();
|
||||
if (sub === 'public') {
|
||||
setMode('public');
|
||||
console.log('✅ Modus: PUBLIC — das Spiel ist unter "/" erreichbar.');
|
||||
} else if (sub === 'private') {
|
||||
const slug = rest[1] || getMode().path;
|
||||
const m = setMode('private', slug);
|
||||
console.log(`✅ Modus: PRIVATE — "/" zeigt "nicht erlaubt".`);
|
||||
console.log(` Spiel jetzt nur unter: /${m.path}`);
|
||||
} else {
|
||||
const m = getMode();
|
||||
console.log(`Aktueller Modus: ${m.mode.toUpperCase()}` + (m.mode === 'private' ? ` (Spiel unter /${m.path})` : ''));
|
||||
console.log('Umschalten: node server/admin.js mode public | node server/admin.js mode private [pfad]');
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
console.log(`füsse.sexy — Verwaltung:
|
||||
|
||||
Rangliste:
|
||||
node server/admin.js list beide Ranglisten anzeigen
|
||||
node server/admin.js delete "<name>" einen bestimmten Spieler loeschen
|
||||
node server/admin.js clear-today nur die heutige Rangliste leeren
|
||||
node server/admin.js clear-all komplette Rangliste leeren
|
||||
|
||||
Betriebsmodus (Spiel oeffentlich / privat):
|
||||
node server/admin.js mode aktuellen Modus anzeigen
|
||||
node server/admin.js mode public Spiel oeffentlich unter "/"
|
||||
node server/admin.js mode private [pfad] "/" gesperrt, Spiel unter "/<pfad>" (Default: play)
|
||||
`);
|
||||
if (cmd) process.exit(1);
|
||||
}
|
||||
Reference in New Issue
Block a user