'Method not allowed']); exit; } if (empty($_SESSION['access_token'])) { echo json_encode(['reauth' => true]); exit; } if (($_SESSION['token_expires'] ?? 0) <= time()) { echo json_encode(['reauth' => true]); 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; } $token = $_SESSION['access_token']; function ab_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); curl_close($ch); return json_decode($body, true) ?? []; } // Fetch ability names from masterData $mdResult = ab_gql(<< 'tank', 'healers' => 'healer', 'dps' => 'dps']; foreach ($roleMap as $group => $role) { foreach ($pdGroups[$group] ?? [] as $p) { $players[] = ['name' => $p['name'], 'role' => $role]; } } usort($players, fn($a, $b) => strcmp($a['name'], $b['name'])); // Fetch DamageTaken events from NPC sources only (paginated) $filterEsc = 'source.type = \\"NPC\\"'; $seenIds = []; $nextPage = $startTime; for ($page = 0; $page < 10; $page++) { $evResult = ab_gql(<< 7) $seenIds[$abId] = true; } $nextPage = $ev['nextPageTimestamp'] ?? null; if ($nextPage === null || $nextPage >= $endTime) break; } // Build sorted ability list $abilities = []; foreach (array_keys($seenIds) as $id) { $abilities[] = [ 'id' => $id, 'name' => $abilityNames[$id] ?? ('Ability #' . $id), ]; } usort($abilities, fn($a, $b) => strcmp($a['name'], $b['name'])); echo json_encode(['abilities' => $abilities, 'players' => $players]);