From 1f10e7c51954327623ea5a6da32d18793d926358 Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Fri, 17 Apr 2026 11:33:02 +0200 Subject: [PATCH] feat(deploy): enhance deployment scripts with skip options for backend and frontend - Updated `deploy-yourpart-bluegreen.sh` to pass additional arguments for skipping backend or frontend updates. - Enhanced `update.sh` to handle `--skip-backend` and `--skip-frontend` flags, allowing for more flexible deployment based on changes detected. - Modified deployment workflow to conditionally execute based on changes in frontend or backend files, improving deployment efficiency. --- .gitea/workflows/deploy.yml | 45 +- .../scripts/bisaya-course-phase3-extension.js | 598 +++++++++++++----- backend/scripts/bisaya-course-plan-24-43.js | 270 +++++++- .../scripts/create-bisaya-course-content.js | 64 +- .../scripts/extend-bisaya-course-phase3.js | 26 +- backend/scripts/update-bisaya-didactics.js | 4 +- deploy-yourpart-bluegreen.sh | 3 +- update.sh | 45 +- 8 files changed, 887 insertions(+), 168 deletions(-) diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index 3058b97..3e825b3 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -37,6 +37,28 @@ jobs: echo "changed=false" >> "$GITHUB_OUTPUT" fi + if grep -E '^frontend/' changed-files.txt >/dev/null; then + echo "frontend_changed=true" >> "$GITHUB_OUTPUT" + else + echo "frontend_changed=false" >> "$GITHUB_OUTPUT" + fi + + if grep -E '^backend/' changed-files.txt \ + | grep -Ev '^(backend/scripts/.*(bisaya|course|didactics|vocab)|backend/sql/.*vocab|backend/migrations/.*vocab)$' >/dev/null; then + echo "backend_app_changed=true" >> "$GITHUB_OUTPUT" + else + echo "backend_app_changed=false" >> "$GITHUB_OUTPUT" + fi + + # App-Code-Änderungen, die einen echten Deploy benötigen + # (Frontend oder Backend außerhalb reiner Kurs-/Dokument-Sync-Dateien) + if grep -E '^(frontend/|backend/)' changed-files.txt \ + | grep -Ev '^(backend/scripts/.*(bisaya|course|didactics|vocab)|backend/sql/.*vocab|backend/migrations/.*vocab|docs/.*(COURSE|VOCAB|BISAYA|GERMAN_FOR_BISAYA))'; then + echo "app_changed=true" >> "$GITHUB_OUTPUT" + else + echo "app_changed=false" >> "$GITHUB_OUTPUT" + fi + - name: Prepare SSH run: | mkdir -p ~/.ssh @@ -54,11 +76,32 @@ jobs: "echo SSH OK" - name: Run deployment script + if: steps.vocab_course_changes.outputs.app_changed == 'true' run: | + DEPLOY_FLAGS="" + if [ "${{ steps.vocab_course_changes.outputs.backend_app_changed }}" = "true" ] && [ "${{ steps.vocab_course_changes.outputs.frontend_changed }}" != "true" ]; then + DEPLOY_FLAGS="--skip-frontend" + elif [ "${{ steps.vocab_course_changes.outputs.frontend_changed }}" = "true" ] && [ "${{ steps.vocab_course_changes.outputs.backend_app_changed }}" != "true" ]; then + DEPLOY_FLAGS="--skip-backend" + fi + + DEPLOY_TARGET="${{ secrets.PROD_DEPLOY_TARGET }}" + if [ -z "$DEPLOY_TARGET" ]; then + DEPLOY_TARGET="/opt/yourpart-green" + fi + + echo "Deploy-Flags: ${DEPLOY_FLAGS:-}" + echo "Deploy-Target: $DEPLOY_TARGET" + ssh -i ~/.ssh/id_ed25519 \ -p "${{ secrets.PROD_PORT }}" \ "${{ secrets.PROD_USER }}@${{ secrets.PROD_HOST }}" \ - "/home/tsschulz/deploy-yourpart-bluegreen.sh" + "/home/tsschulz/deploy-yourpart-bluegreen.sh ${DEPLOY_TARGET} ${DEPLOY_FLAGS}" + + - name: Skip full deployment (no app changes) + if: steps.vocab_course_changes.outputs.app_changed != 'true' + run: | + echo "Kein Full-Deploy: Es wurden keine Frontend/Backend-App-Dateien geändert." - name: Sync vocab course content if: steps.vocab_course_changes.outputs.changed == 'true' diff --git a/backend/scripts/bisaya-course-phase3-extension.js b/backend/scripts/bisaya-course-phase3-extension.js index 697ff7a..1b77d88 100644 --- a/backend/scripts/bisaya-course-phase3-extension.js +++ b/backend/scripts/bisaya-course-phase3-extension.js @@ -1,254 +1,558 @@ export const BISAYA_PHASE3_DIDACTICS = { 'Besuch & Gastfreundschaft': { learningGoals: [ - 'Einfache Besuchssituationen sprachlich eröffnen.', - 'Gäste begrüßen und höflich ins Haus bitten.', - 'Kurze Standardformeln für Einladung und Reaktion verwenden.' + 'Besuchssituationen sicher eröffnen und freundlich strukturieren.', + 'Hereinbitten, Sitzplatz anbieten, Dank ausdrücken und einfache Rückfragen stellen.', + 'Bekannte Familien- und Fürsorgemuster in Besuchsgespräche übertragen.', + 'Eine kurze Besuchsszene mit mindestens vier eigenen Sätzen sprechen.' + ], + corePatterns: [ + { target: 'Sulod lang.', gloss: 'Komm ruhig herein.' }, + { target: 'Lingkod sa.', gloss: 'Setz dich erst einmal.' }, + { target: 'Maayong pag-abot.', gloss: 'Willkommen.' }, + { target: 'Salamat sa pag-anhi.', gloss: 'Danke fürs Kommen.' }, + { target: 'Gimingaw mi nimo.', gloss: 'Wir haben dich vermisst.' }, + { target: 'Kumusta ang biyahe?', gloss: 'Wie war die Reise?' }, + { target: 'Ganahan ka og tubig?', gloss: 'Möchtest du Wasser?' }, + { target: 'Naa ra mi diri.', gloss: 'Wir sind hier.' } + ], + grammarFocus: [ + { title: 'lang und sa als weiche Partikel', text: 'lang und sa machen Aufforderungen oft weniger hart und alltagstauglicher.', example: 'Sulod lang. Lingkod sa.' }, + { title: 'mi statt ko', text: 'mi bedeutet wir und passt, wenn du für deine Familie oder Gruppe sprichst.', example: 'Gimingaw mi nimo.' } ], - corePatterns: ['Sulod lang.', 'Lingkod sa.', 'Gimingaw mi nimo.', 'Salamat sa pag-anhi.'], speakingPrompts: [ - { - title: 'Gast begrüßen', - prompt: 'Begrüße einen Gast, bitte ihn herein und biete einen Sitzplatz an.', - cue: 'Maayong adlaw. Sulod lang. Lingkod sa.' - } + { title: 'Gast empfangen', prompt: 'Empfange einen Gast, bitte ihn herein, biete einen Sitzplatz an und frage nach der Reise.', cue: 'Maayong pag-abot. Sulod lang. Lingkod sa. Kumusta ang biyahe?' }, + { title: 'Familiäre Wärme', prompt: 'Sage, dass ihr die Person vermisst habt und biete Wasser an.', cue: 'Gimingaw mi nimo. Ganahan ka og tubig?' } ], practicalTasks: [ - { - title: 'Mini-Rollenspiel', - text: 'Spiele den Moment nach, wenn ein Familienmitglied zu Besuch kommt.' - } + { title: 'Besuchsszene', text: 'Spiele eine Besuchsszene mit Begrüßung, Einladung, Angebot und Rückfrage.' } ] }, 'Besuch & Haushalt': { learningGoals: [ - 'Wichtige Wörter rund um Besuch und Haushalt erkennen.', - 'Einfache Dinge im Haus benennen.', - 'Wortschatz aus Woche 1 und 2 mit neuen Besuchssituationen verbinden.' + 'Wichtige Haus- und Besuchswörter sicher erkennen.', + 'Dinge im Haus zeigen, benennen und in kurzen Sätzen verwenden.', + 'Besuchswortschatz mit bereits bekannten Fragen verbinden.', + 'Mindestens sechs Haushaltswörter aktiv abrufen.' ], - corePatterns: ['bisita', 'balay', 'lamisa', 'lingkuranan'] + corePatterns: [ + { target: 'bisita', gloss: 'Besuch / Gast' }, + { target: 'balay', gloss: 'Haus / Zuhause' }, + { target: 'kwarto', gloss: 'Zimmer' }, + { target: 'kusina', gloss: 'Küche' }, + { target: 'lamisa', gloss: 'Tisch' }, + { target: 'lingkuranan', gloss: 'Stuhl' }, + { target: 'pultahan', gloss: 'Tür' }, + { target: 'Naa sa kusina.', gloss: 'Es ist in der Küche.' }, + { target: 'Asa ang lamisa?', gloss: 'Wo ist der Tisch?' } + ], + grammarFocus: [ + { title: 'Naa sa ...', text: 'Mit naa sa sagst du, wo etwas ist.', example: 'Naa sa kusina. Naa sa kwarto.' } + ], + speakingPrompts: [ + { title: 'Im Haus zeigen', prompt: 'Sage, wo Tisch, Stuhl und Küche sind.', cue: 'Naa sa kusina. Naa ang lingkuranan diri.' } + ], + practicalTasks: [ + { title: 'Hausrunde', text: 'Gehe gedanklich durch ein Haus und nenne sechs Dinge mit Ort.' } + ] }, 'Fragen im Alltag vertiefen': { learningGoals: [ - 'Fragen mit mehr Varianten bilden.', - 'Rückfragen höflich wiederholen.', - 'Zwischen Frage, Bitte und Bestätigung sicher wechseln.' + 'Mehrstufige Frageketten bilden, ohne in lange deutsche Satzstrukturen zu fallen.', + 'Ziel, Vorhaben, Zeit und Bedeutung höflich erfragen.', + 'Bei Unsicherheit nachhaken und eine Frage reparieren.', + 'Drei kurze Folgefragen flüssig hintereinander sprechen.' + ], + corePatterns: [ + { target: 'Asa ka padulong?', gloss: 'Wohin gehst du?' }, + { target: 'Unsa imong buhaton?', gloss: 'Was wirst du machen?' }, + { target: 'Kanus-a ka moadto?', gloss: 'Wann gehst du hin?' }, + { target: 'Kinsa imong kuyog?', gloss: 'Mit wem bist du unterwegs?' }, + { target: 'Pwede ko mangutana?', gloss: 'Darf ich fragen?' }, + { target: 'Unsay pasabot ani?', gloss: 'Was bedeutet das?' }, + { target: 'Palihug ka mubalik?', gloss: 'Kannst du das bitte wiederholen?' }, + { target: 'Hinay-hinay lang.', gloss: 'Bitte langsam.' } ], - corePatterns: ['Asa ka padulong?', 'Unsa imong buhaton?', 'Pwede mangutana?', 'Palihug ka mubalik?'], grammarFocus: [ - { - title: 'Frageketten', - text: 'Im Alltag werden oft zwei kurze Fragen nacheinander gestellt statt eines langen Satzes.', - example: 'Asa ka padulong? Unsa imong buhaton didto?' - } + { title: 'Frageketten', text: 'Bisaya-Alltagsgespräche nutzen oft mehrere kurze Fragen statt einer langen Konstruktion.', example: 'Asa ka padulong? Unsa imong buhaton didto?' }, + { title: 'ka und imong', text: 'ka bezieht sich auf du als Person, imong auf dein/deine.', example: 'Asa ka padulong? Unsa imong buhaton?' } ], speakingPrompts: [ - { - title: 'Nachfragen', - prompt: 'Frage nach Ziel, Zeit und Vorhaben einer Person.', - cue: 'Asa ka padulong? Kanus-a ka moadto?' - } + { title: 'Drei-Fragen-Kette', prompt: 'Frage nach Ziel, Zeit und Begleitung.', cue: 'Asa ka padulong? Kanus-a ka moadto? Kinsa imong kuyog?' }, + { title: 'Reparaturfrage', prompt: 'Sage, dass du fragen möchtest, bitte um Wiederholung und frage nach Bedeutung.', cue: 'Pwede ko mangutana? Palihug ka mubalik? Unsay pasabot ani?' } + ], + practicalTasks: [ + { title: 'Frageleiter', text: 'Baue aus drei kurzen Fragen eine natürliche Alltagsszene.' } ] }, 'Termine & Verabredungen': { learningGoals: [ - 'Einfache Treffen verabreden.', - 'Zeitangaben und Zusagen kombinieren.', - 'Kurze Planungsdialoge laut üben.' + 'Einfache Treffen verabreden und bestätigen.', + 'Zeitangaben mit morgen, später, heute und Uhrzeit verbinden.', + 'Zusage, Absage und Verschieben weich ausdrücken.', + 'Einen kurzen Termin-Dialog mit Uhrzeit sprechen.' + ], + corePatterns: [ + { target: 'Magkita ta ugma.', gloss: 'Wir treffen uns morgen.' }, + { target: 'Unsa orasa?', gloss: 'Um wie viel Uhr?' }, + { target: 'Pwede ko karon.', gloss: 'Ich kann jetzt / heute.' }, + { target: 'Dili ko pwede karon.', gloss: 'Ich kann jetzt / heute nicht.' }, + { target: 'Pwede ugma?', gloss: 'Geht morgen?' }, + { target: 'Sige, kita ta.', gloss: 'Okay, wir sehen uns.' }, + { target: 'Human sa trabaho.', gloss: 'Nach der Arbeit.' }, + { target: 'Texti lang ko.', gloss: 'Schreib mir einfach.' } + ], + grammarFocus: [ + { title: 'ta für wir beide / lass uns', text: 'ta verbindet dich und die andere Person in gemeinsamen Handlungen.', example: 'Magkita ta ugma. Kita ta.' }, + { title: 'pwede für Möglichkeit', text: 'pwede hilft bei Zusage, Frage und Absage.', example: 'Pwede ko karon. Pwede ugma?' } ], - corePatterns: ['Magkita ta ugma.', 'Unsa orasa?', 'Pwede ko karon.', 'Sige, kita ta.'], speakingPrompts: [ - { - title: 'Treffen planen', - prompt: 'Vereinbare ein Treffen für morgen und frage nach der Uhrzeit.', - cue: 'Magkita ta ugma. Unsa orasa?' - } + { title: 'Treffen planen', prompt: 'Vereinbare ein Treffen für morgen, frage nach der Uhrzeit und bestätige.', cue: 'Magkita ta ugma. Unsa orasa? Sige, kita ta.' }, + { title: 'Termin verschieben', prompt: 'Sage, dass du heute nicht kannst, und schlage morgen vor.', cue: 'Dili ko pwede karon. Pwede ugma?' } + ], + practicalTasks: [ + { title: 'Kalenderdialog', text: 'Sprich zwei Varianten: eine Zusage und eine weiche Verschiebung.' } ] }, 'Woche 5 - Intensivwiederholung I': { learningGoals: [ - 'Muster aus Familie, Fürsorge, Zeit und Besuch zusammen abrufen.', - 'Zwischen alten und neuen Themen schneller wechseln.', - 'Mehrere Mini-Szenen ohne deutsche Stütze lösen.' + 'Besuch, Familie, Fürsorge und Terminplanung unter Abrufdruck mischen.', + 'Neue Muster mit alten Grundlagen aus Begrüßung, Essen, Zeit und Beziehung verbinden.', + 'Schnell zwischen Rollen wechseln: Gastgeber, Gast, Familienmitglied.', + 'Mindestens acht Situationsantworten ohne deutsche Stütze geben.' ], - corePatterns: ['Kumusta ka?', 'Nikaon na ka?', 'Magkita ta ugma.', 'Sulod lang.'] + corePatterns: [ + { target: 'Kumusta ka?', gloss: 'Wie geht es dir?' }, + { target: 'Nikaon na ka?', gloss: 'Hast du schon gegessen?' }, + { target: 'Sulod lang.', gloss: 'Komm ruhig herein.' }, + { target: 'Lingkod sa.', gloss: 'Setz dich erst einmal.' }, + { target: 'Magkita ta ugma.', gloss: 'Wir treffen uns morgen.' }, + { target: 'Unsa orasa?', gloss: 'Um wie viel Uhr?' }, + { target: 'Ganahan ka og tubig?', gloss: 'Möchtest du Wasser?' }, + { target: 'Palangga taka.', gloss: 'Ich hab dich lieb / Ich liebe dich.' } + ], + speakingPrompts: [ + { title: 'Rollenwechsel', prompt: 'Wechsle zwischen Gast empfangen, nach Essen fragen und Termin vereinbaren.', cue: 'Sulod lang. Nikaon na ka? Magkita ta ugma.' } + ], + practicalTasks: [ + { title: 'Acht schnelle Antworten', text: 'Beantworte acht kurze Situationen aus Besuch, Familie und Terminplanung laut.' } + ] }, 'Spiralwiederholung - Familie & Fürsorge': { learningGoals: [ 'Frühe Familien- und Fürsorgemuster aktiv festigen.', - 'Bekannte Wörter in neuen Dialogen wiedererkennen.', - 'Von Einzelwörtern zu flüssigen Alltagsformeln übergehen.' + 'Familienwörter nicht isoliert, sondern in kurzen Handlungen verwenden.', + 'Nähe, Essen, Müdigkeit und Hilfe in einem Mini-Dialog verbinden.', + 'Alte Kernmuster mit neuen Besuchssätzen kombinieren.' ], - corePatterns: ['Nanay', 'Tatay', 'Palangga taka.', 'Nikaon na ka?'] + corePatterns: [ + { target: 'Nanay', gloss: 'Mutter' }, + { target: 'Tatay', gloss: 'Vater' }, + { target: 'anak', gloss: 'Kind' }, + { target: 'pamilya', gloss: 'Familie' }, + { target: 'Nikaon na ka?', gloss: 'Hast du schon gegessen?' }, + { target: 'Kapoy na ka?', gloss: 'Bist du schon müde?' }, + { target: 'Tabangi ko, palihug.', gloss: 'Hilf mir bitte.' }, + { target: 'Palangga taka.', gloss: 'Ich hab dich lieb / Ich liebe dich.' } + ], + speakingPrompts: [ + { title: 'Familien-Mini-Dialog', prompt: 'Sprich mit einem Familienmitglied über Essen, Müdigkeit und Hilfe.', cue: 'Nikaon na ka? Kapoy na ka? Tabangi ko, palihug.' } + ], + practicalTasks: [ + { title: 'Spiralabruf', text: 'Nimm vier alte Familienwörter und bilde mit jedem einen kurzen Alltagssatz.' } + ] }, 'Gesundheit im Alltag': { learningGoals: [ - 'Einfache Beschwerden und Fürsorge im Gespräch ausdrücken.', - 'Nach dem Befinden fragen und Hilfe anbieten.', - 'Kurze Gesundheitsdialoge in der Familie üben.' + 'Einfache Beschwerden erfragen, beantworten und fürsorglich reagieren.', + 'Körper, Medizin, Ruhe und Wasser in einem Pflegegespräch verbinden.', + 'Zwischen Frage, Rat und Rückmeldung unterscheiden.', + 'Ein Gesundheitsgespräch mit mindestens fünf Sätzen sprechen.' + ], + corePatterns: [ + { target: 'Sakit imong ulo?', gloss: 'Tut dein Kopf weh?' }, + { target: 'Sakit akong tiyan.', gloss: 'Mein Bauch tut weh.' }, + { target: 'Niinom ka og tambal?', gloss: 'Hast du Medizin genommen?' }, + { target: 'Magpahuway sa.', gloss: 'Ruh dich erst einmal aus.' }, + { target: 'Uminom og tubig.', gloss: 'Trink Wasser.' }, + { target: 'Mas maayo na ka?', gloss: 'Geht es dir schon besser?' }, + { target: 'Maayo ra ko.', gloss: 'Mir geht es okay.' }, + { target: 'Tawag ta og doktor?', gloss: 'Sollen wir einen Arzt rufen?' } + ], + grammarFocus: [ + { title: 'akong und imong', text: 'akong bedeutet mein, imong bedeutet dein. Beides steht direkt vor dem Körperteil.', example: 'akong tiyan, imong ulo' }, + { title: 'Frage mit na', text: 'na kann schon/jetzt markieren und kommt in Gesundheitsfragen häufig vor.', example: 'Mas maayo na ka?' } ], - corePatterns: ['Sakit imong ulo?', 'Niinom ka og tambal?', 'Magpahuway sa.', 'Maayo ra ko.'], speakingPrompts: [ - { - title: 'Nach dem Befinden fragen', - prompt: 'Frage nach Schmerzen und biete Ruhe oder Medizin an.', - cue: 'Sakit imong ulo? Magpahuway sa.' - } + { title: 'Pflegegespräch', prompt: 'Frage nach Schmerzen, biete Ruhe und Wasser an und frage nach Besserung.', cue: 'Sakit imong ulo? Magpahuway sa. Uminom og tubig. Mas maayo na ka?' } + ], + practicalTasks: [ + { title: 'Fünf-Satz-Szene', text: 'Sprich eine Szene: Beschwerde, Nachfrage, Medizin, Ruhe, Besserung.' } ] }, 'Medikamente & Beschwerden': { learningGoals: [ - 'Wichtige Wörter zu Schmerzen und Medizin erkennen.', - 'Zwischen Körperteil, Symptom und Hilfe unterscheiden.', - 'Gesundheitswortschatz mit Fürsorge verbinden.' + 'Gesundheitswortschatz zu Symptomen, Körper und Hilfe sicher abrufen.', + 'Symptomwörter in kurze Fürsorgesätze einbauen.', + 'Zwischen Wortabruf und situativer Reaktion wechseln.', + 'Mindestens acht Gesundheitsbegriffe aktiv verwenden.' ], - corePatterns: ['tambal', 'ubo', 'hilanat', 'kasakit'] + corePatterns: [ + { target: 'tambal', gloss: 'Medizin' }, + { target: 'ubo', gloss: 'Husten' }, + { target: 'hilanat', gloss: 'Fieber' }, + { target: 'kasakit', gloss: 'Schmerz' }, + { target: 'ulo', gloss: 'Kopf' }, + { target: 'tiyan', gloss: 'Bauch' }, + { target: 'doktor', gloss: 'Arzt / Ärztin' }, + { target: 'tubig', gloss: 'Wasser' }, + { target: 'Aduna kay hilanat?', gloss: 'Hast du Fieber?' } + ], + speakingPrompts: [ + { title: 'Symptom zu Hilfe', prompt: 'Ordne Husten, Fieber und Schmerz je einer passenden Hilfe zu.', cue: 'Aduna kay hilanat? Magpahuway sa. Uminom og tubig.' } + ], + practicalTasks: [ + { title: 'Gesundheitskarten', text: 'Ziehe gedanklich acht Gesundheitswörter und bilde daraus vier kurze Hilfesätze.' } + ] }, 'Woche 5 - Intensivwiederholung II': { learningGoals: [ - 'Gesundheit, Fragen, Besuch und Organisation gemischt trainieren.', - 'Wackelige Muster noch einmal unter Zeitdruck abrufen.', - 'Sprechtempo und Reaktionssicherheit erhöhen.' + 'Gesundheit, Besuch, Fragen und Terminplanung gemischt reaktivieren.', + 'Ähnliche Muster gezielt unterscheiden: Frage, Bitte, Angebot, Rat.', + 'Unter leichtem Zeitdruck verständlich reagieren.', + 'Fehlercluster aus Woche 5 für SRS und Wiederholung sichtbar machen.' ], - corePatterns: ['Pwede mangutana?', 'Magkita ta.', 'Niinom ka og tambal?', 'Salamat sa pag-anhi.'] + corePatterns: [ + { target: 'Pwede ko mangutana?', gloss: 'Darf ich fragen?' }, + { target: 'Palihug ka mubalik?', gloss: 'Kannst du das bitte wiederholen?' }, + { target: 'Magkita ta ugma.', gloss: 'Wir treffen uns morgen.' }, + { target: 'Salamat sa pag-anhi.', gloss: 'Danke fürs Kommen.' }, + { target: 'Niinom ka og tambal?', gloss: 'Hast du Medizin genommen?' }, + { target: 'Mas maayo na ka?', gloss: 'Geht es dir schon besser?' }, + { target: 'Dili ko pwede karon.', gloss: 'Ich kann heute nicht.' }, + { target: 'Ganahan ka og tubig?', gloss: 'Möchtest du Wasser?' } + ], + speakingPrompts: [ + { title: 'Mischrunde', prompt: 'Reagiere nacheinander auf Besuch, Krankheit, Termin und Verständnisproblem.', cue: 'Sulod lang. Niinom ka og tambal? Pwede ugma? Palihug ka mubalik?' } + ], + practicalTasks: [ + { title: 'Fehlercluster', text: 'Notiere nach der Übung drei Sätze, bei denen du gezögert hast, und wiederhole sie laut.' } + ] }, 'Woche 5 - Checkpoint': { learningGoals: [ - 'Die wichtigsten Inhalte von Woche 5 abrufen.', - 'Sicherheit bei Alltags- und Besuchsdialogen prüfen.', - 'Stärken und Lücken vor Woche 6 sichtbar machen.' + 'Die Inhalte von Woche 5 diagnostisch sichern.', + 'Besuch, Termine, Fragen und Gesundheit in freien Antworten kombinieren.', + 'Schwache Muster für die nächste Wiederholungsphase markieren.', + 'Eine kurze Besuchs- oder Pflegesituation ohne Vorlage lösen.' ], - corePatterns: ['Sulod lang.', 'Unsa orasa?', 'Magpahuway sa.', 'Palihug ka mubalik?'] + corePatterns: [ + { target: 'Sulod lang.', gloss: 'Komm ruhig herein.' }, + { target: 'Unsa orasa?', gloss: 'Um wie viel Uhr?' }, + { target: 'Dili ko pwede karon.', gloss: 'Ich kann heute nicht.' }, + { target: 'Magpahuway sa.', gloss: 'Ruh dich erst einmal aus.' }, + { target: 'Sakit imong ulo?', gloss: 'Tut dein Kopf weh?' }, + { target: 'Kumusta ang biyahe?', gloss: 'Wie war die Reise?' }, + { target: 'Pwede ko mangutana?', gloss: 'Darf ich fragen?' }, + { target: 'Hinay-hinay lang.', gloss: 'Bitte langsam.' } + ], + speakingPrompts: [ + { title: 'Checkpoint-Szene', prompt: 'Löse eine Szene mit Besuch, Termin und Gesundheitsfrage.', cue: 'Sulod lang. Magkita ta ugma? Sakit imong ulo?' } + ], + practicalTasks: [ + { title: 'Diagnose', text: 'Beantworte fünf freie Situationen und markiere alle Sätze, die nicht sofort kamen.' } + ] }, 'Unterwegs & Transport': { learningGoals: [ - 'Unterwegs nach Weg, Fahrt und Ziel fragen.', - 'Kurze Transportsituationen bewältigen.', - 'Richtungen und Verkehrswörter im Kontext nutzen.' + 'Nach Weg, Haltestelle, Fahrpreis und Ziel fragen.', + 'Sagen, wohin man fährt und wo man aussteigen möchte.', + 'Transportfragen mit Orts- und Preiswissen aus früheren Wochen verbinden.', + 'Eine einfache Fahrt sprachlich organisieren.' + ], + corePatterns: [ + { target: 'Asa ang sakayan?', gloss: 'Wo ist die Haltestelle / Mitfahrstelle?' }, + { target: 'Moadto ko sa lungsod.', gloss: 'Ich fahre/gehe in die Stadt.' }, + { target: 'Hunong lang dinhi.', gloss: 'Bitte hier anhalten.' }, + { target: 'Pila ang plite?', gloss: 'Wie viel kostet die Fahrt?' }, + { target: 'Asa ko manaog?', gloss: 'Wo soll ich aussteigen?' }, + { target: 'Duol ra ba?', gloss: 'Ist es nah?' }, + { target: 'Layo pa ba?', gloss: 'Ist es noch weit?' }, + { target: 'Padulong ko sa balay.', gloss: 'Ich bin auf dem Weg nach Hause.' } + ], + grammarFocus: [ + { title: 'moadto und padulong', text: 'moadto betont das Hingehen/Fahren, padulong beschreibt die Richtung.', example: 'Moadto ko sa lungsod. Padulong ko sa balay.' }, + { title: 'dinhi', text: 'dinhi bedeutet hier und ist beim Aussteigen oder Anhalten praktisch.', example: 'Hunong lang dinhi.' } ], - corePatterns: ['Asa ang sakayan?', 'Moadto ko sa lungsod.', 'Hunong lang dinhi.', 'Pila ang plite?'], speakingPrompts: [ - { - title: 'Transport fragen', - prompt: 'Frage nach Haltestelle, Preis und Zielort.', - cue: 'Asa ang sakayan? Pila ang plite?' - } + { title: 'Weg erfragen', prompt: 'Frage nach Haltestelle, Preis und Ausstieg.', cue: 'Asa ang sakayan? Pila ang plite? Asa ko manaog?' }, + { title: 'Fahrt beschreiben', prompt: 'Sage, dass du in die Stadt und später nach Hause fährst.', cue: 'Moadto ko sa lungsod. Padulong ko sa balay.' } + ], + practicalTasks: [ + { title: 'Transportdialog', text: 'Sprich eine kurze Fahrt: Ziel, Preis, Ausstieg, Dank.' } ] }, 'Wege & Verkehr': { learningGoals: [ - 'Weg- und Verkehrswortschatz ausbauen.', - 'Transportwörter mit Richtungen verbinden.', - 'Häufige Reise- und Bewegungsverben wiederholen.' + 'Verkehrs- und Wegwörter aktiv abrufen.', + 'Route, Fahrzeug und Halt in einfachen Sätzen beschreiben.', + 'Frühere Richtungswörter mit Transport verbinden.', + 'Eine kurze Route mit mindestens vier Stationen erklären.' ], - corePatterns: ['sakyanan', 'dalan', 'hunong', 'biyahe'] + corePatterns: [ + { target: 'sakyanan', gloss: 'Fahrzeug / Auto' }, + { target: 'jeepney', gloss: 'Jeepney' }, + { target: 'dalan', gloss: 'Straße / Weg' }, + { target: 'hunong', gloss: 'Halt / anhalten' }, + { target: 'biyahe', gloss: 'Reise / Fahrt' }, + { target: 'tuo', gloss: 'rechts' }, + { target: 'wala', gloss: 'links' }, + { target: 'diretso', gloss: 'geradeaus' }, + { target: 'Duol ra.', gloss: 'Es ist nur nah.' } + ], + speakingPrompts: [ + { title: 'Route beschreiben', prompt: 'Beschreibe eine einfache Route mit geradeaus, rechts und links.', cue: 'Diretso. Tuo. Wala. Duol ra.' } + ], + practicalTasks: [ + { title: 'Wegskizze', text: 'Erkläre den Weg von Zuhause zur Haltestelle in vier kurzen Sätzen.' } + ] }, 'Arbeit & Aufgaben': { learningGoals: [ - 'Über einfache Tätigkeiten und Pflichten sprechen.', - 'Arbeit, Haushalt und Tagesaufgaben benennen.', - 'Kurze Aussagen über To-dos machen.' + 'Über Arbeit, Haushaltspflichten und To-dos sprechen.', + 'Sagen, was man noch erledigen muss und ob man fertig ist.', + 'Hilfe anbieten oder erbitten.', + 'Eine Tagesaufgabe mit Zeit und Grund erklären.' + ], + corePatterns: [ + { target: 'Naa koy trabaho karon.', gloss: 'Ich habe heute Arbeit.' }, + { target: 'Aduna koy buhaton.', gloss: 'Ich habe etwas zu erledigen.' }, + { target: 'Human na ko.', gloss: 'Ich bin fertig.' }, + { target: 'Wala pa ko nahuman.', gloss: 'Ich bin noch nicht fertig.' }, + { target: 'Tabang ta.', gloss: 'Lass uns helfen.' }, + { target: 'Tabangi ko, palihug.', gloss: 'Hilf mir bitte.' }, + { target: 'Unahon nako ni.', gloss: 'Das mache ich zuerst.' }, + { target: 'Human sa paniudto.', gloss: 'Nach dem Mittagessen.' } + ], + grammarFocus: [ + { title: 'naa koy / aduna koy', text: 'Beide Muster drücken aus, dass du etwas hast oder erledigen musst.', example: 'Naa koy trabaho. Aduna koy buhaton.' }, + { title: 'human na vs. wala pa', text: 'human na zeigt fertig, wala pa zeigt noch nicht.', example: 'Human na ko. Wala pa ko nahuman.' } ], - corePatterns: ['Naa koy trabaho karon.', 'Aduna koy buhaton.', 'Human na ko.', 'Tabang ta.'], speakingPrompts: [ - { - title: 'Tagesaufgaben', - prompt: 'Erkläre kurz, was du heute noch erledigen musst.', - cue: 'Aduna koy buhaton karon. Human na ko unya.' - } + { title: 'Tagesaufgabe', prompt: 'Erkläre, was du heute erledigen musst, was zuerst kommt und wann du fertig bist.', cue: 'Aduna koy buhaton. Unahon nako ni. Human na ko unya.' } + ], + practicalTasks: [ + { title: 'To-do laut', text: 'Sprich drei Aufgaben: eine erledigt, eine offen, eine mit Hilfe.' } ] }, 'Tätigkeiten & Organisation': { learningGoals: [ - 'Wörter für Aufgaben, Arbeit und Organisation erkennen.', - 'Bekannte Verben in neue Alltagssituationen übertragen.', - 'Kurze Planungs- und Erledigungssätze vorbereiten.' + 'Organisationswortschatz für Alltag und Haushalt erweitern.', + 'Listen, Aufgaben und Hilfe in kurzen Sätzen verwenden.', + 'Zwischen Tätigkeit, Person und Reihenfolge unterscheiden.', + 'Eine einfache To-do-Liste auf Bisaya sprechen.' ], - corePatterns: ['trabaho', 'buluhaton', 'lista', 'tabang'] + corePatterns: [ + { target: 'trabaho', gloss: 'Arbeit' }, + { target: 'buluhaton', gloss: 'Aufgabe / Tätigkeit' }, + { target: 'lista', gloss: 'Liste' }, + { target: 'tabang', gloss: 'Hilfe' }, + { target: 'una', gloss: 'zuerst' }, + { target: 'sunod', gloss: 'als Nächstes' }, + { target: 'human', gloss: 'fertig / danach' }, + { target: 'Kinsa ang motabang?', gloss: 'Wer hilft?' }, + { target: 'Unsa ang sunod?', gloss: 'Was kommt als Nächstes?' } + ], + speakingPrompts: [ + { title: 'Organisation', prompt: 'Sage, was zuerst kommt, was danach kommt und wer hilft.', cue: 'Una kini. Sunod kana. Kinsa ang motabang?' } + ], + practicalTasks: [ + { title: 'Mini-Liste', text: 'Erstelle mündlich eine Liste mit drei Aufgaben und einer Bitte um Hilfe.' } + ] }, 'Freies Gespräch - Familie & Alltag': { learningGoals: [ 'Frühere Themen ohne enge Führung kombinieren.', - 'Längere Alltagsantworten aufbauen.', - 'Im freien Sprechen bei bekannten Themen stabil bleiben.' + 'Längere Alltagsantworten mit Familie, Zuhause, Befinden und Plan aufbauen.', + 'Bei Unsicherheit Reparaturstrategien verwenden statt abzubrechen.', + 'Mindestens fünf zusammenhängende Sätze frei sprechen.' + ], + corePatterns: [ + { target: 'Maayo ra ko karon.', gloss: 'Mir geht es heute okay.' }, + { target: 'Naa mi sa balay.', gloss: 'Wir sind zuhause.' }, + { target: 'Nikaon na mi.', gloss: 'Wir haben schon gegessen.' }, + { target: 'Aduna koy buhaton unya.', gloss: 'Ich habe später etwas zu erledigen.' }, + { target: 'Magkita mi unya.', gloss: 'Wir sehen uns später.' }, + { target: 'Gimingaw ko nimo.', gloss: 'Ich vermisse dich.' }, + { target: 'Wala ko kasabot, palihug balik.', gloss: 'Ich verstehe nicht, bitte wiederhole es.' }, + { target: 'Amping kanunay.', gloss: 'Pass immer auf dich auf.' } + ], + grammarFocus: [ + { title: 'mi für wir', text: 'mi nutzt du, wenn du über wir sprichst und die angesprochene Person nicht einschließt.', example: 'Naa mi sa balay. Nikaon na mi.' }, + { title: 'Freies Sprechen mit Ankern', text: 'Nutze bekannte Satzanker und füge nur kleine neue Teile hinzu.', example: 'Maayo ra ko karon. Aduna koy buhaton unya.' } ], - corePatterns: ['Maayo ra.', 'Naa mi sa balay.', 'Magkita mi unya.', 'Gimingaw ko nimo.'], speakingPrompts: [ - { - title: 'Alltagsgespräch', - prompt: 'Erzähle kurz von Familie, Tagesplan und aktuellem Befinden.', - cue: 'Naa mi sa balay. Maayo ra ko. Aduna koy buhaton unya.' - } + { title: 'Fünf Sätze frei', prompt: 'Erzähle von deinem Tag mit Befinden, Zuhause, Essen, Plan und Nähe.', cue: 'Maayo ra ko karon. Naa mi sa balay. Nikaon na mi. Aduna koy buhaton unya. Gimingaw ko nimo.' } + ], + practicalTasks: [ + { title: 'Freie Aufnahme', text: 'Sprich 30 Sekunden frei und verwende mindestens einen Reparatursatz, wenn du stockst.' } ] }, 'Spiralwiederholung - Wochen 1 bis 4': { learningGoals: [ - 'Frühe Kursinhalte blockübergreifend wiederholen.', - 'Ähnliche Muster sauber unterscheiden.', - 'Vor dem Schnellstart-Abschluss zentrale Formen stabilisieren.' + 'Grundlagen aus den ersten vier Wochen breit reaktivieren.', + 'Begrüßung, Essen, Zeit, Preise, Gefühle und Gesundheit mischen.', + 'Alte Muster in neuen Kontexten wiederfinden.', + 'Langzeitabruf stärker gewichten als neues Material.' ], - corePatterns: ['Kumusta ka?', 'Tagpila ni?', 'Ni-kaon ko.', 'Nalipay ko.'] + corePatterns: [ + { target: 'Kumusta ka?', gloss: 'Wie geht es dir?' }, + { target: 'Maayong gabii.', gloss: 'Guten Abend.' }, + { target: 'Nikaon na ka?', gloss: 'Hast du schon gegessen?' }, + { target: 'Tagpila ni?', gloss: 'Wie viel kostet das?' }, + { target: 'Karon', gloss: 'jetzt / heute' }, + { target: 'Ugma', gloss: 'morgen' }, + { target: 'Nalipay ko.', gloss: 'Ich freue mich / bin glücklich.' }, + { target: 'Sakit akong ulo.', gloss: 'Mein Kopf tut weh.' }, + { target: 'Palihug ka mubalik?', gloss: 'Kannst du das bitte wiederholen?' } + ], + speakingPrompts: [ + { title: 'Blockmix', prompt: 'Baue aus Begrüßung, Essen, Preis und Gesundheit eine Alltagsszene.', cue: 'Kumusta ka? Nikaon na ka? Tagpila ni? Sakit akong ulo.' } + ], + practicalTasks: [ + { title: 'Langzeitabruf', text: 'Ziehe zehn alte Wörter/Sätze zufällig und bilde daraus fünf kurze Dialogantworten.' } + ] }, 'Konflikte & Missverständnisse': { learningGoals: [ - 'Missverständnisse höflich ansprechen.', - 'Um Wiederholung oder langsamere Erklärung bitten.', - 'Kleine Konflikte sprachlich entschärfen.' + 'Missverständnisse höflich ansprechen und entschärfen.', + 'Um Wiederholung, langsameres Sprechen oder Erklärung bitten.', + 'Eigene Unsicherheit ausdrücken, ohne das Gespräch abzubrechen.', + 'Eine kleine heikle Situation ruhig reparieren.' + ], + corePatterns: [ + { target: 'Wala ko kasabot.', gloss: 'Ich verstehe nicht.' }, + { target: 'Hinay-hinay lang.', gloss: 'Bitte langsam.' }, + { target: 'Palihug ka mubalik?', gloss: 'Kannst du das bitte wiederholen?' }, + { target: 'Pwede nato istoryahan?', gloss: 'Können wir darüber sprechen?' }, + { target: 'Pasayloa ko.', gloss: 'Entschuldige mich.' }, + { target: 'Dili mao akong pasabot.', gloss: 'Das meinte ich nicht.' }, + { target: 'Sige lang.', gloss: 'Schon okay.' }, + { target: 'Salamat sa pagsabot.', gloss: 'Danke fürs Verständnis.' } + ], + grammarFocus: [ + { title: 'Reparieren statt abbrechen', text: 'Ein Reparatursatz hält das Gespräch offen, auch wenn du etwas nicht verstanden hast.', example: 'Wala ko kasabot. Palihug ka mubalik?' }, + { title: 'Weich entschärfen', text: 'Sige lang und Salamat sa pagsabot helfen, Spannung aus dem Gespräch zu nehmen.', example: 'Sige lang. Salamat sa pagsabot.' } ], - corePatterns: ['Wala ko kasabot.', 'Hinay-hinay lang.', 'Pwede nato istoryahan?', 'Pasayloa ko.'], speakingPrompts: [ - { - title: 'Missverständnis lösen', - prompt: 'Bitte um Wiederholung und entschuldige dich höflich.', - cue: 'Wala ko kasabot. Palihug ka mubalik. Pasayloa ko.' - } + { title: 'Missverständnis lösen', prompt: 'Sage, dass du nicht verstanden hast, bitte um Wiederholung und entschuldige dich.', cue: 'Wala ko kasabot. Palihug ka mubalik? Pasayloa ko.' }, + { title: 'Heikle Korrektur', prompt: 'Sage, dass du etwas nicht so gemeint hast, und danke fürs Verständnis.', cue: 'Dili mao akong pasabot. Salamat sa pagsabot.' } + ], + practicalTasks: [ + { title: 'Konfliktanker', text: 'Übe fünf Reparatursätze, bis du sie ohne Lesen sagen kannst.' } ] }, 'Abschlusstest - Schnellstart': { learningGoals: [ - 'Wichtige Wörter aus dem gesamten Schnellstart sicher abrufen.', - 'Zwischen ähnlichen Antworten sauber unterscheiden.', - 'Den aktiven Grundwortschatz stabilisieren.' + 'Aktiven Grundwortschatz aus dem gesamten 6-Wochen-Schnellstart prüfen.', + 'Wörter und kurze Sätze in beide Richtungen abrufen.', + 'Ähnliche Muster sicher unterscheiden.', + 'Schwächen für die nächste SRS-Wiederholung markieren.' ], - corePatterns: ['Kumusta', 'bisita', 'tambal', 'plite'] + corePatterns: [ + { target: 'Kumusta', gloss: 'Wie geht es / Hallo' }, + { target: 'bisita', gloss: 'Besuch / Gast' }, + { target: 'tambal', gloss: 'Medizin' }, + { target: 'plite', gloss: 'Fahrpreis' }, + { target: 'trabaho', gloss: 'Arbeit' }, + { target: 'buluhaton', gloss: 'Aufgabe' }, + { target: 'dalan', gloss: 'Straße / Weg' }, + { target: 'pamilya', gloss: 'Familie' }, + { target: 'Gimingaw ko nimo.', gloss: 'Ich vermisse dich.' }, + { target: 'Palihug ka mubalik?', gloss: 'Kannst du das bitte wiederholen?' } + ], + speakingPrompts: [ + { title: 'Aktiver Wortschatz', prompt: 'Wähle acht Wörter und bilde vier Alltagssätze daraus.', cue: 'bisita -> Sulod lang. tambal -> Niinom ka og tambal?' } + ], + practicalTasks: [ + { title: 'Beide Richtungen', text: 'Übersetze zehn Einheiten Deutsch -> Bisaya und Bisaya -> Deutsch.' } + ] }, 'Abschlussprüfung - Schnellstart': { learningGoals: [ - 'Den 6-Wochen-Schnellstart in gemischten Aufgaben überprüfen.', - 'Abruf, Musterverständnis und situative Anwendung kombinieren.', - 'Die Grundlage für die Alltagsphase absichern.' + 'Den 6-Wochen-Schnellstart in Dialog, Abruf und freier Anwendung prüfen.', + 'Besuch, Gesundheit, Transport, Arbeit und Familie zusammenführen.', + 'Mehrere Sätze ohne starre Vorlage produzieren.', + 'Vor dem Übergang in die Alltagsphase stabile Grundfähigkeit zeigen.' ], - corePatterns: ['Sulod lang.', 'Magkita ta ugma.', 'Niinom ka og tambal?', 'Asa ang sakayan?'] + corePatterns: [ + { target: 'Sulod lang. Lingkod sa.', gloss: 'Komm herein. Setz dich erst einmal.' }, + { target: 'Magkita ta ugma. Unsa orasa?', gloss: 'Wir treffen uns morgen. Um wie viel Uhr?' }, + { target: 'Niinom ka og tambal?', gloss: 'Hast du Medizin genommen?' }, + { target: 'Asa ang sakayan?', gloss: 'Wo ist die Haltestelle?' }, + { target: 'Pila ang plite?', gloss: 'Wie viel kostet die Fahrt?' }, + { target: 'Aduna koy buhaton karon.', gloss: 'Ich habe heute etwas zu erledigen.' }, + { target: 'Wala ko kasabot. Hinay-hinay lang.', gloss: 'Ich verstehe nicht. Bitte langsam.' }, + { target: 'Amping kanunay.', gloss: 'Pass immer auf dich auf.' } + ], + speakingPrompts: [ + { title: 'Große Alltagsszene', prompt: 'Verbinde Besuch, Termin, Gesundheit und Transport in einem Mini-Dialog.', cue: 'Sulod lang. Magkita ta ugma? Niinom ka og tambal? Asa ang sakayan?' }, + { title: 'Freie Antwort', prompt: 'Antworte in mindestens fünf Sätzen auf: Was machst du heute und wen triffst du?', cue: 'Aduna koy buhaton karon. Magkita ta ugma. Amping kanunay.' } + ], + practicalTasks: [ + { title: 'Abschlussaufnahme', text: 'Sprich eine 45-Sekunden-Szene mit mindestens sechs Kernmustern aus Woche 1-6.' } + ] }, 'Kulturelle Vertiefung im Familienalltag': { learningGoals: [ - 'Sprachgebrauch und Familienkultur besser einordnen.', - 'Höflichkeit, Nähe und indirekte Kommunikation bewusster wahrnehmen.', - 'Kulturelle Unterschiede mit dem gelernten Sprachmaterial verknüpfen.' + 'Sprache, Familiennähe und Respekt kulturell einordnen.', + 'Indirekte Kommunikation als soziale Strategie verstehen.', + 'Nähe, Hilfe und Ablehnung passend formulieren.', + 'Kulturelles Verständnis in konkrete Antwortwahl übertragen.' ], - corePatterns: ['pakikisama', 'respeto', 'amping', 'palihug'] + corePatterns: [ + { target: 'pakikisama', gloss: 'soziale Harmonie / gutes Miteinander' }, + { target: 'respeto', gloss: 'Respekt' }, + { target: 'amping', gloss: 'Pass auf dich auf' }, + { target: 'palihug', gloss: 'bitte' }, + { target: 'Dili lang sa karon.', gloss: 'Jetzt lieber nicht.' }, + { target: 'Sige lang.', gloss: 'Schon okay.' }, + { target: 'Tabang ta.', gloss: 'Lass uns helfen.' }, + { target: 'Salamat sa pagsabot.', gloss: 'Danke fürs Verständnis.' } + ], + grammarFocus: [ + { title: 'Indirekt ist oft höflicher', text: 'In Familien- und Besuchskontexten kann eine weiche Formulierung natürlicher sein als ein direktes Nein.', example: 'Dili lang sa karon. Sunod na lang.' }, + { title: 'Sprache als Beziehungspflege', text: 'Viele Formeln transportieren nicht nur Inhalt, sondern Fürsorge und Nähe.', example: 'Amping kanunay. Tabang ta.' } + ], + speakingPrompts: [ + { title: 'Kulturell passend reagieren', prompt: 'Lehne eine Einladung weich ab und bedanke dich fürs Verständnis.', cue: 'Dili lang sa karon. Salamat sa pagsabot.' }, + { title: 'Hilfe anbieten', prompt: 'Biete Hilfe an, ohne aufdringlich zu klingen.', cue: 'Tabang ta. Sige lang.' } + ], + practicalTasks: [ + { title: 'Antwortwahl', text: 'Vergleiche drei direkte deutsche Antworten und formuliere sie weicher auf Bisaya.' } + ] } }; export const BISAYA_PHASE3_LESSONS = [ - { week: 5, day: 1, num: 44, type: 'conversation', title: 'Besuch & Gastfreundschaft', desc: 'Besuch empfangen, hereinbitten und freundlich reagieren', targetMin: 18, targetScore: 80, review: false, cultural: 'Gastfreundschaft ist im philippinischen Familienalltag zentral.' }, - { week: 5, day: 1, num: 45, type: 'vocab', title: 'Besuch & Haushalt', desc: 'Wichtige Wörter für Besuch, Haus und gemeinsame Zeit', targetMin: 18, targetScore: 85, review: true, cultural: null }, - { week: 5, day: 2, num: 46, type: 'grammar', title: 'Fragen im Alltag vertiefen', desc: 'Rückfragen, Folgefragen und höfliches Nachhaken', targetMin: 22, targetScore: 78, review: true, cultural: null }, - { week: 5, day: 2, num: 47, type: 'conversation', title: 'Termine & Verabredungen', desc: 'Treffen planen und Uhrzeiten absprechen', targetMin: 18, targetScore: 80, review: false, cultural: null }, - { week: 5, day: 3, num: 48, type: 'review', title: 'Woche 5 - Intensivwiederholung I', desc: 'Erste große Wiederholung zu Besuch, Alltag und Fürsorge', targetMin: 28, targetScore: 80, review: false, cultural: null }, - { week: 5, day: 3, num: 49, type: 'vocab', title: 'Spiralwiederholung - Familie & Fürsorge', desc: 'Alte Kernmuster gezielt wiederholen und festigen', targetMin: 20, targetScore: 85, review: true, cultural: null }, - { week: 5, day: 4, num: 50, type: 'conversation', title: 'Gesundheit im Alltag', desc: 'Nach Beschwerden fragen und Hilfe anbieten', targetMin: 18, targetScore: 80, review: false, cultural: null }, - { week: 5, day: 4, num: 51, type: 'vocab', title: 'Medikamente & Beschwerden', desc: 'Schmerz, Medizin und Fürsorgewortschatz', targetMin: 18, targetScore: 85, review: true, cultural: null }, - { week: 5, day: 5, num: 52, type: 'review', title: 'Woche 5 - Intensivwiederholung II', desc: 'Große Mischwiederholung mit Fokus auf Abruf und Tempo', targetMin: 28, targetScore: 80, review: false, cultural: null }, - { week: 5, day: 5, num: 53, type: 'vocab', title: 'Woche 5 - Checkpoint', desc: 'Checkpoint zu den Inhalten von Woche 5', targetMin: 16, targetScore: 82, review: true, cultural: null }, - { week: 6, day: 1, num: 54, type: 'conversation', title: 'Unterwegs & Transport', desc: 'Nach Weg, Fahrt, Preis und Ziel fragen', targetMin: 18, targetScore: 80, review: false, cultural: null }, - { week: 6, day: 1, num: 55, type: 'vocab', title: 'Wege & Verkehr', desc: 'Verkehrs- und Bewegungswortschatz für den Alltag', targetMin: 18, targetScore: 85, review: true, cultural: null }, - { week: 6, day: 2, num: 56, type: 'conversation', title: 'Arbeit & Aufgaben', desc: 'Über Pflichten, Arbeit und Erledigungen sprechen', targetMin: 18, targetScore: 80, review: false, cultural: null }, - { week: 6, day: 2, num: 57, type: 'vocab', title: 'Tätigkeiten & Organisation', desc: 'Verben und Wörter für Aufgaben, Listen und Hilfe', targetMin: 18, targetScore: 85, review: true, cultural: null }, - { week: 6, day: 3, num: 58, type: 'conversation', title: 'Freies Gespräch - Familie & Alltag', desc: 'Freier sprechen über Familie, Zuhause und Tagesablauf', targetMin: 22, targetScore: 78, review: false, cultural: null }, - { week: 6, day: 3, num: 59, type: 'review', title: 'Spiralwiederholung - Wochen 1 bis 4', desc: 'Frühere Inhalte blockübergreifend wiederholen', targetMin: 28, targetScore: 82, review: false, cultural: null }, - { week: 6, day: 4, num: 60, type: 'conversation', title: 'Konflikte & Missverständnisse', desc: 'Höflich um Wiederholung bitten und Missverständnisse klären', targetMin: 20, targetScore: 80, review: false, cultural: 'Ruhiger, indirekter Umgang hilft in heiklen Gesprächen.' }, - { week: 6, day: 4, num: 61, type: 'vocab', title: 'Abschlusstest - Schnellstart', desc: 'Finaler Wortschatztest über den 6-Wochen-Schnellstart', targetMin: 18, targetScore: 82, review: true, cultural: null }, - { week: 6, day: 5, num: 62, type: 'review', title: 'Abschlussprüfung - Schnellstart', desc: 'Große Abschlussprüfung mit gemischten Inhalten', targetMin: 30, targetScore: 82, review: false, cultural: 'Die Abschlussphase prüft vor allem sichere Alltagsfähigkeit.' }, - { week: 6, day: 5, num: 63, type: 'culture', title: 'Kulturelle Vertiefung im Familienalltag', desc: 'Vertiefe wichtige kulturelle Muster für Sprache und Familienalltag', targetMin: 16, targetScore: 0, review: false, cultural: 'Sprache, Respekt und Familienrollen sind eng miteinander verbunden.' } + { week: 5, day: 1, num: 44, type: 'conversation', title: 'Besuch & Gastfreundschaft', desc: 'Besuch empfangen, hereinbitten, etwas anbieten und nach der Reise fragen', targetMin: 24, targetScore: 80, review: false, cultural: 'Gastfreundschaft ist im philippinischen Familienalltag zentral und wird oft durch konkrete Fürsorge gezeigt.' }, + { week: 5, day: 1, num: 45, type: 'vocab', title: 'Besuch & Haushalt', desc: 'Haus-, Besuchs- und Haushaltswörter in kurzen Ortssätzen verwenden', targetMin: 22, targetScore: 85, review: true, cultural: null }, + { week: 5, day: 2, num: 46, type: 'grammar', title: 'Fragen im Alltag vertiefen', desc: 'Rückfragen, Folgefragen, Bedeutung und höfliches Nachhaken sicher kombinieren', targetMin: 26, targetScore: 78, review: true, cultural: null }, + { week: 5, day: 2, num: 47, type: 'conversation', title: 'Termine & Verabredungen', desc: 'Treffen planen, Uhrzeiten absprechen, zusagen und weich verschieben', targetMin: 24, targetScore: 80, review: false, cultural: null }, + { week: 5, day: 3, num: 48, type: 'review', title: 'Woche 5 - Intensivwiederholung I', desc: 'Besuch, Familie, Fürsorge und Terminplanung in schnellen Rollenwechseln mischen', targetMin: 34, targetScore: 82, review: false, cultural: null }, + { week: 5, day: 3, num: 49, type: 'vocab', title: 'Spiralwiederholung - Familie & Fürsorge', desc: 'Alte Familien- und Fürsorgemuster aktiv reaktivieren und in neue Szenen übertragen', targetMin: 24, targetScore: 85, review: true, cultural: null }, + { week: 5, day: 4, num: 50, type: 'conversation', title: 'Gesundheit im Alltag', desc: 'Beschwerden erfragen, Ruhe/Wasser/Medizin anbieten und nach Besserung fragen', targetMin: 26, targetScore: 80, review: false, cultural: null }, + { week: 5, day: 4, num: 51, type: 'vocab', title: 'Medikamente & Beschwerden', desc: 'Symptome, Körperwörter und Hilfewortschatz in Fürsorgesätzen verwenden', targetMin: 24, targetScore: 85, review: true, cultural: null }, + { week: 5, day: 5, num: 52, type: 'review', title: 'Woche 5 - Intensivwiederholung II', desc: 'Gesundheit, Besuch, Fragen und Terminplanung unter Abrufdruck kontrastieren', targetMin: 34, targetScore: 82, review: false, cultural: null }, + { week: 5, day: 5, num: 53, type: 'vocab', title: 'Woche 5 - Checkpoint', desc: 'Diagnostischer Checkpoint zu Besuch, Termin, Frageketten und Gesundheit', targetMin: 24, targetScore: 84, review: true, cultural: null }, + { week: 6, day: 1, num: 54, type: 'conversation', title: 'Unterwegs & Transport', desc: 'Nach Weg, Haltestelle, Fahrpreis, Ziel und Ausstieg fragen', targetMin: 26, targetScore: 80, review: false, cultural: null }, + { week: 6, day: 1, num: 55, type: 'vocab', title: 'Wege & Verkehr', desc: 'Verkehrs-, Richtungs- und Bewegungswortschatz in einfachen Routen verwenden', targetMin: 24, targetScore: 85, review: true, cultural: null }, + { week: 6, day: 2, num: 56, type: 'conversation', title: 'Arbeit & Aufgaben', desc: 'Über Arbeit, Pflichten, Reihenfolge, Fertigsein und Hilfe sprechen', targetMin: 26, targetScore: 80, review: false, cultural: null }, + { week: 6, day: 2, num: 57, type: 'vocab', title: 'Tätigkeiten & Organisation', desc: 'Aufgaben, Listen, Reihenfolge und Hilfe als To-do-Sprache festigen', targetMin: 24, targetScore: 85, review: true, cultural: null }, + { week: 6, day: 3, num: 58, type: 'conversation', title: 'Freies Gespräch - Familie & Alltag', desc: 'Fünf zusammenhängende Sätze zu Familie, Zuhause, Befinden und Tagesplan sprechen', targetMin: 30, targetScore: 78, review: false, cultural: null }, + { week: 6, day: 3, num: 59, type: 'review', title: 'Spiralwiederholung - Wochen 1 bis 4', desc: 'Begrüßung, Essen, Zeit, Preise, Gefühle und Gesundheit als Langzeitabruf mischen', targetMin: 34, targetScore: 84, review: false, cultural: null }, + { week: 6, day: 4, num: 60, type: 'conversation', title: 'Konflikte & Missverständnisse', desc: 'Missverständnisse höflich reparieren, um Wiederholung bitten und Spannung entschärfen', targetMin: 26, targetScore: 80, review: false, cultural: 'Ruhiger, indirekter Umgang hilft in heiklen Gesprächen oft mehr als direkte Korrektur.' }, + { week: 6, day: 4, num: 61, type: 'vocab', title: 'Abschlusstest - Schnellstart', desc: 'Aktiver Wortschatztest über den 6-Wochen-Schnellstart in beide Richtungen', targetMin: 24, targetScore: 84, review: true, cultural: null }, + { week: 6, day: 5, num: 62, type: 'review', title: 'Abschlussprüfung - Schnellstart', desc: 'Große Abschlussprüfung mit Besuch, Gesundheit, Transport, Arbeit und freier Anwendung', targetMin: 38, targetScore: 84, review: false, cultural: 'Die Abschlussphase prüft Verständlichkeit und Alltagsfähigkeit, nicht perfekte Grammatik.' }, + { week: 6, day: 5, num: 63, type: 'culture', title: 'Kulturelle Vertiefung im Familienalltag', desc: 'Respekt, Nähe, indirekte Kommunikation und Hilfe im Familienalltag einordnen', targetMin: 22, targetScore: 0, review: false, cultural: 'Sprache, Respekt und Familienrollen sind eng miteinander verbunden.' } ]; diff --git a/backend/scripts/bisaya-course-plan-24-43.js b/backend/scripts/bisaya-course-plan-24-43.js index 965fbdf..ca26a35 100644 --- a/backend/scripts/bisaya-course-plan-24-43.js +++ b/backend/scripts/bisaya-course-plan-24-43.js @@ -1,4 +1,4 @@ -export const BISAYA_LESSONS_24_43 = [ +const BISAYA_LESSONS_24_43_BASE = [ { week: 3, day: 1, num: 24, type: 'conversation', title: 'Gefühle im Alltag', desc: 'Gefühle ausdrücken und im Gespräch passend darauf reagieren', targetMin: 18, targetScore: 80, review: false, cultural: 'Gefühle werden oft indirekt und mit Fürsorge beantwortet.' }, { week: 3, day: 1, num: 25, type: 'vocab', title: 'Gefühlswortschatz & Reaktionen', desc: 'Freude, Sorge, Müdigkeit, Vermissen und Beruhigung sicher unterscheiden', targetMin: 20, targetScore: 85, review: true, cultural: null }, { week: 3, day: 2, num: 26, type: 'conversation', title: 'Gesundheit & Wohlbefinden', desc: 'Einfache Beschwerden erfragen und fürsorglich reagieren', targetMin: 18, targetScore: 80, review: false, cultural: null }, @@ -21,6 +21,34 @@ export const BISAYA_LESSONS_24_43 = [ { week: 4, day: 5, num: 43, type: 'culture', title: 'Kultur: Höflichkeit, Familie, Alltag', desc: 'Respekt, indirekte Bitte und Familiennähe sprachlich einordnen', targetMin: 16, targetScore: 0, review: false, cultural: 'Kulturelles Verständnis hilft, Sätze passend und nicht nur wörtlich zu verwenden.' } ]; +const BISAYA_LESSON_24_43_TARGET_MINUTES = { + 24: 24, + 25: 24, + 26: 24, + 27: 24, + 28: 26, + 29: 24, + 30: 24, + 31: 24, + 32: 34, + 33: 24, + 34: 28, + 35: 34, + 36: 28, + 37: 32, + 38: 30, + 39: 34, + 40: 30, + 41: 24, + 42: 38, + 43: 22 +}; + +export const BISAYA_LESSONS_24_43 = BISAYA_LESSONS_24_43_BASE.map((lesson) => ({ + ...lesson, + targetMin: BISAYA_LESSON_24_43_TARGET_MINUTES[lesson.num] || lesson.targetMin +})); + export const BISAYA_LESSONS_24_43_BY_NUMBER = Object.fromEntries( BISAYA_LESSONS_24_43.map((lesson) => [lesson.num, lesson]) ); @@ -83,7 +111,238 @@ export const BISAYA_RELATIONSHIP_ANCHOR_DIDACTICS = { } }; -export const BISAYA_DIDACTICS_24_43 = { +const BISAYA_DIDACTICS_24_43_ENRICHMENTS = { + 'Gefühle im Alltag': { + corePatterns: [ + { target: 'Nalipay ko karon.', gloss: 'Ich bin heute froh.' }, + { target: 'Naguol ka?', gloss: 'Bist du besorgt / traurig?' }, + { target: 'Naa ra ko diri.', gloss: 'Ich bin hier.' } + ], + speakingPrompts: [ + { title: 'Gefühl plus Fürsorge', prompt: 'Sage dein Gefühl, frage nach dem Gefühl der anderen Person und reagiere fürsorglich.', cue: 'Kapoy ko karon. Naguol ka? Naa ra ko diri.' } + ] + }, + 'Gefühlswortschatz & Reaktionen': { + corePatterns: [ + { target: 'kabalaka', gloss: 'Sorge' }, + { target: 'hilom', gloss: 'still / ruhig' }, + { target: 'Nalipay ko para nimo.', gloss: 'Ich freue mich für dich.' } + ], + grammarFocus: [ + { title: 'Wort zu Satz', text: 'Aus einem Gefühlswort wird mit ko oder ka schnell ein alltagstauglicher Satz.', example: 'Kapoy ko. Naguol ka?' } + ] + }, + 'Gesundheit & Wohlbefinden': { + corePatterns: [ + { target: 'Aduna kay hilanat?', gloss: 'Hast du Fieber?' }, + { target: 'Sakit pa?', gloss: 'Tut es noch weh?' }, + { target: 'Tawag ta og doktor?', gloss: 'Sollen wir einen Arzt rufen?' } + ], + speakingPrompts: [ + { title: 'Gesundheitsverlauf', prompt: 'Frage nach Fieber, Schmerz, Medizin und Besserung.', cue: 'Aduna kay hilanat? Sakit pa? Niinom ka og tambal? Mas maayo na ka?' } + ] + }, + 'Körper & Symptome': { + corePatterns: [ + { target: 'likod', gloss: 'Rücken' }, + { target: 'tutunlan', gloss: 'Hals / Kehle' }, + { target: 'Sakit akong tutunlan.', gloss: 'Mein Hals tut weh.' } + ], + grammarFocus: [ + { title: 'Symptom konkretisieren', text: 'Körperwörter werden nützlicher, wenn du sie direkt mit sakit oder hilanat in Sätze setzt.', example: 'Sakit akong tutunlan.' } + ] + }, + 'Höflichkeitsformen praktisch': { + corePatterns: [ + { target: 'Sunod na lang.', gloss: 'Dann ein anderes Mal.' }, + { target: 'Okay ra.', gloss: 'Ist okay.' }, + { target: 'Ayaw kabalaka.', gloss: 'Mach dir keine Sorgen.' } + ], + speakingPrompts: [ + { title: 'Weich ablehnen', prompt: 'Lehne etwas heute weich ab, schlage später vor und bedanke dich.', cue: 'Dili lang sa karon. Sunod na lang. Salamat sa pagsabot.' } + ] + }, + 'Bitten & Nachfragen': { + corePatterns: [ + { target: 'Balika palihug.', gloss: 'Wiederhole es bitte.' }, + { target: 'Unsa gani?', gloss: 'Was war das nochmal?' }, + { target: 'Pwede nimo isulat?', gloss: 'Kannst du es aufschreiben?' } + ], + grammarFocus: [ + { title: 'Reparatur in Stufen', text: 'Beginne mit Nichtverstehen, bitte um Wiederholung und frage dann nach Bedeutung oder Schriftform.', example: 'Wala ko kasabot. Balika palihug. Pwede nimo isulat?' } + ] + }, + 'Kinder & Familie': { + corePatterns: [ + { target: 'Ayaw pagdali.', gloss: 'Beeil dich nicht / Kein Stress.' }, + { target: 'Dali na.', gloss: 'Komm, beeil dich.' }, + { target: 'Kuhaa imong bag.', gloss: 'Hol deine Tasche.' } + ], + grammarFocus: [ + { title: 'Kinderfreundliche Kürze', text: 'Kurze klare Aufforderungen funktionieren im Alltag besser als lange Erklärungen.', example: 'Kuhaa imong bag. Dali na.' } + ] + }, + 'Kinder, Spiel & Routine': { + corePatterns: [ + { target: 'Ayaw kalimot.', gloss: 'Vergiss es nicht.' }, + { target: 'Hugas sa kamot.', gloss: 'Wasch dir die Hände.' }, + { target: 'Patya ang suga.', gloss: 'Mach das Licht aus.' } + ], + grammarFocus: [ + { title: 'Routineketten', text: 'Routinen bestehen aus kurzen Handlungsaufforderungen in fester Reihenfolge.', example: 'Hugas sa kamot. Matulog na ta. Patya ang suga.' } + ] + }, + 'Woche 3 - Intensivwiederholung': { + corePatterns: [ + { target: 'Naa ra ko diri.', gloss: 'Ich bin hier.' }, + { target: 'Hugas sa kamot.', gloss: 'Wasch dir die Hände.' }, + { target: 'Balika palihug.', gloss: 'Wiederhole es bitte.' } + ], + speakingPrompts: [ + { title: 'Acht schnelle Antworten', prompt: 'Reagiere auf acht gemischte Situationen aus Gefühl, Gesundheit, Kind und Verständnisproblem.', cue: 'Naa ra ko diri. Sakit pa? Hugas sa kamot. Balika palihug.' } + ] + }, + 'Woche 3 - Checkpoint': { + corePatterns: [ + { target: 'Sakit pa?', gloss: 'Tut es noch weh?' }, + { target: 'Ayaw pagdali.', gloss: 'Kein Stress.' }, + { target: 'Pwede nimo isulat?', gloss: 'Kannst du es aufschreiben?' } + ], + grammarFocus: [ + { title: 'Checkpoint als Diagnose', text: 'Der Checkpoint soll zeigen, ob du spontan reagieren kannst, nicht nur wiedererkennst.', example: 'Naguol ka? Naa ra ko diri.' } + ] + }, + 'Alltagsszene: Zuhause morgens': { + corePatterns: [ + { target: 'Hugas sa nawong.', gloss: 'Wasch dein Gesicht.' }, + { target: 'Kuhaa imong bag.', gloss: 'Hol deine Tasche.' }, + { target: 'Mogawas na ta.', gloss: 'Wir gehen jetzt raus.' } + ], + speakingPrompts: [ + { title: 'Morgenroutine komplett', prompt: 'Sprich eine Morgenroutine mit Aufstehen, Waschen, Essen, Tasche und Losgehen.', cue: 'Bangon na. Hugas sa nawong. Nikaon na ka? Kuhaa imong bag. Mogawas na ta.' } + ] + }, + 'Spiralreview: Woche 1-2 im Alltag': { + corePatterns: [ + { target: 'Maayong gabii.', gloss: 'Guten Abend.' }, + { target: 'Katulog og maayo.', gloss: 'Schlaf gut.' }, + { target: 'Tagpila ni?', gloss: 'Wie viel kostet das?' } + ], + grammarFocus: [ + { title: 'Alte Muster aktivieren', text: 'Alte Sätze sollen in neuen Szenen auftauchen, damit sie nicht nur passiv bekannt bleiben.', example: 'Maayong gabii. Katulog og maayo.' } + ] + }, + 'Alltagsszene: Besuch am Nachmittag': { + corePatterns: [ + { target: 'Kumusta ang biyahe?', gloss: 'Wie war die Reise?' }, + { target: 'Kaon sa.', gloss: 'Iss erst einmal.' }, + { target: 'Naa mi diri.', gloss: 'Wir sind hier.' } + ], + grammarFocus: [ + { title: 'Besuch als Fürsorge', text: 'Besuchssprache verbindet Willkommen, Angebot und Nähe.', example: 'Sulod lang. Lingkod sa. Kaon sa.' } + ] + }, + 'Spiralreview: Gefühle & Gesundheit': { + corePatterns: [ + { target: 'Aduna kay hilanat?', gloss: 'Hast du Fieber?' }, + { target: 'Naa ra ko diri.', gloss: 'Ich bin hier.' }, + { target: 'Tawag ta og doktor?', gloss: 'Sollen wir einen Arzt rufen?' } + ], + grammarFocus: [ + { title: 'Problem und Reaktion', text: 'Die Wiederholung koppelt jedes Problem an eine konkrete Antwort.', example: 'Sakit akong ulo. Magpahuway sa.' } + ] + }, + 'Längeres Gespräch: Planung und Familie': { + corePatterns: [ + { target: 'Kinsa imong kuyog?', gloss: 'Mit wem bist du unterwegs?' }, + { target: 'Human sa trabaho.', gloss: 'Nach der Arbeit.' }, + { target: 'Texti lang ko.', gloss: 'Schreib mir einfach.' } + ], + speakingPrompts: [ + { title: 'Plan plus Rückfrage', prompt: 'Erzähle deinen Plan und frage nach Begleitung oder Uhrzeit.', cue: 'Una, moadto ko sa merkado. Kinsa imong kuyog? Human sa trabaho. Texti lang ko.' } + ] + }, + 'Gesamtwiederholung mit Fehlerclustern': { + corePatterns: [ + { target: 'Dili ko pwede karon.', gloss: 'Ich kann heute nicht.' }, + { target: 'Pwede ugma?', gloss: 'Geht morgen?' }, + { target: 'Dili mao akong pasabot.', gloss: 'Das meinte ich nicht.' } + ], + speakingPrompts: [ + { title: 'Fehlercluster Termin und Bitte', prompt: 'Kontrastiere Vergangenheit, Zukunft, Absage, Wiederholung und Missverständnis.', cue: 'Ni-adto ko ganiha. Mo-adto ko ugma. Dili ko pwede karon. Palihug ka mubalik?' } + ] + }, + 'Praktische Übung: Markt + Familie': { + corePatterns: [ + { target: 'Pila tanan?', gloss: 'Wie viel insgesamt?' }, + { target: 'Barato ra.', gloss: 'Es ist günstig.' }, + { target: 'Mahal ra.', gloss: 'Es ist zu teuer.' } + ], + grammarFocus: [ + { title: 'Kaufen mit Grund', text: 'Ein Marktsatz wird alltagstauglich, wenn Preis, Menge und Grund zusammenkommen.', example: 'Mupalit ko para sa pamilya.' } + ] + }, + 'Abschlusstest Wortschatz aktiv': { + corePatterns: [ + { target: 'Sulod lang.', gloss: 'Komm herein.' }, + { target: 'Sakit akong ulo.', gloss: 'Mein Kopf tut weh.' }, + { target: 'Tagpila ni?', gloss: 'Wie viel kostet das?' } + ], + grammarFocus: [ + { title: 'Aktiver Wortschatztest', text: 'Der Test verlangt nicht nur Einzelwörter, sondern kurze abrufbare Satzanker.', example: 'Tubig -> Gusto ka og tubig?' } + ] + }, + 'Abschlussprüfung Grundphase': { + corePatterns: [ + { target: 'Sulod lang. Lingkod sa.', gloss: 'Komm herein. Setz dich erst einmal.' }, + { target: 'Sakit imong ulo? Magpahuway sa.', gloss: 'Tut dein Kopf weh? Ruh dich erst einmal aus.' }, + { target: 'Tagpila ni? Mupalit ko para sa pamilya.', gloss: 'Wie viel kostet das? Ich kaufe für die Familie.' } + ], + grammarFocus: [ + { title: 'Prüfung über Szenen', text: 'Die Abschlussprüfung bewertet, ob du mehrere bekannte Muster zu einer verständlichen Szene verbinden kannst.', example: 'Kumusta ka? Nikaon na ka? Magpahuway sa.' } + ] + }, + 'Kultur: Höflichkeit, Familie, Alltag': { + corePatterns: [ + { target: 'Sunod na lang.', gloss: 'Dann ein anderes Mal.' }, + { target: 'Tabang ta.', gloss: 'Lass uns helfen.' }, + { target: 'Salamat sa pagsabot.', gloss: 'Danke fürs Verständnis.' } + ], + speakingPrompts: [ + { title: 'Kultur in Antwortwahl', prompt: 'Formuliere eine direkte deutsche Ablehnung weicher auf Bisaya.', cue: 'Dili lang sa karon. Sunod na lang. Salamat sa pagsabot.' } + ] + } +}; + +function normalizePatternKey(entry) { + return typeof entry === 'string' ? entry : entry?.target; +} + +function mergePatternLists(base = [], extra = []) { + const merged = []; + const seen = new Set(); + for (const entry of [...base, ...extra]) { + const key = normalizePatternKey(entry); + if (!key || seen.has(key)) continue; + seen.add(key); + merged.push(entry); + } + return merged; +} + +function mergeDidactics(base = {}, enrichment = {}) { + return { + ...base, + ...enrichment, + learningGoals: [...(base.learningGoals || []), ...(enrichment.learningGoals || [])], + corePatterns: mergePatternLists(base.corePatterns || [], enrichment.corePatterns || []), + grammarFocus: [...(base.grammarFocus || []), ...(enrichment.grammarFocus || [])], + speakingPrompts: [...(base.speakingPrompts || []), ...(enrichment.speakingPrompts || [])], + practicalTasks: [...(base.practicalTasks || []), ...(enrichment.practicalTasks || [])] + }; +} + +const BISAYA_DIDACTICS_24_43_BASE = { 'Gefühle im Alltag': { learningGoals: [ 'Eigene Gefühle mit kurzen, natürlichen Sätzen ausdrücken.', @@ -538,3 +797,10 @@ export const BISAYA_DIDACTICS_24_43 = { ] } }; + +export const BISAYA_DIDACTICS_24_43 = Object.fromEntries( + Object.entries(BISAYA_DIDACTICS_24_43_BASE).map(([title, didactics]) => [ + title, + mergeDidactics(didactics, BISAYA_DIDACTICS_24_43_ENRICHMENTS[title]) + ]) +); diff --git a/backend/scripts/create-bisaya-course-content.js b/backend/scripts/create-bisaya-course-content.js index a6284a3..0403808 100644 --- a/backend/scripts/create-bisaya-course-content.js +++ b/backend/scripts/create-bisaya-course-content.js @@ -14,7 +14,7 @@ import VocabGrammarExercise from '../models/community/vocab_grammar_exercise.js' import VocabCourse from '../models/community/vocab_course.js'; import User from '../models/community/user.js'; import { BISAYA_DIDACTICS_24_43, BISAYA_RELATIONSHIP_ANCHOR_DIDACTICS } from './bisaya-course-plan-24-43.js'; -import { BISAYA_PHASE3_DIDACTICS } from './bisaya-course-phase3-extension.js'; +import { BISAYA_PHASE3_DIDACTICS, BISAYA_PHASE3_LESSONS } from './bisaya-course-phase3-extension.js'; import { BISAYA_PHASE4_DIDACTICS } from './bisaya-course-phase4-extension.js'; import { BISAYA_PHASE5_DIDACTICS } from './bisaya-course-phase5-extension.js'; @@ -33,6 +33,10 @@ const GENERATED_BISAYA_DIDACTICS = { ...BISAYA_PHASE5_DIDACTICS }; +const SAFE_EXERCISE_UPDATE_TITLES = new Set( + BISAYA_PHASE3_LESSONS.map((lesson) => lesson.title) +); + function normalizeText(value) { return String(value || '') .trim() @@ -5338,6 +5342,7 @@ async function createBisayaCourseContent() { console.log(`Gefunden: ${courses.length} Bisaya-Kurse\n`); let totalExercisesAdded = 0; + let totalExercisesUpdated = 0; let totalLessonsProcessed = 0; for (const course of courses) { @@ -5368,6 +5373,62 @@ async function createBisayaCourseContent() { where: { lessonId: lesson.id } }); + if (existingCount > 0 && !replacePlaceholders && !forceRebuildAll && SAFE_EXERCISE_UPDATE_TITLES.has(lesson.title)) { + const lessonDidactics = getLessonDidactics(lesson); + const mergedGrammarFocus = mergeGrammarFocusForLesson( + lessonDidactics.grammarFocus, + buildGrammarCurriculumFocus(lesson) + ); + const derivedCorePatterns = deriveLessonCorePatternsFromExercises(exercises); + const mergedCorePatterns = mergeCorePatternsForLesson(lessonDidactics, derivedCorePatterns, 8); + await lesson.update({ + ...(mergedGrammarFocus.length > 0 ? { grammarFocus: mergedGrammarFocus } : {}), + ...(mergedCorePatterns.length >= 8 ? { corePatterns: mergedCorePatterns } : {}) + }); + + const existingExercises = await VocabGrammarExercise.findAll({ + where: { lessonId: lesson.id }, + order: [['exerciseNumber', 'ASC']] + }); + + let exerciseNumber = 1; + for (const exerciseData of exercises) { + const { exercise } = sanitizeExerciseForConsistency( + lesson, + exerciseData, + lessonDidactics + ); + const exerciseTypeId = await resolveExerciseTypeId(exercise); + const existingExercise = existingExercises[exerciseNumber - 1]; + const payload = { + exerciseTypeId, + exerciseNumber, + title: exercise.title, + instruction: exercise.instruction, + questionData: JSON.stringify(exercise.questionData), + answerData: JSON.stringify(exercise.answerData), + explanation: exercise.explanation, + createdByUserId: course.ownerUserId || systemUser.id + }; + + if (existingExercise) { + await existingExercise.update(payload); + totalExercisesUpdated++; + } else { + await VocabGrammarExercise.create({ + lessonId: lesson.id, + ...payload + }); + totalExercisesAdded++; + } + exerciseNumber++; + } + + console.log(` 🔄 Lektion ${lesson.lessonNumber}: "${lesson.title}" - ${exercises.length} Übung(en) sicher aktualisiert`); + totalLessonsProcessed++; + continue; + } + if (existingCount > 0 && !replacePlaceholders && !forceRebuildAll) { console.log(` ⏭️ Lektion ${lesson.lessonNumber}: "${lesson.title}" - bereits ${existingCount} Übung(en) vorhanden`); continue; @@ -5440,6 +5501,7 @@ async function createBisayaCourseContent() { console.log(`\n🎉 Zusammenfassung:`); console.log(` ${totalLessonsProcessed} Lektionen bearbeitet`); console.log(` ${totalExercisesAdded} Grammatik-Übungen erstellt`); + console.log(` ${totalExercisesUpdated} Grammatik-Übungen aktualisiert`); } createBisayaCourseContent() diff --git a/backend/scripts/extend-bisaya-course-phase3.js b/backend/scripts/extend-bisaya-course-phase3.js index b7aace9..73774ad 100644 --- a/backend/scripts/extend-bisaya-course-phase3.js +++ b/backend/scripts/extend-bisaya-course-phase3.js @@ -30,6 +30,7 @@ async function extendBisayaCoursePhase3() { }); let addedLessons = 0; + let updatedLessons = 0; for (const course of courses) { await course.update({ @@ -45,17 +46,9 @@ async function extendBisayaCoursePhase3() { } }); - if (existing) { - continue; - } - const didactics = BISAYA_PHASE3_DIDACTICS[lessonData.title] || {}; const pedagogy = getBisayaLessonPedagogy(lessonData.num) || {}; - - await VocabCourseLesson.create({ - courseId: course.id, - chapterId: null, - lessonNumber: lessonData.num, + const lessonPayload = { title: lessonData.title, description: lessonData.desc, weekNumber: lessonData.week, @@ -77,6 +70,20 @@ async function extendBisayaCoursePhase3() { newUnitTarget: pedagogy.newUnitTarget ?? null, reviewWeight: pedagogy.reviewWeight ?? null, isIntensiveReview: Boolean(pedagogy.isIntensiveReview) + }; + + if (existing) { + await existing.update(lessonPayload); + updatedLessons++; + console.log(`🔄 Kurs ${course.id}: Lektion ${lessonData.num} - ${lessonData.title} aktualisiert`); + continue; + } + + await VocabCourseLesson.create({ + ...lessonPayload, + courseId: course.id, + chapterId: null, + lessonNumber: lessonData.num }); addedLessons++; @@ -87,6 +94,7 @@ async function extendBisayaCoursePhase3() { console.log(`\n🎉 Phase 3 vorbereitet.`); console.log(` Kurse: ${courses.length}`); console.log(` Neue Lektionen ergänzt: ${addedLessons}`); + console.log(` Bestehende Lektionen aktualisiert: ${updatedLessons}`); console.log(' Danach create-bisaya-course-content.js ausführen, wenn für die neuen Lektionen zusätzliche Übungen eingespielt werden sollen.'); } diff --git a/backend/scripts/update-bisaya-didactics.js b/backend/scripts/update-bisaya-didactics.js index 9886bbe..083d519 100644 --- a/backend/scripts/update-bisaya-didactics.js +++ b/backend/scripts/update-bisaya-didactics.js @@ -16,6 +16,7 @@ import { BISAYA_LESSONS_24_43_BY_NUMBER, BISAYA_RELATIONSHIP_ANCHOR_DIDACTICS } from './bisaya-course-plan-24-43.js'; +import { BISAYA_PHASE3_DIDACTICS } from './bisaya-course-phase3-extension.js'; /** Alte Kurstitel → aktueller Schlüssel in LESSON_DIDACTICS (bestehende Datenbanken). */ export const LEGACY_DIDACTICS_TITLE_MAP = { @@ -485,7 +486,8 @@ export const LESSON_DIDACTICS = { corePatterns: ['Kumusta', 'Salamat', 'Lami', 'Mingaw ko nimo'] }, ...BISAYA_RELATIONSHIP_ANCHOR_DIDACTICS, - ...BISAYA_DIDACTICS_24_43 + ...BISAYA_DIDACTICS_24_43, + ...BISAYA_PHASE3_DIDACTICS }; function resolveDidacticsForLesson(lesson) { diff --git a/deploy-yourpart-bluegreen.sh b/deploy-yourpart-bluegreen.sh index d724565..87e3d85 100755 --- a/deploy-yourpart-bluegreen.sh +++ b/deploy-yourpart-bluegreen.sh @@ -11,6 +11,7 @@ set -euo pipefail CURRENT_LINK="${CURRENT_LINK:-/opt/yourpart}" TARGET="${1:?Ziel-Slot-Verzeichnis fehlt (z. B. /opt/yourpart-green)}" +shift || true if [ ! -L "$CURRENT_LINK" ]; then echo "❌ ERROR: $CURRENT_LINK ist kein Symlink! (Blue-Green erfordert Symlink auf den aktiven Slot.)" >&2 @@ -20,4 +21,4 @@ fi SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "$SCRIPT_DIR" -exec ./update.sh "$TARGET" +exec ./update.sh "$TARGET" "$@" diff --git a/update.sh b/update.sh index d3774a8..9b1d256 100755 --- a/update.sh +++ b/update.sh @@ -2,10 +2,33 @@ set -euo pipefail TARGET_DIR="${1:?Zielverzeichnis fehlt: ./update.sh }" +shift || true + +SKIP_BACKEND="0" +SKIP_FRONTEND="0" + +while [[ $# -gt 0 ]]; do + case "$1" in + --skip-backend) + SKIP_BACKEND="1" + ;; + --skip-frontend) + SKIP_FRONTEND="1" + ;; + *) + echo "Unbekannte Option: $1" >&2 + echo "Verwendung: ./update.sh [--skip-backend] [--skip-frontend]" >&2 + exit 1 + ;; + esac + shift +done echo "=== YourPart Update Script ===" echo "Ziel-Slot: $TARGET_DIR" echo "Aktualisiert die Anwendung, ohne .env-Dateien zu überschreiben" +echo "Skip Backend: $SKIP_BACKEND" +echo "Skip Frontend: $SKIP_FRONTEND" echo "" # Prüfen ob wir im richtigen Verzeichnis sind @@ -36,13 +59,23 @@ if ! command -v sudo >/dev/null 2>&1; then exit 1 fi -echo "" -echo "=== Updating Backend ===" -./update-backend.sh "$TARGET_DIR" +if [[ "$SKIP_BACKEND" == "1" ]]; then + echo "" + echo "=== Backend-Update übersprungen (--skip-backend) ===" +else + echo "" + echo "=== Updating Backend ===" + ./update-backend.sh "$TARGET_DIR" +fi -echo "" -echo "=== Building and Updating Frontend ===" -./update-frontend.sh "$TARGET_DIR" +if [[ "$SKIP_FRONTEND" == "1" ]]; then + echo "" + echo "=== Frontend-Build/Update übersprungen (--skip-frontend) ===" +else + echo "" + echo "=== Building and Updating Frontend ===" + ./update-frontend.sh "$TARGET_DIR" +fi echo "" echo "Link backend .env"