Gesamtbedenkzeit am Modell 30-30-1
1. Definition des Zeitmodells „30-30-1“
Das Modell ist ein hybrides Zeitkonten-System, das auf einem hohen Startpolster und einem moderaten, gedeckelten Inkrement basiert. Die Kernparameter:
- Startbedenkzeit: 30 Tage pro Partie (einmaliges Kontingent, deckt Urlaub/Krankheit ab).
- Inkrement: 1 Tag pro Zug (wird sofort nach Ausführung des Zuges gutgeschrieben).
- Maximal-Cap: 30 Tage (das Konto kann niemals mehr als 30 Tage betragen; überschüssiges Inkrement verfällt).
- Optionale Start-Frist: Der erste Zug muss zwingend innerhalb von 7 Tagen erfolgen (sonst Partieverlust).
- Verlustbedingung: Die Uhr erreicht 00:00 (minutengenaue Abrechnung) oder die Start-Frist wird verletzt.
2. Szenarien & Spielertypen
Der „Sprint-Spieler“ (Zieht mehrmals täglich)
- Verhalten: Sein Konto stößt permanent an das 30-Tage-Cap.
- Dynamik: Er „verschenkt“ mathematisch gesehen Inkrement, gewinnt aber maximale Flexibilität. Er kann jederzeit spontan 3 Wochen pausieren, ohne unter Druck zu geraten.
Der „Berufstätige/Stratege“ (Zieht alle 1–2 Tage)
- Verhalten: Er nutzt das Inkrement fast vollständig auf. Sein Konto schwankt stabil zwischen 25 und 30 Tagen.
- Dynamik: Das Modell ist für ihn ideal, da er durch das tägliche Inkrement seine Startzeit von 30 Tagen als „eiserne Reserve“ für echte Notfälle unberührt lassen kann.
Der „Zeit-Optimierer“ (Nutzt strategisch lange Pausen)
- Verhalten: Er verbraucht in schwierigen Phasen gezielt 10–15 Tage am Stück.
- Dynamik: Hier greift die Selbstregulierung. Er kann dies nicht beliebig oft tun. Nach einer langen Denkpause ist sein Polster geschmolzen und er muss durch eine Serie schnellerer Züge das Konto wieder „auffüllen“.
Der „Inaktive/Abbrecher“
- Verhalten: Er zieht gar nicht mehr.
- Dynamik: Die Partie ist nach exakt der Zeit beendet, die er noch auf der Uhr hatte (maximal 30 Tage + 1 Min). Das Turnier hat eine berechenbare maximale Stillstandszeit.
3. Annahmen & Risiken
Grundlegende Annahmen
- Durchschnittliche Partiedauer: Geht man von ca. 40 Zügen aus, ergibt das bei moderater Spielweise eine Rundendauer von 60–70 Tagen.
- Für die vergleichenden Berechnungen im Anschluss wird mit 50 Zügen pro Partie gerechnet.
4. Bewertung
Das Modell ist hochgradig transparent und administrativ wartungsfrei. Es eliminiert die größte Fehlerquelle im Fernschach: die Verwaltung von Urlaubszeiten und die Diskussion über deren Missbrauch. Die mathematische Deckelung (Cap) verhindert effektiv die Entstehung von „Zeit-Millionären“, die Partien über Jahre verschleppen könnten.
5. Verbesserungsmöglichkeiten für spätere Entwicklung
Um das Modell für ein 200-Personen-Turnier noch robuster zu machen, sind folgende Feinjustierungen denkbar:
- Die 100-Tage-Guillotine (Planbarkeit): Lege eine absolute Höchstdauer für eine Runde fest (z.B. 100 Tage). Partien, die dann noch laufen, Engine-Bewertung (bei klarem Stand) beendet. Alternativ verliert der Spieler mit der wenigsten Zeit auf der Uhr.
- Progressives Inkrement-Modell: Um das „Einfrieren“ in trivialen Endspielen zu verhindern, könnte das Inkrement sinken:
- Zug 1–50: volles Inkrement.
- Ab Zug 51: halbes Inkrement, z. B. 6 h.
- Effekt: Die Qualität der Eröffnung/Mitte bleibt hoch, die „unendliche“ Dehnung des Endspiels wird erschwert.
- Visualisierung des „Rundenzustands“: Ergänze die Gruppentabellen um eine Anzeige: „Erwarteter Start der nächsten Runde: [Datum X]“ (basierend auf der längsten Restlaufzeit der Uhren).
Effizienzgewinne / Turnier-Performance
1. Mathematischer Vergleich (Maximaldauer)
Bei einer Partie über 50 Züge (n=50):
| Modell | Formel | Rechnung | Max. Dauer |
|---|---|---|---|
| Starre Zeit (3d/Zug) | 2 * n * 3d | 2 * 50 * 3 | 300 Tage |
| 30-30-1 | 2 * ({Start} + n * {Inkr.}) | 2 * (30 + 50 * 1) | 160 Tage |
Ergebnis: Das Modell halbiert die theoretische Maximaldauer der Partie nahezu (-46,6%).
2. Warum das Modell in der Praxis noch schneller ist
Die 160 Tage sind das theoretische Maximum, das nur erreicht wird, wenn beide Spieler das Inkrement bei jedem Zug voll ausschöpfen und ihr Startkapital komplett aufbrauchen.
- Der "Cap-Effekt": Im 3-Tage-Modell "spart" ein Spieler Zeit für das System, wenn er schnell zieht, aber er hat keinen persönlichen Anreiz dazu (außer Höflichkeit). Im GBZ-Modell führt schnelles Ziehen dazu, dass das Konto ans Cap (30 Tage) stößt. Alles, was er darüber hinaus schnell zieht, "verfällt" zugunsten des Turnierschwungs.
- Kein Zeit-Hoarding: Im starren Modell kann ein Spieler bei Zug 49 immer noch 3 Tage warten. Im GBZ-Modell kann er bei Zug 49 nur dann lange warten, wenn er vorher extrem diszipliniert Zeit angespart hat.
- Psychologischer Rhythmus: 3 Tage pro Zug verleiten zum "Vergessen" der Partie. 1 Tag Inkrement suggeriert einen täglichen Rhythmus, was die Schlagzahl im Hobbyschach erfahrungsgemäß erhöht.
3. Die "Gefahrenzone" (Annahmen & Realitätscheck)
Obwohl das Modell schneller ist, gibt es eine wichtige Nuance bei der Planbarkeit:
- Annahme: Im 3-Tage-Modell weißt man: "Länger als 3 Tage pro Zug dauert es nie."
- Risiko im neuen Modell: Ein Spieler kann (nachdem er 30 Züge schnell gespielt hat) plötzlich für fast 31 Tage am Stück abtauchen.
- Vergleich: Im 3-Tage-Modell könnte er für einen Zug maximal 3 Tage abtauchen.
Fazit: Das Modell verkürzt die Gesamtdauer dramatisch, erlaubt aber punktuell längere Einzelpausen. Ohne weitere Maßnahmen (Guillotine) ist das Ende einer Partie / Runde nicht zwingend starr. Eine Halbierung des Inkrements nach z. B. 50 Zügen beschleunigt die Restdauer einer Partie, ohne gleich ihr Ende zu erzwingen.
4. Vergleichsrechnung
Wenn eine Partie nach 50 Zügen die maximale Obergrenze im Modell 30-30-1 von 160 Tagen erreicht, teilen wir diese Zeit zu Vergleichszwecken auf die Spieler und die Züge auf:
- Zeit pro Spieler: 160 Tage / 2 = 80 Tage Gesamtkontingent pro Spieler.
- Zeit pro Zug: 80 Tage / 50 Züge = 1,6 Tage.
Das Ergebnis
Das Modell mit 30 Tagen Startzeit und 1 Tag Inkrement entspricht bei einer 50-zügigen Partie einer starren Bedenkzeit von 1,6 Tagen pro Zug.
Was bedeutet das für die Spieler?
- Der "gefühlte" Spielraum: Obwohl das Modell statistisch gesehen die Zeit pro Zug fast halbiert, fühlt es sich für den Spieler großzügiger an. Im 3-Tage-Modell ist man nach 72 Stunden unweigerlich "tot". In dem Modell kann man (durch das Polster) auch mal 10 Tage über einem Problem brüten, sofern man die restlichen Züge in unter 1,6 Tagen absolviert.
- Die 50-Züge-Schwelle:
- Wird die Partie kürzer (z.B. 30 Züge), steigt die äquivalente Zeit pro Zug (60 / 30 = 2 Tage).
- Wird die Partie länger (z.B. 80 Züge), sinkt die äquivalente Zeit pro Zug (110 / 80 = 1,375 Tage).
- Selbstregulation: Das Modell belohnt ökonomisches Spielen. Wer in der Eröffnung Zeit spart, "kauft" sich das Recht, im Endspiel die 1,6-Tage-Marke pro Zug massiv zu überschreiten.
Fazit für die Turnierplanung: Das Modell 30-30-1 drückt die durchschnittliche Antwortzeit pro Zug von 3 Tagen auf unter 2 Tage, ohne den Spielern die Möglichkeit zu nehmen, in komplexen Stellungen tief einzutauchen oder in den Urlaub zu fahren. Für ein Massenturnier mit 200 Personen ist das ein logistischer Durchbruch, da man die theoretische Gesamtlaufzeit des Turniers fast halbiert, während sich die individuelle Freiheit (durch das 30-Tage-Polster) punktuell sogar verzehnfacht.
Kombinationen aus Startpuffer und Inkrement zum Vergleich mit einer starren Bedenkzeit
Eine Partie mit 50 Zügen dauert etwa 200 Tage, sofern man davon ausgeht, dass beide Spieler im Schnitt alle 2 Tage ziehen statt 3 Tage (Standardzeit in der überwiegenden Zahl von Turnieren) auszuschöpfen.
Um z. B. eine Grenze von 160 Tagen (bei 50 Zügen) einzuhalten und gleichzeitig den größtmöglichen Komfort für die Spieler zu bieten, müssen wir das Verhältnis zwischen "Puffer" (Startzeit/Cap) und "Grundgeschwindigkeit" (Inkrement) optimieren. Hier sind die drei sinnvollsten Konfigurationen:
1. Der "Ausgewogene Standard" (Modell 30-30-1)
- Parameter: Start 30d | Cap 30d | Inkrement 1,0d
- Maximaldauer (50 Züge): 2 * (30 + 50 * 1) = 160 Tage
- Charakter: Dieses Modell ist der perfekte Allrounder. Es bietet genug Zeit für einen echten 3-Wochen-Urlaub und erzwingt danach einen soliden Tagesrhythmus.
- Eignung: Bestens für das 200er-Feld geeignet.
2. Der "Urlaubs-Favorit" (Mehr Puffer, weniger Inkrement)
- Parameter: Start 40d | Cap 40d | Inkrement 0,8d (ca. 19 Stunden)
- Maximaldauer (50 Züge): 2 * (40 + 50 * 0,8) = 160 Tage
- Charakter: Hier haben die Spieler einen massiven 40-Tage-Puffer (ideal für längere Krankheiten oder zwei Urlaube). Dafür ist die "Regenerationsrate" etwas knapper. Man muss im Schnitt alle 19 Stunden ziehen, um das Konto stabil zu halten.
- Eignung: Wenn die Spieler eher unregelmäßig, aber wenn, dann intensiv spielen.
3. Der "Dynamische Flow" (Wenig Puffer, hohes Inkrement)
- Parameter: Start 20d | Cap 20d | Inkrement 1,2d (ca. 29 Stunden)
- Maximaldauer (50 Züge): 2 * (20 + 50 * 1,2) = 160 Tage
- Charakter: Das Startkapital ist geringer (knapp 3 Wochen), aber man "verdient" pro Zug mehr Zeit dazu als man für den Tagesrhythmus braucht. Das Konto füllt sich schneller wieder auf.
- Eignung: Fördert die Qualität im Endspiel, da man dort durch das hohe Inkrement wieder Zeit "ansparen" kann.
Mögliches Verbesserungspotential für eine zukünftige Entwicklung
Bei Anmeldung zum Turnier erhält der Spieler die Option, eine für seinen Spielertypen angepasste Konfiguration auszuwählen.
Weitere Kombinationen für elastische Rundenlaufzeiten
| Ziel-Korridor | Modell | Puffer (Start/Cap) | Inkrement | Dauer bei 50 Zügen | Dauer bei 80 Zügen | Charakteristik |
|---|---|---|---|---|---|---|
| ca. 30–45 Tage | 5-5-0,4 | 5 Tage | 0,4d (ca. 10h) | 50 Tage | 74 Tage | "High-Speed": Sehr agil. Das hohe Inkrement erlaubt Qualität trotz Zeitdruck. |
| ca. 60–85 Tage | 10-10-0,6 | 10 Tage | 0,6d (ca. 14h) | 80 Tage | 116 Tage | "Sportlich": Ein solider Standard für aktive Spieler (fast 3 Züge in 2 Tagen). |
| ca. 90–120 Tage | 15-15-0,8 | 15 Tage | 0,8d (ca. 19h) | 110 Tage | 158 Tage | "Ambitioniert": Bietet genug Tiefe für komplexe Mittelspiele und Urlaubspuffer. |
| ca. 120–160 Tage | 20-20-1,0 | 20 Tage | 1,0d (24h) | 140 Tage | 200 Tage | "Souverän": Hohe Qualität. Ein Tag pro Zug. |
Beispielhafte Formulierung der Regeln für GBZ 30-30-1
1. Das Zeitkonto
Jeder Spieler startet mit einer Basisbedenkzeit von 30 Tagen.
- Inkrement: Mit jedem ausgeführten Zug erhältst du 1 Tag Zeitgutschrift.
- Maximum (Cap): Dein Zeitkonto kann nie mehr als 30 Tage betragen. Überschüssiges Inkrement verfällt.
- Taktung: Die Zeit wird minutengenau abgerechnet.
2. Urlaubs- und Abwesenheitsregelung
Es gibt keinen separaten Urlaubsmodus. Die Startzeit von 30 Tagen dient als Puffer für Urlaub, Krankheit oder berufliche Belastungsphasen. Wer sein Polster durch langsames Spiel verbraucht, trägt das Risiko bei unvorhersehbaren Ereignissen selbst.
3. Die Startphase
Die Partie muss innerhalb von 7 Tagen nach der Freigabe durch den ersten Zug eröffnet werden. Erfolgt innerhalb dieser Frist kein Zug, gilt die Partie als kampflos verloren.
4. Partieverlust (Zeitüberschreitung)
Eine Partie ist sofort verloren, wenn:
- das Zeitkonto auf 00:00 sinkt.
- die 7-Tage-Startfrist verletzt wird.
Rundendauern nach statistischer Wahrscheinlichkeit
In einem großen Teilnehmerfeld bestimmt nicht der Durchschnittsspieler das Ende der Runde, sondern der „langsamste Spieler des gesamten Feldes“. Hier ist die Analyse basierend auf der Wahrscheinlichkeitsverteilung (Monte-Carlo-Logik) von Spielertypen.
1. Annahme der Spielertypen-Verteilung
Wir gehen davon aus, dass sich ein Feld (egal welcher Größe) wie folgt zusammensetzt:
- 60% Aktiv-Spieler: Nutzen im Schnitt 0,5 Tage pro Zug.
- 30% Genuss-Spieler: Nutzen im Schnitt 1,0 Tage pro Zug.
- 10% Strategen/Bummler: Nutzen im Schnitt 1,5 bis 2,0 Tage pro Zug (oder schöpfen das Polster voll aus).
2. Vergleichstabelle: Erwartete Rundendauer (in Tagen)
Berechnet für eine durchschnittliche Partie von 50 Zügen (Circa-Angaben). Das starre Modell (3d) endet im Worst-Case nach 300 Tagen.
| Teilnehmerzahl | Erwartetes Rundenende (30-30-1 Modell) | Wahrscheinlichkeit eines "Max-Bummlers" (160d) | Erwartetes Rundenende (Starres 3d-Modell) | Zeitersparnis durch das Modell 30-30-1 |
|---|---|---|---|---|
| 200 | 155 Tage | Sehr hoch (95%) | 280 Tage | 45% |
| 100 | 140 Tage | Hoch (70%) | 250 Tage | 44% |
| 70 | 125 Tage | Mittel (50%) | 230 Tage | 46% |
| 24 | 5 Tage | Gering (15%) | 180 Tage | 47% |
3. Warum das Modell dem starren System überlegen ist
A. Die „Kompression“ des Zeitraums (Beispiel: 50 Züge in einer Partie) Im starren 3-Tage-Modell hat jeder Spieler pro Zug ein Recht auf 72 Stunden. Ein einziger Bummler kann die Partie auf 300 Tage dehnen. In GBZ-Modell ist bei 160 Tagen physikalisch Schluss. Man gewinnt also allein durch die mathematische Obergrenze über 140 Tage Sicherheit.
B. Der „Flaschenhals-Effekt“ bei Massenturnieren
- Bei 200 Spielern: Hier rettet die harte Deckelung. Im starren Modell würde bei 200 Leuten fast sicher jemand die 300 Tage ausreizen. Das Modell „kappt“ diese Extremfälle hart bei 160 Tagen.
- Bei 24 Spielern: Hier glänzt die Durchschnittsgeschwindigkeit. Da die Wahrscheinlichkeit für einen „Extrem-Bummler“ sinkt, beenden die meisten Spieler ihre Partien organisch nach 70–90 Tagen. Die Runde endet also Monate früher als geplant.
C. Dynamik vs. Statik
- Starr (3d): Belohnt Langsamkeit nicht, bestraft sie aber auch nicht. Das System ist träge.
- Flexibel (30-30-1): Belohnt Schnelligkeit durch Zeit-Ansparen (Cap), erlaubt aber Qualitätspausen. Das System „atmet“.
Implementierung des Zeitmodells „30-30-1“
1. Kurzfassung & Zielsetzung
Ziel ist die Erweiterung der Plattform um ein dynamisches Inkrement-Modell bei gleichzeitiger Beibehaltung der bestehenden Starrzeit-Logik. Durch ein neues Time-Travel-Debug-Tool (TTDT) erhält der Betreiber die volle Kontrolle über die Zeitkonten beider Modelle.
- Gesamtaufwand: 8,5 Manntage (MT)
- Architektur: Strategy Pattern (Abstraktion der Zeitlogik)
- Sicherheitsniveau: Hoch (Atomare Transaktionen, Audit-Logs)
2. Meilensteine & Phasen, Ressourcen-Planung
Phase A: Core-Refactoring & Datenbank (2,0 MT)
- Schema-Migration (0,5 MT): Erweiterung der games-Tabelle um remaining_time_ms, last_action_ts und time_control_type.
- Abstraktions-Layer (1,5 MT): Einführung des TimingInterface. Erstellung der Klassen StaticClock (Bestand) und DynamicClock (Neu). Implementierung der Logik für Inkrement und Cap-Begrenzung.
Phase B: Transaktions-Logik & Backend (2,0 MT)
- Move-Submission-Pipeline (1,0 MT): Integration der Zeitberechnung in den Zug-Prozess. Validierung des Zeitbudgets vor der Zug-Ausführung.
- Flagfall-Scanner (1,0 MT): Optimierung des Hintergrundprozesses. Umstellung von "Fester Zeitstempel" auf "Dynamische Projektion" (last_action_ts + remaining_time_ms).
Phase C: Time-Travel-Debug-Tool (TTDT) (1,5 MT)
- TTDT-Service (1,0 MT): Entwicklung der adjustClock-Funktion. Diese berechnet Deltas, prüft Caps und setzt die Deadline neu.
- Admin-Interface (0,5 MT): Minimalistisches UI zur manuellen Korrektur von Partien (Pause, Zeitgutschrift, Reset).
Phase D: Frontend-Integration (2,0 MT)
- UI-Komponenten (1,0 MT): Anpassung der Partienansicht. Anzeige der verbleibenden Zeit und des Inkrement-Typs.
- Sync-Logik (0,5 MT): Implementierung eines "Client-Side-Drift-Schutzes", der die Serverzeit als Referenz nutzt, ohne externe Libraries.
Phase E: Qualitätssicherung & Release (2,0 MT)
- Simulationstests (1,0 MT): Automatisierte Testläufe von Partien mit Extremwerten (0ms Restzeit, Cap-Überschreitung).
- Deployment & Schattenlauf (0,5 MT): Migration der Bestandspartien in das StaticClock-Modell und Live-Gang.
| Phase | Aufwand (MT) | Fokus-Themen |
|---|---|---|
| 1. Datenmodell & Migration | 0,5 | Schema-Erweiterung, Migrationsskript für Bestandspartien. |
| 2. Core-Logik (Backend) | 1,5 | Implementierung der Berechnungslogik, Strategy-Pattern, Unit-Tests. |
| 3. API & Validierung | 1,0 | Absicherung gegen Race-Conditions, Anpassung der move_submit Endpunkte. |
| 4. Background-Worker | 1,0 | Optimierung des Flagfall-Scanners (Indizierung, Performance-Check). |
| 5. TTDT (Service & Admin-UI) | 1,5 | Time-Travel-Debug-Tool |
| 6. Frontend-Anpassung | 2,0 | Dynamische Uhr-Anzeige, lokalisierte Deadline-Berechnung, Tooltips. |
| 7. Testing & QA | 2,0 | Edge-Cases (Cap-Erreichung, Millisekunden-Drift, Lasttests Cronjob). |
| Gesamt | 9,5 (Schnitt) |
Detaillierung
1. Datenstruktur (Datenbank-Ebene)
Das System wechselt von einer statischen Deadline-Berechnung zu einer zustandsbehafteten Persistenz des Zeitkontos.
Erweiterung der Partietabelle (games)
Pro Spieler werden zwei neue Status-Spalten benötigt, um das Konto unabhängig von der Systemzeit zu führen:
remaining_time_ms:BIGINT– Das aktuell verfügbare Zeitguthaben in Millisekunden.last_move_timestamp:TIMESTAMP– Der Zeitpunkt, an dem die Uhr des Spielers nach seinem letzten Zug gestoppt wurde (bzw. die des Gegners gestartet wurde).
Metadaten der Zeitkontrolle (time_control_profiles)
Anstatt Kürzel wie T3_1 hart im Code zu prüfen, werden sie in einer Profil-Tabelle mit folgenden Attributen definiert:
initial_buffer_ms: Das Startguthaben bei Partiebeginn.increment_ms: Die Zeitgutschrift pro Zug.cap_ms: Die absolute Obergrenze des Kontos.is_regenerative: Ein Flag für die UI-Logik (Starr vs. Dynamisch).
2. Transaktionslogik (App-Logik)
Der Prozess beim move_submit wird vereinheitlicht. Die Logik unterscheidet nicht mehr zwischen Modellen, sondern rechnet nur noch mit den Profil-Parametern. Jede Transaktion muss atomar (Database Locking) erfolgen.
- Sperren: Datensatz via
SELECT FOR UPDATEsperren, um Race Conditions zu verhindern. - Validierung: Prüfen, ob
now() < last_move_timestamp + remaining_time_ms. - Verbrauchsberechnung:
used_time = now() - last_move_timestamp. - Konto-Update (Unified Formula):
interim_time = remaining_time_ms - used_time + increment_msnew_balance = MIN(interim_time, cap_ms)
- Status-Update:
remaining_time_msmitnew_balanceüberschreiben. - Switch:
active_player_idwechseln;last_move_timestampdes neuen aktiven Spielers aufnow()setzen. - Deadline-Projektion:
new_deadline = now() + (Gegner->remaining_time_ms)zur schnellen Sortierung in der UI.
3. Hintergrundprozesse (Skalierbarkeit)
Die Überwachung von Zeitüberschreitungen (Flagfall) erfolgt über einen optimierten Worker:
- Indexierung: Ein Index auf die projizierte
new_deadlineermöglicht hocheffiziente Abfragen. - Worker-Query:
SELECT game_id FROM games WHERE active_deadline <= NOW(). - Intervall: Ein 1-Minuten-Takt ist für minutengenaue Abrechnung ideal und verursacht auch bei >10.000 Partien kaum Last.
4. Architektur: Strategy Pattern
Um eine Code-Verschmutzung durch if-else-Kaskaden zu vermeiden, wird die Zeitberechnung in ein Strategy Pattern gekapselt. Das System bleibt agnostisch gegenüber dem gewählten Modell.
Das Interface (ClockInterface)
Definiert die Methoden calculateNewBalance() und getDeadline().
Die Implementierungen
DynamicAccumulationStrategy(für 30-30-1): Nutzt ein moderates Inkrement (z. B. 1 Tag). Das Konto wächst langsam an, wird aber vom Cap begrenzt.StaticResetStrategy(für T3_1, T7_1): Nutzt die mathematische Spezialform, bei derincrement_ms = initial_buffer_msundcap_ms = initial_buffer_msgilt.- Effekt: Durch das Inkrement in Höhe der Gesamtdauer stößt die Uhr nach jedem Zug sofort wieder gegen das Cap. Das Ergebnis ist ein identisches Verhalten zum alten starren Modell, jedoch innerhalb der neuen, sauberen Code-Struktur.
5. Live-Migration (Zero-Downtime)
Da der Server live ist, erfolgt die Einführung in drei Phasen:
- Shadow Schema: Spalten hinzufügen und Profil-Tabelle befüllen (starre Profile erhalten
Inkrement = Cap). - Data Backfill: Einmaliges Skript berechnet für alle laufenden Partien die aktuelle
remaining_time_msbasierend auf der altencurrent_deadline. - Hot Swap: Umstellung des
move_submitCodes auf die neueClockFactory. Da die mathematische Logik für starre Uhren nun identische Ergebnisse liefert, merken Bestandsspieler keinen Unterschied.
Kritische Risiken im Live-System
| Risiko | Level | Qualitativ |
|---|---|---|
| Race Conditions | 5 | Unverzichtbar: Zeilenbasiertes Locking in der DB, da nun Kontostände (Zustände) verändert werden. |
| Migrations-Drift | 3 | Zeitstempel-Differenzen während des Backfills. Lösung: Kurzer Wartungsmodus oder sehr engmaschiger Sync. |
| Client-Latenz | 2 | Ein Zug, der bei 00:01 ms eingeht, könnte als Zeitüberschreitung gewertet werden. Kulanz-Offset von 1-2 Sek. einplanen. |
6. Optionen & Trade-offs
| Option | Vorteil | Nachteil | Trade-off (1–5) |
|---|---|---|---|
| A: Rein Berechnetes Feld | Maximale Datenintegrität (keine Redundanz). | Hohe Last bei Sortierung/Filterung in der UI; komplexe SQL-Queries für Cronjobs. | 2 (Performance-Bottleneck) |
| B: Redundante Deadline (Empfohlen) | Maximale Performance. Ermöglicht einfache WHERE-Abfragen für den Flagfall-Scanner und die UI-Sortierung. |
Erfordert "doppelte Buchführung" (Synchronität von Zeitkonto und Zeitstempel). | 4 (Konsistenz-Fokus) |
Empfehlung & Implementierungs-Details
Priorität: Hoch. Die Wahl fällt auf Option B, da sie die Abwärtskompatibilität zum bestehenden System sichert und die Serverlast minimiert.
- Der "Single Source of Truth"-Ansatz: Die Spalte
remaining_time_msist die führende Information. Diecurrent_deadlineist lediglich ein daraus abgeleiteter "Schattenwert" für die Datenbank-Indizes. - Abstraktion: Implementierung einer
TimeManager-Klasse (oder einesTimingService), die bei jedem Zug die neue Deadline projektiv berechnet:Deadline = Now + RemainingTime. - Datenintegrität: * Verwendung von Datenbank-Constraints (z. B.
CHECK (remaining_time_ms >= 0)), um negative Zeitkonten auf DB-Ebene hart zu verhindern.- Atomarität: Updates der
remaining_time_msund dercurrent_deadlinemüssen zwingend in derselben SQL-Transaktion erfolgen.
- Atomarität: Updates der
- UI & UX: * Transparenz: Zeige dem User sowohl die verbleibende Dauer (z. B. „14 Tage übrig“) als auch den harten Zeitpunkt („Abgabe bis: 14. Mai, 18:00 Uhr“).
- Zeitzonen-Schutz: Die Speicherung erfolgt in
UTC, die Umrechnung in die lokale Zeit findet erst im Client statt, um Missverständnisse bei internationalen Teilnehmern auszuschließen.
- Zeitzonen-Schutz: Die Speicherung erfolgt in
Warum Option B für das Live-System entscheidend ist:
Da das System bereits T3_1 (3 Tage) usw. nutzt, arbeitet der aktuelle Flagfall-Scanner wahrscheinlich schon mit einer Deadline-Logik. Mit Option B muss der Scanner gar nicht umprogrammiert werden. Er prüft weiterhin einfach nur, ob eine Deadline überschritten ist.
Der einzige Unterschied ist, dass die Deadline nun nach jedem Zug dynamisch neu berechnet und in die Tabelle geschrieben wird, anstatt einfach nur LastMove + 3 Tage zu sein.
Annahmen:
- Die Serverzeit ist via NTP synchronisiert.
- "Minutengenaue Abrechnung" bedeutet, dass Sekunden intern getrackt, aber in der UI ggf. gerundet werden.
Beschreibung des Time-Travel-Debug-Tools (TTDT)
1. Funktionsweise & Logik
Das TTDT fungiert als Override-Layer für den TimeController. Es manipuliert nicht nur den Endwert, sondern dokumentiert den Eingriff in der Partie-Historie, um Manipulationen nachvollziehbar zu machen. Das TTDT ist bei einem Inkrement-Modell (30-30-1) die einzige Möglichkeit, bei technischen Problemen fair einzugreifen, da ein einfaches "Verschieben der Deadline" durch die automatische Neuberechnung beim nächsten Zug sofort überschrieben würde.
Die Kernfunktionen:
- Clock-Freeze (Pause): Setzt einen globalen is_paused-Flag in der Partietabelle. Die Berechnung Now() - LastMoveTimestamp wird unterbrochen.
- Temporal Adjustment (Die eigentliche Zeitreise): Manuelle Korrektur des remaining_time_ms-Wertes.
- Deadline-Recalculation: Automatische Neuprojektion der current_deadline basierend auf dem korrigierten Budget.
2. Technische Implementierung (Backend-Ebene)
Ein sauber implementiertes TTDT sollte über eine Event-Sourcing-Logik oder ein Audit-Log verfügen:
- Status-Snapshot: Bevor die Änderung geschrieben wird, speichert das System den Zustand T_0.
- Delta-Applikation: Der Admin gibt z.B. +12 Stunden ein. Das System rechnet dies in Millisekunden um und addiert es zum remaining_time_ms.
- Anpassung der Synchronisation: Der last_move_timestamp muss oft auf Now() gesetzt werden, damit die Uhr ab dem Moment der Korrektur wieder korrekt "tickt".
- Integritäts-Check: Das Tool prüft sofort: „Wäre die Partie durch diese Änderung bereits abgelaufen oder über dem Cap von 30 Tagen?“
3. Benutzeroberfläche (Admin-Panel)
Für den Betreiber sollte das Tool folgende Optionen bieten:
- Absoluter Modus: „Setze Uhr auf exakt 10 Tage, 4 Stunden.“
- Relativer Modus: „Schenke Spieler A zusätzlich 2 Tage“ (z.B. wegen Serverausfall).
- Status-Flip: „Partie pausieren / fortsetzen“.
4. Risiken & Nebenwirkungen (TTDT)
| Risiko | Level | Qualitativ |
|---|---|---|
| Race Conditions | 4 | Admin korrigiert Zeit, während der Spieler zieht. Lösung: Zeilenbasiertes Locking (SELECT FOR UPDATE). |
| Inkonsistente UI | 2 | Spieler sieht alte Zeit im Cache. Lösung: WebSocket-Push oder Cache-Invalidierung bei Korrektur. |
| Fehlannahme: "Nur Kosmetik" | 3 | Wenn die Deadline manuell verschoben wird, ohne das interne Konto (remaining_time) anzupassen, "springt" die Uhr beim nächsten Zug zurück. |
Empfehlung: Der Entwickler sollte das TTDT als Service-Methode innerhalb seines neuen TimingService implementieren: adjustClock(gameId, playerId, deltaMs, reason). Der entscheidende Vorteil: Diese Methode kann er nicht nur für manuelle Korrekturen nutzen, sondern auch automatisieren – zum Beispiel für einen "Globalen Server-Wartungs-Stop". Er kann ein Skript schreiben, das während einer 4-stündigen Wartung bei allen aktiven Partien die Uhr um exakt 4 Stunden erhöht.