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:
parent
e5b70c5589
commit
6363c123b0
@ -20,6 +20,17 @@
|
|||||||
.player-card:hover { border-color: var(--borderem); }
|
.player-card:hover { border-color: var(--borderem); }
|
||||||
.player-card.player-hidden { opacity: 0.35; border-style: dashed; }
|
.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 {
|
.player-job-icon {
|
||||||
width: 28px;
|
width: 28px;
|
||||||
height: 28px;
|
height: 28px;
|
||||||
|
|||||||
@ -85,12 +85,15 @@
|
|||||||
let phaseFilter = { startTime: 0, endTime: Infinity };
|
let phaseFilter = { startTime: 0, endTime: Infinity };
|
||||||
let refEvents = [];
|
let refEvents = [];
|
||||||
let refFightStart = 0;
|
let refFightStart = 0;
|
||||||
|
let refPlayers = [];
|
||||||
|
let currentPlayers = [];
|
||||||
let extFights = [];
|
let extFights = [];
|
||||||
let extReportCode = '';
|
let extReportCode = '';
|
||||||
|
|
||||||
// ── Player grid ──────────────────────────────────────────────────────────
|
// ── Player grid ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
function renderPlayers(players) {
|
function renderPlayers(players) {
|
||||||
|
currentPlayers = players;
|
||||||
const grid = document.getElementById('player-grid');
|
const grid = document.getElementById('player-grid');
|
||||||
const order = { healer: 0, dps: 1, tank: 2 };
|
const order = { healer: 0, dps: 1, tank: 2 };
|
||||||
players.sort((a, b) => {
|
players.sort((a, b) => {
|
||||||
@ -112,6 +115,53 @@
|
|||||||
`).join('');
|
`).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 => {
|
document.getElementById('player-grid').addEventListener('click', e => {
|
||||||
const card = e.target.closest('.player-card');
|
const card = e.target.closest('.player-card');
|
||||||
if (!card) return;
|
if (!card) return;
|
||||||
@ -284,6 +334,8 @@
|
|||||||
if (!refId) {
|
if (!refId) {
|
||||||
refEvents = [];
|
refEvents = [];
|
||||||
refFightStart = 0;
|
refFightStart = 0;
|
||||||
|
refPlayers = [];
|
||||||
|
renderRefPlayers();
|
||||||
renderTimeline(lastEvents, lastFightStart);
|
renderTimeline(lastEvents, lastFightStart);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -310,9 +362,11 @@
|
|||||||
if (!json.error && !json.reauth) {
|
if (!json.error && !json.reauth) {
|
||||||
refEvents = json.aoe_events ?? [];
|
refEvents = json.aoe_events ?? [];
|
||||||
refFightStart = json.fight_start ?? fight.startTime;
|
refFightStart = json.fight_start ?? fight.startTime;
|
||||||
|
refPlayers = json.players ?? [];
|
||||||
}
|
}
|
||||||
} catch { }
|
} catch { }
|
||||||
refExtFightSelect.disabled = false;
|
refExtFightSelect.disabled = false;
|
||||||
|
renderRefPlayers();
|
||||||
renderTimeline(lastEvents, lastFightStart);
|
renderTimeline(lastEvents, lastFightStart);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -584,8 +638,10 @@
|
|||||||
lastFightId = null;
|
lastFightId = null;
|
||||||
refEvents = [];
|
refEvents = [];
|
||||||
refFightStart = 0;
|
refFightStart = 0;
|
||||||
|
refPlayers = [];
|
||||||
extFights = [];
|
extFights = [];
|
||||||
extReportCode = '';
|
extReportCode = '';
|
||||||
|
document.getElementById('ref-player-section').style.display = 'none';
|
||||||
refFightSelect.value = '';
|
refFightSelect.value = '';
|
||||||
refFightSelect.style.display = 'none';
|
refFightSelect.style.display = 'none';
|
||||||
refExtFightSelect.value = '';
|
refExtFightSelect.value = '';
|
||||||
|
|||||||
@ -18,6 +18,10 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div id="player-grid" class="player-grid"></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">
|
<div class="ref-ext-row">
|
||||||
<button id="ref-ext-toggle" class="btn btn-sm">+ Anderer Report</button>
|
<button id="ref-ext-toggle" class="btn btn-sm">+ Anderer Report</button>
|
||||||
<div id="ref-ext-panel" style="display:none">
|
<div id="ref-ext-panel" style="display:none">
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user