togethere.cloud/mds/DISCIPLINE_SETTINGS_ARCHITECTURE.md

18 KiB

🏗️ Architektura Systemu Ustawień Dyscyplin

📐 Diagram Przepływu

┌─────────────────────────────────────────────────────────────────┐
│                         UŻYTKOWNIK                              │
│                     (Admin lub Gracz)                           │
└──────────────────────────┬──────────────────────────────────────┘
                           │
              ┌────────────┴────────────┐
              │                         │
              ▼                         ▼
    ┌──────────────────┐      ┌──────────────────┐
    │  PANEL ADMINA    │      │   GRA KLIENCKA   │
    │  (UI do edycji)  │      │  (Startup gry)   │
    └────────┬─────────┘      └────────┬─────────┘
             │                         │
             │                         │
    GET/POST │                         │ GET
    /admin.. │                         │ /api/..
             │                         │
             └────────────┬────────────┘
                          │
                          ▼
            ┌──────────────────────────┐
            │   KONTROLER (index.php)  │
            │  - Routing GET/POST      │
            │  - Auth check (admin)    │
            │  - JSON handling         │
            └────────────┬─────────────┘
                         │
                         ▼
            ┌──────────────────────────┐
            │ SERVICE (Biznesowa logika)
            │ - Walidacja              │
            │ - Transformacja          │
            │ - Versioning             │
            │ - Snapshot               │
            └────────────┬─────────────┘
                         │
                         ▼
            ┌──────────────────────────┐
            │    MODEL (DB Access)     │
            │ - CRUD                   │
            │ - Walidacja pierwotna    │
            │ - Transakcje             │
            └────────────┬─────────────┘
                         │
                         ▼
            ┌──────────────────────────┐
            │   BAZA DANYCH (MySQL)    │
            │ settings_disciplines     │
            └──────────────────────────┘

🔄 Scenariusz 1: Admin zmienia ustawienia

1. Admin otwiera panel
   GET /administration/disciplines/ping-pong/
   
2. Service pobiera bieżące ustawienia
   $service->getSettingsForAPI('ping-pong')
   
3. UI wyświetla form z obecnymi wartościami
   
4. Admin zmienia pointsToWin (11 → 21) i zapisuje
   POST /administration/disciplines/ping-pong/settings
   
5. Kontroler odbiera JSON:
   {
     "rules": { "pointsToWin": 21, ... },
     "customization": { ... }
   }
   
6. Service waliduje
   ✅ pointsToWin: 21 (OK, od 1 do 100)
   ✅ settingsVersion zwiększ (1 → 2)
   ✅ Nieparzyste (OK)
   
7. Model UPDATE w BD
   UPDATE settings_disciplines SET
     pointsToWin = 21,
     settingsVersion = 2,
     updated_at = NOW(),
     updated_by = admin_id
   WHERE discipline = 'ping-pong'
   
8. Model zwraca: { settingsVersion: 2, ... }
   
9. Service formatuje odpowiedź
   
10. Kontroler zwraca JSON z status 200
    {
      "success": true,
      "message": "Settings updated",
      "data": { settingsVersion: 2, ... }
    }
    
11. UI odświeża panel - pokazuje wersję 2

🎮 Scenariusz 2: Gra pobiera ustawienia

1. Gra startuje w przeglądarce
   
2. JavaScript: loadGameSettings()
   
3. Pobiera snapshot
   GET /api/discipline-settings.php?
       discipline=ping-pong&snapshot=true
   
4. Kontroler (discipline-settings.php):
   - Nie sprawdza auth (publiczny endpoint)
   - Query: discipline=ping-pong
   - Model: getSnapshot('ping-pong')
   
5. Model zwraca snapshot
   {
     "discipline": "ping-pong",
     "settingsVersion": 2,
     "rules": {
       "pointsToWin": 21,
       ...
     },
     "snapshotTimestamp": "2026-01-28 12:35:10"
   }
   
6. Kontroler zwraca JSON
   {
     "success": true,
     "snapshot": { ... }
   }
   
7. JavaScript inicjalizuje grę z snapshot'em
   new PingPongGame({
     pointsToWin: 21,
     setsToWin: 3,
     settingsVersion: 2
   })
   
8. Gracz gra i uzyskuje wynik
   
9. JavaScript wysyła wynik na backend
   POST /api/matches_sync.php
   {
     "team1_score": 3,
     "team2_score": 2,
     "settingsVersion": 2,
     "snapshotTimestamp": "2026-01-28 12:35:10"
   }
   
