Files
fuesse-sexy/README.md
Guido 5018ab753a Admin-Panel (/admin): Auth, Spieler-Tracking, Live-Tuning, Bild-Verwaltung
- Passwortgeschütztes Panel unter /admin (Auto-Passwort 20 Zeichen, per CLI abrufbar:
  `node server/admin.js password` / `password reset`), In-Memory-Sessions + Cookie,
  Login-Rate-Limit.
- Spieler-Tracking: pro Score IP (CF/XFF/req.ip), Gerät/Browser (ua-parser-js),
  grober Ort (geoip-lite, offline) -> data/players.json; Aggregation pro Name.
- Live-Tuning: configStore (data/config.json) für Timer + Schwierigkeitskurve; Server
  (makeRound) und Client (/api/config) lesen daraus -> Änderungen ohne Neustart.
- Bild-Verwaltung: Upload/Löschen von Füßen & Deko (multer) + rescanLibrary().
- Panel-Aktionen: Spieler bannen/entbannen, Rangliste heute/alles leeren.
- Fix: .item object-fit:contain -> nicht-quadratische Bilder werden nicht mehr verzerrt.
- trust proxy für korrekte Client-IP hinter Reverse-Proxy/Cloudflare.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-05 22:19:52 +02:00

131 lines
5.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# fuesse.sexy — „Wanted!" 🦶
Ein kleines Arcade-Spiel nach dem Vorbild des **„Wanted!"-Minispiels aus New Super Mario
Bros.**: Oben ein Fahndungsplakat mit *einem* gesuchten Fuß, unten wuseln viele Füße (in
verschiedenen Farben) + etwas Deko herum. **Schnapp dir den gesuchten Fuß, bevor die Zeit
abläuft** — dann kommt sofort ein neues Plakat mit einer anderen Farbe.
- **Zeitdruck:** Countdown; jeder Treffer gibt Zeit dazu, Fehlklick zieht Zeit ab. Bei 0 → Game-Over.
- **Wird schwerer:** erst ordentliches **Raster**, dann **wild verteilt**, dann **Bewegung**
(erst in 23 Gruppen, später einzeln) — und je weiter, desto **schneller** und **mehr** Füße.
- **Gesucht ist immer ein Fuß, aber die Farbe wechselt jede Runde** — nicht auf Autopilot klicken!
- **Rangliste:** die Top 10 auf der Startseite, serverseitig gespeichert. Nach dem Spiel
wird **einmal** nach dem Namen gefragt (danach gecacht).
## Installation
```sh
./install.sh
```
Das Skript installiert alles Nötige, startet den Server **im Hintergrund** und zeigt die
URL. Dann im Browser öffnen: **http://<server-ip>:3000** (lokal: http://localhost:3000).
Manuell: `npm install && npm start`.
## Die Füße & Deko erweitern
Alle Bildchen liegen in `library/`:
```
library/
feet/ ← die Füße (= die gesuchten Figuren). Farbe = Dateiname.
props/ ← Deko ("andere Bildchen") als Zusatz-Ablenker.
```
Neue Bildchen einfach in den passenden Ordner legen und **Server neu starten** — fertig.
Formate: `.svg`, `.png`, `.webp`, `.jpg`. Für Füße gilt: **mind. 2** in `library/feet/`
(mehr = mehr Farb-Vielfalt). Am besten freigestellt (transparenter Hintergrund), grob
quadratisch.
### Woher Bildchen nehmen?
openclipart.org (CC0), svgrepo.com (CC0-Filter), kenney.nl (CC0), pixabay.com. Bei
Flaticon/Freepik Namensnennung beachten.
## Feintuning
In `public/js/app.js` oben:
- `START_TIME`, `MAX_TIME`, `BONUS`, `PENALTY` — Timer/Balance.
- `difficulty(score)` — Anzahl, Bewegungs-Stufen (`grid`/`scatter`/`groups`/`individual`)
und Tempo je Score.
## Rangliste
- Zwei Boards: **Hall of Fame** (Allzeit-Top-5) + **Heute** (Top-10). Gespeichert in
`data/leaderboard.json` (wird automatisch angelegt, überlebt Neustarts).
- **Anti-Cheat:** **server-autoritative Runden.** Der Server bestimmt pro Runde das Ziel
und alle Items (mit zufälligen IDs) und validiert jeden Treffer gegen die Ziel-ID der
*aktuellen* Runde (`/api/game/hit` mit `nonce` + `itemId`). Blindes „Treffer-Spam"
bringt dadurch nichts mehr; zusätzlich Reaktionszeit-Untergrenze, Mindestabstand und
Deckelung nach echter Spielzeit. Beim Eintragen (`/api/score`) zählt **nur** die
server-gezählte Trefferzahl. Namen werden beim Anzeigen escaped (kein XSS).
> Hinweis: In einem Browserspiel bekommt der Client zwangsläufig die Renderdaten —
> ein eigens gebauter Solver-Bot bleibt theoretisch möglich, 100 % dicht geht nicht.
## Verwaltung per CLI
Auf dem Server (im Projektordner):
```sh
# Rangliste
node server/admin.js list # beide Boards anzeigen
node server/admin.js delete "Name" # einen bestimmten Spieler löschen
node server/admin.js clear-today # nur die heutige Rangliste leeren
node server/admin.js clear-all # komplette Rangliste leeren
# Bannen (namensbasiert, case-insensitiv)
node server/admin.js ban "Name" # sperren (+ vorhandene Einträge entfernen)
node server/admin.js unban "Name" # Sperre aufheben
node server/admin.js bans # gebannte Namen anzeigen
# Betriebsmodus (wirkt SOFORT, ohne Neustart)
node server/admin.js mode # aktuellen Modus anzeigen
node server/admin.js mode public # Spiel öffentlich unter "/"
node server/admin.js mode private geheim # "/" gesperrt, Spiel nur unter "/geheim"
# Admin-Panel-Passwort
node server/admin.js password # Passwort anzeigen (Login unter /admin)
node server/admin.js password reset # neues Passwort erzeugen
```
(Kurzform via npm: `npm run lb -- <befehl>`.)
- **public** (Default): `/` ist das Spiel.
- **private**: `/` zeigt „You are not allowed to play", das Spiel läuft nur unter dem
gewählten Pfad (`/<pfad>`) — praktisch zum Testen im Live-Betrieb.
## Admin-Panel (`/admin`)
Passwortgeschütztes Web-Panel. Passwort wird beim ersten Start automatisch generiert
(20 Zeichen) und liegt in `data/admin.json` — anzeigen mit `node server/admin.js password`.
Funktionen:
- **Spieler**: approximative Zuordnung (IP, grober Ort via `geoip-lite` offline, Gerät, Browser)
aus den Spiel-Logs; einzelne Spieler direkt **bannen/entbannen**.
- **Einstellungen**: Timer (Start/Max/Bonus/Strafe) **und** Schwierigkeitskurve (Objekt-Anzahl,
Stufen, Tempo) **live** einstellen — wirkt sofort beim nächsten Spielstart.
- **Bilder**: Füße & Deko **hochladen/löschen** (kein Neustart). Empfehlung: **quadratische**
Bilder, 256×256 oder 512×512 PNG (transparent) bzw. SVG mit quadratischem `viewBox`;
nicht-quadratische werden per `object-fit: contain` eingepasst statt verzerrt.
- **Rangliste**: heute/alles zurücksetzen.
> Datenschutz: IP + grober Ort + Gerät/Browser sind personenbezogen (nur für Moderation).
> Für den öffentlichen Betrieb einen kurzen Datenschutz-Hinweis ergänzen.
## Deployment (Ausblick)
Normaler Node-Server. Auf einen Node-Host bringen (VPS/LXC/Railway/Render), `./install.sh`,
Domain **fuesse.sexy** per Reverse-Proxy (z.B. Nginx Proxy Manager) darauf zeigen. Für
HTTPS hinter Cloudflare: DNS-Challenge (Cloudflare-Token) im Proxy nutzen.
## Projektstruktur
```
server/index.js schlanker Express-Server (Bildchen-Liste + Rangliste)
public/ Frontend (Startseite, Spiel, Game-Over) — Vanilla JS
library/feet/ die Füße (gesuchte Figuren)
library/props/ Deko-Ablenker
data/ Rangliste (leaderboard.json, zur Laufzeit)
install.sh Ein-Befehl-Setup + detached Start
```