Commit 102e8b47 authored by Mahmoud Aglan's avatar Mahmoud Aglan

fix: complete Swiss API integration fixes for bot tournament flow

1. Content-Type: application/json only sent when body is not null.
   Swiss API rejects bodiless POST/GET with that header.
2. Controller start() now calls Swiss API /start endpoint.
3. simulateNextRound() auto-starts Swiss tournament if local status
   is still draft/registration.
4. generateRound response parsing fixed — data is in {round:{id,...}}.
5. getPairings response wrapped in {data:[...]} — now handled.
6. Pairing field names use camelCase (whitePlayerId not white_player_id).
7. Player ratings fetched from listPlayers instead of expecting them
   embedded in pairing objects.
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent ea0e40bf
......@@ -16,8 +16,7 @@ class ApiProxy
public static function swiss(string $method, string $path, ?array $body = null, ?string $token = null): array
{
$headers = [];
$upperMethod = strtoupper($method);
if ($body !== null || in_array($upperMethod, ['POST', 'PATCH', 'PUT'])) {
if ($body !== null) {
$headers[] = 'Content-Type: application/json';
}
$authToken = $token ?? self::getSwissToken();
......
......@@ -365,6 +365,13 @@ class TournamentsController
'fideRatingStandard' => $profile['elo_blitz'] ?? 1500,
]);
}
// Start tournament in Swiss API
$startResp = ApiProxy::swiss('POST', '/tournaments/' . $tournament['swiss_api_tournament_id'] . '/start');
if (!SwissApiService::isSuccess($startResp)) {
Response::error('فشل في بدء البطولة في Swiss API: ' . SwissApiService::getError($startResp), "/tournaments/{$id}");
return;
}
}
$this->db->update('el3ab_tournaments', ['id' => "eq.{$id}"], [
......
......@@ -200,12 +200,23 @@ class BotSimulationService
return ['success' => false, 'error' => 'الجولة غير مرتبطة بـ Swiss API'];
}
// Get players list for ratings lookup
$playersResp = SwissApiService::listPlayers($tournament['swiss_api_tournament_id']);
$playersBody = SwissApiService::isSuccess($playersResp) ? SwissApiService::getBody($playersResp) : [];
$playersList = $playersBody['data'] ?? $playersBody ?? [];
$ratingsMap = [];
foreach ($playersList as $p) {
$ratingsMap[$p['id']] = $p['fideRatingStandard'] ?? 1200;
}
// Get pairings
$pairingsResponse = SwissApiService::getPairings($swissRoundId);
if (!SwissApiService::isSuccess($pairingsResponse)) {
return ['success' => false, 'error' => 'فشل في جلب المواجهات'];
}
$pairings = SwissApiService::getBody($pairingsResponse);
$pairingsBody = SwissApiService::getBody($pairingsResponse);
$pairings = $pairingsBody['data'] ?? $pairingsBody ?? [];
if (empty($pairings)) {
return ['success' => false, 'error' => 'لا توجد مواجهات في هذه الجولة'];
}
......@@ -216,14 +227,16 @@ class BotSimulationService
foreach ($pairings as $pairing) {
$pairingId = $pairing['id'];
if (!empty($pairing['is_bye']) || empty($pairing['black_player_id'])) {
if (!empty($pairing['isBye']) || !empty($pairing['is_bye']) || empty($pairing['blackPlayerId'] ?? $pairing['black_player_id'])) {
$results[] = ['pairingId' => $pairingId, 'result' => 'bye_full'];
$summary['byes']++;
continue;
}
$ratingWhite = $pairing['white_player']['fide_rating_standard'] ?? $pairing['white_player']['rating'] ?? 1200;
$ratingBlack = $pairing['black_player']['fide_rating_standard'] ?? $pairing['black_player']['rating'] ?? 1200;
$whiteId = $pairing['whitePlayerId'] ?? $pairing['white_player_id'] ?? '';
$blackId = $pairing['blackPlayerId'] ?? $pairing['black_player_id'] ?? '';
$ratingWhite = $ratingsMap[$whiteId] ?? 1200;
$ratingBlack = $ratingsMap[$blackId] ?? 1200;
$result = self::simulateResult($ratingWhite, $ratingBlack, $drawRate);
$results[] = ['pairingId' => $pairingId, 'result' => $result];
......@@ -275,6 +288,7 @@ class BotSimulationService
return ['success' => false, 'error' => 'البطولة غير موجودة أو غير مرتبطة'];
}
$swissTournamentId = $tournament['swiss_api_tournament_id'];
$totalRounds = $tournament['rounds_total'] ?? $tournament['swiss_rounds'] ?? 7;
$currentRound = $tournament['current_round'] ?? 0;
......@@ -282,14 +296,27 @@ class BotSimulationService
return ['success' => true, 'completed' => true, 'round_number' => $currentRound, 'total_rounds' => $totalRounds];
}
$genResponse = SwissApiService::generateRound($tournament['swiss_api_tournament_id']);
// Auto-start Swiss API tournament if local status is draft/registration
if (in_array($tournament['status'], ['draft', 'registration'])) {
$startResp = ApiProxy::swiss('POST', '/tournaments/' . $swissTournamentId . '/start');
if (!SwissApiService::isSuccess($startResp)) {
return ['success' => false, 'error' => 'فشل في بدء البطولة: ' . SwissApiService::getError($startResp)];
}
$db->update('el3ab_tournaments', ['id' => "eq.{$tournamentId}"], [
'status' => 'in_progress',
'updated_at' => date('c'),
]);
}
$genResponse = SwissApiService::generateRound($swissTournamentId);
if (!SwissApiService::isSuccess($genResponse)) {
return ['success' => false, 'error' => 'فشل في إنشاء الجولة: ' . SwissApiService::getError($genResponse)];
}
$roundData = SwissApiService::getBody($genResponse);
$swissRoundId = $roundData['id'] ?? $roundData['round_id'] ?? null;
$roundNumber = $roundData['round_number'] ?? ($currentRound + 1);
$roundInfo = $roundData['round'] ?? $roundData;
$swissRoundId = $roundInfo['id'] ?? null;
$roundNumber = $roundInfo['roundNumber'] ?? $roundInfo['round_number'] ?? ($currentRound + 1);
$roundRecord = $db->insert('el3ab_tournament_rounds', [
'tournament_id' => $tournamentId,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment