135 lines
5.6 KiB
Markdown
135 lines
5.6 KiB
Markdown
|
|
# 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`
|