false, 'error' => 'Could not open data file.'], 500); } flock($handle, $write ? LOCK_EX : LOCK_SH); rewind($handle); $raw = stream_get_contents($handle); $lobbies = json_decode($raw ?: '{}', true); if (!is_array($lobbies)) { $lobbies = []; } $result = $callback($lobbies); if ($write) { rewind($handle); ftruncate($handle, 0); fwrite($handle, json_encode($lobbies, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . "\n"); fflush($handle); } flock($handle, LOCK_UN); fclose($handle); return $result; } function ensure_lobby(array &$lobbies, string $lobbyName): array { if (!isset($lobbies[$lobbyName]) || !is_array($lobbies[$lobbyName])) { $lobbies[$lobbyName] = [ 'name' => $lobbyName, 'players' => [], 'leaderboard' => [], ]; } $lobbies[$lobbyName]['players'] = array_values($lobbies[$lobbyName]['players'] ?? []); $lobbies[$lobbyName]['leaderboard'] = array_values($lobbies[$lobbyName]['leaderboard'] ?? []); return $lobbies[$lobbyName]; } $action = $_GET['action'] ?? ''; $body = read_body(); if ($action === 'createLobby') { $lobbyName = clean_name($body['lobbyName'] ?? ''); if ($lobbyName === '') { respond(['ok' => false, 'error' => 'Lobby name is required.'], 400); } $lobby = with_lobbies(static function (array &$lobbies) use ($lobbyName): array { return ensure_lobby($lobbies, $lobbyName); }, true); respond(['ok' => true, 'lobby' => ['name' => $lobby['name']]]); } if ($action === 'joinLobby') { $lobbyName = clean_name($body['lobbyName'] ?? ''); $playerName = clean_name($body['playerName'] ?? '', 24); if ($lobbyName === '' || $playerName === '') { respond(['ok' => false, 'error' => 'Lobby name and player name are required.'], 400); } $lobby = with_lobbies(static function (array &$lobbies) use ($lobbyName, $playerName): array { ensure_lobby($lobbies, $lobbyName); if (!in_array($playerName, $lobbies[$lobbyName]['players'], true)) { $lobbies[$lobbyName]['players'][] = $playerName; } return $lobbies[$lobbyName]; }, true); respond(['ok' => true, 'lobby' => ['name' => $lobby['name'], 'players' => $lobby['players']]]); } if ($action === 'leaveLobby') { $lobbyName = clean_name($body['lobbyName'] ?? ''); $playerName = clean_name($body['playerName'] ?? '', 24); with_lobbies(static function (array &$lobbies) use ($lobbyName, $playerName): void { if ($lobbyName === '' || $playerName === '' || !isset($lobbies[$lobbyName])) { return; } $lobbies[$lobbyName]['players'] = array_values(array_filter( $lobbies[$lobbyName]['players'] ?? [], static fn ($name): bool => $name !== $playerName, )); }, true); respond(['ok' => true]); } if ($action === 'submitScore') { $lobbyName = clean_name($body['lobbyName'] ?? ''); $playerName = clean_name($body['playerName'] ?? '', 24); if ($lobbyName === '' || $playerName === '') { respond(['ok' => false, 'error' => 'Lobby name and player name are required.'], 400); } $entry = [ 'playerName' => $playerName, 'totalScore' => max(0, min(300, (int) ($body['totalScore'] ?? 0))), 'scores' => clean_scores($body['scores'] ?? []), 'countries' => clean_countries($body['countries'] ?? []), 'date' => gmdate('c'), ]; with_lobbies(static function (array &$lobbies) use ($lobbyName, $playerName, $entry): void { ensure_lobby($lobbies, $lobbyName); if (!in_array($playerName, $lobbies[$lobbyName]['players'], true)) { $lobbies[$lobbyName]['players'][] = $playerName; } $lobbies[$lobbyName]['leaderboard'][] = $entry; usort( $lobbies[$lobbyName]['leaderboard'], static fn (array $a, array $b): int => ($b['totalScore'] ?? 0) <=> ($a['totalScore'] ?? 0), ); $lobbies[$lobbyName]['leaderboard'] = array_slice($lobbies[$lobbyName]['leaderboard'], 0, 20); }, true); respond(['ok' => true, 'entry' => $entry]); } if ($action === 'getLeaderboard') { $lobbyName = clean_name($_GET['lobbyName'] ?? ''); if ($lobbyName === '') { respond(['ok' => false, 'error' => 'Lobby name is required.'], 400); } $leaderboard = with_lobbies(static function (array &$lobbies) use ($lobbyName): array { return $lobbies[$lobbyName]['leaderboard'] ?? []; }); respond(['ok' => true, 'leaderboard' => $leaderboard]); } if ($action === 'getLobby') { $lobbyName = clean_name($_GET['lobbyName'] ?? ''); if ($lobbyName === '') { respond(['ok' => false, 'error' => 'Lobby name is required.'], 400); } $lobby = with_lobbies(static function (array &$lobbies) use ($lobbyName): array { if (!isset($lobbies[$lobbyName])) { return ['name' => $lobbyName, 'players' => []]; } return [ 'name' => $lobbies[$lobbyName]['name'] ?? $lobbyName, 'players' => array_values($lobbies[$lobbyName]['players'] ?? []), ]; }); respond(['ok' => true, 'lobby' => $lobby]); } respond(['ok' => false, 'error' => 'Unknown action.'], 404);