From ef2b279df648b7a766932d55fcf859ea3ce43863 Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Mon, 19 Jan 2026 21:52:13 +0100 Subject: [PATCH] Refactor exercise handling and improve user feedback in VocabLessonView - Enhanced the exercise display logic to provide clearer feedback on available grammar exercises, improving user engagement. - Updated conditional rendering to ensure accurate handling of lesson and exercise data, reducing potential errors. - Improved logging for exercise counts and active tab states, aiding in debugging and performance monitoring. --- .../update-survival-sentences-exercises.js | 270 ++++++++++++++++++ 1 file changed, 270 insertions(+) create mode 100755 backend/scripts/update-survival-sentences-exercises.js diff --git a/backend/scripts/update-survival-sentences-exercises.js b/backend/scripts/update-survival-sentences-exercises.js new file mode 100755 index 0000000..e83a144 --- /dev/null +++ b/backend/scripts/update-survival-sentences-exercises.js @@ -0,0 +1,270 @@ +#!/usr/bin/env node +/** + * Script zum Aktualisieren der "Überlebenssätze"-Übungen in Bisaya-Kursen + * + * Verwendung: + * node backend/scripts/update-survival-sentences-exercises.js + * + * Ersetzt bestehende generische Übungen durch spezifische Überlebenssätze-Übungen. + */ + +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'; + +// Spezifische Übungen für Überlebenssätze +const SURVIVAL_EXERCISES = { + 'Überlebenssätze - Teil 1': [ + { + exerciseTypeId: 2, // multiple_choice + title: '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', 'Palihug', 'Salamat', 'Maayo'] + }, + answerData: { + type: 'multiple_choice', + correctAnswer: 0 + }, + explanation: '"Wala ko kasabot" bedeutet "Ich verstehe nicht" - sehr wichtig für Anfänger!' + }, + { + exerciseTypeId: 2, // multiple_choice + title: 'Wie sagt man "Kannst du das wiederholen?"?', + instruction: 'Wähle die richtige Bitte aus.', + questionData: { + type: 'multiple_choice', + question: 'Wie sagt man "Kannst du das wiederholen?" auf Bisaya?', + options: ['Palihug ka mubalik?', 'Salamat', 'Maayo', 'Kumusta ka?'] + }, + answerData: { + type: 'multiple_choice', + correctAnswer: 0 + }, + explanation: '"Palihug ka mubalik?" bedeutet "Bitte kannst du wiederholen?" - essentiell für das Lernen!' + }, + { + exerciseTypeId: 2, // multiple_choice + title: 'Wie sagt man "Wo ist...?"?', + instruction: 'Wähle die richtige Frage aus.', + questionData: { + type: 'multiple_choice', + question: 'Wie sagt man "Wo ist die Toilette?" auf Bisaya?', + options: ['Asa ang CR?', 'Kumusta ka?', 'Salamat', 'Maayo'] + }, + answerData: { + type: 'multiple_choice', + correctAnswer: 0 + }, + explanation: '"Asa ang CR?" bedeutet "Wo ist die Toilette?" - "Asa" = "Wo", "CR" = "Comfort Room" (Toilette).' + }, + { + exerciseTypeId: 1, // gap_fill + title: 'Überlebenssätze vervollständigen', + instruction: 'Fülle die Lücken mit den richtigen Bisaya-Wörtern.', + questionData: { + type: 'gap_fill', + text: '{gap} ko kasabot. {gap} ka mubalik?', + gaps: 2 + }, + answerData: { + type: 'gap_fill', + answers: ['Wala', 'Palihug'] + }, + explanation: '"Wala ko kasabot" = "Ich verstehe nicht", "Palihug ka mubalik?" = "Bitte wiederholen".' + } + ], + + 'Überlebenssätze - Teil 2': [ + { + exerciseTypeId: 2, // multiple_choice + title: 'Wie sagt man "Wie viel kostet das?"?', + instruction: 'Wähle die richtige Frage aus.', + questionData: { + type: 'multiple_choice', + question: 'Wie sagt man "Wie viel kostet das?" auf Bisaya?', + options: ['Tagpila ni?', 'Asa ni?', 'Unsa ni?', 'Kinsa ni?'] + }, + answerData: { + type: 'multiple_choice', + correctAnswer: 0 + }, + explanation: '"Tagpila ni?" bedeutet "Wie viel kostet das?" - sehr nützlich beim Einkaufen!' + }, + { + exerciseTypeId: 2, // multiple_choice + title: 'Wie sagt man "Entschuldigung"?', + instruction: 'Wähle die richtige Entschuldigung aus.', + questionData: { + type: 'multiple_choice', + question: 'Wie sagt man "Entschuldigung" auf Bisaya?', + options: ['Pasensya', 'Salamat', 'Palihug', 'Maayo'] + }, + answerData: { + type: 'multiple_choice', + correctAnswer: 0 + }, + explanation: '"Pasensya" bedeutet "Entschuldigung" oder "Entschuldige bitte" - wichtig für höfliche Kommunikation.' + }, + { + exerciseTypeId: 1, // gap_fill + title: 'Wichtige Fragen bilden', + instruction: 'Fülle die Lücken mit den richtigen Fragewörtern.', + questionData: { + type: 'gap_fill', + text: '{gap} ni? (Wie viel kostet das?) | {gap} ni? (Was ist das?) | {gap} lang (Bitte langsam)', + gaps: 3 + }, + answerData: { + type: 'gap_fill', + answers: ['Tagpila', 'Unsa', 'Hinay-hinay'] + }, + explanation: '"Tagpila" = "Wie viel", "Unsa" = "Was", "Hinay-hinay lang" = "Bitte langsam".' + }, + { + exerciseTypeId: 4, // transformation + title: 'Überlebenssätze übersetzen', + instruction: 'Übersetze den Satz ins Bisaya.', + questionData: { + type: 'transformation', + text: 'Ich spreche kein Bisaya', + sourceLanguage: 'Deutsch', + targetLanguage: 'Bisaya' + }, + answerData: { + type: 'transformation', + correct: 'Dili ko mag-Bisaya', + alternatives: ['Wala ko mag-Bisaya', 'Dili ko makasabot Bisaya'] + }, + explanation: '"Dili ko mag-Bisaya" bedeutet "Ich spreche kein Bisaya" - nützlich, um zu erklären, dass du noch lernst.' + } + ] +}; + +async function findOrCreateSystemUser() { + let systemUser = await User.findOne({ + where: { + username: 'system' + } + }); + + if (!systemUser) { + systemUser = await User.findOne({ + where: { + username: 'admin' + } + }); + } + + if (!systemUser) { + console.error('❌ System-Benutzer nicht gefunden.'); + throw new Error('System user not found'); + } + + return systemUser; +} + +async function updateSurvivalExercises() { + await sequelize.authenticate(); + console.log('Datenbankverbindung erfolgreich hergestellt.\n'); + + const systemUser = await findOrCreateSystemUser(); + console.log(`Verwende System-Benutzer: ${systemUser.username} (ID: ${systemUser.id})\n`); + + // Finde alle Bisaya-Kurse + 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 id, title, owner_user_id FROM community.vocab_course WHERE language_id = :languageId`, + { + replacements: { languageId: bisayaLanguage.id }, + type: sequelize.QueryTypes.SELECT + } + ); + + console.log(`Gefunden: ${courses.length} Bisaya-Kurse\n`); + + let totalExercisesUpdated = 0; + let totalLessonsUpdated = 0; + + for (const course of courses) { + console.log(`📚 Kurs: ${course.title} (ID: ${course.id})`); + + // Finde "Überlebenssätze"-Lektionen + const lessons = await VocabCourseLesson.findAll({ + where: { + courseId: course.id, + title: ['Überlebenssätze - Teil 1', 'Überlebenssätze - Teil 2'] + }, + order: [['lessonNumber', 'ASC']] + }); + + console.log(` ${lessons.length} "Überlebenssätze"-Lektionen gefunden\n`); + + for (const lesson of lessons) { + const exercises = SURVIVAL_EXERCISES[lesson.title]; + + if (!exercises || exercises.length === 0) { + console.log(` ⚠️ Lektion ${lesson.lessonNumber}: "${lesson.title}" - keine Übungen definiert`); + continue; + } + + // Lösche bestehende Ü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 + let exerciseNumber = 1; + for (const exerciseData of exercises) { + await VocabGrammarExercise.create({ + lessonId: lesson.id, + exerciseTypeId: exerciseData.exerciseTypeId, + exerciseNumber: exerciseNumber++, + title: exerciseData.title, + instruction: exerciseData.instruction, + questionData: JSON.stringify(exerciseData.questionData), + answerData: JSON.stringify(exerciseData.answerData), + explanation: exerciseData.explanation, + createdByUserId: course.owner_user_id || systemUser.id + }); + totalExercisesUpdated++; + } + + console.log(` ✅ Lektion ${lesson.lessonNumber}: "${lesson.title}" - ${exercises.length} neue Übung(en) erstellt`); + totalLessonsUpdated++; + } + + console.log(''); + } + + console.log(`\n🎉 Zusammenfassung:`); + console.log(` ${totalLessonsUpdated} Lektionen aktualisiert`); + console.log(` ${totalExercisesUpdated} neue Grammatik-Übungen erstellt`); +} + +updateSurvivalExercises() + .then(() => { + sequelize.close(); + process.exit(0); + }) + .catch((error) => { + console.error('❌ Fehler:', error); + sequelize.close(); + process.exit(1); + });