Skip to content

Commit 9fe455c

Browse files
committed
Auto-Plan und Ra-Den angepasst
1 parent dd7f7f7 commit 9fe455c

3 files changed

Lines changed: 248 additions & 22 deletions

File tree

static/cd-auto-planner.js

Lines changed: 114 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,28 @@ window.CD_AUTO_PLANNER = (function() {
424424
return (window.classColors && window.classColors[(cls || '').toUpperCase()]) || '#FFFFFF';
425425
}
426426

427+
// Normalisiert einen Spec-Namen für toleranten Vergleich:
428+
// - Kleinschreibung, Whitespace weg
429+
// - "1"-Suffix entfernen (Protection1 → protection, Holy1 → holy, ...)
430+
// - deutsche/alternative Schreibweisen auf den englischen Kern mappen
431+
// So matchen Roster-Spec und required-Spec auch bei Format-Unterschieden.
432+
var _SPEC_ALIASES = {
433+
'schutz': 'protection', 'vergeltung': 'retribution', 'heilig': 'holy',
434+
'wiederherstellung': 'restoration', 'verstaerkung': 'enhancement',
435+
'verstärkung': 'enhancement', 'elementar': 'elemental',
436+
'disziplin': 'discipline', 'schatten': 'shadow', 'waechter': 'guardian',
437+
'wächter': 'guardian', 'wildheit': 'feral', 'gleichgewicht': 'balance',
438+
'blut': 'blood', 'frost': 'frost', 'unheilig': 'unholy',
439+
'braumeister': 'brewmaster', 'nebelwirker': 'mistweaver', 'windläufer': 'windwalker',
440+
'windlaeufer': 'windwalker'
441+
};
442+
function normalizeSpec(spec) {
443+
var s = String(spec || '').toLowerCase().trim().replace(/\s+/g, '');
444+
s = s.replace(/[0-9]+$/, ''); // "protection1" → "protection"
445+
if (_SPEC_ALIASES[s]) s = _SPEC_ALIASES[s];
446+
return s;
447+
}
448+
427449
function getPlayersOfClass(cls, requiredRole, requiredSpec) {
428450
// Immer dynamisch das aktuellste Roster laden
429451
var currentRoster = window.effectiveRoster || window.rosterData || [];
@@ -433,11 +455,11 @@ window.CD_AUTO_PLANNER = (function() {
433455

434456
// 2. Spec-Filter hat Vorrang vor Role-Filter
435457
if (requiredSpec && requiredSpec.length > 0) {
436-
var playerSpec = p.spec || p.specName || '';
437-
if (!playerSpec) return true;
458+
var playerSpec = p.spec || p.specName || p.specialization || '';
459+
if (!playerSpec) return true; // Spieler ohne Spec-Angabe nicht ausschließen
438460
var specList = Array.isArray(requiredSpec) ? requiredSpec : [requiredSpec];
439-
var pSpecLower = playerSpec.toLowerCase();
440-
return specList.some(function(s) { return String(s).toLowerCase() === pSpecLower; });
461+
var pSpecNorm = normalizeSpec(playerSpec);
462+
return specList.some(function(s) { return normalizeSpec(s) === pSpecNorm; });
441463
}
442464

443465
// 3. Role-Filter (wenn kein Spec-Filter gesetzt)
@@ -987,10 +1009,12 @@ window.CD_AUTO_PLANNER = (function() {
9871009
});
9881010
}
9891011

990-
var recIds = {};
991-
recommended.forEach(function(s) { recIds[String(s.spellId)] = true; });
1012+
// "Alle CDs" zeigt ALLE wählbaren Cooldowns — auch die oben empfohlenen.
1013+
// (Früher wurden empfohlene spellIds hier ausgeschlossen, wodurch z.B. die
1014+
// Aura der Hingabe komplett fehlte, sobald sie für irgendeine Spec empfohlen
1015+
// war. Das hat den Prot-Pala-Eintrag unauffindbar gemacht.)
9921016
var allCDs = cooldownsDB.filter(function(cd) {
993-
return cd.name && cd.spellId && cd.name.indexOf('---') !== 0 && cd.name.indexOf('-- ') !== 0 && cd.type !== 'Personal' && !recIds[String(cd.spellId)];
1017+
return cd.name && cd.spellId && cd.name.indexOf('---') !== 0 && cd.name.indexOf('-- ') !== 0 && cd.type !== 'Personal';
9941018
});
9951019
var byClassA = {};
9961020
allCDs.forEach(function(cd) {
@@ -1017,14 +1041,39 @@ window.CD_AUTO_PLANNER = (function() {
10171041
return html;
10181042
}
10191043

1044+
// Markiert die Auto-Assign-Vorschau als veraltet (nach Event-Änderungen),
1045+
// ohne sie neu zu berechnen. Wird durch "Auto-Assign" wieder aufgehoben.
1046+
function markPreviewStale() {
1047+
var btn = document.getElementById('btn-auto-assign');
1048+
if (btn && !btn.dataset._origText) {
1049+
btn.dataset._origText = btn.innerHTML;
1050+
}
1051+
if (btn) {
1052+
btn.classList.add('animate-pulse');
1053+
btn.style.boxShadow = '0 0 0 2px #f59e0b';
1054+
btn.title = 'Events wurden geändert — klicke Auto-Assign, um die Vorschau zu aktualisieren.';
1055+
}
1056+
updateStatus('Events geändert — "Auto-Assign" klicken, um die Vorschau neu zu berechnen.');
1057+
}
1058+
1059+
function clearPreviewStale() {
1060+
var btn = document.getElementById('btn-auto-assign');
1061+
if (btn) {
1062+
btn.classList.remove('animate-pulse');
1063+
btn.style.boxShadow = '';
1064+
btn.title = '';
1065+
}
1066+
}
1067+
10201068
function runAutoAssign() {
10211069

10221070
rosterRef = window.effectiveRoster || window.rosterData || [];
1023-
1071+
10241072
var timeline = generateTimeline();
10251073
assignments = autoAssign(timeline);
10261074
renderTimeline(assignments);
10271075
renderEventManager();
1076+
clearPreviewStale();
10281077
// Manager-Schutz erneut anwenden (neu erzeugte Felder)
10291078
if (typeof window._autoPlannerApplyProtection === 'function') {
10301079
window._autoPlannerApplyProtection();
@@ -1140,7 +1189,8 @@ window.CD_AUTO_PLANNER = (function() {
11401189
var key = e.target.dataset.key;
11411190
if (!eventOverrides[key]) eventOverrides[key] = {};
11421191
eventOverrides[key].disabled = !e.target.checked;
1143-
runAutoAssign();
1192+
renderEventManager();
1193+
markPreviewStale();
11441194
});
11451195
});
11461196

@@ -1207,7 +1257,8 @@ window.CD_AUTO_PLANNER = (function() {
12071257
if (!confirm('Event wirklich löschen?')) return;
12081258
customEvents = customEvents.filter(function(evt) { return evt._key !== key; });
12091259
delete eventOverrides[key];
1210-
runAutoAssign();
1260+
renderEventManager();
1261+
markPreviewStale();
12111262
});
12121263
});
12131264

@@ -1227,7 +1278,8 @@ window.CD_AUTO_PLANNER = (function() {
12271278
eventDuration: 0,
12281279
requiredCDs: []
12291280
});
1230-
runAutoAssign();
1281+
renderEventManager();
1282+
markPreviewStale();
12311283
});
12321284
}
12331285
}
@@ -1241,7 +1293,10 @@ window.CD_AUTO_PLANNER = (function() {
12411293
if (!eventOverrides[key]) eventOverrides[key] = {};
12421294
eventOverrides[key][field] = value;
12431295
}
1244-
runAutoAssign();
1296+
// Event-Änderungen NICHT mehr sofort in die Vorschau verteilen — erst auf
1297+
// "Auto-Assign". Nur den Event-Manager neu zeichnen und Vorschau als veraltet markieren.
1298+
renderEventManager();
1299+
markPreviewStale();
12451300
}
12461301