10. Backend zapisuje mecz z settingsVersion
    Dzięki temu wiadomo, jakie reguły obowiązywały

📊 Tabela Ustawień vs Mechanika Gry

Tabela: settings_disciplines
┌─────────────────┬──────────────────────────────────┐
│ Kolumna         │ Wpływ                           │
├─────────────────┼──────────────────────────────────┤
│ pointsToWin     │ ✅ Logika gry                    │
│ setsToWin       │ ✅ Logika gry                    │
│ serveRotation   │ ✅ Logika gry                    │
│ specialRules    │ ✅ Logika gry (informacyjnie)   │
│ customization   │ ❌ Tylko UI (bez wpływu)        │
│ settingsVersion │ ⚠️  Dla tracking'u               │
└─────────────────┴──────────────────────────────────┘

✅ = Wpływa na wynik meczu
❌ = Tylko wizualne
⚠️  = Metadata

🔒 Warstwy Bezpieczeństwa

┌─────────────────────────────────────────────────┐
│         ENDPOINT ADMINISTRACYJNY                 │
│  /administration/disciplines/{disc}/settings    │
├─────────────────────────────────────────────────┤
│ 1. Session check                                │
│    ✓ Czy zalogowany?                            │
├─────────────────────────────────────────────────┤
│ 2. Role check                                   │
│    ✓ Czy admin?                                 │
├─────────────────────────────────────────────────┤
│ 3. Input validation (Service)                   │
│    ✓ Typy, zakresy, wymagane pola              │
├─────────────────────────────────────────────────┤
│ 4. Business logic validation (Service)          │
│    ✓ Nieparzyste liczby                         │
│    ✓ Logika biznesowa                           │
├─────────────────────────────────────────────────┤
│ 5. Database operations (Model)                  │
│    ✓ Prepared statements (SQL injection)       │
│    ✓ Transakcje (ACID)                         │
└─────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────┐
│          ENDPOINT PUBLICZNY (API)                │
│     /api/discipline-settings.php                │
├─────────────────────────────────────────────────┤
│ 1. Method check                                 │
│    ✓ Tylko GET (bez POST)                      │
├─────────────────────────────────────────────────┤
│ 2. Discipline validation                        │
│    ✓ Tylko znane dyscypliny                    │
├─────────────────────────────────────────────────┤
│ 3. Read-only (brak możliwości zmian)           │
│    ✓ Model tylko SELECT                        │
├─────────────────────────────────────────────────┤
│ 4. Database queries                             │
│    ✓ Prepared statements                       │
└─────────────────────────────────────────────────┘

🗂️ Warianty Danych

┌──────────────────────┬──────────┬──────────┐
│ Variant              │ Gdzie    │ Kiedy    │
├──────────────────────┼──────────┼──────────┤
│ Defaults (hardcoded) │ Code     │ Zawsze   │
│ DB Snapshot 1        │ Database │ Przy DB  │
│ DB Snapshot 2        │ Database │ Po zmian │
│ Match Snapshot       │ Match    │ Start    │
└──────────────────────┴──────────┴──────────┘

Defaults → Database (first run)
                ↓
         Current Version (v1)
                ↓
         Admin zmienia
                ↓
         New Version (v2)
                ↓
         Każdy nowy mecz → Snapshot v2
         Stare mecze (v1) → Zachowują v1

🔁 Cykl Życia Ustawienia

CREATE (v1)
│
├─ Domyślne wartości z kodu
├─ Zapisane w BD
│
MODIFY (v1 → v2)
│
├─ Admin zmienia pointsToWin
├─ Service: walidacja
├─ Model: settingsVersion++
├─ UPDATE w BD
│
SNAPSHOT
│
├─ Gra: pobiera snapshot (v2)
├─ Match: zapisany z version = 2
│
MODIFY (v2 → v3)
│
├─ Admin zmienia kolory
├─ Service: walidacja
├─ Model: settingsVersion++
│
SNAPSHOT
│
├─ Nowe gry: version 3
├─ Stare gry: version 1 i 2 nie zmienią się
│
ANALYTICS
│
├─ Porównanie: średnia czasu meczu v1 vs v2 vs v3
├─ Wnioski: która wersja miała najlepsze wyniki

📱 Komponenty

1. Model (DisciplineSettingsModel)

