Refactor answer checking logic in VocabService to support multiple exercise types

- Updated the _checkAnswer method to handle both multiple choice and gap fill exercises more effectively.
- Enhanced the extraction of correct answers and alternatives based on exercise type, improving accuracy in answer validation.
- Added JSON parsing for answer and question data to ensure compatibility with various input formats.
- Improved fallback mechanisms for answer checking to accommodate different data structures.
This commit is contained in:
Torsten Schulz (local)
2026-01-19 19:35:41 +01:00
parent 1413630f11
commit 44ce6636c0

View File

@@ -1285,7 +1285,7 @@ export default class VocabService {
}
// Überprüfe Antwort (vereinfachte Logik - kann je nach Übungstyp erweitert werden)
const isCorrect = this._checkAnswer(exercise.answerData, userAnswer, exercise.exerciseTypeId);
const isCorrect = this._checkAnswer(exercise.answerData, exercise.questionData, userAnswer, exercise.exerciseTypeId);
// Speichere Fortschritt
const [progress, created] = await VocabGrammarExerciseProgress.findOrCreate({
@@ -1321,11 +1321,36 @@ export default class VocabService {
const answerData = typeof exercise.answerData === 'string'
? JSON.parse(exercise.answerData)
: exercise.answerData;
const questionData = typeof exercise.questionData === 'string'
? JSON.parse(exercise.questionData)
: exercise.questionData;
const correctAnswer = Array.isArray(answerData.correct)
? answerData.correct[0]
: answerData.correct;
const alternatives = answerData.alternatives || [];
let correctAnswer = null;
let alternatives = [];
// Für Multiple Choice: Extrahiere die richtige Antwort aus dem Index
if (exercise.exerciseTypeId === 2 && answerData.correctAnswer !== undefined) {
const options = questionData?.options || [];
const correctIndex = answerData.correctAnswer;
if (options[correctIndex] !== undefined) {
correctAnswer = options[correctIndex];
}
// Alternativen sind alle anderen Optionen
alternatives = options.filter((opt, idx) => idx !== correctIndex);
}
// Für Gap Fill: Extrahiere aus answers Array
else if (exercise.exerciseTypeId === 1 && answerData.answers) {
correctAnswer = Array.isArray(answerData.answers)
? answerData.answers.join(', ')
: answerData.answers;
}
// Fallback: Versuche correct oder correctAnswer
else {
correctAnswer = Array.isArray(answerData.correct)
? answerData.correct[0]
: (answerData.correct || answerData.correctAnswer);
alternatives = answerData.alternatives || [];
}
return {
correct: isCorrect,
@@ -1336,28 +1361,50 @@ export default class VocabService {
};
}
_checkAnswer(answerData, userAnswer, exerciseTypeId) {
_checkAnswer(answerData, questionData, userAnswer, exerciseTypeId) {
// Vereinfachte Antwortprüfung - kann je nach Übungstyp erweitert werden
if (!answerData || !userAnswer) return false;
if (!answerData || userAnswer === undefined || userAnswer === null) return false;
// Für Multiple Choice: Prüfe ob userAnswer eine der richtigen Antworten ist
// Parse JSON strings
const parsedAnswerData = typeof answerData === 'string' ? JSON.parse(answerData) : answerData;
const parsedQuestionData = typeof questionData === 'string' ? JSON.parse(questionData) : questionData;
// Für Multiple Choice: Prüfe ob userAnswer (Index) mit correctAnswer (Index) übereinstimmt
if (exerciseTypeId === 2) { // multiple_choice
const correctAnswers = Array.isArray(answerData.correct) ? answerData.correct : [answerData.correct];
return correctAnswers.includes(userAnswer);
const correctIndex = parsedAnswerData.correctAnswer !== undefined
? parsedAnswerData.correctAnswer
: (parsedAnswerData.correct !== undefined ? parsedAnswerData.correct : null);
if (correctIndex === null) return false;
// userAnswer ist der Index (0, 1, 2, ...)
return Number(userAnswer) === Number(correctIndex);
}
// Für Lückentext: Normalisiere und vergleiche
if (exerciseTypeId === 1) { // gap_fill
const normalize = (str) => String(str || '').trim().toLowerCase();
const correctAnswers = Array.isArray(answerData.correct) ? answerData.correct : [answerData.correct];
const normalizedUserAnswer = normalize(userAnswer);
return correctAnswers.some(correct => normalize(correct) === normalizedUserAnswer);
const correctAnswers = parsedAnswerData.answers || parsedAnswerData.correct || [];
const correctAnswersArray = Array.isArray(correctAnswers) ? correctAnswers : [correctAnswers];
// userAnswer ist ein Array von Antworten
if (Array.isArray(userAnswer)) {
if (userAnswer.length !== correctAnswersArray.length) return false;
return userAnswer.every((ans, idx) => {
const correct = correctAnswersArray[idx];
return normalize(ans) === normalize(correct);
});
} else {
// Fallback: Einzelne Antwort
const normalizedUserAnswer = normalize(userAnswer);
return correctAnswersArray.some(correct => normalize(correct) === normalizedUserAnswer);
}
}
// Für andere Typen: einfacher String-Vergleich (kann später erweitert werden)
const normalize = (str) => String(str || '').trim().toLowerCase();
const correctAnswers = Array.isArray(answerData.correct) ? answerData.correct : [answerData.correct];
return correctAnswers.some(correct => normalize(correct) === normalize(userAnswer));
const correctAnswers = parsedAnswerData.correct || parsedAnswerData.correctAnswer || [];
const correctAnswersArray = Array.isArray(correctAnswers) ? correctAnswers : [correctAnswers];
const normalizedUserAnswer = normalize(userAnswer);
return correctAnswersArray.some(correct => normalize(correct) === normalizedUserAnswer);
}
async getGrammarExerciseProgress(hashedUserId, lessonId) {