From d585f3be5a17a4aaebaf86d3669d226c33051062 Mon Sep 17 00:00:00 2001 From: xziino Date: Fri, 22 May 2026 12:36:16 +0200 Subject: [PATCH 1/3] =?UTF-8?q?Planner:=20=C3=84quivalenz-Hinweise=20f?= =?UTF-8?q?=C3=BCr=20fehlende=20Job-Abilities?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- css/planner.css | 16 ++++++++++++++++ js/planner.js | 40 +++++++++++++++++++++++++++++++++++----- 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/css/planner.css b/css/planner.css index c06fbb9..5ccdb1f 100644 --- a/css/planner.css +++ b/css/planner.css @@ -417,6 +417,22 @@ .ability-chip--other-job { opacity: 0.45; } +/* ── Equivalents hint ────────────────────────────────────────────────────────── */ +.badge-with-hint { + display: inline-flex; + flex-direction: column; + align-items: flex-start; + gap: 2px; +} + +.badge-equiv-hint { + font-size: 11px; + color: var(--red); + white-space: nowrap; + padding: 0 2px; + cursor: default; +} + /* ── Folder Sidebar ──────────────────────────────────────────────────────────── */ .folder-section { margin-bottom: 2px; } diff --git a/js/planner.js b/js/planner.js index c565196..f9aae8e 100644 --- a/js/planner.js +++ b/js/planner.js @@ -350,15 +350,22 @@ function renderMechanicListHtml(plan) { const cls = a.buffType === 'debuff' ? 'badge-assign-debuff' : a.buffType === 'shield' ? 'badge-assign-shield' : 'badge-assign-buff'; - const isMissing = !!a.job && !activeJobSet.has(a.job); - const icon = MITIG_ICONS[a.ability] ?? ''; - const label = a.job ? `${escHtml(a.job)} · ${escHtml(a.ability)}` : escHtml(a.ability); - const title = isMissing ? `${escHtml(a.job)} nicht in Jobaufstellung` : ''; - return ` + const isMissing = !!a.job && !activeJobSet.has(a.job); + const icon = MITIG_ICONS[a.ability] ?? ''; + const label = a.job ? `${escHtml(a.job)} · ${escHtml(a.ability)}` : escHtml(a.ability); + const title = isMissing ? `${escHtml(a.job)} nicht in Jobaufstellung` : ''; + const suggestions = isMissing ? findEquivSuggestions(a.ability, activeJobSet) : []; + const badgeHtml = ` ${icon ? `` : ''} ${label} `; + const hintHtml = suggestions.map(s => + `→ ${escHtml(s.ability)} (${escHtml(s.job)})?` + ).join(''); + return suggestions.length > 0 + ? `${badgeHtml}${hintHtml}` + : badgeHtml; }).join(''); return ` @@ -820,6 +827,29 @@ const MITIG_ICONS = { 'Improvised Finish': 'assets/icons/mitigation/improvised-finish.png', }; +// Groups of abilities that are functionally equivalent across different jobs. +// Used to suggest replacements when a job is missing from the composition. +const ABILITY_EQUIVALENTS = [ + ['Troubadour', 'Tactician', 'Shield Samba'], + ['Sacred Soil', 'Kerachole'], +]; + +function findEquivSuggestions(abilityName, activeJobSet) { + const group = ABILITY_EQUIVALENTS.find(g => g.includes(abilityName)); + if (!group) return []; + const suggestions = []; + for (const equiv of group) { + if (equiv === abilityName) continue; + for (const job of activeJobSet) { + if ((JOB_ABILITIES[job] ?? []).some(a => a.name === equiv)) { + suggestions.push({ ability: equiv, job }); + break; + } + } + } + return suggestions; +} + const ASSIGN_ORDER = { debuff: 0, buff: 1, shield: 2 }; function sortedAssignments(assignments) { From 1c0918a4a3daeb576d48ca20c1b891f5c28a5f96 Mon Sep 17 00:00:00 2001 From: xziino Date: Fri, 22 May 2026 12:43:27 +0200 Subject: [PATCH 2/3] =?UTF-8?q?Planner:=20=C3=84quivalenz-Hinweise=20verfe?= =?UTF-8?q?inert?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Grüner Hinweis wenn Äquivalent verfügbar (z.B. → Kerachole (SGE)?) - Roter Hinweis "→ Kein Äquivalent!" wenn kein Ersatz vorhanden - Grau-kursiv "→ Job zuordnen" bei Abilities ohne Job-Zuordnung Co-Authored-By: Claude Sonnet 4.6 --- css/planner.css | 25 +++++++++++++++++++++---- js/planner.js | 8 ++++++-- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/css/planner.css b/css/planner.css index 5ccdb1f..c989b7b 100644 --- a/css/planner.css +++ b/css/planner.css @@ -426,11 +426,28 @@ } .badge-equiv-hint { - font-size: 11px; - color: var(--red); + font-size: 11px; + color: var(--green); white-space: nowrap; - padding: 0 2px; - cursor: default; + padding: 0 2px; + cursor: default; +} + +.badge-no-equiv-hint { + font-size: 11px; + color: var(--red); + white-space: nowrap; + padding: 0 2px; + cursor: default; +} + +.badge-job-hint { + font-size: 11px; + color: var(--t3); + white-space: nowrap; + padding: 0 2px; + cursor: default; + font-style: italic; } /* ── Folder Sidebar ──────────────────────────────────────────────────────────── */ diff --git a/js/planner.js b/js/planner.js index f9aae8e..dbeb301 100644 --- a/js/planner.js +++ b/js/planner.js @@ -363,8 +363,12 @@ function renderMechanicListHtml(plan) { const hintHtml = suggestions.map(s => `→ ${escHtml(s.ability)} (${escHtml(s.job)})?` ).join(''); - return suggestions.length > 0 - ? `${badgeHtml}${hintHtml}` + const noEquivHint = isMissing && suggestions.length === 0 + ? `→ Kein Äquivalent!` : ''; + const jobHint = !a.job ? `→ Job zuordnen` : ''; + const needsWrap = suggestions.length > 0 || !!noEquivHint || !!jobHint; + return needsWrap + ? `${badgeHtml}${hintHtml}${noEquivHint}${jobHint}` : badgeHtml; }).join(''); From 86d2a106bb1462577bcf476c5c22436fc6576daa Mon Sep 17 00:00:00 2001 From: xziino Date: Fri, 22 May 2026 12:46:52 +0200 Subject: [PATCH 3/3] =?UTF-8?q?Planner:=20Badge-Alignment=20fix=20bei=20?= =?UTF-8?q?=C3=84quivalenz-Hinweisen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- css/planner.css | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/css/planner.css b/css/planner.css index c989b7b..267260b 100644 --- a/css/planner.css +++ b/css/planner.css @@ -224,10 +224,11 @@ } .mechanic-assignments { - display: flex; - flex-wrap: wrap; - gap: 4px; - margin-top: 2px; + display: flex; + flex-wrap: wrap; + gap: 4px; + margin-top: 2px; + align-items: flex-start; } .mechanic-no-assign {