feat(VocabLessonView): improve vocab question generation and answer validation

- Introduced a new method to retrieve equivalent vocabulary answers based on user prompts and direction, enhancing the accuracy of answer options.
- Updated the buildChoiceOptions method to handle multiple correct answers and ensure the prompt is excluded from choices.
- Enhanced the current vocab question structure to support multiple acceptable answers, improving user feedback and engagement during exercises.
This commit is contained in:
Torsten Schulz (local)
2026-03-30 08:45:59 +02:00
parent c9a7619737
commit 10d8ee015c

View File

@@ -1589,11 +1589,30 @@ export default {
// Starte neue Frage im Multiple Choice Modus // Starte neue Frage im Multiple Choice Modus
this.nextVocabQuestion(); this.nextVocabQuestion();
}, },
buildChoiceOptions(correctAnswer, allVocabs, excludePrompt = null) { getEquivalentVocabAnswers(prompt, direction, allVocabs) {
const options = new Set([correctAnswer]); const normalizedPrompt = this.normalizeVocab(prompt);
const matches = [];
allVocabs.forEach((entry) => {
const source = direction === 'L2R' ? entry.learning : entry.reference;
const target = direction === 'L2R' ? entry.reference : entry.learning;
if (!source || !target) return;
if (this.normalizeVocab(source) !== normalizedPrompt) return;
if (!matches.includes(target)) {
matches.push(target);
}
});
return matches;
},
buildChoiceOptions(correctAnswers, allVocabs, excludePrompt = null) {
const normalizedCorrectAnswers = Array.isArray(correctAnswers) ? correctAnswers : [correctAnswers];
const options = new Set(normalizedCorrectAnswers.filter(Boolean));
// Normalisiere alle Werte für den Vergleich (trim + lowercase) // Normalisiere alle Werte für den Vergleich (trim + lowercase)
const normalizedExcludeSet = new Set(); const normalizedExcludeSet = new Set();
normalizedExcludeSet.add(this.normalizeVocab(correctAnswer)); normalizedCorrectAnswers.forEach((answer) => {
normalizedExcludeSet.add(this.normalizeVocab(answer));
});
// Wichtig: Der Prompt (die Frage) darf nicht in den Optionen erscheinen // Wichtig: Der Prompt (die Frage) darf nicht in den Optionen erscheinen
if (excludePrompt) { if (excludePrompt) {
normalizedExcludeSet.add(this.normalizeVocab(excludePrompt)); normalizedExcludeSet.add(this.normalizeVocab(excludePrompt));
@@ -1698,10 +1717,22 @@ export default {
const randomIndex = Math.floor(Math.random() * sourcePool.length); const randomIndex = Math.floor(Math.random() * sourcePool.length);
const vocab = sourcePool[randomIndex]; const vocab = sourcePool[randomIndex];
this.vocabTrainerDirection = Math.random() < 0.5 ? 'L2R' : 'R2L'; this.vocabTrainerDirection = Math.random() < 0.5 ? 'L2R' : 'R2L';
const allTrainerVocabs = [...this.importantVocab, ...this.vocabTrainerMixedPool];
const prompt = this.vocabTrainerDirection === 'L2R' ? vocab.learning : vocab.reference;
const acceptableAnswers = this.getEquivalentVocabAnswers(
prompt,
this.vocabTrainerDirection,
allTrainerVocabs
);
this.currentVocabQuestion = { this.currentVocabQuestion = {
vocab: vocab, vocab: vocab,
prompt: this.vocabTrainerDirection === 'L2R' ? vocab.learning : vocab.reference, prompt,
answer: this.vocabTrainerDirection === 'L2R' ? vocab.reference : vocab.learning, answers: acceptableAnswers.length > 0
? acceptableAnswers
: [this.vocabTrainerDirection === 'L2R' ? vocab.reference : vocab.learning],
answer: acceptableAnswers.length > 0
? acceptableAnswers.join(' / ')
: (this.vocabTrainerDirection === 'L2R' ? vocab.reference : vocab.learning),
key: this.getVocabKey(vocab), key: this.getVocabKey(vocab),
source: questionSource source: questionSource
}; };
@@ -1720,8 +1751,8 @@ export default {
debugLog('[VocabLessonView] Answer:', this.currentVocabQuestion.answer); debugLog('[VocabLessonView] Answer:', this.currentVocabQuestion.answer);
// Wichtig: Der Prompt (die Frage) darf nicht in den Optionen erscheinen // Wichtig: Der Prompt (die Frage) darf nicht in den Optionen erscheinen
this.vocabTrainerChoiceOptions = this.buildChoiceOptions( this.vocabTrainerChoiceOptions = this.buildChoiceOptions(
this.currentVocabQuestion.answer, this.currentVocabQuestion.answers,
[...this.importantVocab, ...this.vocabTrainerMixedPool], allTrainerVocabs,
this.currentVocabQuestion.prompt // Exkludiere den Prompt this.currentVocabQuestion.prompt // Exkludiere den Prompt
); );
debugLog('[VocabLessonView] Choice-Optionen erstellt:', this.vocabTrainerChoiceOptions); debugLog('[VocabLessonView] Choice-Optionen erstellt:', this.vocabTrainerChoiceOptions);
@@ -1757,8 +1788,9 @@ export default {
} }
const normalizedUser = this.normalizeVocab(userAnswer); const normalizedUser = this.normalizeVocab(userAnswer);
const normalizedCorrect = this.normalizeVocab(this.currentVocabQuestion.answer); const normalizedCorrectAnswers = (this.currentVocabQuestion.answers || [this.currentVocabQuestion.answer])
this.vocabTrainerLastCorrect = normalizedUser === normalizedCorrect; .map(answer => this.normalizeVocab(answer));
this.vocabTrainerLastCorrect = normalizedCorrectAnswers.includes(normalizedUser);
// Update Stats // Update Stats
const stats = this.getVocabStats(this.currentVocabQuestion.vocab); const stats = this.getVocabStats(this.currentVocabQuestion.vocab);