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) // Ü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 // Speichere Fortschritt
const [progress, created] = await VocabGrammarExerciseProgress.findOrCreate({ const [progress, created] = await VocabGrammarExerciseProgress.findOrCreate({
@@ -1321,11 +1321,36 @@ export default class VocabService {
const answerData = typeof exercise.answerData === 'string' const answerData = typeof exercise.answerData === 'string'
? JSON.parse(exercise.answerData) ? JSON.parse(exercise.answerData)
: exercise.answerData; : exercise.answerData;
const questionData = typeof exercise.questionData === 'string'
? JSON.parse(exercise.questionData)
: exercise.questionData;
const correctAnswer = Array.isArray(answerData.correct) let correctAnswer = null;
? answerData.correct[0] let alternatives = [];
: answerData.correct;
const alternatives = answerData.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 { return {
correct: isCorrect, 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 // 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 if (exerciseTypeId === 2) { // multiple_choice
const correctAnswers = Array.isArray(answerData.correct) ? answerData.correct : [answerData.correct]; const correctIndex = parsedAnswerData.correctAnswer !== undefined
return correctAnswers.includes(userAnswer); ? 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 // Für Lückentext: Normalisiere und vergleiche
if (exerciseTypeId === 1) { // gap_fill if (exerciseTypeId === 1) { // gap_fill
const normalize = (str) => String(str || '').trim().toLowerCase(); const normalize = (str) => String(str || '').trim().toLowerCase();
const correctAnswers = Array.isArray(answerData.correct) ? answerData.correct : [answerData.correct]; const correctAnswers = parsedAnswerData.answers || parsedAnswerData.correct || [];
const normalizedUserAnswer = normalize(userAnswer); const correctAnswersArray = Array.isArray(correctAnswers) ? correctAnswers : [correctAnswers];
return correctAnswers.some(correct => normalize(correct) === normalizedUserAnswer);
// 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) // Für andere Typen: einfacher String-Vergleich (kann später erweitert werden)
const normalize = (str) => String(str || '').trim().toLowerCase(); const normalize = (str) => String(str || '').trim().toLowerCase();
const correctAnswers = Array.isArray(answerData.correct) ? answerData.correct : [answerData.correct]; const correctAnswers = parsedAnswerData.correct || parsedAnswerData.correctAnswer || [];
return correctAnswers.some(correct => normalize(correct) === normalize(userAnswer)); const correctAnswersArray = Array.isArray(correctAnswers) ? correctAnswers : [correctAnswers];
const normalizedUserAnswer = normalize(userAnswer);
return correctAnswersArray.some(correct => normalize(correct) === normalizedUserAnswer);
} }
async getGrammarExerciseProgress(hashedUserId, lessonId) { async getGrammarExerciseProgress(hashedUserId, lessonId) {