From 502f1fc04e56cac5f6b1926af9645f1ca344ce22 Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Tue, 26 May 2026 11:16:16 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20f=C3=BCge=20generische=20Fallback-?= =?UTF-8?q?=C3=9Cbungen=20hinzu,=20wenn=20keine=20didaktischen=20Inhalte?= =?UTF-8?q?=20vorhanden=20sind?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitea/workflows/deploy.yml | 2 +- .../scripts/create-bisaya-course-content.js | 56 ++++++++++++++++++- 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index 88115f5..5b0e10c 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -119,7 +119,7 @@ jobs: # By default we run the deploy script in --dry-run mode. To enable the # actual run set the secret PHASE3_UPDATE=1 in the repo settings. RUN_FLAG="--dry-run" - if [ "${{ secrets.PHASE3_UPDATE:-}}" = "1" ]; then + if [ "${{ secrets.PHASE3_UPDATE }}" = "1" ]; then RUN_FLAG="" fi diff --git a/backend/scripts/create-bisaya-course-content.js b/backend/scripts/create-bisaya-course-content.js index 9c4c1ca..27922f1 100644 --- a/backend/scripts/create-bisaya-course-content.js +++ b/backend/scripts/create-bisaya-course-content.js @@ -826,6 +826,50 @@ function generateExercisesFromDidactics(lesson) { return generated.filter(Boolean); } +// Generic fallback exercises when no didactics/exercises are present. +function buildGenericFallbackExercises(lesson) { + const title = lesson.title || 'Unbekannte Lektion'; + const clean = String(title).replace(/[^\w\säöüÄÖÜß-]/g, '').trim(); + const tokens = clean.split(/\s+/).slice(0, 4); + + const mcOptions = [clean, ...tokens.map((t, i) => `${t} alt ${i+1}`)].slice(0,4); + + const multipleChoice = { + exerciseTypeId: 2, + title: `${title}: Beispielprüfung (automatisch)` , + instruction: 'Wähle die passende Formulierung (Platzhalter).', + questionData: { + type: 'multiple_choice', + question: `Welcher Ausdruck passt am besten zur Lektion "${title}"?`, + options: mcOptions + }, + answerData: { + type: 'multiple_choice', + correctAnswer: 0 + }, + explanation: 'Automatisch erstellte Platzhalterprüfung — bitte durch sprachspezifische Übungen ersetzen.' + }; + + const gapText = tokens.length ? `${tokens.join(' ')} {gap}` : `{gap}`; + const gapFill = { + exerciseTypeId: 1, + title: `${title}: Lückentest (automatisch)`, + instruction: 'Fülle die Lücke mit dem passenden Wort.', + questionData: { + type: 'gap_fill', + text: gapText, + gaps: 1 + }, + answerData: { + type: 'gap_fill', + answers: [tokens[0] || ''] + }, + explanation: 'Automatisch erzeugte Lücke, dient als Kurznotbehelf.' + }; + + return [multipleChoice, gapFill]; +} + // Bisaya-spezifische Übungen basierend auf Lektionsthemen const BISAYA_EXERCISES = { // Lektion 24: Gefühle im Alltag @@ -6078,7 +6122,17 @@ async function createBisayaCourseContent() { }); } - const exercises = getExercisesForLesson(lesson); + let exercises = getExercisesForLesson(lesson); + + // If generator produced nothing, create a small safe fallback so the UI + // doesn't show the generic placeholder. This keeps behaviour deterministic + // and avoids empty lesson pages when didactics are missing. + if ((!exercises || exercises.length === 0) && !forceRebuildAll) { + const fallback = buildGenericFallbackExercises(lesson); + if (fallback && fallback.length) { + return fallback; + } + } if (exercises.length === 0) { const existingCount = await VocabGrammarExercise.count({ where: { lessonId: lesson.id } }); if (existingCount > 0) {