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) {