togethere.cloud/mds/DISCIPLINE_SETTINGS_IMPLEMENTATION.md

357 lines
8.5 KiB
Markdown

# 🎯 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?