Add REF player grid for cross-report comparison

When an external reference report is loaded and its roster differs from the
current report, a second player section appears below the main grid showing
all REF report players. REF tanks are hidden by default. Clicking any REF
player card toggles their visibility in the REF timeline rows.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
xziino 2026-05-21 14:55:25 +02:00
parent e5b70c5589
commit 6363c123b0
3 changed files with 71 additions and 0 deletions

View File

@ -20,6 +20,17 @@
.player-card:hover { border-color: var(--borderem); }
.player-card.player-hidden { opacity: 0.35; border-style: dashed; }
.player-card--ref { border-color: rgba(100, 160, 255, 0.35); }
.player-card--ref:hover { border-color: rgba(100, 160, 255, 0.7); }
.ref-player-label {
font-size: 11px;
color: var(--t3);
text-transform: uppercase;
letter-spacing: 0.06em;
margin: 10px 0 6px;
}
.player-job-icon {
width: 28px;
height: 28px;

View File

@ -85,12 +85,15 @@
let phaseFilter = { startTime: 0, endTime: Infinity };
let refEvents = [];
let refFightStart = 0;
let refPlayers = [];
let currentPlayers = [];
let extFights = [];
let extReportCode = '';
// ── Player grid ──────────────────────────────────────────────────────────
function renderPlayers(players) {
currentPlayers = players;
const grid = document.getElementById('player-grid');
const order = { healer: 0, dps: 1, tank: 2 };
players.sort((a, b) => {
@ -112,6 +115,53 @@
`).join('');
}
function renderRefPlayers() {
const section = document.getElementById('ref-player-section');
const grid = document.getElementById('ref-player-grid');
if (!refPlayers.length) { section.style.display = 'none'; return; }
const currentNames = new Set(currentPlayers.map(p => p.name));
if (!refPlayers.some(p => !currentNames.has(p.name))) {
section.style.display = 'none';
return;
}
const order = { healer: 0, dps: 1, tank: 2 };
const sorted = [...refPlayers].sort((a, b) => {
const roleCmp = (order[a.role] ?? 2) - (order[b.role] ?? 2);
return roleCmp !== 0 ? roleCmp : a.name.localeCompare(b.name);
});
sorted.filter(p => p.role === 'tank').forEach(p => hiddenPlayerNames.add(p.name));
grid.innerHTML = sorted.map(p => `
<div class="player-card player-card--ref ${hiddenPlayerNames.has(p.name) ? 'player-hidden' : ''}" data-player-name="${p.name}">
<div class="player-job-icon role-${p.role}">${abbr(p.type)}</div>
<div>
<div class="player-name">${p.name}</div>
<div class="player-type">${p.type}</div>
</div>
</div>
`).join('');
section.style.display = '';
}
document.getElementById('ref-player-grid').addEventListener('click', e => {
const card = e.target.closest('.player-card');
if (!card) return;
const name = card.dataset.playerName;
if (hiddenPlayerNames.has(name)) {
hiddenPlayerNames.delete(name);
card.classList.remove('player-hidden');
} else {
hiddenPlayerNames.add(name);
card.classList.add('player-hidden');
}
renderTimeline(lastEvents, lastFightStart);
});
document.getElementById('player-grid').addEventListener('click', e => {
const card = e.target.closest('.player-card');
if (!card) return;
@ -284,6 +334,8 @@
if (!refId) {
refEvents = [];
refFightStart = 0;
refPlayers = [];
renderRefPlayers();
renderTimeline(lastEvents, lastFightStart);
return;
}
@ -310,9 +362,11 @@
if (!json.error && !json.reauth) {
refEvents = json.aoe_events ?? [];
refFightStart = json.fight_start ?? fight.startTime;
refPlayers = json.players ?? [];
}
} catch { }
refExtFightSelect.disabled = false;
renderRefPlayers();
renderTimeline(lastEvents, lastFightStart);
});
@ -584,8 +638,10 @@
lastFightId = null;
refEvents = [];
refFightStart = 0;
refPlayers = [];
extFights = [];
extReportCode = '';
document.getElementById('ref-player-section').style.display = 'none';
refFightSelect.value = '';
refFightSelect.style.display = 'none';
refExtFightSelect.value = '';

View File

@ -18,6 +18,10 @@
</select>
</div>
<div id="player-grid" class="player-grid"></div>
<div id="ref-player-section" style="display:none">
<div class="ref-player-label">REF Spieler</div>
<div id="ref-player-grid" class="player-grid"></div>
</div>
<div class="ref-ext-row">
<button id="ref-ext-toggle" class="btn btn-sm">+ Anderer Report</button>
<div id="ref-ext-panel" style="display:none">