#!/usr/bin/env node /** * Script zum Erstellen von Übungen für die "Familien-Gespräche" Lektion * * Verwendung: * node backend/scripts/update-family-conversations-exercises.js * * Erstellt Gesprächsübungen für die "Familien-Gespräche" Lektion in allen Bisaya-Kursen. */ import { sequelize } from '../utils/sequelize.js'; import VocabCourseLesson from '../models/community/vocab_course_lesson.js'; 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 crypto from 'crypto'; import bcrypt from 'bcryptjs'; import { Op } from 'sequelize'; // Familiengespräche auf Bisaya mit verschiedenen Muttersprachen const FAMILY_CONVERSATIONS = { // Deutsch -> Bisaya 'Deutsch': { conversations: [ { bisaya: 'Kumusta ka, Nanay?', native: 'Wie geht es dir, Mama?', explanation: '"Kumusta ka" ist "Wie geht es dir?" und "Nanay" ist "Mama"' }, { bisaya: 'Maayo ko, Salamat. Ikaw?', native: 'Mir geht es gut, danke. Und dir?', explanation: '"Maayo ko" bedeutet "Mir geht es gut", "Ikaw" ist "du" (formal)' }, { bisaya: 'Asa si Tatay?', native: 'Wo ist Papa?', explanation: '"Asa" bedeutet "wo", "si" ist ein Marker für Personen, "Tatay" ist "Papa"' }, { bisaya: 'Naa siya sa balay.', native: 'Er ist zu Hause.', explanation: '"Naa" bedeutet "ist/sein", "siya" ist "er/sie", "sa balay" ist "zu Hause"' }, { bisaya: 'Kumusta na ang Kuya?', native: 'Wie geht es dem älteren Bruder?', explanation: '"Kumusta na" ist "Wie geht es", "ang" ist ein Artikel, "Kuya" ist "älterer Bruder"' }, { bisaya: 'Maayo ra siya.', native: 'Es geht ihm gut.', explanation: '"Maayo ra" bedeutet "gut/gut geht es", "siya" ist "ihm"' }, { bisaya: 'Gutom na ko, Nanay.', native: 'Ich bin hungrig, Mama.', explanation: '"Gutom" bedeutet "hungrig", "na" zeigt einen Zustand, "ko" ist "ich"' }, { bisaya: 'Hulata lang, hapit na ang pagkaon.', native: 'Warte nur, das Essen ist fast fertig.', explanation: '"Hulata" ist "warte", "lang" ist "nur", "hapit na" ist "fast", "pagkaon" ist "Essen"' } ] }, // Englisch -> Bisaya 'Englisch': { conversations: [ { bisaya: 'Kumusta ka, Nanay?', native: 'How are you, Mom?', explanation: '"Kumusta ka" means "How are you?" and "Nanay" means "Mom"' }, { bisaya: 'Maayo ko, Salamat. Ikaw?', native: 'I\'m fine, thank you. And you?', explanation: '"Maayo ko" means "I\'m fine", "Ikaw" is "you" (formal)' }, { bisaya: 'Asa si Tatay?', native: 'Where is Dad?', explanation: '"Asa" means "where", "si" is a person marker, "Tatay" means "Dad"' }, { bisaya: 'Naa siya sa balay.', native: 'He is at home.', explanation: '"Naa" means "is/be", "siya" is "he/she", "sa balay" means "at home"' }, { bisaya: 'Kumusta na ang Kuya?', native: 'How is the older brother?', explanation: '"Kumusta na" means "How is", "ang" is an article, "Kuya" means "older brother"' }, { bisaya: 'Maayo ra siya.', native: 'He is fine.', explanation: '"Maayo ra" means "fine/well", "siya" means "he"' }, { bisaya: 'Gutom na ko, Nanay.', native: 'I\'m hungry, Mom.', explanation: '"Gutom" means "hungry", "na" shows a state, "ko" is "I"' }, { bisaya: 'Hulata lang, hapit na ang pagkaon.', native: 'Just wait, the food is almost ready.', explanation: '"Hulata" means "wait", "lang" means "just", "hapit na" means "almost", "pagkaon" means "food"' } ] }, // Spanisch -> Bisaya 'Spanisch': { conversations: [ { bisaya: 'Kumusta ka, Nanay?', native: '¿Cómo estás, Mamá?', explanation: '"Kumusta ka" significa "¿Cómo estás?" y "Nanay" significa "Mamá"' }, { bisaya: 'Maayo ko, Salamat. Ikaw?', native: 'Estoy bien, gracias. ¿Y tú?', explanation: '"Maayo ko" significa "Estoy bien", "Ikaw" es "tú" (formal)' }, { bisaya: 'Asa si Tatay?', native: '¿Dónde está Papá?', explanation: '"Asa" significa "dónde", "si" es un marcador de persona, "Tatay" significa "Papá"' }, { bisaya: 'Naa siya sa balay.', native: 'Él está en casa.', explanation: '"Naa" significa "está/ser", "siya" es "él/ella", "sa balay" significa "en casa"' }, { bisaya: 'Kumusta na ang Kuya?', native: '¿Cómo está el hermano mayor?', explanation: '"Kumusta na" significa "¿Cómo está?", "ang" es un artículo, "Kuya" significa "hermano mayor"' }, { bisaya: 'Maayo ra siya.', native: 'Él está bien.', explanation: '"Maayo ra" significa "bien", "siya" significa "él"' }, { bisaya: 'Gutom na ko, Nanay.', native: 'Tengo hambre, Mamá.', explanation: '"Gutom" significa "hambriento", "na" muestra un estado, "ko" es "yo"' }, { bisaya: 'Hulata lang, hapit na ang pagkaon.', native: 'Solo espera, la comida está casi lista.', explanation: '"Hulata" significa "espera", "lang" significa "solo", "hapit na" significa "casi", "pagkaon" significa "comida"' } ] }, // Französisch -> Bisaya 'Französisch': { conversations: [ { bisaya: 'Kumusta ka, Nanay?', native: 'Comment vas-tu, Maman?', explanation: '"Kumusta ka" signifie "Comment vas-tu?" et "Nanay" signifie "Maman"' }, { bisaya: 'Maayo ko, Salamat. Ikaw?', native: 'Je vais bien, merci. Et toi?', explanation: '"Maayo ko" signifie "Je vais bien", "Ikaw" est "tu" (formel)' }, { bisaya: 'Asa si Tatay?', native: 'Où est Papa?', explanation: '"Asa" signifie "où", "si" est un marqueur de personne, "Tatay" signifie "Papa"' }, { bisaya: 'Naa siya sa balay.', native: 'Il est à la maison.', explanation: '"Naa" signifie "est/être", "siya" est "il/elle", "sa balay" signifie "à la maison"' }, { bisaya: 'Kumusta na ang Kuya?', native: 'Comment va le grand frère?', explanation: '"Kumusta na" signifie "Comment va", "ang" est un article, "Kuya" signifie "grand frère"' }, { bisaya: 'Maayo ra siya.', native: 'Il va bien.', explanation: '"Maayo ra" signifie "bien", "siya" signifie "il"' }, { bisaya: 'Gutom na ko, Nanay.', native: 'J\'ai faim, Maman.', explanation: '"Gutom" signifie "faim", "na" montre un état, "ko" est "je"' }, { bisaya: 'Hulata lang, hapit na ang pagkaon.', native: 'Attends juste, la nourriture est presque prête.', explanation: '"Hulata" signifie "attends", "lang" signifie "juste", "hapit na" signifie "presque", "pagkaon" signifie "nourriture"' } ] }, // Italienisch -> Bisaya 'Italienisch': { conversations: [ { bisaya: 'Kumusta ka, Nanay?', native: 'Come stai, Mamma?', explanation: '"Kumusta ka" significa "Come stai?" e "Nanay" significa "Mamma"' }, { bisaya: 'Maayo ko, Salamat. Ikaw?', native: 'Sto bene, grazie. E tu?', explanation: '"Maayo ko" significa "Sto bene", "Ikaw" è "tu" (formale)' }, { bisaya: 'Asa si Tatay?', native: 'Dove è Papà?', explanation: '"Asa" significa "dove", "si" è un marcatore di persona, "Tatay" significa "Papà"' }, { bisaya: 'Naa siya sa balay.', native: 'È a casa.', explanation: '"Naa" significa "è/essere", "siya" è "lui/lei", "sa balay" significa "a casa"' }, { bisaya: 'Kumusta na ang Kuya?', native: 'Come sta il fratello maggiore?', explanation: '"Kumusta na" significa "Come sta", "ang" è un articolo, "Kuya" significa "fratello maggiore"' }, { bisaya: 'Maayo ra siya.', native: 'Sta bene.', explanation: '"Maayo ra" significa "bene", "siya" significa "lui"' }, { bisaya: 'Gutom na ko, Nanay.', native: 'Ho fame, Mamma.', explanation: '"Gutom" significa "fame", "na" mostra uno stato, "ko" è "io"' }, { bisaya: 'Hulata lang, hapit na ang pagkaon.', native: 'Aspetta solo, il cibo è quasi pronto.', explanation: '"Hulata" significa "aspetta", "lang" significa "solo", "hapit na" significa "quasi", "pagkaon" significa "cibo"' } ] }, // Portugiesisch -> Bisaya 'Portugiesisch': { conversations: [ { bisaya: 'Kumusta ka, Nanay?', native: 'Como você está, Mãe?', explanation: '"Kumusta ka" significa "Como você está?" e "Nanay" significa "Mãe"' }, { bisaya: 'Maayo ko, Salamat. Ikaw?', native: 'Estou bem, obrigado. E você?', explanation: '"Maayo ko" significa "Estou bem", "Ikaw" é "você" (formal)' }, { bisaya: 'Asa si Tatay?', native: 'Onde está o Papai?', explanation: '"Asa" significa "onde", "si" é um marcador de pessoa, "Tatay" significa "Papai"' }, { bisaya: 'Naa siya sa balay.', native: 'Ele está em casa.', explanation: '"Naa" significa "está/ser", "siya" é "ele/ela", "sa balay" significa "em casa"' }, { bisaya: 'Kumusta na ang Kuya?', native: 'Como está o irmão mais velho?', explanation: '"Kumusta na" significa "Como está", "ang" é um artigo, "Kuya" significa "irmão mais velho"' }, { bisaya: 'Maayo ra siya.', native: 'Ele está bem.', explanation: '"Maayo ra" significa "bem", "siya" significa "ele"' }, { bisaya: 'Gutom na ko, Nanay.', native: 'Estou com fome, Mãe.', explanation: '"Gutom" significa "fome", "na" mostra um estado, "ko" é "eu"' }, { bisaya: 'Hulata lang, hapit na ang pagkaon.', native: 'Apenas espere, a comida está quase pronta.', explanation: '"Hulata" significa "espere", "lang" significa "apenas", "hapit na" significa "quase", "pagkaon" significa "comida"' } ] } }; async function findOrCreateSystemUser() { // Versuche zuerst einen System-Benutzer zu finden (z.B. mit username "system" oder "admin") let systemUser = await User.findOne({ where: { username: { [sequelize.Sequelize.Op.in]: ['system', 'admin', 'System', 'Admin'] } } }); if (!systemUser) { // Erstelle einen System-Benutzer const password = crypto.randomBytes(32).toString('hex'); const hashedPassword = await bcrypt.hash(password, 10); const hashedId = crypto.createHash('sha256').update(`system-${Date.now()}`).digest('hex'); systemUser = await User.create({ username: 'system', password: hashedPassword, hashedId: hashedId, email: 'system@your-part.de' }); console.log('✅ System-Benutzer erstellt:', systemUser.hashedId); } else { console.log('✅ System-Benutzer gefunden:', systemUser.hashedId); } return systemUser; } function createFamilyConversationExercises(nativeLanguageName) { const exercises = []; const conversations = FAMILY_CONVERSATIONS[nativeLanguageName]?.conversations || []; if (conversations.length === 0) { console.warn(`⚠️ Keine Gespräche für Muttersprache "${nativeLanguageName}" gefunden. Verwende Deutsch als Fallback.`); return createFamilyConversationExercises('Deutsch'); } let exerciseNum = 1; // Multiple Choice: Übersetze Bisaya-Satz in Muttersprache (alle Gespräche) conversations.forEach((conv, idx) => { // Erstelle für jedes Gespräch eine Multiple Choice Übung const wrongOptions = conversations .filter((c, i) => i !== idx) .sort(() => Math.random() - 0.5) .slice(0, 3) .map(c => c.native); const options = [conv.native, ...wrongOptions].sort(() => Math.random() - 0.5); const correctIndex = options.indexOf(conv.native); exercises.push({ exerciseTypeId: 2, // multiple_choice exerciseNumber: exerciseNum++, title: `Familien-Gespräch ${idx + 1} - Übersetzung`, instruction: 'Übersetze den Bisaya-Satz ins ' + nativeLanguageName, questionData: JSON.stringify({ type: 'multiple_choice', question: `Wie sagt man "${conv.bisaya}" auf ${nativeLanguageName}?`, options: options }), answerData: JSON.stringify({ type: 'multiple_choice', correctAnswer: correctIndex }), explanation: conv.explanation }); }); // Multiple Choice: Rückwärts-Übersetzung (Was bedeutet dieser Satz?) conversations.forEach((conv, idx) => { if (idx < 6) { // Erste 6 als Rückwärts-Übersetzung const wrongOptions = conversations .filter((c, i) => i !== idx) .sort(() => Math.random() - 0.5) .slice(0, 3) .map(c => c.native); const options = [conv.native, ...wrongOptions].sort(() => Math.random() - 0.5); const correctIndex = options.indexOf(conv.native); exercises.push({ exerciseTypeId: 2, // multiple_choice exerciseNumber: exerciseNum++, title: `Familien-Gespräch ${idx + 1} - Was bedeutet dieser Satz?`, instruction: 'Was bedeutet dieser Bisaya-Satz?', questionData: JSON.stringify({ type: 'multiple_choice', question: `Was bedeutet "${conv.bisaya}"?`, options: options }), answerData: JSON.stringify({ type: 'multiple_choice', correctAnswer: correctIndex }), explanation: conv.explanation }); } }); // Gap Fill: Vervollständige Familiengespräche (mehrere Varianten) exercises.push({ exerciseTypeId: 1, // gap_fill exerciseNumber: exerciseNum++, title: 'Familien-Gespräch 1 - Vervollständigen', instruction: 'Vervollständige das Gespräch mit den richtigen Bisaya-Wörtern.', questionData: JSON.stringify({ type: 'gap_fill', text: 'Person A: Kumusta ka, {gap}? (Mama)\nPerson B: {gap} ko, Salamat. Ikaw? (Mir geht es gut)', gaps: 2 }), answerData: JSON.stringify({ type: 'gap_fill', answers: ['Nanay', 'Maayo'] }), explanation: '"Nanay" ist "Mama" und "Maayo ko" bedeutet "Mir geht es gut"' }); exercises.push({ exerciseTypeId: 1, // gap_fill exerciseNumber: exerciseNum++, title: 'Familien-Gespräch 2 - Vervollständigen', instruction: 'Vervollständige das Gespräch mit den richtigen Bisaya-Wörtern.', questionData: JSON.stringify({ type: 'gap_fill', text: 'Person A: {gap} si Tatay? (Wo ist)\nPerson B: {gap} siya sa balay. (Er ist)', gaps: 2 }), answerData: JSON.stringify({ type: 'gap_fill', answers: ['Asa', 'Naa'] }), explanation: '"Asa" bedeutet "wo" und "Naa" bedeutet "ist/sein"' }); // Transformation: Übersetze Muttersprache-Satz nach Bisaya (mehrere Varianten) conversations.slice(0, 4).forEach((conv, idx) => { exercises.push({ exerciseTypeId: 3, // transformation exerciseNumber: exerciseNum++, title: `Familien-Gespräch ${idx + 1} - Übersetzung nach Bisaya`, instruction: 'Übersetze den Satz ins Bisaya.', questionData: JSON.stringify({ type: 'transformation', text: conv.native }), answerData: JSON.stringify({ type: 'transformation', correctAnswer: conv.bisaya }), explanation: `"${conv.bisaya}" bedeutet "${conv.native}" auf Bisaya. ${conv.explanation}` }); }); return exercises; } async function updateFamilyConversationExercises() { await sequelize.authenticate(); console.log('✅ Datenbankverbindung erfolgreich hergestellt.\n'); const systemUser = await findOrCreateSystemUser(); // Finde Bisaya-Sprache mit SQL const [bisayaLangResult] = await sequelize.query( `SELECT id FROM community.vocab_language WHERE name = 'Bisaya' LIMIT 1`, { type: sequelize.QueryTypes.SELECT } ); if (!bisayaLangResult) { console.error('❌ Bisaya-Sprache nicht gefunden.'); return; } const bisayaLanguageId = bisayaLangResult.id; // Hole alle Bisaya-Kurse mit native language info const courses = await sequelize.query( `SELECT c.id, c.title, c.native_language_id, nl.name as native_language_name FROM community.vocab_course c LEFT JOIN community.vocab_language nl ON c.native_language_id = nl.id WHERE c.language_id = :bisayaLanguageId`, { replacements: { bisayaLanguageId }, type: sequelize.QueryTypes.SELECT } ); console.log(`📚 Gefunden: ${courses.length} Bisaya-Kurse\n`); let totalExercisesCreated = 0; let totalLessonsProcessed = 0; for (const course of courses) { console.log(`📖 Kurs: ${course.title} (ID: ${course.id})`); // Finde native language name const nativeLanguageName = course.native_language_name || 'Deutsch'; console.log(` Muttersprache: ${nativeLanguageName}`); // Finde "Familien-Gespräche" Lektion const lessons = await VocabCourseLesson.findAll({ where: { courseId: course.id, title: 'Familien-Gespräche' }, attributes: ['id', 'title', 'lessonNumber'] }); console.log(` ${lessons.length} "Familien-Gespräche"-Lektion(en) gefunden`); for (const lesson of lessons) { // Lösche vorhandene Übungen const deletedCount = await VocabGrammarExercise.destroy({ where: { lessonId: lesson.id } }); console.log(` 🗑️ Lektion ${lesson.lessonNumber}: "${lesson.title}" - ${deletedCount} alte Übung(en) gelöscht`); // Erstelle neue Übungen const exercises = createFamilyConversationExercises(nativeLanguageName); if (exercises.length > 0) { const exercisesToCreate = exercises.map(ex => ({ ...ex, lessonId: lesson.id, createdByUserId: systemUser.id })); await VocabGrammarExercise.bulkCreate(exercisesToCreate); totalExercisesCreated += exercisesToCreate.length; console.log(` ✅ ${exercisesToCreate.length} neue Übung(en) erstellt`); } else { console.log(` ⚠️ Keine Übungen erstellt`); } totalLessonsProcessed++; } console.log(''); } console.log(`\n🎉 Zusammenfassung:`); console.log(` ${totalLessonsProcessed} "Familien-Gespräche"-Lektion(en) verarbeitet`); console.log(` ${totalExercisesCreated} Grammatik-Übungen erstellt`); } updateFamilyConversationExercises() .then(() => { sequelize.close(); process.exit(0); }) .catch((error) => { console.error('❌ Fehler:', error); sequelize.close(); process.exit(1); });