diff --git a/backend/scripts/create-bisaya-course-content.js b/backend/scripts/create-bisaya-course-content.js index 97dfe1a..b96e5a4 100644 --- a/backend/scripts/create-bisaya-course-content.js +++ b/backend/scripts/create-bisaya-course-content.js @@ -738,7 +738,7 @@ async function createBisayaCourseContent() { } const courses = await sequelize.query( - `SELECT id, title FROM community.vocab_course WHERE language_id = :languageId`, + `SELECT id, title, owner_user_id AS "ownerUserId" FROM community.vocab_course WHERE language_id = :languageId`, { replacements: { languageId: bisayaLanguage.id }, type: sequelize.QueryTypes.SELECT @@ -761,24 +761,33 @@ async function createBisayaCourseContent() { console.log(` ${lessons.length} Lektionen gefunden\n`); for (const lesson of lessons) { - // Prüfe, ob bereits Übungen existieren + const exercises = getExercisesForLesson(lesson.title); + if (exercises.length === 0) { + const existingCount = await VocabGrammarExercise.count({ where: { lessonId: lesson.id } }); + if (existingCount > 0) { + console.log(` ⏭️ Lektion ${lesson.lessonNumber}: "${lesson.title}" - bereits ${existingCount} Übung(en) vorhanden`); + } else { + console.log(` ⚠️ Lektion ${lesson.lessonNumber}: "${lesson.title}" - keine Übungen definiert`); + } + continue; + } + + // Bei Woche-1-Wiederholung/Vokabeltest: Alte Platzhalter entfernen und ersetzen + const replacePlaceholders = ['Woche 1 - Wiederholung', 'Woche 1 - Vokabeltest'].includes(lesson.title); const existingCount = await VocabGrammarExercise.count({ where: { lessonId: lesson.id } }); - if (existingCount > 0) { + if (existingCount > 0 && !replacePlaceholders) { console.log(` ⏭️ Lektion ${lesson.lessonNumber}: "${lesson.title}" - bereits ${existingCount} Übung(en) vorhanden`); continue; } - // Hole Übungen für diese Lektion - const exercises = getExercisesForLesson(lesson.title); - - if (exercises.length === 0) { - console.log(` ⚠️ Lektion ${lesson.lessonNumber}: "${lesson.title}" - keine Übungen definiert`); - continue; + if (replacePlaceholders && existingCount > 0) { + const deleted = await VocabGrammarExercise.destroy({ where: { lessonId: lesson.id } }); + console.log(` 🗑️ Lektion ${lesson.lessonNumber}: "${lesson.title}" - ${deleted} Platzhalter entfernt`); } - + // Erstelle Übungen let exerciseNumber = 1; for (const exerciseData of exercises) { diff --git a/backend/scripts/update-week1-bisaya-exercises.js b/backend/scripts/update-week1-bisaya-exercises.js new file mode 100644 index 0000000..a5116e5 --- /dev/null +++ b/backend/scripts/update-week1-bisaya-exercises.js @@ -0,0 +1,129 @@ +#!/usr/bin/env node +/** + * Script zum Aktualisieren der Woche-1-Lektionen in Bisaya-Kursen + * + * Verwendung: + * node backend/scripts/update-week1-bisaya-exercises.js + * + * - Entfernt alte Platzhalter-Übungen + * - Ersetzt durch korrekte Inhalte für "Woche 1 - Wiederholung" und "Woche 1 - Vokabeltest" + */ + +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 User from '../models/community/user.js'; + +const LESSON_TITLES = ['Woche 1 - Wiederholung', 'Woche 1 - Vokabeltest']; + +const BISAYA_EXERCISES = { + 'Woche 1 - Wiederholung': [ + { exerciseTypeId: 2, title: 'Wiederholung: Wie sagt man "Wie geht es dir?"?', instruction: 'Wähle die richtige Begrüßung aus.', questionData: { type: 'multiple_choice', question: 'Wie sagt man "Wie geht es dir?" auf Bisaya?', options: ['Kumusta ka?', 'Maayo', 'Salamat', 'Palihug'] }, answerData: { type: 'multiple_choice', correctAnswer: 0 }, explanation: '"Kumusta ka?" ist die Standard-Begrüßung auf Bisaya.' }, + { exerciseTypeId: 2, title: 'Wiederholung: Wie sagt man "Mutter" auf Bisaya?', instruction: 'Wähle die richtige Übersetzung.', questionData: { type: 'multiple_choice', question: 'Wie sagt man "Mutter" auf Bisaya?', options: ['Nanay', 'Tatay', 'Kuya', 'Ate'] }, answerData: { type: 'multiple_choice', correctAnswer: 0 }, explanation: '"Nanay" bedeutet "Mutter" auf Bisaya.' }, + { exerciseTypeId: 2, title: 'Wiederholung: Was bedeutet "Palangga taka"?', instruction: 'Wähle die richtige Bedeutung.', questionData: { type: 'multiple_choice', question: 'Was bedeutet "Palangga taka"?', options: ['Ich hab dich lieb', 'Danke', 'Guten Tag', 'Auf Wiedersehen'] }, answerData: { type: 'multiple_choice', correctAnswer: 0 }, explanation: '"Palangga taka" bedeutet "Ich hab dich lieb" - wärmer als "I love you" im Familienkontext.' }, + { exerciseTypeId: 2, title: 'Wiederholung: Was fragt man mit "Nikaon ka?"?', instruction: 'Wähle die richtige Bedeutung.', questionData: { type: 'multiple_choice', question: 'Was bedeutet "Nikaon ka?"?', options: ['Hast du schon gegessen?', 'Wie geht es dir?', 'Danke', 'Bitte'] }, answerData: { type: 'multiple_choice', correctAnswer: 0 }, explanation: '"Nikaon ka?" bedeutet "Hast du schon gegessen?" - typisch fürsorglich auf den Philippinen.' }, + { exerciseTypeId: 2, title: 'Wiederholung: Wie sagt man "Ich verstehe nicht"?', instruction: 'Wähle die richtige Übersetzung.', questionData: { type: 'multiple_choice', question: 'Wie sagt man "Ich verstehe nicht" auf Bisaya?', options: ['Wala ko kasabot', 'Salamat', 'Maayo', 'Palihug'] }, answerData: { type: 'multiple_choice', correctAnswer: 0 }, explanation: '"Wala ko kasabot" bedeutet "Ich verstehe nicht".' } + ], + 'Woche 1 - Vokabeltest': [ + { exerciseTypeId: 2, title: 'Vokabeltest: Kumusta', instruction: 'Was bedeutet "Kumusta"?', questionData: { type: 'multiple_choice', question: 'Was bedeutet "Kumusta"?', options: ['Wie geht es dir?', 'Danke', 'Bitte', 'Auf Wiedersehen'] }, answerData: { type: 'multiple_choice', correctAnswer: 0 }, explanation: '"Kumusta" kommt von spanisch "¿Cómo está?" - "Wie geht es dir?"' }, + { exerciseTypeId: 2, title: 'Vokabeltest: Lola', instruction: 'Wähle die richtige Übersetzung.', questionData: { type: 'multiple_choice', question: 'Was bedeutet "Lola"?', options: ['Großmutter', 'Großvater', 'Mutter', 'Vater'] }, answerData: { type: 'multiple_choice', correctAnswer: 0 }, explanation: '"Lola" = Großmutter, "Lolo" = Großvater.' }, + { exerciseTypeId: 2, title: 'Vokabeltest: Salamat', instruction: 'Wähle die richtige Bedeutung.', questionData: { type: 'multiple_choice', question: 'Was bedeutet "Salamat"?', options: ['Danke', 'Bitte', 'Entschuldigung', 'Gern geschehen'] }, answerData: { type: 'multiple_choice', correctAnswer: 0 }, explanation: '"Salamat" bedeutet "Danke".' }, + { exerciseTypeId: 2, title: 'Vokabeltest: Lami', instruction: 'Was bedeutet "Lami"?', questionData: { type: 'multiple_choice', question: 'Was bedeutet "Lami"?', options: ['Lecker', 'Viel', 'Gut', 'Schnell'] }, answerData: { type: 'multiple_choice', correctAnswer: 0 }, explanation: '"Lami" bedeutet "lecker" oder "schmackhaft" - wichtig beim Essen!' }, + { exerciseTypeId: 2, title: 'Vokabeltest: Mingaw ko nimo', instruction: 'Wähle die richtige Bedeutung.', questionData: { type: 'multiple_choice', question: 'Was bedeutet "Mingaw ko nimo"?', options: ['Ich vermisse dich', 'Ich freue mich', 'Ich mag dich', 'Ich liebe dich'] }, answerData: { type: 'multiple_choice', correctAnswer: 0 }, explanation: '"Mingaw ko nimo" bedeutet "Ich vermisse dich".' } + ] +}; + +async function updateWeek1BisayaExercises() { + await sequelize.authenticate(); + console.log('Datenbankverbindung erfolgreich hergestellt.\n'); + + let systemUser; + try { + systemUser = await User.findOne({ where: { username: 'system' } }); + if (!systemUser) systemUser = await User.findOne({ where: { username: 'admin' } }); + if (!systemUser) throw new Error('System user not found'); + } catch (e) { + console.error('❌ System-Benutzer nicht gefunden.'); + throw e; + } + + const [bisayaLanguage] = await sequelize.query( + `SELECT id FROM community.vocab_language WHERE name = 'Bisaya' LIMIT 1`, + { type: sequelize.QueryTypes.SELECT } + ); + + if (!bisayaLanguage) { + console.error('❌ Bisaya-Sprache nicht gefunden.'); + return; + } + + const courses = await sequelize.query( + `SELECT c.id, c.title, c.owner_user_id + FROM community.vocab_course c + WHERE c.language_id = :languageId`, + { + replacements: { languageId: bisayaLanguage.id }, + type: sequelize.QueryTypes.SELECT + } + ); + + console.log(`Gefunden: ${courses.length} Bisaya-Kurs(e)\n`); + + let totalDeleted = 0; + let totalAdded = 0; + + for (const course of courses) { + console.log(`📚 Kurs: ${course.title} (ID: ${course.id})`); + + for (const lessonTitle of LESSON_TITLES) { + const exercises = BISAYA_EXERCISES[lessonTitle]; + if (!exercises || exercises.length === 0) continue; + + const lessons = await VocabCourseLesson.findAll({ + where: { courseId: course.id, title: lessonTitle }, + order: [['lessonNumber', 'ASC']] + }); + + for (const lesson of lessons) { + const deletedCount = await VocabGrammarExercise.destroy({ + where: { lessonId: lesson.id } + }); + totalDeleted += deletedCount; + console.log(` 🗑️ Lektion ${lesson.lessonNumber}: "${lesson.title}" - ${deletedCount} alte Übung(en) entfernt`); + + let exerciseNumber = 1; + for (const ex of exercises) { + await VocabGrammarExercise.create({ + lessonId: lesson.id, + exerciseTypeId: ex.exerciseTypeId, + exerciseNumber: exerciseNumber++, + title: ex.title, + instruction: ex.instruction, + questionData: JSON.stringify(ex.questionData), + answerData: JSON.stringify(ex.answerData), + explanation: ex.explanation, + createdByUserId: course.owner_user_id || systemUser.id + }); + totalAdded++; + } + console.log(` ✅ Lektion ${lesson.lessonNumber}: "${lesson.title}" - ${exercises.length} neue Übung(en)`); + } + } + console.log(''); + } + + console.log(`\n🎉 Zusammenfassung:`); + console.log(` ${totalDeleted} Platzhalter-Übungen entfernt`); + console.log(` ${totalAdded} neue Übungen erstellt`); +} + +updateWeek1BisayaExercises() + .then(() => { + sequelize.close(); + process.exit(0); + }) + .catch((error) => { + console.error('❌ Fehler:', error); + sequelize.close(); + process.exit(1); + }); diff --git a/frontend/src/views/social/VocabLessonView.vue b/frontend/src/views/social/VocabLessonView.vue index 8b0b46b..318f7fa 100644 --- a/frontend/src/views/social/VocabLessonView.vue +++ b/frontend/src/views/social/VocabLessonView.vue @@ -24,7 +24,7 @@ class="tab-button" > {{ $t('socialnetwork.vocab.courses.exercises') }} - ({{ lesson?.grammarExercises?.length || 0 }}) + ({{ effectiveExercises?.length || 0 }}) @@ -160,11 +160,11 @@ - +
{{ exercise.instruction }}
@@ -351,7 +351,7 @@{{ $t('socialnetwork.vocab.courses.noExercises') }}