Files
yourpart3/backend/scripts/create-bisaya-course.js
Torsten Schulz (local) b6a4607e60 Implement vocab course and grammar exercise features in backend and frontend
- Added new course management functionalities in VocabController, including creating, updating, and deleting courses and lessons.
- Implemented enrollment and progress tracking for courses, along with grammar exercise creation and management.
- Updated database schema to include tables for courses, lessons, enrollments, and grammar exercises.
- Enhanced frontend with new routes and views for course listing and details, including internationalization support for course-related texts.
- Improved user experience by adding navigation to courses from the main vocab trainer view.
2026-01-19 10:58:53 +01:00

310 lines
13 KiB
JavaScript
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
/**
* Script zum Erstellen eines vollständigen 4-Wochen Bisaya-Kurses
*
* Verwendung:
* node backend/scripts/create-bisaya-course.js <languageId> <ownerHashedId>
*/
import { sequelize } from '../utils/sequelize.js';
import VocabCourse from '../models/community/vocab_course.js';
import VocabCourseLesson from '../models/community/vocab_course_lesson.js';
import User from '../models/community/user.js';
import crypto from 'crypto';
const LESSONS = [
// WOCHE 1: Grundlagen & Aussprache
{ week: 1, day: 1, num: 1, type: 'conversation', title: 'Begrüßungen & Höflichkeit',
desc: 'Lerne die wichtigsten Begrüßungen und Höflichkeitsformeln',
targetMin: 15, targetScore: 80, review: false,
cultural: 'Philippiner schätzen Höflichkeit sehr. Lächeln ist wichtig!' },
{ week: 1, day: 1, num: 2, type: 'vocab', title: 'Überlebenssätze - Teil 1',
desc: 'Die 10 wichtigsten Sätze für den Alltag',
targetMin: 20, targetScore: 85, review: true,
cultural: 'Diese Sätze helfen dir sofort im Alltag weiter.' },
{ week: 1, day: 2, num: 3, type: 'vocab', title: 'Familienwörter',
desc: 'Mama, Papa, Kuya, Ate, Lola, Lolo und mehr',
targetMin: 20, targetScore: 85, review: true,
cultural: 'Kuya und Ate werden auch für Nicht-Verwandte verwendet sehr respektvoll!' },
{ week: 1, day: 2, num: 4, type: 'conversation', title: 'Familien-Gespräche',
desc: 'Einfache Gespräche mit Familienmitgliedern',
targetMin: 15, targetScore: 80, review: false,
cultural: 'Familienkonversationen sind herzlicher als formelle Gespräche.' },
{ week: 1, day: 3, num: 5, type: 'conversation', title: 'Gefühle & Zuneigung',
desc: 'Mingaw ko nimo, Palangga taka und mehr',
targetMin: 15, targetScore: 80, review: false,
cultural: 'Palangga taka ist wärmer als "I love you" im Familienkontext.' },
{ week: 1, day: 3, num: 6, type: 'vocab', title: 'Überlebenssätze - Teil 2',
desc: 'Weitere wichtige Alltagssätze',
targetMin: 20, targetScore: 85, review: true,
cultural: null },
{ week: 1, day: 4, num: 7, type: 'conversation', title: 'Essen & Fürsorge',
desc: 'Nikaon ka? Kaon ta! Lami!',
targetMin: 15, targetScore: 80, review: false,
cultural: 'Essen = Liebe! "Nikaon na ka?" ist sehr fürsorglich.' },
{ week: 1, day: 4, num: 8, type: 'vocab', title: 'Essen & Trinken',
desc: 'Wichtige Wörter rund ums Essen',
targetMin: 20, targetScore: 85, review: true,
cultural: null },
{ week: 1, day: 5, num: 9, type: 'review', title: 'Woche 1 - Wiederholung',
desc: 'Wiederhole alle Inhalte der ersten Woche',
targetMin: 30, targetScore: 80, review: false,
cultural: 'Wiederholung ist der Schlüssel zum Erfolg!' },
{ week: 1, day: 5, num: 10, type: 'vocab', title: 'Woche 1 - Vokabeltest',
desc: 'Teste dein Wissen aus Woche 1',
targetMin: 15, targetScore: 80, review: true,
cultural: null },
// WOCHE 2: Alltag & Familie
{ week: 2, day: 1, num: 11, type: 'conversation', title: 'Alltagsgespräche - Teil 1',
desc: 'Wie war dein Tag? Was machst du?',
targetMin: 15, targetScore: 80, review: false,
cultural: 'Alltagsgespräche sind wichtig für echte Kommunikation.' },
{ week: 2, day: 1, num: 12, type: 'vocab', title: 'Haus & Familie',
desc: 'Balay, Kwarto, Kusina, Pamilya',
targetMin: 20, targetScore: 85, review: true,
cultural: null },
{ week: 2, day: 2, num: 13, type: 'conversation', title: 'Alltagsgespräche - Teil 2',
desc: 'Wohin gehst du? Was machst du heute?',
targetMin: 15, targetScore: 80, review: false,
cultural: null },
{ week: 2, day: 2, num: 14, type: 'vocab', title: 'Ort & Richtung',
desc: 'Asa, dinhi, didto, padulong',
targetMin: 20, targetScore: 85, review: true,
cultural: null },
{ week: 2, day: 3, num: 15, type: 'grammar', title: 'Zeitformen - Grundlagen',
desc: 'Ni-kaon ko, Mo-kaon ko - Vergangenheit und Zukunft',
targetMin: 25, targetScore: 75, review: true,
cultural: 'Cebuano hat keine komplexen Zeiten wie Deutsch. Zeit wird mit Präfixen ausgedrückt.' },
{ week: 2, day: 3, num: 16, type: 'vocab', title: 'Zeit & Datum',
desc: 'Karon, ugma, gahapon, karon adlaw',
targetMin: 20, targetScore: 85, review: true,
cultural: null },
{ week: 2, day: 4, num: 17, type: 'conversation', title: 'Einkaufen & Preise',
desc: 'Tagpila ni? Pwede barato?',
targetMin: 15, targetScore: 80, review: false,
cultural: 'Handeln ist in den Philippinen üblich und erwartet.' },
{ week: 2, day: 4, num: 18, type: 'vocab', title: 'Zahlen & Preise',
desc: '1-100, Preise, Mengen',
targetMin: 25, targetScore: 85, review: true,
cultural: null },
{ week: 2, day: 5, num: 19, type: 'review', title: 'Woche 2 - Wiederholung',
desc: 'Wiederhole alle Inhalte der zweiten Woche',
targetMin: 30, targetScore: 80, review: false,
cultural: null },
{ week: 2, day: 5, num: 20, type: 'vocab', title: 'Woche 2 - Vokabeltest',
desc: 'Teste dein Wissen aus Woche 2',
targetMin: 15, targetScore: 80, review: true,
cultural: null },
// WOCHE 3: Vertiefung
{ week: 3, day: 1, num: 21, type: 'conversation', title: 'Gefühle & Emotionen',
desc: 'Nalipay, nasubo, nahadlok, naguol',
targetMin: 15, targetScore: 80, review: false,
cultural: 'Emotionen auszudrücken ist wichtig für echte Verbindung.' },
{ week: 3, day: 1, num: 22, type: 'vocab', title: 'Gefühle & Emotionen',
desc: 'Wörter für verschiedene Gefühle',
targetMin: 20, targetScore: 85, review: true,
cultural: null },
{ week: 3, day: 2, num: 23, type: 'conversation', title: 'Gesundheit & Wohlbefinden',
desc: 'Sakit, maayo, tambal, doktor',
targetMin: 15, targetScore: 80, review: false,
cultural: null },
{ week: 3, day: 2, num: 24, type: 'vocab', title: 'Körper & Gesundheit',
desc: 'Wörter rund um den Körper und Gesundheit',
targetMin: 20, targetScore: 85, review: true,
cultural: null },
{ week: 3, day: 3, num: 25, type: 'grammar', title: 'Höflichkeitsformen',
desc: 'Palihug, Pwede, Tabang',
targetMin: 20, targetScore: 75, review: true,
cultural: 'Höflichkeit ist extrem wichtig in der philippinischen Kultur.' },
{ week: 3, day: 3, num: 26, type: 'conversation', title: 'Bitten & Fragen',
desc: 'Wie man höflich fragt und bittet',
targetMin: 15, targetScore: 80, review: false,
cultural: null },
{ week: 3, day: 4, num: 27, type: 'conversation', title: 'Kinder & Familie',
desc: 'Gespräche mit und über Kinder',
targetMin: 15, targetScore: 80, review: false,
cultural: 'Kinder sind sehr wichtig in philippinischen Familien.' },
{ week: 3, day: 4, num: 28, type: 'vocab', title: 'Kinder & Spiel',
desc: 'Wörter für Kinder und Spielsachen',
targetMin: 20, targetScore: 85, review: true,
cultural: null },
{ week: 3, day: 5, num: 29, type: 'review', title: 'Woche 3 - Wiederholung',
desc: 'Wiederhole alle Inhalte der dritten Woche',
targetMin: 30, targetScore: 80, review: false,
cultural: null },
{ week: 3, day: 5, num: 30, type: 'vocab', title: 'Woche 3 - Vokabeltest',
desc: 'Teste dein Wissen aus Woche 3',
targetMin: 15, targetScore: 80, review: true,
cultural: null },
// WOCHE 4: Freies Sprechen
{ week: 4, day: 1, num: 31, type: 'conversation', title: 'Freies Gespräch - Thema 1',
desc: 'Übe freies Sprechen zu verschiedenen Themen',
targetMin: 20, targetScore: 75, review: false,
cultural: 'Fehler sind okay! Philippiner schätzen das Bemühen.' },
{ week: 4, day: 1, num: 32, type: 'vocab', title: 'Wiederholung - Woche 1 & 2',
desc: 'Wiederhole wichtige Vokabeln aus den ersten beiden Wochen',
targetMin: 25, targetScore: 85, review: true,
cultural: null },
{ week: 4, day: 2, num: 33, type: 'conversation', title: 'Freies Gespräch - Thema 2',
desc: 'Weitere Übung im freien Sprechen',
targetMin: 20, targetScore: 75, review: false,
cultural: null },
{ week: 4, day: 2, num: 34, type: 'vocab', title: 'Wiederholung - Woche 3',
desc: 'Wiederhole wichtige Vokabeln aus Woche 3',
targetMin: 25, targetScore: 85, review: true,
cultural: null },
{ week: 4, day: 3, num: 35, type: 'conversation', title: 'Komplexere Gespräche',
desc: 'Längere Gespräche zu verschiedenen Themen',
targetMin: 25, targetScore: 75, review: false,
cultural: 'Je mehr du sprichst, desto besser wirst du!' },
{ week: 4, day: 3, num: 36, type: 'review', title: 'Gesamtwiederholung',
desc: 'Wiederhole alle wichtigen Inhalte des Kurses',
targetMin: 30, targetScore: 80, review: false,
cultural: null },
{ week: 4, day: 4, num: 37, type: 'conversation', title: 'Praktische Übung',
desc: 'Simuliere echte Gesprächssituationen',
targetMin: 25, targetScore: 75, review: false,
cultural: null },
{ week: 4, day: 4, num: 38, type: 'vocab', title: 'Abschlusstest - Vokabeln',
desc: 'Finaler Vokabeltest über den gesamten Kurs',
targetMin: 20, targetScore: 80, review: true,
cultural: null },
{ week: 4, day: 5, num: 39, type: 'review', title: 'Abschlussprüfung',
desc: 'Finale Prüfung über alle Kursinhalte',
targetMin: 30, targetScore: 80, review: false,
cultural: 'Gratulation zum Abschluss des Kurses!' },
{ week: 4, day: 5, num: 40, type: 'culture', title: 'Kulturelle Tipps & Tricks',
desc: 'Wichtige kulturelle Hinweise für den Alltag',
targetMin: 15, targetScore: 0, review: false,
cultural: 'Kulturelles Verständnis ist genauso wichtig wie die Sprache selbst.' }
];
async function createBisayaCourse(languageId, ownerHashedId) {
try {
// Finde User
const user = await User.findOne({ where: { hashedId: ownerHashedId } });
if (!user) {
throw new Error(`User mit hashedId ${ownerHashedId} nicht gefunden`);
}
// Prüfe, ob Sprache existiert
const [lang] = await sequelize.query(
`SELECT id FROM community.vocab_language WHERE id = :langId`,
{ replacements: { langId: languageId }, type: sequelize.QueryTypes.SELECT }
);
if (!lang) {
throw new Error(`Sprache mit ID ${languageId} nicht gefunden`);
}
// Erstelle Kurs
const shareCode = crypto.randomBytes(8).toString('hex');
const course = await VocabCourse.create({
ownerUserId: user.id,
title: 'Bisaya für Familien - Schnellstart in 4 Wochen',
description: 'Lerne Bisaya (Cebuano) schnell und praktisch für den Familienalltag. Fokus auf Sprechen & Hören mit strukturiertem 4-Wochen-Plan.',
languageId: Number(languageId),
difficultyLevel: 1,
isPublic: true,
shareCode
});
console.log(`✅ Kurs erstellt: ${course.id} - "${course.title}"`);
console.log(` Share-Code: ${shareCode}`);
// Erstelle Lektionen
for (const lessonData of LESSONS) {
const lesson = await VocabCourseLesson.create({
courseId: course.id,
chapterId: null, // Wird später mit Vokabeln verknüpft
lessonNumber: lessonData.num,
title: lessonData.title,
description: lessonData.desc,
weekNumber: lessonData.week,
dayNumber: lessonData.day,
lessonType: lessonData.type,
culturalNotes: lessonData.cultural,
targetMinutes: lessonData.targetMin,
targetScorePercent: lessonData.targetScore,
requiresReview: lessonData.review
});
console.log(` ✅ Lektion ${lessonData.num}: ${lessonData.title} (Woche ${lessonData.week}, Tag ${lessonData.day})`);
}
console.log(`\n🎉 Kurs erfolgreich erstellt mit ${LESSONS.length} Lektionen!`);
console.log(`\n📊 Kurs-Statistik:`);
console.log(` - Gesamte Lektionen: ${LESSONS.length}`);
console.log(` - Vokabel-Lektionen: ${LESSONS.filter(l => l.type === 'vocab').length}`);
console.log(` - Konversations-Lektionen: ${LESSONS.filter(l => l.type === 'conversation').length}`);
console.log(` - Grammatik-Lektionen: ${LESSONS.filter(l => l.type === 'grammar').length}`);
console.log(` - Wiederholungs-Lektionen: ${LESSONS.filter(l => l.type === 'review').length}`);
console.log(` - Durchschnittliche Zeit pro Tag: ~${Math.round(LESSONS.reduce((sum, l) => sum + l.targetMin, 0) / (4 * 5))} Minuten`);
console.log(`\n💡 Nächste Schritte:`);
console.log(` 1. Füge Vokabeln zu den Vokabel-Lektionen hinzu`);
console.log(` 2. Erstelle Grammatik-Übungen für die Grammatik-Lektionen`);
console.log(` 3. Teile den Kurs mit anderen (Share-Code: ${shareCode})`);
return course;
} catch (error) {
console.error('❌ Fehler beim Erstellen des Kurses:', error);
throw error;
}
}
// CLI-Aufruf
const languageId = process.argv[2];
const ownerHashedId = process.argv[3];
if (!languageId || !ownerHashedId) {
console.error('Verwendung: node create-bisaya-course.js <languageId> <ownerHashedId>');
console.error('Beispiel: node create-bisaya-course.js 1 abc123def456');
process.exit(1);
}
createBisayaCourse(languageId, ownerHashedId)
.then(() => {
process.exit(0);
})
.catch((error) => {
console.error(error);
process.exit(1);
});