# 🎯 Wdrażanie Endpoint'u Ustawień Dyscyplin ## 📋 Szybki Start Wszystkie pliki zostały już stworzone. Aby wdrożyć system: ### 1. Pliki do wdrażania ``` ✅ private_html/api/DisciplineSettingsModel.php ✅ private_html/api/DisciplineSettingsService.php ✅ private_html/api/discipline-settings.php ✅ private_html/administration/disciplines/ping-pong/settings/index.php ✅ private_html/administration/disciplines/rock-paper-scissors/settings/index.php ✅ private_html/administration/disciplines/table-football/settings/index.php ✅ private_html/administration/disciplines/ping-pong/index.php (zaktualizowany panel) ✅ private_html/tests/discipline_settings_test.php ``` ### 2. Baza danych Tabela `settings_disciplines` jest **automatycznie tworzona** na pierwszy GET request. Jeśli chcesz ją ręcznie stworzyć: ```sql CREATE TABLE IF NOT EXISTS settings_disciplines ( id INT AUTO_INCREMENT PRIMARY KEY, discipline VARCHAR(50) NOT NULL UNIQUE, -- Reguły gry (logika) pointsToWin INT NOT NULL DEFAULT 10, setsToWin INT NOT NULL DEFAULT 2, serveRotation INT NOT NULL DEFAULT 2, specialRules TEXT, -- Personalizacja UI (nie wpływa na logiką gry) customization JSON, -- Versioning ustawień settingsVersion INT NOT NULL DEFAULT 1, -- Metadane created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, updated_by INT, INDEX idx_discipline (discipline), INDEX idx_version (settingsVersion) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; ``` --- ## 🧪 Testowanie ### Test 1: Uruchom test jednostkowy ```bash cd private_html/tests/ php discipline_settings_test.php ``` Oczekiwana odpowiedź: 10 testów PASS ✅ ### Test 2: Pobierz ustawienia (cURL) ```bash # Zaloguj się jako admin curl -c cookies.txt -X POST \ "http://localhost/login/login.php" \ -d "email=admin@example.com&password=hasło" # Pobierz ustawienia curl -b cookies.txt \ "http://localhost/administration/disciplines/ping-pong/settings" ``` Oczekiwana odpowiedź: ```json { "success": true, "data": { "discipline": "ping-pong", "settingsVersion": 1, "rules": { ... }, "customization": { ... } } } ``` ### Test 3: Pobierz snapshot (bez admin) ```bash curl "http://localhost/api/discipline-settings.php?discipline=ping-pong&snapshot=true" ``` ### Test 4: Panel administracyjny Otwórz w przeglądarce: ``` http://localhost/administration/disciplines/ping-pong/ ``` --- ## 🚀 Użycie w Grze ### JavaScript - pobierz ustawienia na start meczu: ```javascript async function loadGameSettings() { const response = await fetch( '/api/discipline-settings.php?discipline=ping-pong&snapshot=true' ); const result = await response.json(); if (result.success) { const snapshot = result.snapshot; // Uruchom grę z ustawieniami const game = new PingPongGame({ pointsToWin: snapshot.rules.pointsToWin, setsToWin: snapshot.rules.setsToWin, serveRotation: snapshot.rules.serveRotation, settingsVersion: snapshot.settingsVersion }); // Stosuj customization document.body.style.backgroundColor = snapshot.customization.tableColor; } } ``` ### PHP - zapisz snapshot w meczu: ```php $model = new DisciplineSettingsModel($pdo); $snapshot = $model->getSnapshot('ping-pong'); // Zapisz w bazie $stmt = $pdo->prepare( "UPDATE matches SET settingsSnapshot = ? WHERE id = ?" ); $stmt->execute([json_encode($snapshot), $matchId]); ``` --- ## 📊 Struktura Odpowiedzi API ### GET /administration/disciplines/ping-pong/settings ```json { "success": true, "data": { "discipline": "ping-pong", "settingsVersion": 1, "rules": { "pointsToWin": 11, "setsToWin": 3, "serveRotation": 2, "specialRules": "Deuce at 10-10..." }, "customization": { "tableColor": "#2d5016", "ballColor": "#ff6600", "paddleColor": "#000000", "uiTheme": "dark" }, "metadata": { "created_at": "2026-01-28 12:30:45", "updated_at": "2026-01-28 12:30:45", "updated_by": 1 }, "status": "custom" } } ``` ### POST /administration/disciplines/ping-pong/settings ```json { "success": true, "message": "Settings for ping-pong have been updated successfully", "data": { ... } } ``` ### GET /api/discipline-settings.php?snapshot=true ```json { "success": true, "snapshot": { "discipline": "ping-pong", "settingsVersion": 1, "rules": { "pointsToWin": 11, "setsToWin": 3, "serveRotation": 2, "specialRules": "..." }, "snapshotTimestamp": "2026-01-28 12:35:10" } } ``` --- ## 🔐 Bezpieczeństwo ### Panel administracyjny (`/administration/disciplines/*/settings`) - ✅ Wymaga zalogowania - ✅ Wymaga roli `admin` - ✅ POST zawsze wymaga admin role - ✅ GET wymaga admin role ### API publiczny (`/api/discipline-settings.php`) - ✅ Nie wymaga logowania - ✅ Tylko GET - ✅ Brak zmian - ✅ Ratelimiting (opcjonalnie): można dodać w przyszłości --- ## 💡 Najlepsze Praktyki ### 1. Snapshot dla startu meczu ```php // ❌ ŹLE - ustawienia mogą się zmienić w trakcie meczu $settings = $model->getSettings('ping-pong'); // ✅ DOBRZE - snapshot z momentu startu $snapshot = $model->getSnapshot('ping-pong'); saveMatchSnapshot($matchId, $snapshot); ``` ### 2. Versioning ```php // Każda zmiana automatycznie zwiększa wersję // Wersja 1 → 2 → 3 → ... $updated = $service->validateAndUpdate('ping-pong', $input, $userId); echo $updated['settingsVersion']; // 2 ``` ### 3. Walidacja ```php // ✅ Walidacja zawsze w serwisie try { $result = $service->validateAndUpdate('ping-pong', $input, $userId); } catch (InvalidArgumentException $e) { // Błędy walidacji echo "Błąd: " . $e->getMessage(); } ``` --- ## 🔧 Integracja z Istniejącymi Systemami ### 1. Z tabelą matches Dodaj kolumnę do `matches`: ```sql ALTER TABLE matches ADD COLUMN settingsSnapshot JSON AFTER Score; ``` ### 2. Z systemem meczy ```php // Przy starcie meczu pobierz snapshot $snapshot = $model->getSnapshot($discipline); $match = createMatch([ 'team1_id' => $team1, 'team2_id' => $team2, 'settingsSnapshot' => json_encode($snapshot) ]); ``` ### 3. Z systemem auditowania ```php // Log zmian $before = $service->getSettingsForAPI('ping-pong'); $service->validateAndUpdate('ping-pong', $input, $adminId); $after = $service->getSettingsForAPI('ping-pong'); $changes = $service->compareVersions($before, $after); logAuditEvent('settings_updated', [ 'discipline' => 'ping-pong', 'changes' => $changes, 'admin_id' => $adminId ]); ``` --- ## 📈 Rozszerzenia w Przyszłości ### Historia zmian ```sql CREATE TABLE settings_disciplines_history ( id INT AUTO_INCREMENT PRIMARY KEY, discipline VARCHAR(50), version INT, settings JSON, changed_by INT, changed_at DATETIME, PRIMARY KEY (discipline, version) ); ``` ### Scheduled changes ```php // Zmiana ustawień w określonym czasie INSERT INTO settings_scheduled_changes ( discipline, settings_json, scheduled_at ) VALUES ('ping-pong', '...', '2026-02-01 00:00:00'); ``` ### A/B testing ```php // Różne ustawienia dla różnych grup graczy INSERT INTO settings_ab_tests ( discipline, variant_a, variant_b, split_percentage ) VALUES ('ping-pong', '...', '...', 50); ``` --- ## ⚠️ Troubleshooting ### Problem: "Table not found" **Rozwiązanie:** Tabela tworzy się automatycznie na pierwszy GET. Jeśli nie działa: ```php $model = new DisciplineSettingsModel($pdo); $model->ensureTableExists(); // Ręczne wywołanie ``` ### Problem: "Invalid JSON" **Rozwiązanie:** Sprawdź czy customization jest poprawnym JSON: ```php json_validate($input['customization']); // PHP 8.3+ // lub json_last_error() === JSON_ERROR_NONE ``` ### Problem: "Validation failed - odd numbers" **Rozwiązanie:** pointsToWin i setsToWin muszą być nieparzyste: - ✅ Poprawne: 11, 21, 3, 5 - ❌ Błędne: 10, 20, 2, 4 --- ## 📞 Wsparcie Jeśli masz problemy: 1. Sprawdź logi: `error_log` w PHP 2. Uruchom testy: `php discipline_settings_test.php` 3. Sprawdź logowanie: czy jesteś zalogowany jako admin? 4. Walidacja: czy dane spełniają wymagania?