document.addEventListener('DOMContentLoaded', () => { window.App = { reportCode: null, fightId: null, fightStart: 0, fightEnd: 0, phases: [], fights: [] }; const form = document.getElementById('report-form'); const output = document.getElementById('output'); const outputCard = document.getElementById('output-card'); const initialHint = document.getElementById('initial-hint'); const fightSelectCard = document.getElementById('fight-select-card'); const fightSelect = document.getElementById('fight-select'); const explorerCard = document.getElementById('event-explorer-card'); const exLoadBtn = document.getElementById('ex-load-btn'); const exAbilitySelect = document.getElementById('ex-ability'); const exPlayerSelect = document.getElementById('ex-player-name'); let allFights = []; function formatDuration(ms) { const min = Math.floor(ms / 60000); const sec = String(Math.floor((ms % 60000) / 1000)).padStart(2, '0'); return `${min}:${sec}`; } function formatBossHp(fight) { if (fight.kill) return 'Kill'; const pct = fight.fightPercentage; if (pct == null) return '?'; return pct.toFixed(2) + '%'; } function displayFight(fight) { output.textContent = JSON.stringify(fight, null, 2); outputCard.style.display = 'block'; } fightSelect.addEventListener('change', () => { if (!fightSelect.value) return; const id = parseInt(fightSelect.value, 10); const fight = allFights.find(f => f.id === id); if (!fight) return; window.App.fightId = id; window.App.fightStart = fight.startTime; window.App.fightEnd = fight.endTime; window.App.phases = buildPhases(fight); displayFight(fight); explorerCard.style.display = 'block'; window.analysisTab?.onFightSelected?.(); loadAbilities(id, fight.startTime, fight.endTime); }); function buildPhases(fight) { const transitions = fight.phaseTransitions ?? []; if (transitions.length === 0) return []; const phases = transitions.map((t, i) => ({ id: t.id, name: `Phase ${t.id}`, startTime: t.startTime, endTime: transitions[i + 1]?.startTime ?? fight.endTime, })); return [{ id: 0, name: 'Ganzer Fight', startTime: fight.startTime, endTime: fight.endTime }, ...phases]; } async function loadAbilities(fightId, startTime, endTime) { exAbilitySelect.innerHTML = ''; try { const res = await fetch('api/abilities.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ report_code: window.App.reportCode, fight_id: fightId, start_time: startTime, end_time: endTime, }), }); const json = await res.json(); exAbilitySelect.innerHTML = ''; (json.abilities ?? []).forEach(ab => { const opt = document.createElement('option'); opt.value = ab.id; opt.textContent = ab.name; exAbilitySelect.appendChild(opt); }); exPlayerSelect.innerHTML = ''; (json.players ?? []).forEach(p => { const opt = document.createElement('option'); opt.value = p.name; opt.textContent = p.name; exPlayerSelect.appendChild(opt); }); } catch { exAbilitySelect.innerHTML = ''; } } exLoadBtn.addEventListener('click', async () => { if (!window.App.fightId) return; output.textContent = '// loading events...'; outputCard.style.display = 'block'; const params = { report_code: window.App.reportCode, fight_id: window.App.fightId, start_time: window.App.fightStart, end_time: window.App.fightEnd, data_type: document.getElementById('ex-data-type').value, ability_id: exAbilitySelect.value, event_type: document.getElementById('ex-event-type').value.trim(), player_name: document.getElementById('ex-player-name').value.trim(), limit: document.getElementById('ex-limit').value, start_offset: document.getElementById('ex-start-offset').value, end_offset: document.getElementById('ex-end-offset').value, }; try { const res = await fetch('api/debug-events.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams(params), }); const json = await res.json(); if (json.reauth) { window.location.href = 'auth/start.php'; return; } output.textContent = JSON.stringify(json, null, 2); } catch (err) { output.textContent = '// Fehler: ' + err.message; } }); form.addEventListener('submit', async (e) => { e.preventDefault(); initialHint.style.display = 'none'; outputCard.style.display = 'block'; output.textContent = '// fetching...'; fightSelectCard.style.display = 'none'; explorerCard.style.display = 'none'; fightSelect.innerHTML = ''; allFights = []; const reportCode = form.elements['report_code'].value.trim(); window.App.reportCode = reportCode; window.App.fightId = null; window.App.fightStart = 0; window.App.fightEnd = 0; window.App.phases = []; window.App.fights = []; window.analysisTab?.reset?.(); let response, json; try { response = await fetch('api/fight.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ report_code: reportCode }), }); json = await response.json(); } catch (err) { output.textContent = '// network error: ' + err.message; return; } if (json.reauth) { output.textContent = '// session expired — redirecting...'; setTimeout(() => { window.location.href = 'auth/start.php'; }, 1500); return; } if (json.errors) { output.textContent = '// GraphQL error:\n' + JSON.stringify(json.errors, null, 2); return; } const report = json?.data?.reportData?.report; if (!report) { output.textContent = JSON.stringify(json, null, 2); return; } allFights = report.fights ?? []; if (allFights.length === 0) { output.textContent = '// Keine Fights in diesem Report gefunden.'; return; } allFights.forEach(fight => { const duration = formatDuration(fight.endTime - fight.startTime); const hp = formatBossHp(fight); const opt = document.createElement('option'); opt.value = fight.id; opt.textContent = `${fight.name} — ${duration} — ${hp}`; fightSelect.appendChild(opt); }); window.App.fights = allFights; fightSelectCard.style.display = 'block'; output.textContent = '// Fight auswählen ↑'; window.analysisTab?.onFightsLoaded?.(allFights); }); });