#!/usr/bin/env node /** * Erstellt den eigenständigen Anschlusskurs „Bisaya A2 – Alltag & Gespräch“. * Verwendung: node backend/scripts/create-bisaya-a2-course.js */ import crypto from 'crypto'; import { sequelize } from '../utils/sequelize.js'; import User from '../models/community/user.js'; import VocabCourse from '../models/community/vocab_course.js'; import VocabCourseLesson from '../models/community/vocab_course_lesson.js'; const BLOCKS = [ ['Wohnen & Reparaturen', 'Wohnung beschreiben, Probleme melden und eine Reparatur organisieren.', 'Naa’y problema sa balay.', 'Es gibt ein Problem im Haus.'], ['Arbeit & Tagesorganisation', 'Aufgaben, Arbeitszeiten und Prioritäten nachvollziehbar erklären.', 'Humanon nako una kini.', 'Ich mache das zuerst fertig.'], ['Schule & digitale Kommunikation', 'Schule, Nachrichten und einfache Absprachen verbinden.', 'Magpadala ko ug mensahe unya.', 'Ich schicke später eine Nachricht.'], ['Familie & Beziehungen', 'Gefühle, Wünsche und Rücksicht in längeren Antworten ausdrücken.', 'Importante ka para nako.', 'Du bist mir wichtig.'], ['Meinung & Entscheidungen', 'Zustimmen, begründen und höflich eine andere Meinung sagen.', 'Para nako, mas maayo kung…', 'Für mich wäre es besser, wenn …'], ['Erlebnisse erzählen', 'Erlebtes in sinnvoller Reihenfolge erzählen und nachfragen.', 'Pagkahuman, miadto mi sa merkado.', 'Danach gingen wir zum Markt.'], ['Reisen & Unterkunft', 'Fahrt, Unterkunft und Änderungen eines Plans klären.', 'Pwede ba nato usbon ang plano?', 'Können wir den Plan ändern?'], ['Geld, Dokumente & Dienste', 'Zahlung, Dokumente und öffentliche Erledigungen bewältigen.', 'Kinahanglan nako ang resibo.', 'Ich brauche die Quittung.'], ['Gesundheit & unerwartete Probleme', 'Beschwerden genauer beschreiben und Hilfe organisieren.', 'Dugay na ni nagsakit.', 'Das tut schon länger weh.'], ['A2-Transfer: Alltag', 'Mehrere Alltagsthemen ohne feste Reihenfolge verbinden.', 'Una, kinahanglan nato…', 'Zuerst müssen wir …'], ['A2-Transfer: Gespräch', 'Ein längeres Gespräch beginnen, tragen und freundlich beenden.', 'Nasabtan nako imong giingon.', 'Ich verstehe, was du gesagt hast.'], ['A2-Abschluss & Weiterlernen', 'Eigene Stärken und nächste Lernziele benennen.', 'Gusto pa ko mopadayon ug praktis.', 'Ich möchte weiter üben.'] ]; const TYPES = ['vocab', 'grammar', 'conversation', 'listening', 'conversation', 'review']; const SUFFIXES = ['Wortschatz im Kontext', 'Muster & Grammatik', 'Geführtes Gespräch', 'Hörverstehen', 'Rollenspiel', 'Checkpoint']; async function main() { const ownerHashedId = String(process.argv[2] || '').trim(); if (!ownerHashedId) throw new Error('Bitte ownerHashedId angeben.'); await sequelize.authenticate(); const owner = await User.findOne({ where: { hashedId: ownerHashedId } }); if (!owner) throw new Error('Nutzer nicht gefunden.'); const [language] = await sequelize.query("SELECT id FROM community.vocab_language WHERE name = 'Bisaya' LIMIT 1", { type: sequelize.QueryTypes.SELECT }); if (!language) throw new Error('Bisaya-Sprache nicht gefunden.'); const baseCourse = await VocabCourse.findOne({ where: { languageId: language.id, courseKind: 'core' }, order: [['id', 'ASC']] }); const [course] = await VocabCourse.findOrCreate({ where: { title: 'Bisaya A2 – Alltag & Gespräch', languageId: language.id }, defaults: { ownerUserId: owner.id, description: 'Anschlusskurs für variablere Alltagssprache, Hörverstehen und längere Gespräche.', nativeLanguageId: null, difficultyLevel: 2, cefrLevel: 'A2', courseKind: 'continuation', prerequisiteCourseId: baseCourse?.id || null, isPublic: true, shareCode: crypto.randomBytes(8).toString('hex') } }); let created = 0; for (const [blockIndex, block] of BLOCKS.entries()) { const [topic, goal, target, gloss] = block; for (let offset = 0; offset < 6; offset += 1) { const lessonNumber = blockIndex * 6 + offset + 1; const [lesson, made] = await VocabCourseLesson.findOrCreate({ where: { courseId: course.id, lessonNumber }, defaults: { courseId: course.id, chapterId: null, lessonNumber, title: `${topic}: ${SUFFIXES[offset]}`, description: goal, weekNumber: blockIndex + 1, dayNumber: offset + 1, lessonType: TYPES[offset], didacticMode: TYPES[offset] === 'review' ? 'checkpoint' : TYPES[offset] === 'listening' ? 'listening' : 'real_life_scenario', phaseLabel: 'a2', blockNumber: blockIndex + 1, difficultyWeight: 2, newUnitTarget: offset === 5 ? 0 : 6, reviewWeight: offset === 5 ? 70 : 35, isIntensiveReview: offset === 5, targetMinutes: offset === 3 ? 25 : 30, targetScorePercent: 80, requiresReview: offset === 5, learningGoals: [goal, 'Mindestens vier eigene Sätze zum Thema formulieren.', 'Frühere Muster passend wiederverwenden.'], corePatterns: [ { target, gloss }, { target: 'Pwede nimo ko tabangan?', gloss: 'Kannst du mir helfen?' }, { target: 'Sa akong hunahuna, maayo ni.', gloss: 'Ich finde, das ist gut.' }, { target: 'Kung mahimo, buhaton nato unya.', gloss: 'Wenn möglich, machen wir es später.' } ], grammarFocus: [{ title: 'Muster im Kontext', text: 'Nutze die neuen Formen, um einen vollständigen Gedanken zu verbinden.', example: target }], speakingPrompts: [{ title: 'Eigene Antwort', prompt: `${goal} Antworte frei in vier bis sechs Sätzen.`, cue: target }], practicalTasks: [{ title: 'Transfer', text: 'Nutze ein Kernmuster heute in einer echten oder simulierten Nachricht.' }] } }); if (made) created += 1; } } console.log(`A2-Kurs ${course.id}: ${created} Lektionen angelegt.`); } main().then(() => sequelize.close()).catch((error) => { console.error(error); sequelize.close(); process.exitCode = 1; });