- getSettings($discipline)
- getSettingsByVersion($discipline, $version)
- updateSettings($discipline, $settings, $userId)
- getSnapshot($discipline, $version)
- ensureTableExists()
- getDefaults($discipline)

2. Service (DisciplineSettingsService)

- getSettingsForAPI($discipline)
- validateAndUpdate($discipline, $input, $userId)
- getMatchSnapshot($discipline, $version)
- resetToDefaults($discipline, $userId)
- compareVersions($old, $new)

3. Controller (index.php)

handleGetSettings($service, $discipline)
handlePostSettings($service, $discipline)
- Routing
- Auth
- JSON parsing
- Error handling

4. Public API (discipline-settings.php)

- GET only
- No auth required
- Zwraca snapshot
- Dla gry kliencka

🧮 Walidacja - Etapy

┌─────────────────────────────────────────┐
│ Input: POST JSON                        │
└────────────┬────────────────────────────┘
             │
             ▼
┌─────────────────────────────────────────┐
│ JSON Parse (Controller)                 │
│ Czy to poprawny JSON?                   │
└────────────┬────────────────────────────┘
             │
             ▼
┌─────────────────────────────────────────┐
│ Type Check (Service)                    │
│ Czy rules to array? Czy customization   │
│ to object?                              │
└────────────┬────────────────────────────┘
             │
             ▼
┌─────────────────────────────────────────┐
│ Range Check (Service)                   │
│ pointsToWin: 1-100?                     │
│ setsToWin: 1-100?                       │
│ serveRotation: 1-50?                    │
└────────────┬────────────────────────────┘
             │
             ▼
┌─────────────────────────────────────────┐
│ Business Logic (Service)                │
│ Nieparzyste liczby?                     │
│ Consistency check?                      │
└────────────┬────────────────────────────┘
             │
             ▼
┌─────────────────────────────────────────┐
│ DB Level (Model)                        │
│ Constraints (unique, NOT NULL)          │
│ Prepared statements                     │
└────────────┬────────────────────────────┘
             │
             ▼
┌─────────────────────────────────────────┐
│ ✅ Sukces lub ❌ Błąd                   │
│ Z powrotem do controllera               │
└─────────────────────────────────────────┘

🚦 HTTP Status Codes

┌─────┬─────────────────────────────────────────┐
│ 200 │ OK - Operacja udana                     │
├─────┼─────────────────────────────────────────┤
│ 400 │ Bad Request - Błąd walidacji            │
├─────┼─────────────────────────────────────────┤
│ 401 │ Unauthorized - Nie zalogowany           │
├─────┼─────────────────────────────────────────┤
│ 403 │ Forbidden - Brak roli admin             │
├─────┼─────────────────────────────────────────┤
│ 405 │ Method Not Allowed - Typ request        │
├─────┼─────────────────────────────────────────┤
│ 500 │ Server Error - Błąd bazy / inne        │
└─────┴─────────────────────────────────────────┘

🔄 Versioning Strategy

v1 (Initial)
  ├─ pointsToWin: 11
  ├─ setsToWin: 3
  └─ serveRotation: 2

v2 (After change)
  ├─ pointsToWin: 21  ← ZMIANA
  ├─ setsToWin: 3
  └─ serveRotation: 2

v3 (After another change)
  ├─ pointsToWin: 21
  ├─ setsToWin: 3
  └─ serveRotation: 3  ← ZMIANA

Każda zmiana = nowa wersja
Snapshot zawsze ma konkretną wersję
Stare gry zawsze "widzą" swoją wersję

📈 Możliwości Rozszerzenia

Teraz:
  settings_disciplines (bieżące)
  
Przyszłość:
  settings_disciplines_history
    ├─ Pełna historia zmian
    ├─ Kto zmienił i kiedy
    ├─ Co się zmieniło
    └─ Rollback
    
  settings_scheduled_changes
    ├─ Zmiana planowana na czasę
    ├─ Notyfikacja dla użytkowników
    
  settings_ab_tests
    ├─ Grupa A: wersja 1
    ├─ Grupa B: wersja 2
    └─ Analytics

🎯 Kluczowe Założenia

  1. Immutability - snapshot po starcie nie zmienia się
  2. Versioning - każda zmiana = nowa wersja
  3. Transparency - każdy mecz wie jakie reguły obowiązywały
  4. Backward Compatibility - stare gry nie wpływane zmianami
  5. Auditability - każda zmiana jest zalogowana
  6. Extensibility - łatwo dodać nową dyscyplinę