db = $db; } /** * Waliduje wynik gry * @param array $gameData - Dane z gry * @return array - Rezultat walidacji */ public function validateGameResult($gameData) { $errors = []; // 1. Sprawdź czy wszystkie wymagane pola są obecne $requiredFields = ['playerScore', 'botScore', 'gameDuration', 'difficulty', 'sessionToken']; foreach ($requiredFields as $field) { if (!isset($gameData[$field])) { $errors[] = "Missing required field: $field"; } } if (!empty($errors)) { return ['valid' => false, 'errors' => $errors]; } // 2. Sprawdź token sesji if (!$this->validateSessionToken($gameData['sessionToken'])) { $errors[] = "Invalid session token"; } // 3. Sprawdź wyniki if ($gameData['playerScore'] > $this->maxScore || $gameData['botScore'] > $this->maxScore) { $errors[] = "Score exceeds maximum allowed"; } if ($gameData['playerScore'] < 0 || $gameData['botScore'] < 0) { $errors[] = "Negative scores not allowed"; } // Jeden z graczy musi mieć 10 punktów if ($gameData['playerScore'] != $this->maxScore && $gameData['botScore'] != $this->maxScore) { $errors[] = "Invalid game end condition"; } // 4. Sprawdź czas gry if ($gameData['gameDuration'] < $this->minGameDuration) { $errors[] = "Game duration too short (possible speed hack)"; } if ($gameData['gameDuration'] > $this->maxGameDuration) { $errors[] = "Game duration too long"; } // 5. Sprawdź statystyki gracza (wykryj cheating) if (!$this->checkPlayerStats($gameData)) { $errors[] = "Suspicious player statistics detected"; } // 6. Rate limiting - max 10 gier na godzinę if (!$this->checkRateLimit($gameData['userId'])) { $errors[] = "Too many games in short time"; } if (!empty($errors)) { $this->logSuspiciousActivity($gameData, $errors); return ['valid' => false, 'errors' => $errors]; } return ['valid' => true, 'message' => 'Game result validated successfully']; } /** * Waliduje token sesji */ private function validateSessionToken($token) { // TODO: Zaimplementuj weryfikację tokenu z bazy danych // Token powinien być generowany przy starcie gry i weryfikowany tutaj if (empty($token) || strlen($token) < 32) { return false; } // Przykładowa weryfikacja (zaimplementuj według swojej logiki) /* $stmt = $this->db->prepare("SELECT * FROM game_sessions WHERE token = ? AND expires_at > NOW()"); $stmt->execute([$token]); return $stmt->rowCount() > 0; */ return true; // Tymczasowo } /** * Sprawdza statystyki gracza pod kątem cheating */ private function checkPlayerStats($gameData) { // Przykładowe sprawdzenia: // 1. Niemożliwy czas reakcji if (isset($gameData['averageReactionTime']) && $gameData['averageReactionTime'] < 50) { return false; // Ludzki czas reakcji to ~150-250ms } // 2. Idealna celność (100%) jest podejrzana if (isset($gameData['accuracy']) && $gameData['accuracy'] >= 99) { return false; } // 3. Sprawdź historię gracza $userId = $gameData['userId'] ?? null; if ($userId) { $winRate = $this->getPlayerWinRate($userId); if ($winRate > 95) { // 95%+ win rate jest podejrzane return false; } } return true; } /** * Sprawdza rate limiting */ private function checkRateLimit($userId) { if (!$userId) return true; // TODO: Zaimplementuj sprawdzanie w bazie /* $stmt = $this->db->prepare(" SELECT COUNT(*) as game_count FROM game_results WHERE user_id = ? AND created_at > DATE_SUB(NOW(), INTERVAL 1 HOUR) "); $stmt->execute([$userId]); $result = $stmt->fetch(PDO::FETCH_ASSOC); return $result['game_count'] < 10; */ return true; // Tymczasowo } /** * Pobiera współczynnik wygranych gracza */ private function getPlayerWinRate($userId) { // TODO: Zaimplementuj /* $stmt = $this->db->prepare(" SELECT (SUM(CASE WHEN player_score = 10 THEN 1 ELSE 0 END) * 100.0 / COUNT(*)) as win_rate FROM game_results WHERE user_id = ? "); $stmt->execute([$userId]); $result = $stmt->fetch(PDO::FETCH_ASSOC); return $result['win_rate'] ?? 0; */ return 50; // Tymczasowo } /** * Loguje podejrzaną aktywność */ private function logSuspiciousActivity($gameData, $errors) { // TODO: Zapisz do bazy danych lub pliku log $logEntry = [ 'timestamp' => date('Y-m-d H:i:s'), 'user_id' => $gameData['userId'] ?? 'unknown', 'ip' => $_SERVER['REMOTE_ADDR'] ?? 'unknown', 'errors' => $errors, 'data' => $gameData ]; // Zapisz do pliku log $logFile = __DIR__ . '/../../logs/suspicious_activity.log'; file_put_contents($logFile, json_encode($logEntry) . PHP_EOL, FILE_APPEND); // Opcjonalnie: wyślij alert do adminów // mail('admin@example.com', 'Suspicious game activity', json_encode($logEntry)); } /** * Zapisuje zweryfikowany wynik gry */ public function saveGameResult($gameData) { // TODO: Zapisz do bazy danych /* $stmt = $this->db->prepare(" INSERT INTO game_results (user_id, player_score, bot_score, difficulty, game_duration, created_at) VALUES (?, ?, ?, ?, ?, NOW()) "); return $stmt->execute([ $gameData['userId'], $gameData['playerScore'], $gameData['botScore'], $gameData['difficulty'], $gameData['gameDuration'] ]); */ return true; } } /** * Endpoint API do walidacji wyników */ if ($_SERVER['REQUEST_METHOD'] === 'POST') { define('VALID_REQUEST', true); header('Content-Type: application/json'); // Pobierz dane z requestu $input = file_get_contents('php://input'); $gameData = json_decode($input, true); if (!$gameData) { http_response_code(400); echo json_encode(['error' => 'Invalid JSON data']); exit; } // TODO: Połącz z bazą danych // $db = new PDO(...); $db = null; $validator = new GameValidator($db); $result = $validator->validateGameResult($gameData); if ($result['valid']) { $validator->saveGameResult($gameData); http_response_code(200); echo json_encode([ 'success' => true, 'message' => 'Game result validated and saved' ]); } else { http_response_code(400); echo json_encode([ 'success' => false, 'errors' => $result['errors'] ]); } } ?>