'Method not allowed']); exit; } $reportCode = preg_replace('/[^a-zA-Z0-9]/', '', $_POST['report_code'] ?? ''); $fightId = (int)($_POST['fight_id'] ?? 0); $startTime = (float)($_POST['start_time'] ?? 0); $endTime = (float)($_POST['end_time'] ?? 0); if (!$reportCode || !$fightId || !$endTime) { http_response_code(400); echo json_encode(['error' => 'Missing params']); exit; } $cacheParts = [$fightId, (int)$startTime, (int)$endTime]; $cached = read_cached_log('players', $reportCode, 'en', $cacheParts); if ($cached !== null) { echo $cached; exit; } if (empty($_SESSION['access_token'])) { echo json_encode(['reauth' => true]); exit; } if (($_SESSION['token_expires'] ?? 0) <= time()) { echo json_encode(['reauth' => true]); exit; } $token = $_SESSION['access_token']; function pl_gql(string $query): array { global $token; $ch = curl_init(GRAPHQL_URI); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode(['query' => $query]), CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Authorization: Bearer ' . $token], CURLOPT_SSL_VERIFYPEER => !DEV_MODE, ]); $body = curl_exec($ch); $err = curl_error($ch); $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($err) return ['_curl_error' => $err]; if ($code === 401) return ['_reauth' => true]; return json_decode($body, true) ?? ['_parse_error' => true]; } // Single query: playerDetails + first page of DamageTaken with resources to get maxHp $result = pl_gql(<< true]); exit; } if (isset($result['_curl_error'])) { http_response_code(502); echo json_encode(['error' => $result['_curl_error']]); exit; } // Parse player details: id → {name, type, role, maxHp} $pdRaw = $result['data']['reportData']['report']['playerDetails'] ?? null; $pdParsed = is_string($pdRaw) ? json_decode($pdRaw, true) : $pdRaw; $pdGroups = $pdParsed['data']['playerDetails'] ?? []; $players = []; $roleMap = ['tanks' => 'tank', 'healers' => 'healer', 'dps' => 'dps']; foreach ($roleMap as $group => $role) { foreach ($pdGroups[$group] ?? [] as $p) { $players[(int)$p['id']] = [ 'name' => $p['name'], 'type' => $p['type'] ?? '', 'role' => $role, 'maxHp' => 0, ]; } } // Extract maxHp from first damage events (skip DoT ticks — they may lack resources) foreach ($result['data']['reportData']['report']['events']['data'] ?? [] as $ev) { if ($ev['tick'] ?? false) continue; $tid = (int)($ev['targetID'] ?? 0); $maxHp = (int)($ev['targetResources']['maxHitPoints'] ?? 0); if (isset($players[$tid]) && $players[$tid]['maxHp'] === 0 && $maxHp > 0) { $players[$tid]['maxHp'] = $maxHp; } } $response = json_encode(['players' => array_values($players)]); if ($response === false) { http_response_code(500); echo json_encode(['error' => 'Could not encode players response']); exit; } write_cached_log('players', $reportCode, 'en', $cacheParts, $response); echo $response;