All checks were successful
Deploy to production / deploy (push) Successful in 3m12s
- Modified the create-german-for-bisaya-course.js script to allow optional ownerHashedId parameter.
- Implemented a new function to find a default owner ('system' or 'admin') if no ownerHashedId is provided.
- Updated documentation to reflect the change in usage for the script.
154 lines
5.2 KiB
JavaScript
154 lines
5.2 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 } 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);
|
|
|
|
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: lessonData.targetMin,
|
|
targetScorePercent: lessonData.targetScore,
|
|
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);
|
|
});
|
|
}
|