Files
yourpart3/backend/scripts/create-german-for-bisaya-course.js
Torsten Schulz (local) 4205639de3
All checks were successful
Deploy to production / deploy (push) Successful in 1m31s
feat(bisaya-course): enhance phase 4 didactics with new learning goals and speaking prompts
- Expanded the BISAYA_PHASE4_DIDACTICS by adding new learning goals, core patterns, speaking prompts, and practical tasks to improve language acquisition.
- Updated the course content generation scripts to incorporate the new lesson structures and ensure alignment with the latest didactic updates.
- Enhanced the logic for generating exercises based on lesson types, introducing additional situational and speaking exercises for advanced lessons.
2026-04-17 15:12:21 +02:00

158 lines
5.4 KiB
JavaScript

#!/usr/bin/env node
/**
* Erstellt den Phase-1-Deutschkurs für Bisaya-Lernende.
*
* Verwendung:
* node backend/scripts/create-german-for-bisaya-course.js [ownerHashedId]
*/
import crypto from 'crypto';
import { Op } from 'sequelize';
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 { GERMAN_FOR_BISAYA_PHASE1_DIDACTICS, GERMAN_FOR_BISAYA_PHASE1_LESSONS } from './german-for-bisaya-phase1.js';
import { GERMAN_FOR_BISAYA_PHASE3_DIDACTICS, GERMAN_FOR_BISAYA_PHASE3_LESSONS } from './german-for-bisaya-phase3-extension.js';
import { GERMAN_FOR_BISAYA_PHASE4_DIDACTICS, GERMAN_FOR_BISAYA_PHASE4_LESSONS } from './german-for-bisaya-phase4-extension.js';
import { GERMAN_FOR_BISAYA_PHASE5_DIDACTICS, GERMAN_FOR_BISAYA_PHASE5_LESSONS } from './german-for-bisaya-phase5-extension.js';
import {
getGermanForBisayaLessonPedagogy,
getGermanForBisayaProgressTargets
} from './german-for-bisaya-phase2-pedagogy.js';
const ALL_GERMAN_FOR_BISAYA_LESSONS = [
...GERMAN_FOR_BISAYA_PHASE1_LESSONS,
...GERMAN_FOR_BISAYA_PHASE3_LESSONS,
...GERMAN_FOR_BISAYA_PHASE4_LESSONS,
...GERMAN_FOR_BISAYA_PHASE5_LESSONS
];
const ALL_GERMAN_FOR_BISAYA_DIDACTICS = {
...GERMAN_FOR_BISAYA_PHASE1_DIDACTICS,
...GERMAN_FOR_BISAYA_PHASE3_DIDACTICS,
...GERMAN_FOR_BISAYA_PHASE4_DIDACTICS,
...GERMAN_FOR_BISAYA_PHASE5_DIDACTICS
};
async function getLanguageId(languageName) {
const [language] = await sequelize.query(
`SELECT id FROM community.vocab_language WHERE name = :name LIMIT 1`,
{
replacements: { name: languageName },
type: sequelize.QueryTypes.SELECT
}
);
if (!language) {
throw new Error(`Sprache "${languageName}" nicht gefunden`);
}
return Number(language.id);
}
async function getOwnerByHashedId(ownerHashedId) {
const user = await User.findOne({ where: { hashedId: ownerHashedId } });
if (!user) {
throw new Error(`Benutzer mit hashedId "${ownerHashedId}" nicht gefunden`);
}
return user;
}
async function findDefaultOwner() {
let user = await User.findOne({ where: { username: 'system' } });
if (!user) {
user = await User.findOne({ where: { username: 'admin' } });
}
if (!user) {
throw new Error('Weder system- noch admin-Benutzer gefunden');
}
return user;
}
async function createGermanForBisayaCourse(ownerHashedId) {
await sequelize.authenticate();
const owner = ownerHashedId
? await getOwnerByHashedId(ownerHashedId)
: await findDefaultOwner();
const germanLanguageId = await getLanguageId('Deutsch');
const bisayaLanguageId = await getLanguageId('Bisaya');
const existingCourse = await VocabCourse.findOne({
where: {
ownerUserId: owner.id,
languageId: germanLanguageId,
nativeLanguageId: bisayaLanguageId,
title: {
[Op.like]: 'Deutsch für Bisaya-Lernende%'
}
}
});
if (existingCourse) {
console.log(`Kurs bereits vorhanden: ${existingCourse.title} (ID: ${existingCourse.id})`);
return existingCourse;
}
const shareCode = crypto.randomBytes(8).toString('hex');
const course = await VocabCourse.create({
ownerUserId: owner.id,
title: 'Deutsch für Bisaya-Lernende - Alltag & Stabilisierung',
description: '15 Wochen Deutsch-Lernpfad aus Sicht von Bisaya-Lernenden mit Alltag, Fehlertraining, Intensivwiederholung und Stabilisierung.',
languageId: germanLanguageId,
nativeLanguageId: bisayaLanguageId,
difficultyLevel: 1,
isPublic: false,
shareCode
});
for (const lessonData of ALL_GERMAN_FOR_BISAYA_LESSONS) {
const didactics = ALL_GERMAN_FOR_BISAYA_DIDACTICS[lessonData.title] || {};
const pedagogy = getGermanForBisayaLessonPedagogy(lessonData.num, lessonData.type, lessonData.title);
const progressTargets = getGermanForBisayaProgressTargets(lessonData, pedagogy);
await VocabCourseLesson.create({
courseId: course.id,
chapterId: null,
lessonNumber: lessonData.num,
title: lessonData.title,
description: lessonData.desc,
weekNumber: lessonData.week,
dayNumber: lessonData.day,
lessonType: lessonData.type,
didacticMode: pedagogy.didacticMode,
phaseLabel: pedagogy.phaseLabel,
blockNumber: pedagogy.blockNumber,
difficultyWeight: pedagogy.difficultyWeight,
newUnitTarget: pedagogy.newUnitTarget,
reviewWeight: pedagogy.reviewWeight,
isIntensiveReview: pedagogy.isIntensiveReview,
culturalNotes: lessonData.cultural,
learningGoals: didactics.learningGoals || null,
corePatterns: didactics.corePatterns || null,
grammarFocus: didactics.grammarFocus || null,
speakingPrompts: didactics.speakingPrompts || null,
practicalTasks: didactics.practicalTasks || null,
targetMinutes: progressTargets.targetMinutes,
targetScorePercent: progressTargets.targetScorePercent,
requiresReview: lessonData.review
});
}
console.log(`Kurs erstellt: ${course.title} (ID: ${course.id})`);
console.log(`Lektionen erstellt: ${ALL_GERMAN_FOR_BISAYA_LESSONS.length}`);
return course;
}
if (import.meta.url === `file://${process.argv[1]}`) {
const ownerHashedId = process.argv[2];
createGermanForBisayaCourse(ownerHashedId)
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
}