feat: add time controls, correspondence games, and tournament mode

**Zeitmodi (Blitz/Rapid):**
- 5, 10, 30 Min Zeitkontrolle bei Spielerstellung
- Server-seitige Uhren: Zeit wird bei jedem Zug abgezogen
- Timeout-Erkennung via claimTimeout Socket-Event
- Schachuhr-Anzeige in GamePage (rot bei < 30s)
- Turnierspiele erhalten automatisch Zeitkontrolle

**Tagespartien (Correspondence):**
- Neue DB-Tabelle correspondence_game
- REST API: erstellen, beitreten, Zug machen, aufgeben
- Seite /correspondence: Liste aktiver Tagespartien
- Seite /correspondence/[code]: Spielen mit interaktivem Brett
- Einladungslink teilen, Gegner tritt via Link bei

**Turniermodus (Round-Robin):**
- Neue DB-Tabellen: tournament, tournament_player, tournament_round
- Round-Robin Paarungen mit Circle-Methode
- Turnier erstellen: /tournament/create
- Turnierliste: /tournament
- Turnierseite /tournament/[code]: Standings, Runden, Spiele
- Automatische Aktivisierung der nächsten Runde
- Turnierspiele werden als normale activeGames erstellt
- Ergebnisse aktualisieren Punkte automatisch

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Michess
2026-04-14 09:44:35 +02:00
parent 09e5271dfb
commit aeb5fe313e
25 changed files with 1653 additions and 16 deletions

View File

@@ -19,10 +19,11 @@ export default function CreateGame() {
const target = e.target as HTMLFormElement;
const unlisted = target.elements.namedItem("createUnlisted") as HTMLInputElement;
const startingSide = (target.elements.namedItem("createStartingSide") as HTMLSelectElement)
.value;
const startingSide = (target.elements.namedItem("createStartingSide") as HTMLSelectElement).value;
const timeControlVal = parseInt((target.elements.namedItem("createTimeControl") as HTMLSelectElement).value);
const timeControl = timeControlVal > 0 ? timeControlVal : undefined;
const game = await createGame(startingSide, unlisted.checked);
const game = await createGame(startingSide, unlisted.checked, timeControl);
if (game) {
router.push(`/${game.code}`);
@@ -38,6 +39,16 @@ export default function CreateGame() {
<span className="label-text text-sm">Nur per Einladung</span>
<input type="checkbox" className="checkbox checkbox-primary checkbox-sm" name="createUnlisted" id="createUnlisted" />
</label>
<select
className="select select-bordered select-sm w-full"
name="createTimeControl"
id="createTimeControl"
>
<option value="0">Keine Uhr</option>
<option value="5">5 Min (Blitz)</option>
<option value="10">10 Min (Blitz)</option>
<option value="30">30 Min (Rapid)</option>
</select>
<div className="flex gap-2">
<select
className="select select-bordered select-sm flex-1"