Enhance Phrasen-Matcher: add Kernstoff/All/Zusatz filter and strict 'falsch ist falsch' rules with no trial-and-error cheating
This commit is contained in:
1 parent
64dfd30853
commit
eb0c464112
2 files changed
+218
-76
No files matched your search
+217
-75
@@ -720,23 +720,41 @@
|
|||||||
<!-- VIEW 3: PHRASEN-MATCHER (Mini-Game) -->
|
<!-- VIEW 3: PHRASEN-MATCHER (Mini-Game) -->
|
||||||
<!-- ========================================== -->
|
<!-- ========================================== -->
|
||||||
<section id="view-matcher" class="hidden space-y-4 sm:space-y-6">
|
<section id="view-matcher" class="hidden space-y-4 sm:space-y-6">
|
||||||
<div class="bg-white p-4 sm:p-5 rounded-2xl border border-slate-200 shadow-sm flex flex-col sm:flex-row justify-between items-start sm:items-center gap-3 sm:gap-4">
|
<div class="bg-white p-4 sm:p-5 rounded-2xl border border-slate-200 shadow-sm flex flex-col lg:flex-row justify-between items-start lg:items-center gap-3 sm:gap-4">
|
||||||
<div>
|
<div>
|
||||||
<h2 class="text-base sm:text-xl font-extrabold text-slate-900 flex items-center gap-2">
|
<h2 class="text-base sm:text-xl font-extrabold text-slate-900 flex items-center gap-2">
|
||||||
<i class="fa-solid fa-puzzle-piece text-indigo-600"></i>
|
<i class="fa-solid fa-puzzle-piece text-indigo-600"></i>
|
||||||
<span>Phrasen-Matcher (Schnell-Zuordnung)</span>
|
<span>Phrasen-Matcher (Direkt-Zuordnung)</span>
|
||||||
</h2>
|
</h2>
|
||||||
<p class="text-xs sm:text-sm text-slate-500 mt-0.5">Tippe zuerst auf ein Zitat und anschließend auf das passende Stilmittel.</p>
|
<p class="text-xs sm:text-sm text-slate-500 mt-0.5">
|
||||||
|
Wähle ein Zitat und tippe auf das passende Stilmittel. <strong>Achtung: Nur 1 Versuch pro Paar – falsch ist falsch!</strong>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center gap-2.5 w-full sm:w-auto justify-between sm:justify-end">
|
|
||||||
<div class="px-3.5 py-1.5 bg-emerald-50 text-emerald-800 border border-emerald-200 rounded-xl text-xs sm:text-sm font-bold">
|
<div class="flex flex-wrap items-center gap-2.5 w-full lg:w-auto justify-between lg:justify-end">
|
||||||
Gelöst: <span id="matchScore">0</span> / 5 Paare
|
<!-- Selection Filter: Kernstoff (bevorzugt) | Alle | Zusatz -->
|
||||||
|
<div class="inline-flex p-1 bg-slate-100 rounded-xl border border-slate-200 text-xs sm:text-sm font-bold">
|
||||||
|
<button id="matcherFilterKernBtn" onclick="setMatcherFilter('highlighted')" class="px-2.5 sm:px-3 py-1.5 rounded-lg bg-white text-indigo-700 shadow-sm font-bold transition">🌟 Kernstoff (17)</button>
|
||||||
|
<button id="matcherFilterAllBtn" onclick="setMatcherFilter('all')" class="px-2.5 sm:px-3 py-1.5 rounded-lg text-slate-600 hover:text-slate-900 transition font-semibold">Alle (23)</button>
|
||||||
|
<button id="matcherFilterZusatzBtn" onclick="setMatcherFilter('zusatz')" class="px-2.5 sm:px-3 py-1.5 rounded-lg text-slate-600 hover:text-slate-900 transition font-semibold">🔍 Zusatz (6)</button>
|
||||||
</div>
|
</div>
|
||||||
<button onclick="initMatcherGame()" class="px-3.5 py-1.5 bg-slate-100 hover:bg-slate-200 text-slate-700 rounded-xl text-xs sm:text-sm font-bold transition flex items-center gap-1.5">
|
|
||||||
<i class="fa-solid fa-arrows-rotate"></i> Neu mischen
|
<!-- Score & Mistakes Badges -->
|
||||||
|
<div class="flex items-center gap-2 text-xs sm:text-sm font-bold">
|
||||||
|
<div class="px-3 py-1.5 bg-emerald-50 text-emerald-800 border border-emerald-200 rounded-xl flex items-center gap-1.5">
|
||||||
|
<i class="fa-solid fa-check text-emerald-600"></i>
|
||||||
|
<span>Richtig: <span id="matchScore">0</span> / 5</span>
|
||||||
|
</div>
|
||||||
|
<div class="px-3 py-1.5 bg-rose-50 text-rose-800 border border-rose-200 rounded-xl flex items-center gap-1.5">
|
||||||
|
<i class="fa-solid fa-xmark text-rose-600"></i>
|
||||||
|
<span>Fehler: <span id="matchFailScore">0</span></span>
|
||||||
|
</div>
|
||||||
|
<button onclick="initMatcherGame()" title="Neu mischen" class="p-2 sm:px-3 sm:py-2 bg-slate-100 hover:bg-slate-200 text-slate-700 rounded-xl font-bold transition flex items-center gap-1">
|
||||||
|
<i class="fa-solid fa-arrows-rotate"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Matcher Board -->
|
<!-- Matcher Board -->
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 sm:gap-6 max-w-4xl mx-auto">
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 sm:gap-6 max-w-4xl mx-auto">
|
||||||
@@ -757,13 +775,22 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="matcherWinBanner" class="hidden bg-emerald-500 text-white p-6 sm:p-8 rounded-3xl text-center space-y-3 shadow-xl max-w-md mx-auto">
|
<!-- Matcher Result Screen (Fehler & Richtig) -->
|
||||||
<div class="text-4xl"><i class="fa-solid fa-circle-check"></i></div>
|
<div id="matcherResultBanner" class="hidden text-white p-6 sm:p-8 rounded-3xl text-center space-y-4 shadow-xl max-w-md mx-auto transition-all">
|
||||||
<h4 class="text-2xl font-black">Perfekt zugeordnet!</h4>
|
<div id="matcherResultIcon" class="text-4xl"><i class="fa-solid fa-circle-check"></i></div>
|
||||||
<p class="text-sm sm:text-base text-emerald-100">Du hast alle 5 Paare fehlerfrei zusammengeführt.</p>
|
<div>
|
||||||
<button onclick="initMatcherGame()" class="px-6 py-3 rounded-2xl bg-white text-emerald-800 font-black text-base shadow-md hover:bg-emerald-50 transition">
|
<h4 id="matcherResultTitle" class="text-2xl font-black">Perfekt zugeordnet!</h4>
|
||||||
Nächste Runde spielen
|
<p id="matcherResultSubtitle" class="text-sm sm:text-base text-white/90 mt-1">Du hast alle 5 Paare fehlerfrei zusammengeführt.</p>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col sm:flex-row gap-2.5 justify-center pt-2">
|
||||||
|
<button onclick="initMatcherGame()" class="px-6 py-3 rounded-2xl bg-white text-slate-900 font-extrabold text-sm sm:text-base shadow hover:bg-slate-100 transition">
|
||||||
|
Nächste Runde
|
||||||
</button>
|
</button>
|
||||||
|
<button id="matcherWeakspotsBtn" onclick="switchTab('quiz'); startWeakSpotsQuiz();" class="hidden px-5 py-3 rounded-2xl bg-rose-600 hover:bg-rose-700 text-white font-extrabold text-sm transition flex items-center justify-center gap-1.5">
|
||||||
|
<i class="fa-solid fa-triangle-exclamation"></i>
|
||||||
|
<span>Fehler im Quiz üben</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -1877,10 +1904,6 @@
|
|||||||
let isQuestionAnswered = false;
|
let isQuestionAnswered = false;
|
||||||
let currentQuizMode = 'highlighted';
|
let currentQuizMode = 'highlighted';
|
||||||
|
|
||||||
// Matcher Game State
|
|
||||||
let matcherSelectedPhrase = null;
|
|
||||||
let matcherSelectedTerm = null;
|
|
||||||
let matcherMatchedCount = 0;
|
|
||||||
let currentMatcherPairs = [];
|
let currentMatcherPairs = [];
|
||||||
|
|
||||||
// Glossary State
|
// Glossary State
|
||||||
@@ -2917,19 +2940,68 @@
|
|||||||
repeatBtn.classList.add('hidden');
|
repeatBtn.classList.add('hidden');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// MATCHER GAME
|
// ==========================================
|
||||||
|
// PHRASEN-MATCHER GAME ENGINE ("Falsch ist falsch")
|
||||||
|
// ==========================================
|
||||||
|
let matcherFilter = 'highlighted'; // 'highlighted' (bevorzugt) | 'all' | 'zusatz'
|
||||||
|
let matcherSelectedPhrase = null;
|
||||||
|
let matcherSelectedTerm = null;
|
||||||
|
let matcherCorrectCount = 0;
|
||||||
|
let matcherFailedCount = 0;
|
||||||
|
|
||||||
|
function setMatcherFilter(filter) {
|
||||||
|
matcherFilter = filter;
|
||||||
|
['matcherFilterKernBtn', 'matcherFilterAllBtn', 'matcherFilterZusatzBtn'].forEach(id => {
|
||||||
|
const el = document.getElementById(id);
|
||||||
|
if (el) el.className = 'px-2.5 sm:px-3 py-1.5 rounded-lg text-slate-600 hover:text-slate-900 transition font-semibold';
|
||||||
|
});
|
||||||
|
|
||||||
|
const activeMap = {
|
||||||
|
'highlighted': 'matcherFilterKernBtn',
|
||||||
|
'all': 'matcherFilterAllBtn',
|
||||||
|
'zusatz': 'matcherFilterZusatzBtn'
|
||||||
|
};
|
||||||
|
const activeEl = document.getElementById(activeMap[filter]);
|
||||||
|
if (activeEl) {
|
||||||
|
activeEl.className = 'px-2.5 sm:px-3 py-1.5 rounded-lg bg-white text-indigo-700 shadow-sm font-bold transition';
|
||||||
|
}
|
||||||
|
|
||||||
|
initMatcherGame();
|
||||||
|
}
|
||||||
|
|
||||||
function initMatcherGame() {
|
function initMatcherGame() {
|
||||||
matcherSelectedPhrase = null;
|
matcherSelectedPhrase = null;
|
||||||
matcherSelectedTerm = null;
|
matcherSelectedTerm = null;
|
||||||
matcherMatchedCount = 0;
|
matcherCorrectCount = 0;
|
||||||
|
matcherFailedCount = 0;
|
||||||
document.getElementById('matchScore').innerText = '0';
|
document.getElementById('matchScore').innerText = '0';
|
||||||
document.getElementById('matcherWinBanner').classList.add('hidden');
|
document.getElementById('matchFailScore').innerText = '0';
|
||||||
|
document.getElementById('matcherResultBanner').classList.add('hidden');
|
||||||
|
|
||||||
const shuffled = [...STILMITTEL_DATA].sort(() => Math.random() - 0.5).slice(0, 5);
|
let pool = STILMITTEL_DATA;
|
||||||
|
if (matcherFilter === 'highlighted') {
|
||||||
|
pool = STILMITTEL_DATA.filter(x => x.highlighted);
|
||||||
|
} else if (matcherFilter === 'zusatz') {
|
||||||
|
pool = STILMITTEL_DATA.filter(x => !x.highlighted);
|
||||||
|
}
|
||||||
|
if (pool.length < 5) pool = [...STILMITTEL_DATA];
|
||||||
|
|
||||||
|
const shuffled = [...pool].sort(() => Math.random() - 0.5).slice(0, 5);
|
||||||
currentMatcherPairs = shuffled;
|
currentMatcherPairs = shuffled;
|
||||||
|
|
||||||
const phrases = shuffled.map(x => ({ id: x.id, text: x.examples[0] })).sort(() => Math.random() - 0.5);
|
// Pick randomly from all 10 examples for rich variation
|
||||||
const terms = shuffled.map(x => ({ id: x.id, name: x.term })).sort(() => Math.random() - 0.5);
|
const phrases = shuffled.map(x => ({
|
||||||
|
id: x.id,
|
||||||
|
term: x.term,
|
||||||
|
text: x.examples[Math.floor(Math.random() * x.examples.length)],
|
||||||
|
resolved: false
|
||||||
|
})).sort(() => Math.random() - 0.5);
|
||||||
|
|
||||||
|
const terms = shuffled.map(x => ({
|
||||||
|
id: x.id,
|
||||||
|
name: x.term,
|
||||||
|
resolved: false
|
||||||
|
})).sort(() => Math.random() - 0.5);
|
||||||
|
|
||||||
const phrasesContainer = document.getElementById('matcherPhrasesContainer');
|
const phrasesContainer = document.getElementById('matcherPhrasesContainer');
|
||||||
const termsContainer = document.getElementById('matcherTermsContainer');
|
const termsContainer = document.getElementById('matcherTermsContainer');
|
||||||
@@ -2938,93 +3010,163 @@
|
|||||||
termsContainer.innerHTML = '';
|
termsContainer.innerHTML = '';
|
||||||
|
|
||||||
phrases.forEach(p => {
|
phrases.forEach(p => {
|
||||||
const btn = document.createElement('div');
|
const card = document.createElement('div');
|
||||||
btn.className = 'match-phrase-card p-4 bg-white rounded-2xl border-2 border-slate-200 text-sm font-serif italic text-slate-800 cursor-pointer hover:border-indigo-400 hover:bg-slate-50 transition shadow-sm select-none';
|
card.id = `match-phrase-${p.id}`;
|
||||||
btn.innerText = `„${p.text}“`;
|
card.className = 'match-phrase-card p-4 bg-white rounded-2xl border-2 border-slate-200 text-sm font-serif italic text-slate-800 cursor-pointer hover:border-indigo-400 hover:bg-slate-50 transition shadow-sm select-none flex items-start justify-between gap-2';
|
||||||
btn.onclick = () => selectMatcherPhrase(p.id, btn);
|
|
||||||
phrasesContainer.appendChild(btn);
|
const cleanSpeechText = p.text.replace(/'/g, "\\'").replace(/"/g, '"');
|
||||||
|
card.innerHTML = `
|
||||||
|
<div class="leading-relaxed">„${p.text}“</div>
|
||||||
|
<button onclick="speakText('${cleanSpeechText}', event)" title="Vorlesen" class="p-1 rounded-lg text-slate-400 hover:text-indigo-600 hover:bg-indigo-50 transition shrink-0 not-italic">
|
||||||
|
<i class="fa-solid fa-volume-high text-xs"></i>
|
||||||
|
</button>
|
||||||
|
`;
|
||||||
|
card.onclick = () => selectMatcherPhrase(p.id, card, p.term, p.text);
|
||||||
|
phrasesContainer.appendChild(card);
|
||||||
});
|
});
|
||||||
|
|
||||||
terms.forEach(t => {
|
terms.forEach(t => {
|
||||||
const btn = document.createElement('div');
|
const card = document.createElement('div');
|
||||||
btn.className = 'match-term-card p-4 bg-white rounded-2xl border-2 border-slate-200 text-sm font-sans font-bold text-slate-800 cursor-pointer hover:border-indigo-400 hover:bg-slate-50 transition shadow-sm select-none flex items-center justify-between';
|
card.id = `match-term-${t.id}`;
|
||||||
btn.innerHTML = `<span>${t.name}</span><i class="fa-solid fa-link text-slate-300 text-xs"></i>`;
|
card.className = 'match-term-card p-4 bg-white rounded-2xl border-2 border-slate-200 text-sm font-sans font-bold text-slate-800 cursor-pointer hover:border-indigo-400 hover:bg-slate-50 transition shadow-sm select-none flex items-center justify-between';
|
||||||
btn.onclick = () => selectMatcherTerm(t.id, btn);
|
card.innerHTML = `<span>${t.name}</span><i class="fa-solid fa-link text-slate-300 text-xs"></i>`;
|
||||||
termsContainer.appendChild(btn);
|
card.onclick = () => selectMatcherTerm(t.id, card, t.name);
|
||||||
|
termsContainer.appendChild(card);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectMatcherPhrase(id, el) {
|
function selectMatcherPhrase(id, el, term, text) {
|
||||||
if (el.classList.contains('opacity-40')) return;
|
if (el.classList.contains('pointer-events-none')) return;
|
||||||
document.querySelectorAll('.match-phrase-card').forEach(c => {
|
document.querySelectorAll('.match-phrase-card').forEach(c => {
|
||||||
if (!c.classList.contains('opacity-40')) {
|
if (!c.classList.contains('pointer-events-none')) {
|
||||||
c.classList.remove('border-indigo-600', 'bg-indigo-50');
|
c.classList.remove('border-indigo-600', 'bg-indigo-50', 'ring-2', 'ring-indigo-300');
|
||||||
c.classList.add('border-slate-200');
|
c.classList.add('border-slate-200');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
matcherSelectedPhrase = { id, el };
|
matcherSelectedPhrase = { id, el, term, text };
|
||||||
el.classList.remove('border-slate-200');
|
el.classList.remove('border-slate-200');
|
||||||
el.classList.add('border-indigo-600', 'bg-indigo-50');
|
el.classList.add('border-indigo-600', 'bg-indigo-50', 'ring-2', 'ring-indigo-300');
|
||||||
playTone('flip');
|
playTone('flip');
|
||||||
checkMatcherMatch();
|
checkMatcherMatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectMatcherTerm(id, el) {
|
function selectMatcherTerm(id, el, name) {
|
||||||
if (el.classList.contains('opacity-40')) return;
|
if (el.classList.contains('pointer-events-none')) return;
|
||||||
document.querySelectorAll('.match-term-card').forEach(c => {
|
document.querySelectorAll('.match-term-card').forEach(c => {
|
||||||
if (!c.classList.contains('opacity-40')) {
|
if (!c.classList.contains('pointer-events-none')) {
|
||||||
c.classList.remove('border-indigo-600', 'bg-indigo-50');
|
c.classList.remove('border-indigo-600', 'bg-indigo-50', 'ring-2', 'ring-indigo-300');
|
||||||
c.classList.add('border-slate-200');
|
c.classList.add('border-slate-200');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
matcherSelectedTerm = { id, el };
|
matcherSelectedTerm = { id, el, name };
|
||||||
el.classList.remove('border-slate-200');
|
el.classList.remove('border-slate-200');
|
||||||
el.classList.add('border-indigo-600', 'bg-indigo-50');
|
el.classList.add('border-indigo-600', 'bg-indigo-50', 'ring-2', 'ring-indigo-300');
|
||||||
playTone('flip');
|
playTone('flip');
|
||||||
checkMatcherMatch();
|
checkMatcherMatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkMatcherMatch() {
|
function checkMatcherMatch() {
|
||||||
if (matcherSelectedPhrase && matcherSelectedTerm) {
|
if (!matcherSelectedPhrase || !matcherSelectedTerm) return;
|
||||||
if (matcherSelectedPhrase.id === matcherSelectedTerm.id) {
|
|
||||||
|
const pObj = matcherSelectedPhrase;
|
||||||
|
const tObj = matcherSelectedTerm;
|
||||||
|
const isMatch = pObj.id === tObj.id;
|
||||||
|
|
||||||
|
if (isMatch) {
|
||||||
|
// Richtig zugeordnet!
|
||||||
playTone('success');
|
playTone('success');
|
||||||
const pEl = matcherSelectedPhrase.el;
|
matcherCorrectCount++;
|
||||||
const tEl = matcherSelectedTerm.el;
|
document.getElementById('matchScore').innerText = matcherCorrectCount;
|
||||||
|
|
||||||
pEl.className = 'p-4 bg-emerald-50 border-2 border-emerald-400 text-sm font-serif italic text-emerald-900 rounded-2xl opacity-40 pointer-events-none transition';
|
// Phrase dauerhaft als RICHTIG sperren
|
||||||
tEl.className = 'p-4 bg-emerald-50 border-2 border-emerald-400 text-sm font-sans font-bold text-emerald-900 rounded-2xl opacity-40 pointer-events-none transition flex items-center justify-between';
|
pObj.el.className = 'p-4 bg-emerald-50 border-2 border-emerald-500 text-sm font-serif italic text-emerald-950 rounded-2xl transition shadow-sm pointer-events-none flex items-start justify-between gap-2';
|
||||||
tEl.innerHTML += `<i class="fa-solid fa-check text-emerald-600"></i>`;
|
pObj.el.innerHTML = `
|
||||||
|
<div class="leading-relaxed">„${pObj.text}“</div>
|
||||||
|
<span class="px-2 py-0.5 rounded-lg bg-emerald-200 text-emerald-950 text-xs font-sans font-bold flex items-center gap-1 shrink-0">
|
||||||
|
<i class="fa-solid fa-check"></i> Richtig
|
||||||
|
</span>
|
||||||
|
`;
|
||||||
|
|
||||||
matcherMatchedCount++;
|
// Begriff dauerhaft als RICHTIG sperren
|
||||||
document.getElementById('matchScore').innerText = matcherMatchedCount;
|
tObj.el.className = 'p-4 bg-emerald-50 border-2 border-emerald-500 text-sm font-sans font-bold text-emerald-950 rounded-2xl transition shadow-sm pointer-events-none flex items-center justify-between';
|
||||||
|
tObj.el.innerHTML = `<span>${tObj.name}</span><i class="fa-solid fa-check text-emerald-600 text-base"></i>`;
|
||||||
|
|
||||||
|
addXP(20, 'Matcher Paar gelöst');
|
||||||
|
matcherSelectedPhrase = null;
|
||||||
|
matcherSelectedTerm = null;
|
||||||
|
} else {
|
||||||
|
// "FALSCH IST FALSCH!" - Ein Fehlversuch verbrennt dieses Zitat unwiderruflich!
|
||||||
|
playTone('error');
|
||||||
|
matcherFailedCount++;
|
||||||
|
document.getElementById('matchFailScore').innerText = matcherFailedCount;
|
||||||
|
|
||||||
|
// Phrase DAUERHAFT als FALSCH sperren und Lösung aufdecken
|
||||||
|
pObj.el.className = 'p-4 bg-rose-50 border-2 border-rose-500 text-sm font-serif italic text-rose-950 rounded-2xl transition shadow-sm pointer-events-none space-y-1.5';
|
||||||
|
pObj.el.innerHTML = `
|
||||||
|
<div class="leading-relaxed">„${pObj.text}“</div>
|
||||||
|
<div class="pt-1.5 border-t border-rose-200/80 flex items-center justify-between font-sans text-xs">
|
||||||
|
<span class="text-rose-700 font-extrabold flex items-center gap-1"><i class="fa-solid fa-xmark"></i> Falsch!</span>
|
||||||
|
<span class="text-slate-700 font-medium">Lösung: <strong class="text-indigo-950 font-black">${pObj.term}</strong></span>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Begriff blinkt kurz rot auf und wird dann wieder neutral freigegeben (für andere Zitate)
|
||||||
|
tObj.el.classList.add('border-rose-500', 'bg-rose-50');
|
||||||
|
setTimeout(() => {
|
||||||
|
tObj.el.classList.remove('border-rose-500', 'bg-rose-50', 'border-indigo-600', 'bg-indigo-50', 'ring-2', 'ring-indigo-300');
|
||||||
|
tObj.el.classList.add('border-slate-200');
|
||||||
|
}, 450);
|
||||||
|
|
||||||
|
// Als Schwachstelle speichern für gezieltes Nachlernen
|
||||||
|
if (!quizMistakes.includes(pObj.id)) {
|
||||||
|
quizMistakes.push(pObj.id);
|
||||||
|
localStorage.setItem('rhetorik_quiz_mistakes', JSON.stringify(quizMistakes));
|
||||||
|
updateQuizMistakesBadge();
|
||||||
|
}
|
||||||
|
|
||||||
matcherSelectedPhrase = null;
|
matcherSelectedPhrase = null;
|
||||||
matcherSelectedTerm = null;
|
matcherSelectedTerm = null;
|
||||||
|
|
||||||
if (matcherMatchedCount === 5) {
|
|
||||||
playTone('win');
|
|
||||||
document.getElementById('matcherWinBanner').classList.remove('hidden');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prüfen, ob alle 5 Paare versucht wurden (richtig + falsch = 5)
|
||||||
|
if (matcherCorrectCount + matcherFailedCount === 5) {
|
||||||
|
setTimeout(finishMatcherRound, 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function finishMatcherRound() {
|
||||||
|
const banner = document.getElementById('matcherResultBanner');
|
||||||
|
const title = document.getElementById('matcherResultTitle');
|
||||||
|
const subtitle = document.getElementById('matcherResultSubtitle');
|
||||||
|
const icon = document.getElementById('matcherResultIcon');
|
||||||
|
const weakBtn = document.getElementById('matcherWeakspotsBtn');
|
||||||
|
|
||||||
|
banner.classList.remove('hidden', 'bg-emerald-600', 'bg-indigo-600', 'bg-slate-900', 'bg-rose-600');
|
||||||
|
|
||||||
|
if (matcherCorrectCount === 5) {
|
||||||
|
playTone('win');
|
||||||
|
banner.classList.add('bg-emerald-600');
|
||||||
|
icon.innerHTML = '<i class="fa-solid fa-crown text-amber-300 text-5xl"></i>';
|
||||||
|
title.innerText = 'Perfekt zugeordnet! 🏆';
|
||||||
|
subtitle.innerText = 'Alle 5 Paare auf Anhieb fehlerfrei erkannt. Keine Fehler gemacht!';
|
||||||
|
addXP(60, 'Matcher fehlerfrei');
|
||||||
|
weakBtn.classList.add('hidden');
|
||||||
|
} else if (matcherCorrectCount >= 3) {
|
||||||
|
playTone(matcherCorrectCount >= 4 ? 'win' : 'flip');
|
||||||
|
banner.classList.add('bg-indigo-600');
|
||||||
|
icon.innerHTML = '<i class="fa-solid fa-trophy text-amber-300 text-5xl"></i>';
|
||||||
|
title.innerText = `Runde beendet: ${matcherCorrectCount} von 5 richtig!`;
|
||||||
|
subtitle.innerText = `Falsch ist falsch: ${matcherFailedCount} Fehler gemacht. Die verpassten Begriffe wurden in deine Schwachstellen übernommen.`;
|
||||||
|
weakBtn.classList.remove('hidden');
|
||||||
} else {
|
} else {
|
||||||
playTone('error');
|
playTone('error');
|
||||||
const pEl = matcherSelectedPhrase.el;
|
banner.classList.add('bg-slate-900');
|
||||||
const tEl = matcherSelectedTerm.el;
|
icon.innerHTML = '<i class="fa-solid fa-triangle-exclamation text-rose-400 text-5xl"></i>';
|
||||||
|
title.innerText = `Ergebnis: ${matcherCorrectCount} von 5 Paaren richtig`;
|
||||||
pEl.classList.add('border-rose-500', 'bg-rose-50');
|
subtitle.innerText = `Falsch ist falsch: ${matcherFailedCount} Fehlversuche. Wiederhole die Begriffe gezielt im Schwachstellen-Trainer oder Glossar.`;
|
||||||
tEl.classList.add('border-rose-500', 'bg-rose-50');
|
weakBtn.classList.remove('hidden');
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
pEl.classList.remove('border-rose-500', 'bg-rose-50', 'border-indigo-600', 'bg-indigo-50');
|
|
||||||
tEl.classList.remove('border-rose-500', 'bg-rose-50', 'border-indigo-600', 'bg-indigo-50');
|
|
||||||
pEl.classList.add('border-slate-200');
|
|
||||||
tEl.classList.add('border-slate-200');
|
|
||||||
matcherSelectedPhrase = null;
|
|
||||||
matcherSelectedTerm = null;
|
|
||||||
}, 350);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// GLOSSAR & SUCHE
|
// GLOSSAR & SUCHE
|
||||||
function setGlossaryFilter(filter) {
|
function setGlossaryFilter(filter) {
|
||||||
currentGlossaryFilter = filter;
|
currentGlossaryFilter = filter;
|
||||||
|
|||||||
Reference in new issue
Block a user