feat(vocabService): enhance answer validation for multiple choice exercises
- Improved answer validation logic by expanding multiple choice answer data based on lesson context. - Added methods to extract indices of correct answers and normalize question prompts for better accuracy. - Refactored existing answer checking to accommodate new data handling, ensuring robust evaluation of user responses.
This commit is contained in:
@@ -1702,8 +1702,18 @@ export default class VocabService {
|
|||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Überprüfe Antwort (vereinfachte Logik - kann je nach Übungstyp erweitert werden)
|
const originalAnswerData = typeof exercise.answerData === 'string'
|
||||||
const isCorrect = this._checkAnswer(exercise.answerData, exercise.questionData, userAnswer, exercise.exerciseTypeId);
|
? JSON.parse(exercise.answerData)
|
||||||
|
: exercise.answerData;
|
||||||
|
const questionData = typeof exercise.questionData === 'string'
|
||||||
|
? JSON.parse(exercise.questionData)
|
||||||
|
: exercise.questionData;
|
||||||
|
const effectiveAnswerData = exercise.exerciseTypeId === 2
|
||||||
|
? await this._expandMultipleChoiceAnswerData(exercise, originalAnswerData, questionData)
|
||||||
|
: originalAnswerData;
|
||||||
|
|
||||||
|
// Überprüfe Antwort
|
||||||
|
const isCorrect = this._checkAnswer(effectiveAnswerData, questionData, userAnswer, exercise.exerciseTypeId);
|
||||||
|
|
||||||
// Speichere Fortschritt
|
// Speichere Fortschritt
|
||||||
const [progress, created] = await VocabGrammarExerciseProgress.findOrCreate({
|
const [progress, created] = await VocabGrammarExerciseProgress.findOrCreate({
|
||||||
@@ -1736,12 +1746,7 @@ export default class VocabService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Extrahiere richtige Antwort und Alternativen
|
// Extrahiere richtige Antwort und Alternativen
|
||||||
const answerData = typeof exercise.answerData === 'string'
|
const answerData = effectiveAnswerData;
|
||||||
? JSON.parse(exercise.answerData)
|
|
||||||
: exercise.answerData;
|
|
||||||
const questionData = typeof exercise.questionData === 'string'
|
|
||||||
? JSON.parse(exercise.questionData)
|
|
||||||
: exercise.questionData;
|
|
||||||
|
|
||||||
let correctAnswer = null;
|
let correctAnswer = null;
|
||||||
let alternatives = [];
|
let alternatives = [];
|
||||||
@@ -1817,6 +1822,86 @@ export default class VocabService {
|
|||||||
return type ? type.id : null;
|
return type ? type.id : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_extractMultipleChoiceIndices(answerData) {
|
||||||
|
if (!answerData) return [];
|
||||||
|
if (answerData.correctAnswer !== undefined) {
|
||||||
|
return Array.isArray(answerData.correctAnswer)
|
||||||
|
? answerData.correctAnswer.map(idx => Number(idx)).filter(Number.isInteger)
|
||||||
|
: [Number(answerData.correctAnswer)].filter(Number.isInteger);
|
||||||
|
}
|
||||||
|
if (answerData.correct !== undefined) {
|
||||||
|
return Array.isArray(answerData.correct)
|
||||||
|
? answerData.correct.map(idx => Number(idx)).filter(Number.isInteger)
|
||||||
|
: [Number(answerData.correct)].filter(Number.isInteger);
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
_getMultipleChoicePrompt(questionData) {
|
||||||
|
return this._normalizeTextAnswer(
|
||||||
|
questionData?.question || questionData?.text || questionData?.prompt || ''
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async _expandMultipleChoiceAnswerData(exercise, answerData, questionData) {
|
||||||
|
const options = Array.isArray(questionData?.options) ? questionData.options : [];
|
||||||
|
const baseIndices = this._extractMultipleChoiceIndices(answerData);
|
||||||
|
if (!options.length || !baseIndices.length || !exercise?.lessonId) {
|
||||||
|
return answerData;
|
||||||
|
}
|
||||||
|
|
||||||
|
const prompt = this._getMultipleChoicePrompt(questionData);
|
||||||
|
if (!prompt) {
|
||||||
|
return answerData;
|
||||||
|
}
|
||||||
|
|
||||||
|
const optionIndexMap = new Map();
|
||||||
|
options.forEach((option, index) => {
|
||||||
|
const normalizedOption = this._normalizeTextAnswer(option);
|
||||||
|
if (!normalizedOption) return;
|
||||||
|
const existing = optionIndexMap.get(normalizedOption) || [];
|
||||||
|
existing.push(index);
|
||||||
|
optionIndexMap.set(normalizedOption, existing);
|
||||||
|
});
|
||||||
|
|
||||||
|
const lessonExercises = await VocabGrammarExercise.findAll({
|
||||||
|
where: {
|
||||||
|
lessonId: exercise.lessonId,
|
||||||
|
exerciseTypeId: 2
|
||||||
|
},
|
||||||
|
attributes: ['id', 'questionData', 'answerData']
|
||||||
|
});
|
||||||
|
|
||||||
|
const expandedIndices = new Set(baseIndices);
|
||||||
|
lessonExercises.forEach((candidate) => {
|
||||||
|
const candidateQuestionData = typeof candidate.questionData === 'string'
|
||||||
|
? JSON.parse(candidate.questionData)
|
||||||
|
: candidate.questionData;
|
||||||
|
const candidatePrompt = this._getMultipleChoicePrompt(candidateQuestionData);
|
||||||
|
if (candidatePrompt !== prompt) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const candidateAnswerData = typeof candidate.answerData === 'string'
|
||||||
|
? JSON.parse(candidate.answerData)
|
||||||
|
: candidate.answerData;
|
||||||
|
const candidateOptions = Array.isArray(candidateQuestionData?.options) ? candidateQuestionData.options : [];
|
||||||
|
const candidateIndices = this._extractMultipleChoiceIndices(candidateAnswerData);
|
||||||
|
|
||||||
|
candidateIndices.forEach((candidateIndex) => {
|
||||||
|
const candidateOption = candidateOptions[candidateIndex];
|
||||||
|
const normalizedOption = this._normalizeTextAnswer(candidateOption);
|
||||||
|
const matchingIndices = optionIndexMap.get(normalizedOption) || [];
|
||||||
|
matchingIndices.forEach((matchingIndex) => expandedIndices.add(matchingIndex));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
...answerData,
|
||||||
|
correctAnswer: Array.from(expandedIndices).sort((a, b) => a - b)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
_checkAnswer(answerData, questionData, 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 === undefined || userAnswer === null) return false;
|
if (!answerData || userAnswer === undefined || userAnswer === null) return false;
|
||||||
|
|||||||
Reference in New Issue
Block a user