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:
@@ -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;
|
||||||
|
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[0]
|
||||||
: answerData.correct;
|
: (answerData.correct || answerData.correctAnswer);
|
||||||
const alternatives = answerData.alternatives || [];
|
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 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);
|
const normalizedUserAnswer = normalize(userAnswer);
|
||||||
return correctAnswers.some(correct => normalize(correct) === normalizedUserAnswer);
|
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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user