feat(bisaya-course): add word count validation and exercise audit warnings
Some checks failed
Deploy to production / deploy (push) Has been cancelled
Some checks failed
Deploy to production / deploy (push) Has been cancelled
- Introduced a `countWords` function to calculate the number of words in a given text. - Added `collectExerciseAuditWarnings` function to generate warnings for gap-fill exercises with potentially misleading hints. - Updated the `createBisayaCourseContent` function to log audit warnings when the VOCAB_STRICT_AUDIT environment variable is set, enhancing the validation process for exercise content.
This commit is contained in:
@@ -36,6 +36,44 @@ function normalizeText(value) {
|
||||
.replace(/\s+/g, ' ');
|
||||
}
|
||||
|
||||
function countWords(value) {
|
||||
return normalizeText(value).split(' ').filter(Boolean).length;
|
||||
}
|
||||
|
||||
function collectExerciseAuditWarnings(lessonTitle, exerciseData, exerciseNumber) {
|
||||
const warnings = [];
|
||||
const questionData = exerciseData?.questionData || {};
|
||||
const answerData = exerciseData?.answerData || {};
|
||||
if (questionData.type !== 'gap_fill') return warnings;
|
||||
|
||||
const text = String(questionData.text || '');
|
||||
const answers = Array.isArray(answerData.answers) ? answerData.answers : [];
|
||||
if (!text || !answers.length) return warnings;
|
||||
|
||||
const hints = [];
|
||||
const hintRegex = /\(([^)]+)\)/g;
|
||||
let match = hintRegex.exec(text);
|
||||
while (match) {
|
||||
hints.push(normalizeText(match[1]));
|
||||
match = hintRegex.exec(text);
|
||||
}
|
||||
|
||||
for (let i = 0; i < Math.min(answers.length, hints.length); i += 1) {
|
||||
const answer = normalizeText(answers[i]);
|
||||
const hint = hints[i];
|
||||
if (!answer || !hint) continue;
|
||||
const answerWords = countWords(answer);
|
||||
const hintWords = countWords(hint);
|
||||
if (answerWords <= 2 && hintWords >= 4) {
|
||||
warnings.push(
|
||||
`[${lessonTitle} #${exerciseNumber}] Gap-Fill-Hinweis wirkt zu lang für eine Kurzantwort: "${answer}" <-> "${hint}"`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return warnings;
|
||||
}
|
||||
|
||||
function normalizeCorePatternEntry(entry) {
|
||||
if (entry === null || entry === undefined || entry === '') {
|
||||
return null;
|
||||
@@ -2206,7 +2244,7 @@ const BISAYA_EXERCISES = {
|
||||
instruction: 'Fülle die Lücken mit den richtigen Bisaya-Wörtern.',
|
||||
questionData: {
|
||||
type: 'gap_fill',
|
||||
text: '{gap} ka padulong? (Wohin gehst du?) | {gap} imong plano? (Was ist dein Plan?)',
|
||||
text: '{gap} ka padulong? (wo/wohin) | {gap} imong plano? (was)',
|
||||
gaps: 2
|
||||
},
|
||||
answerData: {
|
||||
@@ -2221,7 +2259,7 @@ const BISAYA_EXERCISES = {
|
||||
instruction: 'Fülle die Lücken mit den richtigen Bisaya-Wörtern.',
|
||||
questionData: {
|
||||
type: 'gap_fill',
|
||||
text: 'Moadto ko sa {gap}. (Ich gehe nach Hause.) | Moadto ko sa {gap}. (Ich gehe zum Markt.)',
|
||||
text: 'Moadto ko sa {gap}. (Haus) | Moadto ko sa {gap}. (Markt)',
|
||||
gaps: 2
|
||||
},
|
||||
answerData: {
|
||||
@@ -4337,6 +4375,10 @@ async function createBisayaCourseContent() {
|
||||
// Erstelle Übungen
|
||||
let exerciseNumber = 1;
|
||||
for (const exerciseData of exercises) {
|
||||
if (process.env.VOCAB_STRICT_AUDIT === '1') {
|
||||
const warnings = collectExerciseAuditWarnings(lesson.title, exerciseData, exerciseNumber);
|
||||
warnings.forEach((warning) => console.warn(` ⚠️ ${warning}`));
|
||||
}
|
||||
const exerciseTypeId = await resolveExerciseTypeId(exerciseData);
|
||||
await VocabGrammarExercise.create({
|
||||
lessonId: lesson.id,
|
||||
|
||||
Reference in New Issue
Block a user