feat: normalize questionData for gap-fill exercises and add placeholders if necessary
All checks were successful
Deploy to production / deploy (push) Successful in 2m1s

This commit is contained in:
Torsten Schulz (local)
2026-05-26 16:24:20 +02:00
parent d808d54dd6
commit 2ca008806f

View File

@@ -3873,6 +3873,35 @@ export default class VocabService {
const plainLesson = lesson.get({ plain: true }); const plainLesson = lesson.get({ plain: true });
const list = exercises.map((e) => e.get({ plain: true })); const list = exercises.map((e) => e.get({ plain: true }));
// Normalize questionData for gap-fill hints: if text contains placeholders
list.forEach((ex) => {
try {
const qData = typeof ex.questionData === 'string' ? JSON.parse(ex.questionData || '{}') : (ex.questionData || {});
const text = String(qData.text || qData.question || '').trim();
const hasUnderscoreGap = /_{3,}/.test(text);
const hasBraceGap = /\{\s*gap\s*\}/i.test(text);
const hasParenPlaceholders = /\(\s*_{0,}\s*\)/.test(text);
// If answerData suggests a gap-like exercise and question text contains gap markers, ensure type is gap_fill
if ((hasUnderscoreGap || hasBraceGap || hasParenPlaceholders) && qData.type !== 'gap_fill') {
qData.type = 'gap_fill';
ex.questionData = qData;
}
// If answerData has explicit answers but there's no question text, and exerciseTypeId indicates input, add a placeholder
const aData = typeof ex.answerData === 'string' ? JSON.parse(ex.answerData || '{}') : (ex.answerData || {});
const answers = Array.isArray(aData.answers) ? aData.answers : (aData.correct ? (Array.isArray(aData.correct) ? aData.correct : [aData.correct]) : []);
if ((!qData.text && (!qData.question || String(qData.question).trim() === '')) && answers.length && qData.type !== 'multiple_choice') {
// build a minimal gap_fill text using learning hint if available in ex.title
const learningHintMatch = String(ex.title || '').match(/:(.*)$/);
const hint = learningHintMatch ? learningHintMatch[1].trim() : '';
qData.type = 'gap_fill';
qData.text = hint ? `{gap} (${hint})` : '{gap}';
ex.questionData = qData;
}
} catch (err) {
// ignore parse errors
}
});
return await this._mergeSyntheticChapterLexemeMcExercises(plainLesson, list); return await this._mergeSyntheticChapterLexemeMcExercises(plainLesson, list);
} }