docs: add PROJECT_MAP, AGENTS.md; add PROJECT_MAP update rule to CLAUDE.md
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
# Codex Instructions – helldivers
|
||||
|
||||
## Pflichtlektüre vor dem ersten Code-Zugriff
|
||||
Lies **PROJECT_MAP.md** in diesem Verzeichnis – sie enthält alle Funktionen, API-Routen, WebSocket-Message-Types, State-Struktur und Datenbank-Details.
|
||||
|
||||
## Projekt-Überblick
|
||||
- **Port:** 3012
|
||||
- **Typ:** Authenticated Multiplayer App (WebSocket, SQLite, ELO-Rating)
|
||||
- **Stack:** Node.js / Express, WebSocket (ws), SQLite (better-sqlite3), bcrypt, Helmet, rate-limit, Vanilla JS
|
||||
- **Features:** Stratagem-Trainer (Timed/Endless/Drill/Speedrun), 1v1-Multiplayer-Matches, ELO-Rangliste, Tages-Challenge, Admin-Panel
|
||||
|
||||
## Struktur
|
||||
```
|
||||
helldivers/
|
||||
├── server.js # Express + WebSocket + SQLite (~650 Zeilen)
|
||||
├── public/app.js # Gesamte Client-Logik (~1840 Zeilen)
|
||||
├── public/styles.css
|
||||
├── public/index.html
|
||||
├── scripts/ # DB-Migrations / Seed
|
||||
└── data/helldivers.db # SQLite (Scores, Users, History, Sessions)
|
||||
```
|
||||
|
||||
## Git-Workflow
|
||||
1. Branch: immer `bugfixes-features` für Änderungen
|
||||
2. Commit: `type: kurze Beschreibung` – **keine Co-Authored-By-Zeile**
|
||||
3. Vor Commit: `CHANGELOG.md` aktualisieren
|
||||
4. Vor Commit: `PROJECT_MAP.md` aktualisieren, falls Funktionen/Routen/WS-Types geändert wurden
|
||||
5. `git add` nur einzelne Dateien – kein `git add -A`
|
||||
6. Merge nach `main` nur auf explizite Anweisung
|
||||
|
||||
## Sicherheit
|
||||
- Niemals `data/helldivers.db` committen
|
||||
@@ -0,0 +1,42 @@
|
||||
# CLAUDE.md – helldivers
|
||||
|
||||
## Overview
|
||||
Port: 3012
|
||||
Type: Authenticated Multiplayer App (WebSocket, SQLite, ELO-Rating, Bcrypt, Helmet)
|
||||
|
||||
## Running
|
||||
```bash
|
||||
node server.js # Produktion
|
||||
npm run dev # Entwicklung
|
||||
```
|
||||
|
||||
## Structure
|
||||
```
|
||||
helldivers/
|
||||
├── server.js # Express + WebSocket (ws) + SQLite (better-sqlite3)
|
||||
├── public/app.js # Gesamte Client-Logik (~1840 Zeilen)
|
||||
├── public/styles.css
|
||||
├── public/index.html
|
||||
├── scripts/ # DB-Migrations / Seed
|
||||
└── data/helldivers.db
|
||||
```
|
||||
|
||||
## Deployment
|
||||
- Runs under PM2 on the host
|
||||
- Nginx reverse-proxies to port 3012
|
||||
|
||||
## Branches
|
||||
- `main` – stable, production-ready code
|
||||
- `bugfixes-features` – active development
|
||||
|
||||
## Commit Convention
|
||||
`type: short description`
|
||||
Types: `feat`, `fix`, `refactor`, `docs`, `chore`
|
||||
|
||||
## PROJECT_MAP.md – Pflege
|
||||
|
||||
Falls Funktionen, API-Routen, WebSocket-Message-Types oder State-Variablen **hinzugefügt, geändert oder entfernt** werden, muss `PROJECT_MAP.md` **vor dem Commit** aktualisiert werden. Gilt für beide KIs (Claude und Codex) gleichermaßen.
|
||||
|
||||
## Changelog
|
||||
- Nach jeder Änderung `CHANGELOG.md` aktualisieren
|
||||
- Format: `## [Unreleased]` für laufende Änderungen
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
# Project Map – helldivers
|
||||
|
||||
## Files
|
||||
| File | Purpose |
|
||||
|---|---|
|
||||
| `server.js` | Express + WebSocket (ws) + SQLite (better-sqlite3) – Auth, Scores, Matchmaking |
|
||||
| `public/app.js` | Gesamte Client-Logik (WebSocket-Client, Practice/Match/Lobby) |
|
||||
| `public/styles.css` | Alle Styles |
|
||||
| `public/index.html` | App-Shell |
|
||||
| `data/helldivers.db` | SQLite-Datenbank (Scores, Users, Sessions, History) |
|
||||
| `scripts/` | Migrations / Seed-Skripte |
|
||||
|
||||
---
|
||||
|
||||
## app.js
|
||||
|
||||
### State Object
|
||||
```js
|
||||
state = {
|
||||
user, currentView, stratagems,
|
||||
settings: { timerDuration, difficulty },
|
||||
practice: {
|
||||
active, mode, current, queue, progress, timeLeft, timerHandle, startTime,
|
||||
score, streak, selectedCats, dailyTarget,
|
||||
lives, // Endless mode
|
||||
drillPool, drillCompleted, drillTotal, // Drill mode
|
||||
speedrunStart, speedrunPool, speedrunElapsed, // Speedrun mode
|
||||
sessionStats: { completed, missed, bestTime, stratagems, mistakes, maxStreak }
|
||||
},
|
||||
lobby: { online, incoming, pendingChallenge },
|
||||
match: { roomId, opponent, matchScores, current, myProgress, oppProgress, roundActive, roundHistory },
|
||||
leaderboard: { activeTab },
|
||||
history: { page, total },
|
||||
ws, wsReconnectTimer
|
||||
}
|
||||
```
|
||||
|
||||
### Constants
|
||||
| Constant | Purpose |
|
||||
|---|---|
|
||||
| `RING_CIRCUMFERENCE` | `219.9` – Kreis-Umfang für Timer-Ring-Canvas (r=35) |
|
||||
| `ELO_RANKS` | Array `{ min, label, color }` – ELO-Rangstufen |
|
||||
| `STRATAGEMS` | Array aller Stratagems mit `name`, `category`, `icon`, `sequence` |
|
||||
|
||||
### Key Functions – Settings & Navigation
|
||||
| Function | Purpose |
|
||||
|---|---|
|
||||
| `loadSettings() / saveSettings()` | localStorage-Persistenz für Settings |
|
||||
| `applySettingsToUI()` | Settings auf UI-Elemente anwenden |
|
||||
| `showView(name)` | Ansicht wechseln (login/dashboard/practice/leaderboard/history/admin) |
|
||||
| `connectWS() / wsSend(type, payload)` | WebSocket-Verbindung + Nachrichten senden |
|
||||
| `handleWSMessage({ type, payload })` | Eingehende WS-Nachrichten dispatchen |
|
||||
|
||||
### Key Functions – Practice
|
||||
| Function | Purpose |
|
||||
|---|---|
|
||||
| `initPracticeView()` | Practice-View initialisieren |
|
||||
| `getPool()` | Stratagem-Pool nach Filter + Modus aufbauen |
|
||||
| `buildQueue() / renderQueue(queue)` | Warteschlange aufbauen und rendern |
|
||||
| `nextStratagem()` | Nächstes Stratagem anzeigen |
|
||||
| `handlePracticeInput(dir)` | Pfeilrichtung auswerten (Treffer/Fehler) |
|
||||
| `startPracticeTimer() / stopPracticeTimer()` | Timer für Timed-Modus |
|
||||
| `startSpeedrunTimer()` | Timer für Speedrun-Modus |
|
||||
| `renderPracticeStratagem()` | Aktuelles Stratagem + Pfeile rendern |
|
||||
| `renderArrows(containerId, sequence, progress)` | Pfeil-Sequenz rendern |
|
||||
| `updateScoreDisplay() / updateStreakDisplay() / updateLivesDisplay()` | Score-UI |
|
||||
| `openSessionSummary() / closeSessionSummary()` | Sitzungs-Zusammenfassung Modal |
|
||||
|
||||
### Key Functions – Lobby & Match
|
||||
| Function | Purpose |
|
||||
|---|---|
|
||||
| `updateLobbyView()` | Online-Nutzer-Liste aktualisieren |
|
||||
| `sendChallenge(target) / acceptChallenge(from) / declineChallenge(from)` | Herausforderungen verwalten |
|
||||
| `openChallengeModal(from, elo) / closeChallengeModal()` | Challenge-Dialog |
|
||||
| `renderMatchRound()` | Aktive Match-Runde rendern |
|
||||
| `handleMatchInput(dir)` | Match-Eingabe auswerten |
|
||||
| `renderRoundResult(winner)` | Rundensieger anzeigen |
|
||||
| `openMatchResultModal({ winner, eloChanges, roundHistory })` | Match-Ergebnis-Modal |
|
||||
|
||||
### Key Functions – Admin & History
|
||||
| Function | Purpose |
|
||||
|---|---|
|
||||
| `renderAdminOverview(data)` | Admin-Dashboard: Nutzer, Scores, Aktivität |
|
||||
| `renderAdminUsers(users)` | Nutzertabelle im Admin-Bereich |
|
||||
| `renderAdminActivity(data)` | Aktivitätslog rendern |
|
||||
| `renderHistoryChart(sessions)` | Verlaufs-Diagramm (Canvas) |
|
||||
| `renderHistoryPagination(limit)` | Pagination-Buttons |
|
||||
| `renderDashboard({ stats, rank, elo, ... })` | Haupt-Dashboard-Kacheln |
|
||||
|
||||
---
|
||||
|
||||
## server.js
|
||||
|
||||
### Besonderheiten
|
||||
- **SQLite** (better-sqlite3) statt JSON-Dateien
|
||||
- **WebSocket** (ws-Library) für Multiplayer: Lobby, Challenges, Live-Matches
|
||||
- **ELO-Rating-System** für 1v1-Matches
|
||||
|
||||
### Server-Side State
|
||||
| Variable | Purpose |
|
||||
|---|---|
|
||||
| `userSockets` | `Map<userId, ws>` – aktive WebSocket-Verbindungen |
|
||||
| `pendingChallenges` | `Map<challengerId, targetId>` |
|
||||
| `rooms` | `Map<roomId, roomState>` – aktive Match-Räume |
|
||||
|
||||
### API Routes
|
||||
| Route | Purpose |
|
||||
|---|---|
|
||||
| `POST /api/login` | Login (rate-limited) |
|
||||
| `POST /api/logout` | Logout |
|
||||
| `GET /api/me` | Session-Info |
|
||||
| `POST /api/change-password` | Passwort ändern |
|
||||
| `GET /api/users` | Alle Nutzer (Admin) |
|
||||
| `POST /api/users` | Nutzer erstellen (Admin) |
|
||||
| `DELETE /api/users/:username` | Nutzer löschen (Admin) |
|
||||
| `POST /api/users/:username/reset-password` | Temp-Passwort (Admin) |
|
||||
| `PATCH /api/users/:username` | Nutzerdaten ändern (Admin) |
|
||||
| `GET /api/admin/overview` | Admin-Dashboard-Daten |
|
||||
| `GET /api/admin/activity` | Aktivitätslog (Admin) |
|
||||
| `GET /api/dashboard` | Dashboard-Daten (Stats, Rank, ELO, Daily) |
|
||||
| `POST /api/scores/practice` | Practice-Session speichern |
|
||||
| `GET /api/scores/leaderboard` | Gesamt-Leaderboard |
|
||||
| `GET /api/scores/leaderboard/elo` | ELO-Rangliste |
|
||||
| `GET /api/scores/leaderboard/speedrun` | Speedrun-Rangliste |
|
||||
| `GET /api/scores/me` | Eigene Statistiken |
|
||||
| `GET /api/history` | Session-Verlauf (paginiert) |
|
||||
| `GET /api/stats/stratagems` | Stratagem-Trefferquoten |
|
||||
| `GET /api/stratagems` | Stratagem-Liste (für Client-Sync) |
|
||||
|
||||
### WebSocket Message Types (Client → Server)
|
||||
`join`, `challenge`, `accept_challenge`, `decline_challenge`, `ready`, `input`, `leave_match`
|
||||
|
||||
### WebSocket Message Types (Server → Client)
|
||||
`lobby_update`, `challenge_received`, `challenge_declined`, `match_start`, `round_start`, `round_result`, `match_end`, `opponent_progress`, `error`
|
||||
Reference in New Issue
Block a user