diff --git a/public/js/app.js b/public/js/app.js index 1245b34..736a41b 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -507,17 +507,49 @@ function SoloQuizPage({ params, navigate }) { const checkAnswer = () => { const rawCorrect = (q['Richtige Antwort'] || '').trim(); - let correct, ok; + let correctKeysResolved, ok; + if (typ === 'freitext') { - correct = []; setCorrectText(rawCorrect); + correctKeysResolved = []; + setCorrectText(rawCorrect); ok = normalizeText(selected[0]) === normalizeText(rawCorrect); } else { - correct = rawCorrect.split(',').map((s) => s.trim().toUpperCase()).filter(Boolean); - const correctSet = new Set(correct); + // Resolve correct answer: could be keys ("A","B") or text ("Wahr","Falsch") + const parts = rawCorrect.split(',').map((s) => s.trim()).filter(Boolean); + const validKeys = new Set(['A', 'B', 'C', 'D']); + const allAreKeys = parts.length > 0 && parts.every((p) => validKeys.has(p.toUpperCase())); + + if (allAreKeys) { + correctKeysResolved = parts.map((p) => p.toUpperCase()); + } else { + // Match text against answer options + correctKeysResolved = []; + for (const part of parts) { + const partLower = part.toLowerCase().trim(); + // Search in all answers (including shuffled ones which keep their original keys) + const allAnswers = []; + ['A', 'B', 'C', 'D'].forEach((k) => { + if (q[`Antwort ${k}`]) allAnswers.push({ key: k, text: q[`Antwort ${k}`] }); + }); + for (const ans of allAnswers) { + if (ans.text.toLowerCase().trim() === partLower) { + correctKeysResolved.push(ans.key); + break; + } + } + } + // Fallback + if (correctKeysResolved.length === 0) { + correctKeysResolved = parts.map((p) => p.toUpperCase()); + } + } + + const correctSet = new Set(correctKeysResolved); const selectedSet = new Set(selected.map((s) => s.toUpperCase())); - ok = correct.length === selectedSet.size && correct.every((c) => selectedSet.has(c)); + ok = correctKeysResolved.length === selectedSet.size && correctKeysResolved.every((c) => selectedSet.has(c)); } - setCorrectKeys(correct); + + setCorrectKeys(correctKeysResolved); setIsCorrect(ok); setShowFeedback(true); diff --git a/server/quiz-logic.js b/server/quiz-logic.js index c5e3925..fa5a2a8 100644 --- a/server/quiz-logic.js +++ b/server/quiz-logic.js @@ -25,14 +25,50 @@ function checkFreitext(userAnswer, correctAnswer) { return normalizeText(userAnswer) === normalizeText(correctAnswer); } +/** + * Resolve correct answer(s) to keys (A/B/C/D). + * Handles both: + * - "A" or "A,C" (key-based) + * - "Falsch" or "Stuttgart" (text-based → resolved to matching key) + */ function parseCorrectAnswers(question) { const raw = (question['Richtige Antwort'] || '').trim(); const typ = getTyp(question); if (typ === 'freitext') return [raw]; - return raw - .split(',') - .map((s) => s.trim().toUpperCase()) - .filter(Boolean); + + const parts = raw.split(',').map((s) => s.trim()).filter(Boolean); + const validKeys = new Set(['A', 'B', 'C', 'D']); + + // Check if all parts are valid keys already + const allAreKeys = parts.length > 0 && parts.every((p) => validKeys.has(p.toUpperCase())); + if (allAreKeys) { + return parts.map((p) => p.toUpperCase()); + } + + // Otherwise: try to match each part against the answer texts + const resolved = []; + for (const part of parts) { + const partLower = part.toLowerCase().trim(); + const keys = ['A', 'B', 'C', 'D']; + let found = false; + for (const k of keys) { + const answerText = (question[`Antwort ${k}`] || '').trim(); + if (answerText && answerText.toLowerCase() === partLower) { + resolved.push(k); + found = true; + break; + } + } + // If it looks like a key anyway (single char), use it + if (!found && part.length === 1 && validKeys.has(part.toUpperCase())) { + resolved.push(part.toUpperCase()); + } + } + + if (resolved.length > 0) return resolved; + + // Fallback: return as-is uppercase + return parts.map((p) => p.toUpperCase()); } function countOptions(question) { @@ -104,7 +140,6 @@ function sanitizeQuestion(question) { kategorie: extractFieldValue(question['Kategorie'], ''), }; - // Rewrite image URL to use proxy const bild = question['Bild']; if (bild && Array.isArray(bild) && bild.length > 0 && bild[0].url) { sanitized.bild = `/api/img?url=${encodeURIComponent(bild[0].url)}`;