357 lines
8.5 KiB
Markdown
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?
|
|
|