12471302
// ── Trigger-Picker pro Event ──
@@ -1389,6 +1444,7 @@ window.CD_AUTO_PLANNER = (function() {
13891444
}
13901445
document.body.removeChild(overlay);
13911446
renderEventManager();
1447+
markPreviewStale();
13921448
});
13931449
modal.querySelector('#trg-pick-cancel').addEventListener('click', function() {
13941450
document.body.removeChild(overlay);
@@ -2676,6 +2732,52 @@ window.CD_AUTO_PLANNER = (function() {
26762732
}
26772733
}, 500);
26782734
setTimeout(function() { clearInterval(w); }, 15000);
2735+
},
2736+
2737+
// Diagnose-Helper: in der Browser-Konsole `CD_AUTO_PLANNER.debugRoster()` aufrufen,
2738+
// um zu sehen, welche class/spec/roles-Werte die Spieler tatsächlich haben.
2739+
// Zeigt auch, wie normalizeSpec sie interpretiert.
2740+
debugRoster: function(filterClass) {
2741+
var roster = window.effectiveRoster || window.rosterData || [];
2742+
var rows = roster
2743+
.filter(function(p) { return !filterClass || (p.class || '').toUpperCase() === filterClass.toUpperCase(); })
2744+
.map(function(p) {
2745+
return {
2746+
name: p.name,
2747+
class: p.class,
2748+
spec: p.spec || p.specName || p.specialization || '(keine)',
2749+
specNormalisiert: normalizeSpec(p.spec || p.specName || p.specialization || ''),
2750+
roles: (p.roles || []).join(',')
2751+
};
2752+
});
2753+
console.table(rows);
2754+
return rows;
2755+
},
2756+
2757+
// Testet, welche Spieler für eine Klasse+Spec gefunden werden.
2758+
// z.B. CD_AUTO_PLANNER.debugMatch('PALADIN', 'Protection1')
2759+
debugMatch: function(cls, spec) {
2760+
var players = getPlayersOfClass(cls, null, spec ? [spec] : null);
2761+
console.log('Treffer für', cls, spec || '(alle)', '→', players);
2762+
2763+
// Detail-Analyse: warum matcht/matcht nicht jeder Spieler der Klasse?
2764+
var roster = window.effectiveRoster || window.rosterData || [];
2765+
var detail = roster
2766+
.filter(function(p) { return (p.class || '').toUpperCase() === (cls || '').toUpperCase(); })
2767+
.map(function(p) {
2768+
var pSpec = p.spec || p.specName || p.specialization || '';
2769+
var pNorm = normalizeSpec(pSpec);
2770+
var reqNorm = spec ? normalizeSpec(spec) : '(kein Spec-Filter)';
2771+
return {
2772+
name: p.name,
2773+
spec_roh: pSpec || '(keine)',
2774+
spec_normalisiert: pNorm,
2775+
gesucht_normalisiert: reqNorm,
2776+
match: spec ? (pNorm === normalizeSpec(spec)) : true
2777+
};
2778+
});
2779+
console.table(detail);
2780+
return players;
26792781
}
26802782
};
26812783
})();

0 commit comments

Comments
 (0)