feat: Erweiterung der Antwortvarianten für Vokabelübungen zur Unterstützung von Alternativen und Phrasen
All checks were successful
Deploy to production / deploy (push) Successful in 1m58s

This commit is contained in:
Torsten Schulz (local)
2026-05-19 11:24:01 +02:00
parent ba70c706c8
commit 97b4b01b22

View File

@@ -4152,6 +4152,67 @@ export default {
: s;
return this.normalizeComparableText(source);
},
expandSingleAnswerVariants(answer) {
const base = String(answer || '').trim();
if (!base) return [];
const words = base.split(/\s+/).map((word) => {
if (!word.includes('/')) {
return [word];
}
const match = word.match(/^([([{„\"'“‘]*)(.*?)([)\]}.,!?;:»\"'”’]*)$/);
const prefix = match?.[1] || '';
const core = match?.[2] || word;
const suffix = match?.[3] || '';
const parts = core
.split('/')
.map((part) => part.trim())
.filter(Boolean);
if (parts.length < 2 || parts.length > 8) {
return [word];
}
return parts.map((part) => `${prefix}${part}${suffix}`);
});
const variants = [''];
for (const options of words) {
const next = [];
for (const current of variants) {
for (const option of options) {
next.push(`${current}${current ? ' ' : ''}${option}`);
}
}
if (next.length > 48) {
return [base];
}
variants.splice(0, variants.length, ...next);
}
return [...new Set([base, ...variants])];
},
splitPhraseAlternatives(answer) {
const base = String(answer || '').trim();
if (!base) return [];
// Splits full-phrase alternatives like "A / B" into ["A", "B"] when they look like phrase-level alternatives.
const parts = base.split(/\s*[\/|;]\s*/).map(p => p.trim()).filter(Boolean);
if (parts.length >= 2 && parts.length <= 6) return parts;
return [base];
},
expandAnswerVariants(answer) {
const base = String(answer || '').trim();
if (!base) return [];
const phraseAlternatives = this.splitPhraseAlternatives(base);
if (phraseAlternatives.length >= 2) {
const expanded = phraseAlternatives.flatMap((part) => this.expandSingleAnswerVariants(part));
return [...new Set(expanded)];
}
return this.expandSingleAnswerVariants(base);
},
reportSrsReviewForCurrentQuestion(isCorrect) {
if (!this.currentVocabQuestion?.vocab || !this.courseId) {
return;
@@ -4185,10 +4246,11 @@ export default {
const normalizedUser = this.normalizeVocab(userAnswer, {
ignoreTrailingParentheticalNotes: useTypingNormalization
});
const normalizedCorrectAnswers = (this.currentVocabQuestion.answers || [this.currentVocabQuestion.answer])
.map(answer => this.normalizeVocab(answer, {
ignoreTrailingParentheticalNotes: useTypingNormalization
}));
const rawAnswers = this.currentVocabQuestion.answers || [this.currentVocabQuestion.answer];
// Expand alternatives like "A / B" into separate acceptable answers
const expandedAnswers = rawAnswers.flatMap(a => this.expandAnswerVariants(a));
const normalizedCorrectAnswers = expandedAnswers
.map(answer => this.normalizeVocab(answer, { ignoreTrailingParentheticalNotes: useTypingNormalization }));
this.vocabTrainerLastCorrect = normalizedCorrectAnswers.includes(normalizedUser);
// Update Stats