feat(falukant): add age information to lovers in family view
All checks were successful
Deploy to production / deploy (push) Successful in 3m7s

- Updated FalukantService to include age details for partners in relationships.
- Added translations for 'age' in English, German, and Spanish localization files.
- Enhanced FamilyView component to display age information for lovers and candidates, improving user experience.
This commit is contained in:
Torsten Schulz (local)
2026-03-31 11:36:12 +02:00
parent db0e80a559
commit 0d625f1727
16 changed files with 2249 additions and 1 deletions

View File

@@ -0,0 +1,735 @@
#!/usr/bin/env node
/**
* Script zum Erstellen von Übungen für Deutschkurse aus Sicht von Bisaya-Lernenden.
*
* Verwendung:
* node backend/scripts/create-german-for-bisaya-course-content.js
*/
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';
import { GERMAN_FOR_BISAYA_PHASE1_DIDACTICS } from './german-for-bisaya-phase1.js';
import { GERMAN_FOR_BISAYA_PHASE3_DIDACTICS } from './german-for-bisaya-phase3-extension.js';
import { GERMAN_FOR_BISAYA_PHASE4_DIDACTICS } from './german-for-bisaya-phase4-extension.js';
import { GERMAN_FOR_BISAYA_PHASE5_DIDACTICS } from './german-for-bisaya-phase5-extension.js';
function withTypeName(exerciseTypeName, exercise) {
return {
...exercise,
exerciseTypeName
};
}
const GERMAN_DIDACTICS = {
...GERMAN_FOR_BISAYA_PHASE1_DIDACTICS,
...GERMAN_FOR_BISAYA_PHASE3_DIDACTICS,
...GERMAN_FOR_BISAYA_PHASE4_DIDACTICS,
...GERMAN_FOR_BISAYA_PHASE5_DIDACTICS
};
const GENERIC_DISTRACTOR_PATTERNS = Array.from(new Set(
Object.values(GERMAN_DIDACTICS)
.flatMap((entry) => Array.isArray(entry?.corePatterns) ? entry.corePatterns : [])
.map((pattern) => String(pattern || '').trim())
.filter(Boolean)
)).slice(0, 300);
function normalizeText(value) {
return String(value || '')
.trim()
.replace(/\s+/g, ' ');
}
function simpleHash(value) {
return Array.from(String(value || '')).reduce((sum, char) => sum + char.charCodeAt(0), 0);
}
function rotateArray(values, offset) {
if (!Array.isArray(values) || values.length === 0) return [];
const normalizedOffset = ((offset % values.length) + values.length) % values.length;
return values.slice(normalizedOffset).concat(values.slice(0, normalizedOffset));
}
function getLessonDidactics(lesson) {
const staticDidactics = GERMAN_DIDACTICS[lesson.title] || {};
return {
learningGoals: Array.isArray(lesson.learningGoals) ? lesson.learningGoals : (staticDidactics.learningGoals || []),
corePatterns: (Array.isArray(lesson.corePatterns) ? lesson.corePatterns : (staticDidactics.corePatterns || []))
.map((entry) => normalizeText(entry))
.filter(Boolean),
grammarFocus: Array.isArray(lesson.grammarFocus) ? lesson.grammarFocus : (staticDidactics.grammarFocus || []),
speakingPrompts: Array.isArray(lesson.speakingPrompts) ? lesson.speakingPrompts : (staticDidactics.speakingPrompts || []),
practicalTasks: Array.isArray(lesson.practicalTasks) ? lesson.practicalTasks : (staticDidactics.practicalTasks || [])
};
}
function getScenarioPrompt(lesson, didactics) {
const speakingPrompt = Array.isArray(didactics.speakingPrompts) ? didactics.speakingPrompts[0] : null;
const practicalTask = Array.isArray(didactics.practicalTasks) ? didactics.practicalTasks[0] : null;
if (speakingPrompt?.prompt) return speakingPrompt.prompt;
if (practicalTask?.text) return practicalTask.text;
if (lesson.description) return lesson.description;
return `Reagiere passend in einer Alltagssituation aus der Lektion "${lesson.title}".`;
}
function getChoiceQuestion(lesson, didactics) {
const scenarioPrompt = getScenarioPrompt(lesson, didactics);
switch (lesson.lessonType) {
case 'conversation':
return `${scenarioPrompt} Welche deutsche Formulierung passt am besten?`;
case 'grammar':
return `Welche deutsche Struktur passt am besten zum Schwerpunkt "${lesson.title}"?`;
case 'review':
return `Welche Formulierung solltest du aus "${lesson.title}" sicher wiedererkennen?`;
case 'culture':
return `Welche Formulierung passt besonders gut zum kulturellen Schwerpunkt "${lesson.title}"?`;
case 'vocab':
default:
return `Welche Formulierung gehört thematisch zu "${lesson.title}"?`;
}
}
function pickDistractors(pattern, allPatterns, count) {
return allPatterns
.filter((entry) => entry !== pattern)
.slice(0, count);
}
function buildChoiceExercise(lesson, didactics, pattern, allPatterns, variant = 0) {
const distractors = pickDistractors(pattern, allPatterns, 3);
if (distractors.length < 3) return null;
const options = rotateArray([pattern, ...distractors], simpleHash(`${lesson.title}:${pattern}:${variant}`) % 4);
return {
exerciseTypeId: 2,
title: `${lesson.title}: Passende Formulierung wählen`,
instruction: 'Wähle die natürlichste deutsche Formulierung für die Situation oder den Schwerpunkt der Lektion.',
questionData: {
type: 'multiple_choice',
question: getChoiceQuestion(lesson, didactics),
options
},
answerData: {
type: 'multiple_choice',
correctAnswer: options.indexOf(pattern)
},
explanation: `"${pattern}" ist ein zentrales deutsches Muster dieser Lektion.`
};
}
function pickGapTarget(pattern) {
const tokens = normalizeText(pattern)
.split(' ')
.map((token) => token.trim())
.filter(Boolean);
const candidates = tokens
.map((token, index) => ({ token, index, score: token.replace(/[.,?!]/g, '').length }))
.filter(({ token }) => token.replace(/[.,?!]/g, '').length >= 3);
if (candidates.length === 0) return null;
candidates.sort((left, right) => right.score - left.score);
return candidates[0];
}
function buildGapExercise(lessonTitle, pattern) {
const gapTarget = pickGapTarget(pattern);
if (!gapTarget) return null;
const tokens = normalizeText(pattern).split(' ');
tokens[gapTarget.index] = '{gap}';
return {
exerciseTypeId: 1,
title: `${lessonTitle}: Muster vervollständigen`,
instruction: 'Fülle die Lücke mit dem passenden deutschen Ausdruck.',
questionData: {
type: 'gap_fill',
text: tokens.join(' '),
gaps: 1
},
answerData: {
type: 'gap_fill',
answers: [gapTarget.token.replace(/[.,?!]/g, '')]
},
explanation: `Das vollständige deutsche Kernmuster lautet: "${pattern}".`
};
}
function buildSentenceExercise(lessonTitle, pattern) {
const tokens = normalizeText(pattern)
.replace(/[?!]/g, '')
.split(' ')
.filter(Boolean);
if (tokens.length < 2) return null;
return {
exerciseTypeId: 3,
title: `${lessonTitle}: Satz bauen`,
instruction: 'Ordne die Wörter zu einem korrekten deutschen Satz.',
questionData: {
type: 'sentence_building',
question: `Baue das Kernmuster aus der Lektion "${lessonTitle}".`,
tokens
},
answerData: {
correct: [normalizeText(pattern)]
},
explanation: `Dieses Kernmuster gehört zur Lektion "${lessonTitle}".`
};
}
function buildSpeakingExercise(lessonTitle, didactics, fallbackPattern) {
const speakingPrompt = Array.isArray(didactics.speakingPrompts) ? didactics.speakingPrompts[0] : null;
const expectedText = normalizeText(speakingPrompt?.cue || fallbackPattern);
if (!expectedText) return null;
const keywords = expectedText
.toLowerCase()
.replace(/[.,?!]/g, '')
.split(' ')
.filter((token) => token.length >= 3)
.slice(0, 5);
return {
exerciseTypeId: 8,
title: `${lessonTitle}: Frei sprechen`,
instruction: 'Sprich das zentrale deutsche Muster frei nach.',
questionData: {
type: 'speaking_from_memory',
question: speakingPrompt?.prompt || `Sprich ein zentrales Muster aus der Lektion "${lessonTitle}".`,
expectedText,
keywords
},
answerData: {
type: 'speaking_from_memory'
},
explanation: 'Wichtig sind ein flüssiger Abruf und die zentralen deutschen Schlüsselwörter.'
};
}
function buildSituationalExercise(lessonTitle, didactics, fallbackPattern) {
const speakingPrompt = Array.isArray(didactics.speakingPrompts) ? didactics.speakingPrompts[0] : null;
const modelAnswer = normalizeText(speakingPrompt?.cue || fallbackPattern);
if (!modelAnswer) return null;
const keywords = modelAnswer
.toLowerCase()
.replace(/[.,?!]/g, '')
.split(' ')
.filter((token) => token.length >= 3)
.slice(0, 5);
return withTypeName('situational_response', {
title: `${lessonTitle}: Situativ reagieren`,
instruction: 'Antworte kurz und passend auf Deutsch.',
questionData: {
type: 'situational_response',
question: speakingPrompt?.prompt || `Reagiere passend mit einem Ausdruck aus der Lektion "${lessonTitle}".`,
keywords
},
answerData: {
modelAnswer,
keywords
},
explanation: `Das Kernmuster "${modelAnswer}" passt natürlich zu dieser Situation.`
});
}
function buildCultureExercise(lesson, pattern, allPatterns) {
const distractors = pickDistractors(pattern, allPatterns, 3);
if (distractors.length < 3) return null;
const options = rotateArray([pattern, ...distractors], simpleHash(`${lesson.title}:culture`) % 4);
const culturalNote = normalizeText(lesson.culturalNotes || '');
return {
exerciseTypeId: 2,
title: `${lesson.title}: Kulturell einordnen`,
instruction: 'Ordne den Ausdruck dem kulturellen Schwerpunkt der Lektion zu.',
questionData: {
type: 'multiple_choice',
question: culturalNote
? `${culturalNote} Welche Formulierung passt dazu besonders gut?`
: `Welche Formulierung passt besonders gut zum Schwerpunkt "${lesson.title}"?`,
options
},
answerData: {
type: 'multiple_choice',
correctAnswer: options.indexOf(pattern)
},
explanation: `"${pattern}" ist eng mit dem kulturellen Schwerpunkt dieser Lektion verbunden.`
};
}
function generateExercisesFromDidactics(lesson) {
const didactics = getLessonDidactics(lesson);
const corePatterns = didactics.corePatterns;
if (corePatterns.length === 0) return [];
const patternA = corePatterns[0];
const patternB = corePatterns[1] || corePatterns[0];
const pool = Array.from(new Set([...corePatterns, ...GENERIC_DISTRACTOR_PATTERNS]));
if (lesson.lessonType === 'conversation') {
return [
buildChoiceExercise(lesson, didactics, patternA, pool, 0),
buildGapExercise(lesson.title, patternA),
buildSentenceExercise(lesson.title, patternB),
buildSituationalExercise(lesson.title, didactics, patternA),
buildSpeakingExercise(lesson.title, didactics, patternB)
].filter(Boolean);
}
if (lesson.lessonType === 'grammar') {
return [
buildChoiceExercise(lesson, didactics, patternA, pool, 0),
buildChoiceExercise(lesson, didactics, patternB, pool, 1),
buildGapExercise(lesson.title, patternA),
buildSentenceExercise(lesson.title, patternB),
buildSpeakingExercise(lesson.title, didactics, patternA)
].filter(Boolean);
}
if (lesson.lessonType === 'review' || lesson.didacticMode === 'intensive_review') {
return [
buildChoiceExercise(lesson, didactics, patternA, pool, 0),
buildChoiceExercise(lesson, didactics, patternB, pool, 1),
buildGapExercise(lesson.title, patternA),
buildSentenceExercise(lesson.title, patternB),
buildSituationalExercise(lesson.title, didactics, patternA),
buildSpeakingExercise(lesson.title, didactics, patternB)
].filter(Boolean);
}
if (lesson.lessonType === 'culture') {
return [
buildCultureExercise(lesson, patternA, pool),
buildGapExercise(lesson.title, patternA),
buildSpeakingExercise(lesson.title, didactics, patternB)
].filter(Boolean);
}
return [
buildChoiceExercise(lesson, didactics, patternA, pool, 0),
buildChoiceExercise(lesson, didactics, patternB, pool, 1),
buildGapExercise(lesson.title, patternA),
buildSentenceExercise(lesson.title, patternB)
].filter(Boolean);
}
const GERMAN_EXERCISES = {
'Begrüßung & Vorstellung': [
{
exerciseTypeId: 2,
title: 'Vorstellung erkennen',
instruction: 'Wähle die passendste deutsche Vorstellung.',
questionData: {
type: 'multiple_choice',
question: 'Du triffst jemanden zum ersten Mal. Welche Formulierung passt?',
options: ['Hallo, ich heiße Maria.', 'Ich habe Maria.', 'Wo Maria?', 'Nicht Maria.']
},
answerData: {
type: 'multiple_choice',
correctAnswer: 0
},
explanation: '"Hallo, ich heiße Maria." ist eine natürliche deutsche Selbstvorstellung.'
},
{
exerciseTypeId: 1,
title: 'Herkunft ergänzen',
instruction: 'Fülle die Lücke mit dem passenden Ausdruck.',
questionData: {
type: 'gap_fill',
text: 'Ich komme {gap} Cebu.',
gaps: 1
},
answerData: {
type: 'gap_fill',
answers: ['aus']
},
explanation: 'Im Deutschen sagt man "Ich komme aus Cebu."'
},
withTypeName('situational_response', {
title: 'Kurz reagieren bei der Begrüßung',
instruction: 'Antworte kurz und passend auf Deutsch.',
questionData: {
type: 'situational_response',
question: 'Jemand sagt: "Hallo, ich heiße Anna." Wie reagierst du mit deiner eigenen Vorstellung?',
keywords: ['hallo', 'heiße', 'ich']
},
answerData: {
modelAnswer: 'Hallo, ich heiße Maria.',
keywords: ['hallo', 'heiße', 'ich']
},
explanation: 'Die sicherste frühe Reaktion ist eine eigene kurze Vorstellung mit "ich heiße".'
})
],
'der / die / das - Einstieg': [
{
exerciseTypeId: 2,
title: 'Artikel als Chunk erkennen',
instruction: 'Wähle die Form mit dem richtigen Artikel.',
questionData: {
type: 'multiple_choice',
question: 'Welche Form ist als Lern-Chunk richtig?',
options: ['der Tisch', 'die Tisch', 'das Tasche', 'der Kind']
},
answerData: {
type: 'multiple_choice',
correctAnswer: 0
},
explanation: 'Nomen sollen möglichst zusammen mit dem Artikel gelernt werden.'
},
{
exerciseTypeId: 1,
title: 'Artikel ergänzen',
instruction: 'Fülle den passenden Artikel ein.',
questionData: {
type: 'gap_fill',
text: '{gap} Tasche',
gaps: 1
},
answerData: {
type: 'gap_fill',
answers: ['die']
},
explanation: 'Es heißt "die Tasche".'
},
{
exerciseTypeId: 3,
title: 'Chunk richtig bauen',
instruction: 'Ordne die Wörter zu einem korrekten Lern-Chunk.',
questionData: {
type: 'sentence_building',
question: 'Baue den richtigen Chunk für "child".',
tokens: ['das', 'Kind']
},
answerData: {
correct: ['das Kind']
},
explanation: 'Auch sehr kurze Strukturen sollen als vollständiger Chunk gelernt werden.'
}
],
'nicht / kein - Einstieg': [
{
exerciseTypeId: 2,
title: 'Negation unterscheiden',
instruction: 'Wähle die passende deutsche Negation.',
questionData: {
type: 'multiple_choice',
question: 'Welche Formulierung ist richtig?',
options: ['Ich habe kein Geld.', 'Ich habe nicht Geld.', 'Ich bin kein müde.', 'Ich kein habe Geld.']
},
answerData: {
type: 'multiple_choice',
correctAnswer: 0
},
explanation: '"Kein" steht hier vor dem Nomen, deshalb ist "Ich habe kein Geld." richtig.'
},
{
exerciseTypeId: 2,
title: 'Adjektiv negieren',
instruction: 'Wähle die richtige Form für eine Aussage mit Adjektiv.',
questionData: {
type: 'multiple_choice',
question: 'Wie sagst du korrekt: "Ich bin nicht müde"?',
options: ['Ich bin nicht müde.', 'Ich bin kein müde.', 'Ich nicht bin müde.', 'Ich bin müde kein.']
},
answerData: {
type: 'multiple_choice',
correctAnswer: 0
},
explanation: 'Adjektive und Aussagen werden im Deutschen oft mit "nicht" negiert.'
},
{
exerciseTypeId: 1,
title: 'Kein ergänzen',
instruction: 'Ergänze die passende Negation.',
questionData: {
type: 'gap_fill',
text: 'Ich habe {gap} Zeit.',
gaps: 1
},
answerData: {
type: 'gap_fill',
answers: ['keine']
},
explanation: 'Bei "Zeit" braucht man hier "keine".'
}
],
'wo / wohin - Kontrast': [
{
exerciseTypeId: 2,
title: 'Ort oder Richtung?',
instruction: 'Wähle die Frage nach einem Ziel.',
questionData: {
type: 'multiple_choice',
question: 'Welche Frage passt, wenn du nach dem Ziel fragst?',
options: ['Wohin gehst du?', 'Wo gehst du?', 'Wie gehst du?', 'Wann gehst du?']
},
answerData: {
type: 'multiple_choice',
correctAnswer: 0
},
explanation: '"Wohin" fragt nach einer Richtung oder einem Ziel.'
},
{
exerciseTypeId: 1,
title: 'Fragewort ergänzen',
instruction: 'Setze das passende Fragewort ein.',
questionData: {
type: 'gap_fill',
text: '{gap} bist du? Ich bin zu Hause.',
gaps: 1
},
answerData: {
type: 'gap_fill',
answers: ['Wo']
},
explanation: 'Bei einem Ort fragt man im Deutschen mit "Wo".'
}
],
'du / Sie - Einstieg': [
{
exerciseTypeId: 2,
title: 'Höfliche Anrede erkennen',
instruction: 'Wähle die höfliche deutsche Form.',
questionData: {
type: 'multiple_choice',
question: 'Du sprichst eine fremde erwachsene Person höflich an. Welche Frage passt?',
options: ['Wie heißen Sie?', 'Wie heißt du?', 'Wo bist du?', 'Wie bist du?']
},
answerData: {
type: 'multiple_choice',
correctAnswer: 0
},
explanation: '"Sie" markiert im Deutschen die höfliche Anrede.'
},
{
exerciseTypeId: 1,
title: 'Anredeform ergänzen',
instruction: 'Fülle die passende Anredeform ein.',
questionData: {
type: 'gap_fill',
text: 'Können {gap} mir helfen?',
gaps: 1
},
answerData: {
type: 'gap_fill',
answers: ['Sie']
},
explanation: 'In einer höflichen Bitte heißt es "Können Sie mir helfen?".'
}
],
'Perfekt - Einstieg': [
{
exerciseTypeId: 2,
title: 'Perfektform erkennen',
instruction: 'Wähle die passende deutsche Vergangenheitsform.',
questionData: {
type: 'multiple_choice',
question: 'Welche Form ist ein korrektes frühes Perfekt?',
options: ['Ich habe gearbeitet.', 'Ich habe arbeiten.', 'Ich bin gearbeitet.', 'Ich arbeitete habe.']
},
answerData: {
type: 'multiple_choice',
correctAnswer: 0
},
explanation: 'Viele frühe Alltagsverben bilden das Perfekt mit "haben" + Partizip II.'
},
{
exerciseTypeId: 1,
title: 'Hilfsverb ergänzen',
instruction: 'Ergänze das passende Hilfsverb.',
questionData: {
type: 'gap_fill',
text: 'Ich {gap} gestern gearbeitet.',
gaps: 1
},
answerData: {
type: 'gap_fill',
answers: ['habe']
},
explanation: 'Im Perfekt braucht man hier das Hilfsverb "habe".'
}
]
};
async function resolveExerciseTypeId(exercise) {
if (exercise.exerciseTypeId) {
return exercise.exerciseTypeId;
}
const trimmedName =
exercise.exerciseTypeName != null && exercise.exerciseTypeName !== ''
? String(exercise.exerciseTypeName).trim()
: '';
if (!trimmedName) {
throw new Error(`Kein exerciseTypeId oder exerciseTypeName für Übung "${exercise.title || 'unbenannt'}" definiert`);
}
const [type] = await sequelize.query(
`SELECT id FROM community.vocab_grammar_exercise_type WHERE name = :name LIMIT 1`,
{
replacements: { name: trimmedName },
type: sequelize.QueryTypes.SELECT
}
);
if (!type) {
throw new Error(`Übungstyp "${trimmedName}" nicht gefunden`);
}
return Number(type.id);
}
async function findOrCreateSystemUser() {
let 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');
}
return systemUser;
}
function getExercisesForLesson(lesson) {
if (GERMAN_EXERCISES[lesson.title]) {
return GERMAN_EXERCISES[lesson.title];
}
for (const [key, exercises] of Object.entries(GERMAN_EXERCISES)) {
if (lesson.title.includes(key) || key.includes(lesson.title)) {
return exercises;
}
}
return generateExercisesFromDidactics(lesson);
}
async function createGermanForBisayaCourseContent() {
await sequelize.authenticate();
console.log('Datenbankverbindung erfolgreich hergestellt.\n');
const systemUser = await findOrCreateSystemUser();
console.log(`Verwende System-Benutzer: ${systemUser.username} (ID: ${systemUser.id})\n`);
const [germanLanguage] = await sequelize.query(
`SELECT id FROM community.vocab_language WHERE name = 'Deutsch' LIMIT 1`,
{
type: sequelize.QueryTypes.SELECT
}
);
const [bisayaLanguage] = await sequelize.query(
`SELECT id FROM community.vocab_language WHERE name = 'Bisaya' LIMIT 1`,
{
type: sequelize.QueryTypes.SELECT
}
);
if (!germanLanguage || !bisayaLanguage) {
throw new Error('Deutsch oder Bisaya als Sprache nicht gefunden');
}
const courses = await sequelize.query(
`SELECT id, title, owner_user_id AS "ownerUserId"
FROM community.vocab_course
WHERE language_id = :languageId
AND native_language_id = :nativeLanguageId
AND title LIKE 'Deutsch für Bisaya-Lernende%'`,
{
replacements: {
languageId: germanLanguage.id,
nativeLanguageId: bisayaLanguage.id
},
type: sequelize.QueryTypes.SELECT
}
);
console.log(`Gefunden: ${courses.length} Deutsch-für-Bisaya-Kurse\n`);
let totalExercisesAdded = 0;
let totalLessonsProcessed = 0;
const replaceLessons = new Set(Object.keys(GERMAN_EXERCISES));
for (const course of courses) {
console.log(`📚 Kurs: ${course.title} (ID: ${course.id})`);
const lessons = await VocabCourseLesson.findAll({
where: { courseId: course.id },
order: [['lessonNumber', 'ASC']]
});
console.log(` ${lessons.length} Lektionen gefunden\n`);
for (const lesson of lessons) {
const exercises = getExercisesForLesson(lesson);
if (exercises.length === 0) {
console.log(` ⚠️ Lektion ${lesson.lessonNumber}: "${lesson.title}" - keine Übungen definiert`);
continue;
}
const existingCount = await VocabGrammarExercise.count({ where: { lessonId: lesson.id } });
const replaceExisting = replaceLessons.has(lesson.title);
if (existingCount > 0 && !replaceExisting) {
console.log(` ⏭️ Lektion ${lesson.lessonNumber}: "${lesson.title}" - bereits ${existingCount} Übung(en) vorhanden`);
continue;
}
if (replaceExisting && existingCount > 0) {
const deleted = await VocabGrammarExercise.destroy({ where: { lessonId: lesson.id } });
console.log(` 🗑️ Lektion ${lesson.lessonNumber}: "${lesson.title}" - ${deleted} bestehende Übung(en) entfernt`);
}
let exerciseNumber = 1;
for (const exerciseData of exercises) {
const exerciseTypeId = await resolveExerciseTypeId(exerciseData);
await VocabGrammarExercise.create({
lessonId: lesson.id,
exerciseTypeId,
exerciseNumber: exerciseNumber++,
title: exerciseData.title,
instruction: exerciseData.instruction,
questionData: JSON.stringify(exerciseData.questionData),
answerData: JSON.stringify(exerciseData.answerData),
explanation: exerciseData.explanation,
createdByUserId: course.ownerUserId || systemUser.id
});
totalExercisesAdded++;
}
console.log(` ✅ Lektion ${lesson.lessonNumber}: "${lesson.title}" - ${exercises.length} Übung(en) erstellt`);
totalLessonsProcessed++;
}
console.log('');
}
console.log('\n🎉 Zusammenfassung:');
console.log(` ${totalLessonsProcessed} Lektionen bearbeitet`);
console.log(` ${totalExercisesAdded} Übungen erstellt`);
}
createGermanForBisayaCourseContent()
.then(() => {
sequelize.close();
process.exit(0);
})
.catch((error) => {
console.error('❌ Fehler:', error);
sequelize.close();
process.exit(1);
});

View File

@@ -0,0 +1,145 @@
#!/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 createGermanForBisayaCourse(ownerHashedId) {
await sequelize.authenticate();
const owner = await getOwnerByHashedId(ownerHashedId);
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];
if (!ownerHashedId) {
console.error('Verwendung: node backend/scripts/create-german-for-bisaya-course.js <ownerHashedId>');
process.exit(1);
}
createGermanForBisayaCourse(ownerHashedId)
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
}

View File

@@ -0,0 +1,84 @@
#!/usr/bin/env node
import { sequelize } from '../utils/sequelize.js';
import VocabCourse from '../models/community/vocab_course.js';
import VocabCourseLesson from '../models/community/vocab_course_lesson.js';
import { GERMAN_FOR_BISAYA_PHASE3_DIDACTICS, GERMAN_FOR_BISAYA_PHASE3_LESSONS } from './german-for-bisaya-phase3-extension.js';
import { getGermanForBisayaLessonPedagogy } from './german-for-bisaya-phase2-pedagogy.js';
async function getLanguageId(name) {
const [language] = await sequelize.query(
`SELECT id FROM community.vocab_language WHERE name = :name LIMIT 1`,
{ replacements: { name }, type: sequelize.QueryTypes.SELECT }
);
if (!language) throw new Error(`Sprache "${name}" nicht gefunden`);
return Number(language.id);
}
async function extendGermanForBisayaPhase3() {
await sequelize.authenticate();
const germanLanguageId = await getLanguageId('Deutsch');
const bisayaLanguageId = await getLanguageId('Bisaya');
const courses = await VocabCourse.findAll({
where: {
languageId: germanLanguageId,
nativeLanguageId: bisayaLanguageId
}
});
for (const course of courses) {
if (!String(course.title || '').startsWith('Deutsch für Bisaya-Lernende')) continue;
for (const lessonData of GERMAN_FOR_BISAYA_PHASE3_LESSONS) {
const existing = await VocabCourseLesson.findOne({
where: { courseId: course.id, lessonNumber: lessonData.num }
});
if (existing) continue;
const didactics = GERMAN_FOR_BISAYA_PHASE3_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
});
}
course.title = 'Deutsch für Bisaya-Lernende - Alltagspfad';
course.description = '9 Wochen Deutsch-Lernpfad aus Sicht von Bisaya-Lernenden mit Schnellstart, Alltag und typischen Fehlerfeldern.';
await course.save();
console.log(`Phase 3 erweitert: ${course.title} (ID: ${course.id})`);
}
}
if (import.meta.url === `file://${process.argv[1]}`) {
extendGermanForBisayaPhase3()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
}

View File

@@ -0,0 +1,84 @@
#!/usr/bin/env node
import { sequelize } from '../utils/sequelize.js';
import VocabCourse from '../models/community/vocab_course.js';
import VocabCourseLesson from '../models/community/vocab_course_lesson.js';
import { GERMAN_FOR_BISAYA_PHASE4_DIDACTICS, GERMAN_FOR_BISAYA_PHASE4_LESSONS } from './german-for-bisaya-phase4-extension.js';
import { getGermanForBisayaLessonPedagogy } from './german-for-bisaya-phase2-pedagogy.js';
async function getLanguageId(name) {
const [language] = await sequelize.query(
`SELECT id FROM community.vocab_language WHERE name = :name LIMIT 1`,
{ replacements: { name }, type: sequelize.QueryTypes.SELECT }
);
if (!language) throw new Error(`Sprache "${name}" nicht gefunden`);
return Number(language.id);
}
async function extendGermanForBisayaPhase4() {
await sequelize.authenticate();
const germanLanguageId = await getLanguageId('Deutsch');
const bisayaLanguageId = await getLanguageId('Bisaya');
const courses = await VocabCourse.findAll({
where: {
languageId: germanLanguageId,
nativeLanguageId: bisayaLanguageId
}
});
for (const course of courses) {
if (!String(course.title || '').startsWith('Deutsch für Bisaya-Lernende')) continue;
for (const lessonData of GERMAN_FOR_BISAYA_PHASE4_LESSONS) {
const existing = await VocabCourseLesson.findOne({
where: { courseId: course.id, lessonNumber: lessonData.num }
});
if (existing) continue;
const didactics = GERMAN_FOR_BISAYA_PHASE4_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
});
}
course.title = 'Deutsch für Bisaya-Lernende - Alltagspfad';
course.description = '12 Wochen Deutsch-Lernpfad aus Sicht von Bisaya-Lernenden mit Schnellstart, Alltag und gezieltem Fehlertraining.';
await course.save();
console.log(`Phase 4 erweitert: ${course.title} (ID: ${course.id})`);
}
}
if (import.meta.url === `file://${process.argv[1]}`) {
extendGermanForBisayaPhase4()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
}

View File

@@ -0,0 +1,84 @@
#!/usr/bin/env node
import { sequelize } from '../utils/sequelize.js';
import VocabCourse from '../models/community/vocab_course.js';
import VocabCourseLesson from '../models/community/vocab_course_lesson.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';
async function getLanguageId(name) {
const [language] = await sequelize.query(
`SELECT id FROM community.vocab_language WHERE name = :name LIMIT 1`,
{ replacements: { name }, type: sequelize.QueryTypes.SELECT }
);
if (!language) throw new Error(`Sprache "${name}" nicht gefunden`);
return Number(language.id);
}
async function extendGermanForBisayaPhase5() {
await sequelize.authenticate();
const germanLanguageId = await getLanguageId('Deutsch');
const bisayaLanguageId = await getLanguageId('Bisaya');
const courses = await VocabCourse.findAll({
where: {
languageId: germanLanguageId,
nativeLanguageId: bisayaLanguageId
}
});
for (const course of courses) {
if (!String(course.title || '').startsWith('Deutsch für Bisaya-Lernende')) continue;
for (const lessonData of GERMAN_FOR_BISAYA_PHASE5_LESSONS) {
const existing = await VocabCourseLesson.findOne({
where: { courseId: course.id, lessonNumber: lessonData.num }
});
if (existing) continue;
const didactics = GERMAN_FOR_BISAYA_PHASE5_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
});
}
course.title = 'Deutsch für Bisaya-Lernende - Alltag & Stabilisierung';
course.description = '15 Wochen Deutsch-Lernpfad aus Sicht von Bisaya-Lernenden mit Alltag, Fehlertraining, Intensivwiederholung und Stabilisierung.';
await course.save();
console.log(`Phase 5 erweitert: ${course.title} (ID: ${course.id})`);
}
}
if (import.meta.url === `file://${process.argv[1]}`) {
extendGermanForBisayaPhase5()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
}

View File

@@ -0,0 +1,345 @@
export const GERMAN_FOR_BISAYA_PHASE1_LESSONS = [
{ week: 1, day: 1, num: 1, type: 'conversation', title: 'Begrüßung & Vorstellung', desc: 'Name, Herkunft und erste Standardreaktionen', targetMin: 18, targetScore: 80, review: false, cultural: 'Im Deutschen sind kurze klare Vorstellungsformeln sehr wichtig.' },
{ week: 1, day: 1, num: 2, type: 'vocab', title: 'Name, Land, Sprache', desc: 'Die wichtigsten Wörter für Identität und Herkunft', targetMin: 18, targetScore: 85, review: true, cultural: null },
{ week: 1, day: 2, num: 3, type: 'grammar', title: 'Ich bin / ich heiße / ich komme', desc: 'Frühe Kontraste zwischen sein, heißen und kommen', targetMin: 22, targetScore: 78, review: true, cultural: null },
{ week: 1, day: 2, num: 4, type: 'conversation', title: 'Familie vorstellen', desc: 'Über Mutter, Vater, Kinder und Partner sprechen', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 1, day: 3, num: 5, type: 'vocab', title: 'Familie & Zuhause', desc: 'Familienrollen und zentrale Wörter für Zuhause', targetMin: 18, targetScore: 85, review: true, cultural: null },
{ week: 1, day: 3, num: 6, type: 'conversation', title: 'Im Haus fragen und antworten', desc: 'Wo ist was? Wer ist da? Was machst du?', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 1, day: 4, num: 7, type: 'grammar', title: 'der / die / das - Einstieg', desc: 'Erster Einstieg in Artikel und Genus', targetMin: 22, targetScore: 76, review: true, cultural: 'Artikel müssen früh als Wortbausteine mitgelernt werden.' },
{ week: 1, day: 4, num: 8, type: 'conversation', title: 'Bitte, danke, Entschuldigung', desc: 'Die wichtigsten Höflichkeitsmuster im Alltag', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 1, day: 5, num: 9, type: 'review', title: 'Woche 1 - Intensivwiederholung', desc: 'Abruf von Begrüßung, Familie, Zuhause und Höflichkeit', targetMin: 28, targetScore: 82, review: false, cultural: null },
{ week: 1, day: 5, num: 10, type: 'vocab', title: 'Woche 1 - Checkpoint', desc: 'Diagnose der wichtigsten Schnellstartmuster', targetMin: 16, targetScore: 84, review: true, cultural: null },
{ week: 2, day: 1, num: 11, type: 'conversation', title: 'Essen & Trinken im Alltag', desc: 'Hunger, Durst, Wünsche und Reaktionen', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 2, day: 1, num: 12, type: 'vocab', title: 'Essen, Getränke, Mengen', desc: 'Wichtige Wörter für Mahlzeiten und Getränke', targetMin: 18, targetScore: 85, review: true, cultural: null },
{ week: 2, day: 2, num: 13, type: 'grammar', title: 'ich habe / ich möchte / ich brauche', desc: 'Frühe Kontraste für Besitz, Wunsch und Bedarf', targetMin: 22, targetScore: 78, review: true, cultural: null },
{ week: 2, day: 2, num: 14, type: 'conversation', title: 'Im Café oder Laden', desc: 'Etwas bestellen und höflich reagieren', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 2, day: 3, num: 15, type: 'vocab', title: 'Zahlen, Geld, Preise', desc: 'Zahlen und Preisfragen für den Alltag', targetMin: 20, targetScore: 85, review: true, cultural: null },
{ week: 2, day: 3, num: 16, type: 'conversation', title: 'Einkaufen & Bezahlen', desc: 'Nach Preis, Menge und Bezahlung fragen', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 2, day: 4, num: 17, type: 'grammar', title: 'nicht / kein - Einstieg', desc: 'Negation in kurzen alltagsnahen Sätzen', targetMin: 22, targetScore: 76, review: true, cultural: null },
{ week: 2, day: 4, num: 18, type: 'conversation', title: 'Bedürfnisse & Probleme', desc: 'Ich bin müde, krank, hungrig, beschäftigt', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 2, day: 5, num: 19, type: 'review', title: 'Woche 2 - Intensivwiederholung', desc: 'Mischblock zu Essen, Preisen, Negation und Bedürfnissen', targetMin: 28, targetScore: 82, review: false, cultural: null },
{ week: 2, day: 5, num: 20, type: 'vocab', title: 'Woche 2 - Checkpoint', desc: 'Schnelldiagnose zu den Alltagsmustern der zweiten Woche', targetMin: 16, targetScore: 84, review: true, cultural: null },
{ week: 3, day: 1, num: 21, type: 'conversation', title: 'Wege & Orientierung', desc: 'Nach Orten fragen und kurze Richtungen verstehen', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 3, day: 1, num: 22, type: 'vocab', title: 'Orte, Verkehr, Richtungen', desc: 'Bahnhof, Straße, links, rechts und mehr', targetMin: 18, targetScore: 85, review: true, cultural: null },
{ week: 3, day: 2, num: 23, type: 'grammar', title: 'wo / wohin - Kontrast', desc: 'Ort und Richtung sauber unterscheiden', targetMin: 22, targetScore: 78, review: true, cultural: null },
{ week: 3, day: 2, num: 24, type: 'conversation', title: 'Mit Bus und Bahn', desc: 'Fahrkarten, Ziel und einfache Wege klären', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 3, day: 3, num: 25, type: 'vocab', title: 'Zeit, Uhrzeit, Termine', desc: 'Heute, morgen, Uhrzeiten und Verabredungen', targetMin: 18, targetScore: 85, review: true, cultural: null },
{ week: 3, day: 3, num: 26, type: 'conversation', title: 'Treffen und Planen', desc: 'Zeit ausmachen und Pläne besprechen', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 3, day: 4, num: 27, type: 'grammar', title: 'Verbzweitstellung - Einstieg', desc: 'Ich gehe heute..., Heute gehe ich...', targetMin: 22, targetScore: 76, review: true, cultural: 'Deutsche Satzstellung muss früh als Muster trainiert werden.' },
{ week: 3, day: 4, num: 28, type: 'conversation', title: 'Tagesablauf erzählen', desc: 'Morgens, mittags, abends und einfache Routinen', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 3, day: 5, num: 29, type: 'review', title: 'Woche 3 - Intensivwiederholung', desc: 'Orte, Zeiten, Wege und Satzstellung bündeln', targetMin: 28, targetScore: 82, review: false, cultural: null },
{ week: 3, day: 5, num: 30, type: 'vocab', title: 'Woche 3 - Checkpoint', desc: 'Diagnose zu Ort, Richtung, Zeit und Planen', targetMin: 16, targetScore: 84, review: true, cultural: null },
{ week: 4, day: 1, num: 31, type: 'conversation', title: 'Arzt & Beschwerden', desc: 'Schmerzen, Termin und Hilfe beschreiben', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 4, day: 1, num: 32, type: 'vocab', title: 'Körper, Symptome, Gesundheit', desc: 'Wichtige Wörter für Arzt und Krankheit', targetMin: 18, targetScore: 85, review: true, cultural: null },
{ week: 4, day: 2, num: 33, type: 'grammar', title: 'ich bin / ich habe - Gesundheit', desc: 'Ich bin krank vs. ich habe Schmerzen', targetMin: 22, targetScore: 78, review: true, cultural: null },
{ week: 4, day: 2, num: 34, type: 'conversation', title: 'Hilfe holen & erklären', desc: 'Probleme beschreiben und um Hilfe bitten', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 4, day: 3, num: 35, type: 'vocab', title: 'Kinder, Schule, Alltag', desc: 'Kind, Schule, Tasche, Hausaufgaben und Routine', targetMin: 18, targetScore: 85, review: true, cultural: null },
{ week: 4, day: 3, num: 36, type: 'conversation', title: 'Mit Kindern sprechen', desc: 'Einfache Fragen, Fürsorge und Alltag mit Kindern', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 4, day: 4, num: 37, type: 'grammar', title: 'du / Sie - Einstieg', desc: 'Informell und höflich unterscheiden', targetMin: 20, targetScore: 76, review: true, cultural: 'Im Deutschen ist die Anrede sozial stark markiert.' },
{ week: 4, day: 4, num: 38, type: 'conversation', title: 'Höflich fragen & reagieren', desc: 'Können Sie..., ich hätte gern..., danke', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 4, day: 5, num: 39, type: 'review', title: 'Woche 4 - Intensivwiederholung', desc: 'Gesundheit, Kinder, Hilfe und Höflichkeit bündeln', targetMin: 28, targetScore: 82, review: false, cultural: null },
{ week: 4, day: 5, num: 40, type: 'vocab', title: 'Woche 4 - Checkpoint', desc: 'Diagnose zu Gesundheit, Schule und Anrede', targetMin: 16, targetScore: 84, review: true, cultural: null },
{ week: 5, day: 1, num: 41, type: 'conversation', title: 'Formulare & Termine', desc: 'Name, Adresse, Termin und einfache Behördenmuster', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 5, day: 1, num: 42, type: 'vocab', title: 'Dokumente & Angaben', desc: 'Adresse, Formular, Nummer, Termin und Unterschrift', targetMin: 18, targetScore: 85, review: true, cultural: null },
{ week: 5, day: 2, num: 43, type: 'grammar', title: 'der / die / das - Alltagskontraste', desc: 'Artikeltraining mit typischen Alltagsnomen', targetMin: 22, targetScore: 78, review: true, cultural: null },
{ week: 5, day: 2, num: 44, type: 'conversation', title: 'Arbeit & Aufgaben', desc: 'Über Arbeit, To-dos und Verpflichtungen sprechen', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 5, day: 3, num: 45, type: 'vocab', title: 'Haushalt & Ordnung', desc: 'Zimmer, Dinge, aufräumen, putzen, reparieren', targetMin: 18, targetScore: 85, review: true, cultural: null },
{ week: 5, day: 3, num: 46, type: 'conversation', title: 'Nachbarschaft & Besuch', desc: 'Besuche ankündigen, Hilfe anbieten und reagieren', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 5, day: 4, num: 47, type: 'grammar', title: 'Akkusativ im Alltag - Einstieg', desc: 'Ich sehe den..., ich brauche die..., ich kaufe das...', targetMin: 22, targetScore: 76, review: true, cultural: null },
{ week: 5, day: 4, num: 48, type: 'conversation', title: 'Bitten, verschieben, ablehnen', desc: 'Höflich zusagen, absagen oder später vorschlagen', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 5, day: 5, num: 49, type: 'review', title: 'Woche 5 - Intensivwiederholung', desc: 'Dokumente, Arbeit, Besuch und Kasus bündeln', targetMin: 28, targetScore: 82, review: false, cultural: null },
{ week: 5, day: 5, num: 50, type: 'vocab', title: 'Woche 5 - Checkpoint', desc: 'Diagnose zu Formularen, Arbeit und Bitten', targetMin: 16, targetScore: 84, review: true, cultural: null },
{ week: 6, day: 1, num: 51, type: 'conversation', title: 'Freies Gespräch - Alltag', desc: 'Mehrere bekannte Alltagsthemen freier verbinden', targetMin: 22, targetScore: 78, review: false, cultural: null },
{ week: 6, day: 1, num: 52, type: 'vocab', title: 'Mischtraining - Kernwortschatz', desc: 'Wichtige Wörter aus den ersten fünf Wochen gemischt', targetMin: 20, targetScore: 85, review: true, cultural: null },
{ week: 6, day: 2, num: 53, type: 'grammar', title: 'Fehlertraining - Satzstellung & Negation', desc: 'Typische Hauptsatzfehler gezielt korrigieren', targetMin: 22, targetScore: 78, review: true, cultural: null },
{ week: 6, day: 2, num: 54, type: 'conversation', title: 'Konflikte & Missverständnisse', desc: 'Nachfragen, korrigieren, höflich klären', targetMin: 20, targetScore: 80, review: false, cultural: null },
{ week: 6, day: 3, num: 55, type: 'review', title: 'Spiralwiederholung - Wochen 1 bis 3', desc: 'Frühe Muster wieder in neuen Situationen abrufen', targetMin: 28, targetScore: 82, review: false, cultural: null },
{ week: 6, day: 3, num: 56, type: 'review', title: 'Spiralwiederholung - Wochen 4 bis 5', desc: 'Spätere Alltagsfelder mit Fehlerfokus verdichten', targetMin: 28, targetScore: 82, review: false, cultural: null },
{ week: 6, day: 4, num: 57, type: 'conversation', title: 'Freies Sprechen - Familie, Alltag, Hilfe', desc: 'Längere Minidialoge mit weniger Stütze', targetMin: 24, targetScore: 78, review: false, cultural: null },
{ week: 6, day: 4, num: 58, type: 'vocab', title: 'Abschlusstest - Schnellstart', desc: 'Wortschatztest über den 6-Wochen-Schnellstart', targetMin: 18, targetScore: 84, review: true, cultural: null },
{ week: 6, day: 5, num: 59, type: 'review', title: 'Abschlussprüfung - Schnellstart', desc: 'Gemischte Abschlussprüfung über Muster, Fehlerfelder und Alltag', targetMin: 30, targetScore: 84, review: false, cultural: 'Im Vordergrund steht kommunikative Alltagssicherheit, nicht perfekte Grammatik.' },
{ week: 6, day: 5, num: 60, type: 'culture', title: 'Kulturelle Orientierung in Deutschland', desc: 'Anrede, Direktheit, Termine und Alltagserwartungen', targetMin: 16, targetScore: 0, review: false, cultural: 'Direktheit, Pünktlichkeit und klare Formulierungen wirken im Deutschen oft normal und nicht unhöflich.' }
];
function makeDidactics({ goals = [], patterns = [], grammar = [], speaking = [], tasks = [] }) {
return {
learningGoals: goals,
corePatterns: patterns,
grammarFocus: grammar,
speakingPrompts: speaking,
practicalTasks: tasks
};
}
export const GERMAN_FOR_BISAYA_PHASE1_DIDACTICS = {
'Begrüßung & Vorstellung': makeDidactics({
goals: [
'Sich kurz auf Deutsch vorstellen.',
'Name, Herkunft und Sprache sagen.',
'Auf eine Begrüßung sicher reagieren.'
],
patterns: ['Hallo, ich heiße ...', 'Ich komme aus ...', 'Ich spreche Bisaya.', 'Freut mich.'],
speaking: [
{ title: 'Mini-Vorstellung', prompt: 'Stell dich mit Name und Herkunft kurz vor.', cue: 'Hallo, ich heiße Ana. Ich komme aus Cebu.' }
]
}),
'Name, Land, Sprache': makeDidactics({
goals: ['Wichtige Identitätswörter verstehen.', 'Land und Sprache korrekt nennen.'],
patterns: ['der Name', 'das Land', 'die Sprache', 'Ich spreche Deutsch.']
}),
'Ich bin / ich heiße / ich komme': makeDidactics({
goals: ['Frühe Standardverben unterscheiden.', 'Typische Mischfehler vermeiden.'],
patterns: ['Ich bin müde.', 'Ich heiße Maria.', 'Ich komme aus Bohol.'],
grammar: [
{ title: 'Standardkontraste', text: 'Deutsch nutzt hier drei unterschiedliche Verben mit klaren Funktionen.', example: 'Ich bin ..., ich heiße ..., ich komme aus ...' }
]
}),
'Familie vorstellen': makeDidactics({
goals: ['Über enge Familie sprechen.', 'Einfache Vorstellungsdialoge führen.'],
patterns: ['Das ist meine Mutter.', 'Das ist mein Vater.', 'Ich habe zwei Kinder.']
}),
'Familie & Zuhause': makeDidactics({
goals: ['Zentrale Familien- und Hauswörter lernen.'],
patterns: ['die Mutter', 'der Vater', 'das Kind', 'das Haus']
}),
'Im Haus fragen und antworten': makeDidactics({
goals: ['Im Haus nach Personen und Dingen fragen.'],
patterns: ['Wo ist ...?', 'Er ist in der Küche.', 'Sie ist zu Hause.']
}),
'der / die / das - Einstieg': makeDidactics({
goals: ['Artikel nicht isoliert, sondern als Chunk lernen.'],
patterns: ['der Tisch', 'die Tasche', 'das Kind'],
grammar: [
{ title: 'Artikel als Teil des Wortes', text: 'Lerne Nomen im Deutschen möglichst mit Artikel zusammen.', example: 'nicht nur Tisch, sondern der Tisch' }
]
}),
'Bitte, danke, Entschuldigung': makeDidactics({
goals: ['Höfliche Standardreaktionen beherrschen.'],
patterns: ['Bitte.', 'Danke.', 'Entschuldigung.', 'Kein Problem.']
}),
'Woche 1 - Intensivwiederholung': makeDidactics({
goals: ['Begrüßung, Vorstellung und Familie aktiv wiederholen.'],
patterns: ['Hallo, ich heiße ...', 'Das ist meine Mutter.', 'Danke.', 'Entschuldigung.']
}),
'Woche 1 - Checkpoint': makeDidactics({
goals: ['Schnellstartmuster der ersten Woche prüfen.'],
patterns: ['ich heiße', 'ich komme aus', 'meine Familie', 'bitte']
}),
'Essen & Trinken im Alltag': makeDidactics({
goals: ['Essen und Trinken im Alltag ansprechen.'],
patterns: ['Ich habe Hunger.', 'Ich habe Durst.', 'Ich möchte Wasser.', 'Möchtest du essen?']
}),
'Essen, Getränke, Mengen': makeDidactics({
goals: ['Nahrungs- und Mengenwörter lernen.'],
patterns: ['das Wasser', 'der Reis', 'das Brot', 'eine Flasche']
}),
'ich habe / ich möchte / ich brauche': makeDidactics({
goals: ['Besitz, Wunsch und Bedarf kontrastieren.'],
patterns: ['Ich habe Zeit.', 'Ich möchte Kaffee.', 'Ich brauche Hilfe.'],
grammar: [
{ title: 'Alltagsverben', text: 'Diese drei Verben tragen sehr viel Kommunikation im frühen Deutschkurs.', example: 'Ich habe ..., ich möchte ..., ich brauche ...' }
]
}),
'Im Café oder Laden': makeDidactics({
goals: ['Bestellen und reagieren lernen.'],
patterns: ['Ich hätte gern ...', 'Noch etwas?', 'Das macht ... Euro.']
}),
'Zahlen, Geld, Preise': makeDidactics({
goals: ['Preis- und Zahlmuster trainieren.'],
patterns: ['Wie viel kostet das?', 'Das kostet ... Euro.', 'zu teuer', 'billiger']
}),
'Einkaufen & Bezahlen': makeDidactics({
goals: ['Im Laden sprachlich handeln.'],
patterns: ['Ich nehme das.', 'Kann ich mit Karte zahlen?', 'Haben Sie es billiger?']
}),
'nicht / kein - Einstieg': makeDidactics({
goals: ['Negation sauber unterscheiden.'],
patterns: ['Ich habe kein Geld.', 'Ich bin nicht müde.'],
grammar: [
{ title: 'Negation im Alltag', text: 'Kein negiert meist Nomen, nicht negiert anderes.', example: 'kein Wasser / nicht hier' }
]
}),
'Bedürfnisse & Probleme': makeDidactics({
goals: ['Bedürfnisse und kleine Probleme ausdrücken.'],
patterns: ['Ich bin müde.', 'Ich bin krank.', 'Ich brauche Ruhe.', 'Ich habe ein Problem.']
}),
'Woche 2 - Intensivwiederholung': makeDidactics({
goals: ['Essen, Bedürfnisse und Negation wiederholen.'],
patterns: ['Ich habe Hunger.', 'Ich möchte Wasser.', 'Ich habe kein Geld.', 'Ich brauche Hilfe.']
}),
'Woche 2 - Checkpoint': makeDidactics({
goals: ['Alltagsmuster der zweiten Woche prüfen.'],
patterns: ['ich möchte', 'ich brauche', 'kein', 'Preis']
}),
'Wege & Orientierung': makeDidactics({
goals: ['Nach Wegen fragen und verstehen.'],
patterns: ['Wo ist der Bahnhof?', 'Geradeaus.', 'Links.', 'Rechts.']
}),
'Orte, Verkehr, Richtungen': makeDidactics({
goals: ['Orts- und Verkehrswortschatz aufbauen.'],
patterns: ['der Bahnhof', 'die Straße', 'der Bus', 'die Haltestelle']
}),
'wo / wohin - Kontrast': makeDidactics({
goals: ['Ort und Richtung sauber trennen.'],
patterns: ['Wo bist du?', 'Wohin gehst du?', 'Ich bin hier.', 'Ich gehe nach Hause.']
}),
'Mit Bus und Bahn': makeDidactics({
goals: ['Fahrten im Alltag organisieren.'],
patterns: ['Ich brauche eine Fahrkarte.', 'Wann fährt der Bus?', 'Ich fahre zum Bahnhof.']
}),
'Zeit, Uhrzeit, Termine': makeDidactics({
goals: ['Uhrzeit und Termine ansprechen.'],
patterns: ['heute', 'morgen', 'um drei Uhr', 'am Montag']
}),
'Treffen und Planen': makeDidactics({
goals: ['Zeit ausmachen und planen.'],
patterns: ['Hast du morgen Zeit?', 'Wir treffen uns um sechs.', 'Das passt gut.']
}),
'Verbzweitstellung - Einstieg': makeDidactics({
goals: ['Hauptsatzstellung trainieren.'],
patterns: ['Ich gehe heute arbeiten.', 'Heute gehe ich arbeiten.'],
grammar: [
{ title: 'Verb an Position zwei', text: 'Im deutschen Hauptsatz bleibt das Verb sehr stabil an zweiter Position.', example: 'Heute gehe ich ...' }
]
}),
'Tagesablauf erzählen': makeDidactics({
goals: ['Einfache Routinen erzählen.'],
patterns: ['Morgens arbeite ich.', 'Am Abend koche ich.', 'Danach schlafe ich.']
}),
'Woche 3 - Intensivwiederholung': makeDidactics({
goals: ['Ort, Zeit und Satzbau bündeln.'],
patterns: ['Wo ist ...?', 'Wohin gehst du?', 'Heute gehe ich ...', 'Wir treffen uns ...']
}),
'Woche 3 - Checkpoint': makeDidactics({
goals: ['Wichtige Muster aus Woche 3 prüfen.'],
patterns: ['wo', 'wohin', 'Uhrzeit', 'Satzstellung']
}),
'Arzt & Beschwerden': makeDidactics({
goals: ['Schmerzen und Termine beim Arzt ausdrücken.'],
patterns: ['Ich habe Schmerzen.', 'Ich bin krank.', 'Ich habe einen Termin.']
}),
'Körper, Symptome, Gesundheit': makeDidactics({
goals: ['Wichtige Gesundheitswörter lernen.'],
patterns: ['der Kopf', 'der Bauch', 'Fieber', 'Husten']
}),
'ich bin / ich habe - Gesundheit': makeDidactics({
goals: ['Gesundheitsmuster kontrastieren.'],
patterns: ['Ich bin krank.', 'Ich habe Fieber.', 'Ich habe Kopfschmerzen.']
}),
'Hilfe holen & erklären': makeDidactics({
goals: ['Probleme erklären und Hilfe holen.'],
patterns: ['Ich brauche Hilfe.', 'Können Sie mir helfen?', 'Es tut weh.']
}),
'Kinder, Schule, Alltag': makeDidactics({
goals: ['Schul- und Kinderalltag benennen.'],
patterns: ['das Kind', 'die Schule', 'die Tasche', 'die Hausaufgabe']
}),
'Mit Kindern sprechen': makeDidactics({
goals: ['Einfache Fragen an Kinder stellen.'],
patterns: ['Bist du müde?', 'Hast du Hunger?', 'Wo ist deine Tasche?']
}),
'du / Sie - Einstieg': makeDidactics({
goals: ['Anredeformen unterscheiden.'],
patterns: ['Wie heißt du?', 'Wie heißen Sie?', 'Kannst du ...?', 'Können Sie ...?']
}),
'Höflich fragen & reagieren': makeDidactics({
goals: ['Höfliche Standardmuster trainieren.'],
patterns: ['Können Sie das wiederholen?', 'Ich hätte gern ...', 'Vielen Dank.']
}),
'Woche 4 - Intensivwiederholung': makeDidactics({
goals: ['Gesundheit, Kinder und Höflichkeit bündeln.'],
patterns: ['Ich habe Schmerzen.', 'Können Sie ...?', 'das Kind', 'Hilfe']
}),
'Woche 4 - Checkpoint': makeDidactics({
goals: ['Woche 4 diagnostisch prüfen.'],
patterns: ['ich bin / ich habe', 'du / Sie', 'Schule', 'Arzt']
}),
'Formulare & Termine': makeDidactics({
goals: ['Einfache Verwaltungsdialoge verstehen.'],
patterns: ['Wie ist Ihre Adresse?', 'Hier ist mein Name.', 'Ich habe einen Termin.']
}),
'Dokumente & Angaben': makeDidactics({
goals: ['Dokumenten- und Angabewortschatz aufbauen.'],
patterns: ['das Formular', 'die Adresse', 'die Nummer', 'die Unterschrift']
}),
'der / die / das - Alltagskontraste': makeDidactics({
goals: ['Artikel mit häufigen Alltagswörtern stabilisieren.'],
patterns: ['der Termin', 'die Adresse', 'das Formular']
}),
'Arbeit & Aufgaben': makeDidactics({
goals: ['Über Arbeit und Pflichten sprechen.'],
patterns: ['Ich arbeite heute.', 'Ich habe viel zu tun.', 'Ich muss das machen.']
}),
'Haushalt & Ordnung': makeDidactics({
goals: ['Haushaltswortschatz lernen.'],
patterns: ['die Küche', 'das Zimmer', 'aufräumen', 'putzen']
}),
'Nachbarschaft & Besuch': makeDidactics({
goals: ['Besuche und Nachbarschaft beschreiben.'],
patterns: ['Der Nachbar kommt später.', 'Wir haben Besuch.', 'Komm doch rein.']
}),
'Akkusativ im Alltag - Einstieg': makeDidactics({
goals: ['Akkusativ in häufigen Mustern erkennen.'],
patterns: ['Ich sehe den Bus.', 'Ich brauche die Tasche.', 'Ich kaufe das Brot.']
}),
'Bitten, verschieben, ablehnen': makeDidactics({
goals: ['Höflich zusagen, verschieben oder ablehnen.'],
patterns: ['Heute geht es nicht.', 'Vielleicht morgen.', 'Ja, gern.', 'Leider nicht.']
}),
'Woche 5 - Intensivwiederholung': makeDidactics({
goals: ['Block 5 verdichten.'],
patterns: ['der Termin', 'die Adresse', 'Ich arbeite ...', 'Ich brauche den ...']
}),
'Woche 5 - Checkpoint': makeDidactics({
goals: ['Block 5 prüfen.'],
patterns: ['Formular', 'Arbeit', 'Besuch', 'Akkusativ']
}),
'Freies Gespräch - Alltag': makeDidactics({
goals: ['Bekannte Themen freier verbinden.'],
patterns: ['Heute ...', 'Danach ...', 'Ich brauche ...', 'Wir gehen ...']
}),
'Mischtraining - Kernwortschatz': makeDidactics({
goals: ['Frühen Kernwortschatz mischen.'],
patterns: ['Familie', 'Essen', 'Weg', 'Arzt']
}),
'Fehlertraining - Satzstellung & Negation': makeDidactics({
goals: ['Häufige Hauptsatzfehler reduzieren.'],
patterns: ['Heute gehe ich nicht ...', 'Ich habe kein ...', 'Morgen komme ich ...']
}),
'Konflikte & Missverständnisse': makeDidactics({
goals: ['Nachfragen und korrigieren lernen.'],
patterns: ['Ich verstehe das nicht.', 'Können Sie das bitte wiederholen?', 'So meine ich das nicht.']
}),
'Spiralwiederholung - Wochen 1 bis 3': makeDidactics({
goals: ['Frühe Schnellstartmuster zurückholen.'],
patterns: ['Ich heiße ...', 'Ich habe Hunger.', 'Wo ist ...?', 'Heute gehe ich ...']
}),
'Spiralwiederholung - Wochen 4 bis 5': makeDidactics({
goals: ['Spätere Alltagsfelder verdichten.'],
patterns: ['Ich habe Schmerzen.', 'Wie ist Ihre Adresse?', 'Ich brauche den Termin.']
}),
'Freies Sprechen - Familie, Alltag, Hilfe': makeDidactics({
goals: ['Längere Minidialoge sprechen.'],
patterns: ['Meine Familie ...', 'Heute ...', 'Ich brauche Hilfe.']
}),
'Abschlusstest - Schnellstart': makeDidactics({
goals: ['Kernwortschatz des Schnellstarts prüfen.'],
patterns: ['Begrüßung', 'Familie', 'Preis', 'Arzt']
}),
'Abschlussprüfung - Schnellstart': makeDidactics({
goals: ['Muster, Alltag und Fehlerfelder gemischt prüfen.'],
patterns: ['Vorstellung', 'Bedarf', 'Weg', 'Hilfe']
}),
'Kulturelle Orientierung in Deutschland': makeDidactics({
goals: ['Deutsche Alltagskultur sprachlich einordnen.'],
patterns: ['pünktlich', 'direkt', 'Termin', 'Sie'],
speaking: [
{ title: 'Kulturreflexion', prompt: 'Sprich kurz darüber, wann im Deutschen eher Sie statt du verwendet wird.', cue: 'Im Amt und bei fremden Personen benutzt man oft Sie.' }
]
})
};

View File

@@ -0,0 +1,40 @@
export function getGermanForBisayaLessonPedagogy(lessonNumber, lessonType) {
const phaseLabel = lessonNumber <= 60 ? 'quickstart' : lessonNumber <= 120 ? 'daily_life' : 'stabilization';
const blockNumber = Math.ceil(lessonNumber / 10);
let didacticMode = 'core_input';
if (lessonType === 'conversation') didacticMode = 'guided_dialogue';
if (lessonType === 'grammar') didacticMode = 'pattern_drill';
if (lessonType === 'review') didacticMode = 'intensive_review';
if (lessonType === 'culture') didacticMode = 'real_life_scenario';
const difficultyWeight =
lessonType === 'grammar' ? 3 :
lessonType === 'review' ? 2 :
lessonType === 'conversation' ? 2 :
1;
const newUnitTarget =
lessonType === 'review' ? 2 :
lessonType === 'grammar' ? 4 :
phaseLabel === 'quickstart' ? 6 :
phaseLabel === 'daily_life' ? 5 :
4;
const reviewWeight =
lessonType === 'review' ? 90 :
lessonType === 'grammar' ? 60 :
lessonType === 'vocab' ? 55 :
lessonType === 'culture' ? 20 :
35;
return {
phaseLabel,
blockNumber,
didacticMode,
difficultyWeight,
newUnitTarget,
reviewWeight,
isIntensiveReview: lessonType === 'review'
};
}

View File

@@ -0,0 +1,75 @@
function makeDidactics(goals, patterns, speaking = null, grammar = null) {
return {
learningGoals: goals,
corePatterns: patterns,
speakingPrompts: speaking || [],
grammarFocus: grammar || [],
practicalTasks: []
};
}
export const GERMAN_FOR_BISAYA_PHASE3_DIDACTICS = {
'Wohnung & Nachbarn': makeDidactics(['Über Wohnung und Nachbarschaft sprechen.'], ['die Wohnung', 'der Nachbar', 'Wir wohnen hier.'], [{ title: 'Nachbarschaft', prompt: 'Sag, wo du wohnst und wer dein Nachbar ist.', cue: 'Ich wohne hier. Das ist mein Nachbar.' }]),
'Zimmer, Möbel & Hausarbeit': makeDidactics(['Wichtige Wohnwörter lernen.'], ['das Zimmer', 'der Tisch', 'das Bett', 'putzen']),
'Akkusativ & Artikel vertiefen': makeDidactics(['Häufige Alltagsmuster mit Akkusativ trainieren.'], ['Ich sehe den Bus.', 'Ich putze die Küche.', 'Ich kaufe das Brot.'], null, [{ title: 'Akkusativ im Alltag', text: 'Der Akkusativ taucht in vielen häufigen Sätzen auf.', example: 'Ich brauche den Termin.' }]),
'Besuch empfangen': makeDidactics(['Besuch begrüßen und reagieren.'], ['Komm doch rein.', 'Setz dich bitte.', 'Möchtest du etwas trinken?'], [{ title: 'Besuch', prompt: 'Empfange einen Gast kurz und freundlich.', cue: 'Komm doch rein. Setz dich bitte.' }]),
'Gefühle, Reaktionen & Beziehungen': makeDidactics(['Gefühle und soziale Reaktionen vertiefen.'], ['Ich freue mich.', 'Ich bin nervös.', 'Das ist wichtig.']),
'Hilfe, Bitte, Ablehnung vertiefen': makeDidactics(['Bitten und Ablehnen natürlicher machen.'], ['Kannst du mir helfen?', 'Heute geht es leider nicht.', 'Vielleicht morgen.'], [{ title: 'Bitte', prompt: 'Bitte höflich um Hilfe und verschiebe etwas auf morgen.', cue: 'Kannst du mir helfen? Vielleicht morgen.' }]),
'Modalverben im Alltag': makeDidactics(['können, müssen, wollen im Alltag trainieren.'], ['Ich kann kommen.', 'Ich muss arbeiten.', 'Ich will schlafen.'], null, [{ title: 'Modalverben', text: 'Modalverben tragen viele Alltagsaussagen.', example: 'Ich muss morgen arbeiten.' }]),
'Arbeit & Aufgaben organisieren': makeDidactics(['Über Aufgaben und Arbeit sprechen.'], ['Ich muss das machen.', 'Ich arbeite heute.', 'Ich habe viel zu tun.']),
'Woche 7 - Intensivwiederholung': makeDidactics(['Woche 7 gemischt wiederholen.'], ['die Wohnung', 'Kannst du mir helfen?', 'Ich muss arbeiten.', 'Komm doch rein.']),
'Woche 7 - Checkpoint': makeDidactics(['Woche 7 diagnostisch prüfen.'], ['Wohnung', 'Akkusativ', 'Modalverb', 'Besuch']),
'Arzt, Apotheke, Termin': makeDidactics(['Arzttermine und Apotheke sprachlich tragen.'], ['Ich habe einen Termin.', 'Ich brauche Medikamente.', 'Wo ist die Apotheke?'], [{ title: 'Arzttermin', prompt: 'Sag, dass du einen Termin hast und Medikamente brauchst.', cue: 'Ich habe einen Termin. Ich brauche Medikamente.' }]),
'Gesundheit vertiefen': makeDidactics(['Gesundheitswortschatz ausbauen.'], ['die Tablette', 'das Rezept', 'der Husten', 'die Schmerzen']),
'Perfekt - Einstieg': makeDidactics(['Vergangenheit im Alltag einführen.'], ['Ich habe gearbeitet.', 'Ich bin nach Hause gegangen.'], null, [{ title: 'Perfekt', text: 'Im gesprochenen Deutsch ist das Perfekt sehr wichtig.', example: 'Ich habe gegessen.' }]),
'Über gestern sprechen': makeDidactics(['Kurze Erzählungen über gestern führen.'], ['Gestern habe ich gearbeitet.', 'Danach bin ich nach Hause gegangen.']),
'Schule & Betreuung': makeDidactics(['Schule und Betreuung thematisieren.'], ['die Schule', 'die Lehrerin', 'die Hausaufgabe', 'das Kind']),
'Mit Lehrkraft oder Kita sprechen': makeDidactics(['Kurze Schulsituationen auf Deutsch tragen.'], ['Mein Kind ist krank.', 'Wir haben eine Frage.', 'Wann beginnt die Schule?']),
'nicht / kein vertiefen': makeDidactics(['Negation mit Kontrasten festigen.'], ['Ich habe kein Geld.', 'Ich bin nicht müde.', 'Das ist nicht richtig.'], null, [{ title: 'Negation vertiefen', text: 'Deutsch trennt Nomennegation und Satznegation klarer.', example: 'kein Termin / nicht hier' }]),
'Essen, Kochen, Haushalt': makeDidactics(['Kochen und Haushalt verbinden.'], ['Ich koche heute.', 'Wir brauchen Wasser.', 'Die Küche ist sauber.']),
'Woche 8 - Intensivwiederholung': makeDidactics(['Woche 8 gemischt wiederholen.'], ['Ich habe einen Termin.', 'Gestern habe ich ...', 'kein', 'die Schule']),
'Woche 8 - Checkpoint': makeDidactics(['Woche 8 diagnostisch prüfen.'], ['Arzt', 'Perfekt', 'Schule', 'Negation']),
'Amt, Dokumente, Anmeldung': makeDidactics(['Einfache Amtssprache vorbereiten.'], ['Ich möchte mich anmelden.', 'Hier ist mein Formular.', 'Was ist Ihre Adresse?']),
'Formulare & Angaben vertiefen': makeDidactics(['Wichtige Dokumentwörter vertiefen.'], ['das Formular', 'die Adresse', 'die Nummer', 'die Unterschrift']),
'Dativ im Alltag - Einstieg': makeDidactics(['Erste Dativmuster lernen.'], ['mit dem Bus', 'bei der Schule', 'ich gebe dem Kind Wasser'], null, [{ title: 'Dativ im Alltag', text: 'Dativ erscheint oft mit Präpositionen oder als Empfänger.', example: 'mit dem Bus / dem Kind helfen' }]),
'Mit Bus, Bahn, Ticket': makeDidactics(['Fahrten sprachlich organisieren.'], ['Ich brauche ein Ticket.', 'Wann fährt der Zug?', 'Mit der Bahn ist es schneller.']),
'Verkehr, Fahrten, Uhrzeiten': makeDidactics(['Verkehrs- und Zeitwortschatz mischen.'], ['der Zug', 'der Bus', 'um acht Uhr', 'spät']),
'Weg beschreiben und fragen': makeDidactics(['Wegbeschreibungen vertiefen.'], ['Gehen Sie geradeaus.', 'Dann links.', 'Der Bahnhof ist dort.']),
'Nebensätze mit weil - Einstieg': makeDidactics(['weil-Sätze früh als Muster einführen.'], ['Ich bleibe zu Hause, weil ich krank bin.', 'Ich komme später, weil ich arbeite.'], null, [{ title: 'weil-Satz', text: 'Mit weil verschiebt sich das Verb im Nebensatz.', example: '..., weil ich krank bin.' }]),
'Probleme erklären und begründen': makeDidactics(['Probleme mit einfachen Begründungen erklären.'], ['Ich komme später, weil ...', 'Ich brauche Hilfe, weil ...']),
'Woche 9 - Intensivwiederholung': makeDidactics(['Woche 9 bündeln.'], ['das Formular', 'mit dem Bus', 'weil ich ...', 'der Bahnhof']),
'Woche 9 - Checkpoint': makeDidactics(['Woche 9 prüfen.'], ['Amt', 'Dativ', 'weil', 'Ticket'])
};
export const GERMAN_FOR_BISAYA_PHASE3_LESSONS = [
{ week: 7, day: 1, num: 61, type: 'conversation', title: 'Wohnung & Nachbarn', desc: 'Über Wohnung und Nachbarschaft sprechen', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 7, day: 1, num: 62, type: 'vocab', title: 'Zimmer, Möbel & Hausarbeit', desc: 'Zimmer, Möbel und einfache Hausarbeit benennen', targetMin: 18, targetScore: 85, review: true, cultural: null },
{ week: 7, day: 2, num: 63, type: 'grammar', title: 'Akkusativ & Artikel vertiefen', desc: 'Alltagsnomen mit Artikel und Akkusativ trainieren', targetMin: 22, targetScore: 78, review: true, cultural: null },
{ week: 7, day: 2, num: 64, type: 'conversation', title: 'Besuch empfangen', desc: 'Gäste begrüßen und freundlich reagieren', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 7, day: 3, num: 65, type: 'vocab', title: 'Gefühle, Reaktionen & Beziehungen', desc: 'Wortschatz für Reaktionen und Beziehungen vertiefen', targetMin: 18, targetScore: 85, review: true, cultural: null },
{ week: 7, day: 3, num: 66, type: 'conversation', title: 'Hilfe, Bitte, Ablehnung vertiefen', desc: 'Bitten, Verschieben und Ablehnen natürlicher machen', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 7, day: 4, num: 67, type: 'grammar', title: 'Modalverben im Alltag', desc: 'können, müssen und wollen früh festigen', targetMin: 22, targetScore: 78, review: true, cultural: null },
{ week: 7, day: 4, num: 68, type: 'conversation', title: 'Arbeit & Aufgaben organisieren', desc: 'Über Arbeit, Aufgaben und Zeitdruck sprechen', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 7, day: 5, num: 69, type: 'review', title: 'Woche 7 - Intensivwiederholung', desc: 'Wohnung, Besuch, Arbeit und Hilfe verdichten', targetMin: 28, targetScore: 82, review: false, cultural: null },
{ week: 7, day: 5, num: 70, type: 'vocab', title: 'Woche 7 - Checkpoint', desc: 'Diagnose zu den Inhalten von Woche 7', targetMin: 16, targetScore: 84, review: true, cultural: null },
{ week: 8, day: 1, num: 71, type: 'conversation', title: 'Arzt, Apotheke, Termin', desc: 'Arzt, Apotheke und Termine im Alltag klären', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 8, day: 1, num: 72, type: 'vocab', title: 'Gesundheit vertiefen', desc: 'Medikamente, Symptome und Gesundheit vertiefen', targetMin: 18, targetScore: 85, review: true, cultural: null },
{ week: 8, day: 2, num: 73, type: 'grammar', title: 'Perfekt - Einstieg', desc: 'Vergangenheit in der gesprochenen Sprache aufbauen', targetMin: 22, targetScore: 78, review: true, cultural: null },
{ week: 8, day: 2, num: 74, type: 'conversation', title: 'Über gestern sprechen', desc: 'Kurze Erzählungen über gestern führen', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 8, day: 3, num: 75, type: 'vocab', title: 'Schule & Betreuung', desc: 'Schul- und Betreuungswortschatz vertiefen', targetMin: 18, targetScore: 85, review: true, cultural: null },
{ week: 8, day: 3, num: 76, type: 'conversation', title: 'Mit Lehrkraft oder Kita sprechen', desc: 'Kurze Schulsituationen meistern', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 8, day: 4, num: 77, type: 'grammar', title: 'nicht / kein vertiefen', desc: 'Negation in mehreren Kontexten sauber trennen', targetMin: 22, targetScore: 78, review: true, cultural: null },
{ week: 8, day: 4, num: 78, type: 'conversation', title: 'Essen, Kochen, Haushalt', desc: 'Kochen und Haushalt im Alltag besprechen', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 8, day: 5, num: 79, type: 'review', title: 'Woche 8 - Intensivwiederholung', desc: 'Gesundheit, Schule, Perfekt und Negation bündeln', targetMin: 28, targetScore: 82, review: false, cultural: null },
{ week: 8, day: 5, num: 80, type: 'vocab', title: 'Woche 8 - Checkpoint', desc: 'Diagnose zu Woche 8', targetMin: 16, targetScore: 84, review: true, cultural: null },
{ week: 9, day: 1, num: 81, type: 'conversation', title: 'Amt, Dokumente, Anmeldung', desc: 'Dokumente und Anmeldung im Alltag vorbereiten', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 9, day: 1, num: 82, type: 'vocab', title: 'Formulare & Angaben vertiefen', desc: 'Dokumentwörter und Angaben vertiefen', targetMin: 18, targetScore: 85, review: true, cultural: null },
{ week: 9, day: 2, num: 83, type: 'grammar', title: 'Dativ im Alltag - Einstieg', desc: 'Frühe Dativmuster mit Präpositionen und Empfängern', targetMin: 22, targetScore: 78, review: true, cultural: null },
{ week: 9, day: 2, num: 84, type: 'conversation', title: 'Mit Bus, Bahn, Ticket', desc: 'Fahrten mit Bus und Bahn organisieren', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 9, day: 3, num: 85, type: 'vocab', title: 'Verkehr, Fahrten, Uhrzeiten', desc: 'Verkehr und Uhrzeiten im Alltag mischen', targetMin: 18, targetScore: 85, review: true, cultural: null },
{ week: 9, day: 3, num: 86, type: 'conversation', title: 'Weg beschreiben und fragen', desc: 'Weg fragen und kurze Richtungen geben', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 9, day: 4, num: 87, type: 'grammar', title: 'Nebensätze mit weil - Einstieg', desc: 'Einfache Begründungen mit weil bilden', targetMin: 22, targetScore: 78, review: true, cultural: null },
{ week: 9, day: 4, num: 88, type: 'conversation', title: 'Probleme erklären und begründen', desc: 'Probleme mit kurzen Begründungen erklären', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 9, day: 5, num: 89, type: 'review', title: 'Woche 9 - Intensivwiederholung', desc: 'Amt, Verkehr, Dativ und weil bündeln', targetMin: 28, targetScore: 82, review: false, cultural: null },
{ week: 9, day: 5, num: 90, type: 'vocab', title: 'Woche 9 - Checkpoint', desc: 'Diagnose zu Woche 9', targetMin: 16, targetScore: 84, review: true, cultural: null }
];

View File

@@ -0,0 +1,75 @@
function makeDidactics(goals, patterns, speaking = null, grammar = null) {
return {
learningGoals: goals,
corePatterns: patterns,
speakingPrompts: speaking || [],
grammarFocus: grammar || [],
practicalTasks: []
};
}
export const GERMAN_FOR_BISAYA_PHASE4_DIDACTICS = {
'Arbeitssuche & Termine': makeDidactics(['Über Arbeit und Termine sprechen.'], ['Ich suche Arbeit.', 'Ich habe morgen einen Termin.', 'Wann kann ich anfangen?']),
'Beruf, Zeiten, Aufgaben': makeDidactics(['Wortschatz zu Arbeit und Zeiten vertiefen.'], ['der Beruf', 'die Aufgabe', 'die Schicht', 'früh / spät']),
'Perfekt mit haben / sein': makeDidactics(['haben und sein im Perfekt kontrastieren.'], ['Ich habe gearbeitet.', 'Ich bin gefahren.'], null, [{ title: 'Perfekt-Hilfsverben', text: 'Im Deutschen wechseln die Hilfsverben im Perfekt.', example: 'habe gemacht / bin gegangen' }]),
'Beim Arzt genauer beschreiben': makeDidactics(['Beschwerden genauer erklären.'], ['Ich habe seit gestern Schmerzen.', 'Es tut hier weh.', 'Es ist besser geworden.']),
'Körper, Symptome, Medikamente': makeDidactics(['Gesundheitswortschatz vertiefen.'], ['die Tablette', 'das Medikament', 'der Rücken', 'der Husten']),
'Konflikte höflich klären': makeDidactics(['Konflikte sprachlich entschärfen.'], ['So meine ich das nicht.', 'Können wir darüber sprechen?', 'Entschuldigung.']),
'Trennbare Verben - Einstieg': makeDidactics(['Trennbare Verben im Alltag erkennen.'], ['Ich stehe auf.', 'Ich rufe an.', 'Ich mache das Licht aus.'], null, [{ title: 'Trennbare Verben', text: 'Viele deutsche Alltagsverben trennen sich im Hauptsatz.', example: 'Ich rufe dich an.' }]),
'Tagesablauf mit Trennverben': makeDidactics(['Routinen mit trennbaren Verben erzählen.'], ['Ich stehe um sechs Uhr auf.', 'Dann räume ich auf.']),
'Woche 10 - Intensivwiederholung': makeDidactics(['Woche 10 bündeln.'], ['Arbeit', 'Perfekt', 'Arzt', 'trennbares Verb']),
'Woche 10 - Checkpoint': makeDidactics(['Woche 10 prüfen.'], ['Beruf', 'Perfekt', 'Schmerz', 'anrufen']),
'Kinder, Schule, Freizeit': makeDidactics(['Kinderalltag in mehreren Bereichen beschreiben.'], ['Mein Kind spielt gern.', 'Die Schule beginnt um acht.', 'Am Nachmittag spielen wir.']),
'Schule, Spiel, Familie vertiefen': makeDidactics(['Kinder- und Schulwortschatz mischen.'], ['die Pause', 'das Spiel', 'die Familie', 'der Lehrer']),
'Possessivartikel mein / dein / sein': makeDidactics(['Besitzwörter im Alltag trainieren.'], ['mein Kind', 'deine Tasche', 'sein Zimmer'], null, [{ title: 'Possessivartikel', text: 'Besitz wird im Deutschen häufig mit kleinen Artikelformen markiert.', example: 'mein Bus / deine Adresse' }]),
'Zuhause organisieren': makeDidactics(['Haushalt und Zuhause organisieren.'], ['Ich räume das Zimmer auf.', 'Das ist mein Schlüssel.', 'Wo ist deine Tasche?']),
'Wohnen, Reparaturen, Nachbarschaft': makeDidactics(['Wohnen und kleine Probleme benennen.'], ['Die Lampe ist kaputt.', 'Der Nachbar hilft uns.', 'Wir brauchen einen Termin.']),
'Einladungen & soziale Treffen': makeDidactics(['Einladen und verabreden.'], ['Hast du Zeit?', 'Kommst du morgen?', 'Wir treffen uns um sechs.']),
'du / Sie vertiefen & Bitten': makeDidactics(['Anrede und Höflichkeit vertiefen.'], ['Kannst du ...?', 'Können Sie ...?', 'Ich hätte gern ...'], null, [{ title: 'Anrede vertiefen', text: 'Die Wahl zwischen du und Sie verändert den Ton stark.', example: 'Kannst du helfen? / Können Sie helfen?' }]),
'Telefon, Nachricht, Termin verschieben': makeDidactics(['Telefonisch reagieren und verschieben.'], ['Ich rufe später an.', 'Können wir den Termin verschieben?', 'Ich schreibe dir.']),
'Woche 11 - Intensivwiederholung': makeDidactics(['Woche 11 bündeln.'], ['mein / dein', 'Treffen', 'du / Sie', 'Termin verschieben']),
'Woche 11 - Checkpoint': makeDidactics(['Woche 11 prüfen.'], ['Possessiv', 'Einladung', 'Telefon', 'Anrede']),
'Einkauf, Reklamation, Rückgabe': makeDidactics(['Im Laden reklamieren und zurückgeben.'], ['Das ist kaputt.', 'Ich möchte das zurückgeben.', 'Haben Sie einen Kassenbon?']),
'Geld, Rechnung, Vertrag': makeDidactics(['Wortschatz zu Geld und Dokumenten vertiefen.'], ['die Rechnung', 'der Vertrag', 'bar zahlen', 'das Konto']),
'würde / hätte gern - Einstieg': makeDidactics(['Höfliche Wünsche früher ausbauen.'], ['Ich würde gern ...', 'Ich hätte gern ...'], null, [{ title: 'Höfliche Wünsche', text: 'Diese Formen sind im Deutschen sehr nützlich für höfliche Kommunikation.', example: 'Ich hätte gern einen Termin.' }]),
'Wünsche höflich formulieren': makeDidactics(['Höfliche Bitten und Wünsche trainieren.'], ['Ich hätte gern Hilfe.', 'Ich würde gern einen Termin machen.']),
'Gefühle, Sorgen, Hoffnungen': makeDidactics(['Über Gefühle und Sorgen differenzierter sprechen.'], ['Ich bin besorgt.', 'Ich hoffe das.', 'Ich freue mich darauf.']),
'Freies Erzählen - Alltag & Familie': makeDidactics(['Alltag und Familie freier verbinden.'], ['Heute ...', 'Danach ...', 'Meine Familie ...'], [{ title: 'Freier Bericht', prompt: 'Erzähle kurz von Familie, Arbeit und Plänen.', cue: 'Heute arbeite ich. Danach sehe ich meine Familie.' }]),
'Satzstellung mit Zeit / Ort': makeDidactics(['Zeit- und Ortsangaben im Satz ordnen.'], ['Heute bin ich zu Hause.', 'Am Abend fahre ich nach Hause.'], null, [{ title: 'Zeit / Ort im Satz', text: 'Zeit- und Ortsfelder beeinflussen die deutsche Satzstellung früh spürbar.', example: 'Heute arbeite ich zu Hause.' }]),
'Alltag mit mehreren Schritten': makeDidactics(['Mehrschrittige Alltagsfolgen erzählen.'], ['Zuerst ...', 'Dann ...', 'Danach ...', 'Am Ende ...']),
'Woche 12 - Intensivwiederholung': makeDidactics(['Woche 12 bündeln.'], ['Rückgabe', 'würde gern', 'Sorgen', 'danach']),
'Woche 12 - Checkpoint': makeDidactics(['Woche 12 prüfen.'], ['Rechnung', 'Wunsch', 'Gefühl', 'Satzstellung'])
};
export const GERMAN_FOR_BISAYA_PHASE4_LESSONS = [
{ week: 10, day: 1, num: 91, type: 'conversation', title: 'Arbeitssuche & Termine', desc: 'Über Arbeit und Termine sprechen', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 10, day: 1, num: 92, type: 'vocab', title: 'Beruf, Zeiten, Aufgaben', desc: 'Berufswortschatz und Aufgaben vertiefen', targetMin: 18, targetScore: 85, review: true, cultural: null },
{ week: 10, day: 2, num: 93, type: 'grammar', title: 'Perfekt mit haben / sein', desc: 'Die zwei Perfekt-Hilfsverben alltagsnah trainieren', targetMin: 22, targetScore: 78, review: true, cultural: null },
{ week: 10, day: 2, num: 94, type: 'conversation', title: 'Beim Arzt genauer beschreiben', desc: 'Beschwerden und Entwicklung genauer beschreiben', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 10, day: 3, num: 95, type: 'vocab', title: 'Körper, Symptome, Medikamente', desc: 'Gesundheitswortschatz weiter ausbauen', targetMin: 18, targetScore: 85, review: true, cultural: null },
{ week: 10, day: 3, num: 96, type: 'conversation', title: 'Konflikte höflich klären', desc: 'Missverständnisse und Konflikte höflich klären', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 10, day: 4, num: 97, type: 'grammar', title: 'Trennbare Verben - Einstieg', desc: 'Trennbare Verben im Alltag erkennen und verwenden', targetMin: 22, targetScore: 78, review: true, cultural: null },
{ week: 10, day: 4, num: 98, type: 'conversation', title: 'Tagesablauf mit Trennverben', desc: 'Routinen mit trennbaren Verben erzählen', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 10, day: 5, num: 99, type: 'review', title: 'Woche 10 - Intensivwiederholung', desc: 'Arbeit, Arzt, Perfekt und Trennverben bündeln', targetMin: 28, targetScore: 82, review: false, cultural: null },
{ week: 10, day: 5, num: 100, type: 'vocab', title: 'Woche 10 - Checkpoint', desc: 'Diagnose zu Woche 10', targetMin: 16, targetScore: 84, review: true, cultural: null },
{ week: 11, day: 1, num: 101, type: 'conversation', title: 'Kinder, Schule, Freizeit', desc: 'Kinderalltag in mehreren Bereichen beschreiben', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 11, day: 1, num: 102, type: 'vocab', title: 'Schule, Spiel, Familie vertiefen', desc: 'Schul- und Familienwortschatz mischen', targetMin: 18, targetScore: 85, review: true, cultural: null },
{ week: 11, day: 2, num: 103, type: 'grammar', title: 'Possessivartikel mein / dein / sein', desc: 'Besitz und Beziehungen sprachlich markieren', targetMin: 22, targetScore: 78, review: true, cultural: null },
{ week: 11, day: 2, num: 104, type: 'conversation', title: 'Zuhause organisieren', desc: 'Haushalt, Dinge und Fragen zu Hause organisieren', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 11, day: 3, num: 105, type: 'vocab', title: 'Wohnen, Reparaturen, Nachbarschaft', desc: 'Wortschatz zu Wohnen und kleinen Problemen', targetMin: 18, targetScore: 85, review: true, cultural: null },
{ week: 11, day: 3, num: 106, type: 'conversation', title: 'Einladungen & soziale Treffen', desc: 'Einladungen machen und auf Treffen reagieren', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 11, day: 4, num: 107, type: 'grammar', title: 'du / Sie vertiefen & Bitten', desc: 'Anrede und Bitten weiter festigen', targetMin: 22, targetScore: 78, review: true, cultural: null },
{ week: 11, day: 4, num: 108, type: 'conversation', title: 'Telefon, Nachricht, Termin verschieben', desc: 'Telefonisch reagieren und Termine verschieben', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 11, day: 5, num: 109, type: 'review', title: 'Woche 11 - Intensivwiederholung', desc: 'Kinder, Zuhause, Anrede und Einladungen bündeln', targetMin: 28, targetScore: 82, review: false, cultural: null },
{ week: 11, day: 5, num: 110, type: 'vocab', title: 'Woche 11 - Checkpoint', desc: 'Diagnose zu Woche 11', targetMin: 16, targetScore: 84, review: true, cultural: null },
{ week: 12, day: 1, num: 111, type: 'conversation', title: 'Einkauf, Reklamation, Rückgabe', desc: 'Reklamieren und Rückgaben im Alltag bewältigen', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 12, day: 1, num: 112, type: 'vocab', title: 'Geld, Rechnung, Vertrag', desc: 'Wortschatz zu Geld, Rechnung und Vertrag', targetMin: 18, targetScore: 85, review: true, cultural: null },
{ week: 12, day: 2, num: 113, type: 'grammar', title: 'würde / hätte gern - Einstieg', desc: 'Höfliche Wünsche im Alltag aufbauen', targetMin: 22, targetScore: 78, review: true, cultural: null },
{ week: 12, day: 2, num: 114, type: 'conversation', title: 'Wünsche höflich formulieren', desc: 'Höfliche Bitten und Wünsche im Alltag trainieren', targetMin: 18, targetScore: 80, review: false, cultural: null },
{ week: 12, day: 3, num: 115, type: 'vocab', title: 'Gefühle, Sorgen, Hoffnungen', desc: 'Emotionen, Sorgen und Hoffnungen sprachlich erweitern', targetMin: 18, targetScore: 85, review: true, cultural: null },
{ week: 12, day: 3, num: 116, type: 'conversation', title: 'Freies Erzählen - Alltag & Familie', desc: 'Freier über Familie und Alltag sprechen', targetMin: 20, targetScore: 78, review: false, cultural: null },
{ week: 12, day: 4, num: 117, type: 'grammar', title: 'Satzstellung mit Zeit / Ort', desc: 'Zeit- und Ortsfelder im Satz festigen', targetMin: 22, targetScore: 78, review: true, cultural: null },
{ week: 12, day: 4, num: 118, type: 'conversation', title: 'Alltag mit mehreren Schritten', desc: 'Mehrschrittige Abläufe klar erzählen', targetMin: 20, targetScore: 78, review: false, cultural: null },
{ week: 12, day: 5, num: 119, type: 'review', title: 'Woche 12 - Intensivwiederholung', desc: 'Wünsche, Gefühle und Satzbau bündeln', targetMin: 28, targetScore: 82, review: false, cultural: null },
{ week: 12, day: 5, num: 120, type: 'vocab', title: 'Woche 12 - Checkpoint', desc: 'Diagnose zu Woche 12', targetMin: 16, targetScore: 84, review: true, cultural: null }
];

View File

@@ -0,0 +1,75 @@
function makeDidactics(goals, patterns, speaking = null, grammar = null) {
return {
learningGoals: goals,
corePatterns: patterns,
speakingPrompts: speaking || [],
grammarFocus: grammar || [],
practicalTasks: []
};
}
export const GERMAN_FOR_BISAYA_PHASE5_DIDACTICS = {
'Dialogtag - Alltag': makeDidactics(['Mehrere Alltagsthemen in längeren Dialogen verbinden.'], ['Heute muss ich ...', 'Danach gehe ich ...', 'Ich brauche noch ...']),
'Mischtraining - Kernwortschatz I': makeDidactics(['Frühe Kernwörter gemischt aktivieren.'], ['Familie', 'Arzt', 'Preis', 'Termin']),
'Fehlertraining - Artikel & Kasus I': makeDidactics(['Artikel und Kasus gezielt kontrastieren.'], ['der Termin', 'die Tasche', 'das Formular', 'mit dem Bus'], null, [{ title: 'Kontrastblock', text: 'Schwache Formen werden direkt nebeneinandergestellt.', example: 'der Termin / den Termin / dem Termin' }]),
'Rollenspiel - Amt, Arzt, Einkauf': makeDidactics(['Mehrere Alltagsszenen verbinden.'], ['Ich habe einen Termin.', 'Ich brauche Hilfe.', 'Ich möchte das zurückgeben.']),
'Stabilisierungsblock 1 - Intensiv I': makeDidactics(['Erste Stabilisierungsschleife.'], ['ich heiße', 'ich brauche', 'wo / wohin', 'du / Sie']),
'Fehlerschwerpunkte Satzstellung': makeDidactics(['Satzstellungsfehler gezielt reduzieren.'], ['Heute gehe ich ...', 'Morgen habe ich ...', 'Danach komme ich ...']),
'Freies Erzählen - Familie, Arbeit, Termine': makeDidactics(['Mehrere Themen freier verbinden.'], ['Meine Familie ...', 'Ich arbeite ...', 'Morgen habe ich einen Termin.'], [{ title: 'Freier Bericht', prompt: 'Erzähle kurz von Familie, Arbeit und einem Termin.', cue: 'Ich arbeite heute. Morgen habe ich einen Termin.' }]),
'Mischtraining - Reale Situationen I': makeDidactics(['Reale Situationen mischen.'], ['der Bus', 'der Termin', 'die Schule', 'die Apotheke']),
'Stabilisierungsblock 1 - Intensiv II': makeDidactics(['Erste Stabilisierung verdichten.'], ['kein', 'würde gern', 'Akkusativ', 'Perfekt']),
'Stabilisierungsblock 1 - Checkpoint': makeDidactics(['Ersten Stabilisierungsschritt prüfen.'], ['Artikel', 'Satzstellung', 'Termin', 'Arzt']),
'Dialogtag - Konflikt, Hilfe, Planung': makeDidactics(['Konflikte, Hilfe und Planen verbinden.'], ['Können wir darüber sprechen?', 'Ich brauche Hilfe.', 'Morgen machen wir ...']),
'Mischtraining - Kernwortschatz II': makeDidactics(['Zweite Kernwortschatzrunde.'], ['Weg', 'Familie', 'Arbeit', 'Gesundheit']),
'Fehlertraining - Zeitformen & Modalverben': makeDidactics(['Zeitformen und Modalverben kontrastieren.'], ['Ich habe gearbeitet.', 'Ich muss arbeiten.', 'Ich kann kommen.'], null, [{ title: 'Zeit und Modalität', text: 'Zeitformen und Modalverben werden leicht vermischt und müssen bewusst getrennt werden.', example: 'Ich habe gearbeitet. / Ich muss arbeiten.' }]),
'Rollenspiel - Missverständnisse lösen': makeDidactics(['Missverständnisse ruhig klären.'], ['Ich verstehe das nicht.', 'So meine ich das nicht.', 'Können Sie das bitte wiederholen?']),
'Stabilisierungsblock 2 - Intensiv I': makeDidactics(['Zweite Stabilisierungsrunde verdichten.'], ['Perfekt', 'Modalverb', 'weil', 'Rückgabe']),
'Fehlerschwerpunkte Negation & Artikel': makeDidactics(['nicht/kein und Artikel zusammen trainieren.'], ['kein Termin', 'nicht hier', 'die Tasche', 'den Bus']),
'Freies Sprechen - Alltag ohne Stütze': makeDidactics(['Freier mit minimaler Stütze sprechen.'], ['Zuerst ...', 'Dann ...', 'Später ...', 'Am Ende ...'], [{ title: 'Freie Routine', prompt: 'Erzähle frei von einem typischen Tag.', cue: 'Zuerst ..., dann ..., später ...' }]),
'Mischtraining - Reale Situationen II': makeDidactics(['Zweite Mischrunde realer Situationen.'], ['Apotheke', 'Nachbar', 'Formular', 'Kasse']),
'Stabilisierungsblock 2 - Intensiv II': makeDidactics(['Zweite Stabilisierung verdichten.'], ['du / Sie', 'kein / nicht', 'Perfekt', 'Akkusativ']),
'Stabilisierungsblock 2 - Checkpoint': makeDidactics(['Zweiten Stabilisierungsschritt prüfen.'], ['Negation', 'Kasus', 'Missverständnis', 'Arbeit']),
'Großes Mischreview I': makeDidactics(['Frühe und mittlere Inhalte breit wiederholen.'], ['Vorstellung', 'Essen', 'Weg', 'Arzt']),
'Großes Mischreview II': makeDidactics(['Zweite große Mischrunde mit höherer Dichte.'], ['Formular', 'Rückgabe', 'Treffen', 'Schule']),
'Fehlertraining - letzte Schwächen': makeDidactics(['Die letzten typischen Fehler fokussieren.'], ['ich habe / ich bin', 'der / die / das', 'nicht / kein']),
'Freies Sprechen - längere Antworten': makeDidactics(['Längere Antworten mit mehr Zusammenhalt geben.'], ['Erstens ...', 'Dann ...', 'Außerdem ...', 'Deshalb ...'], [{ title: 'Längere Antwort', prompt: 'Gib eine längere Antwort zu Alltag, Arbeit und Familie.', cue: 'Erstens ..., dann ..., außerdem ...' }]),
'Langzeitreview I': makeDidactics(['Früh gelernte Inhalte gegen Vergessen absichern.'], ['Hallo, ich heiße ...', 'Ich habe Hunger.', 'Wo ist ...?']),
'Langzeitreview II': makeDidactics(['Frühe und späte Inhalte gemeinsam zurückholen.'], ['Ich habe einen Termin.', 'Können Sie ...?', 'Ich brauche Hilfe.']),
'Rollenspiele - echte Situationen': makeDidactics(['Alltagssituationen offen kombinieren.'], ['Ich brauche Hilfe.', 'Ich hätte gern ...', 'Ich komme später, weil ...']),
'Abschlusstest - Stabilisierung': makeDidactics(['Wortschatz der Stabilisierung prüfen.'], ['Artikel', 'Negation', 'Arzt', 'Formular']),
'Abschlussprüfung - Gesamtpfad': makeDidactics(['Gesamten Schnellstart bis Stabilisierung prüfen.'], ['Vorstellung', 'Arbeit', 'Arzt', 'Alltag']),
'Kulturelle Orientierung in Deutschland vertieft': makeDidactics(['Alltagskultur vertieft reflektieren.'], ['Pünktlichkeit', 'Termin', 'Direktheit', 'Sie'], [{ title: 'Kulturreflexion', prompt: 'Erkläre kurz, warum Pünktlichkeit und klare Absprachen im deutschen Alltag wichtig wirken.', cue: 'Termine und Pünktlichkeit sind in Deutschland oft sehr wichtig.' }])
};
export const GERMAN_FOR_BISAYA_PHASE5_LESSONS = [
{ week: 13, day: 1, num: 121, type: 'conversation', title: 'Dialogtag - Alltag', desc: 'Mehrere Alltagsthemen in längeren Dialogen verbinden', targetMin: 22, targetScore: 78, review: false, cultural: null },
{ week: 13, day: 1, num: 122, type: 'vocab', title: 'Mischtraining - Kernwortschatz I', desc: 'Frühe Kernwörter blockübergreifend mischen', targetMin: 20, targetScore: 85, review: true, cultural: null },
{ week: 13, day: 2, num: 123, type: 'grammar', title: 'Fehlertraining - Artikel & Kasus I', desc: 'Artikel und Kasus in problematischen Mustern kontrastieren', targetMin: 22, targetScore: 78, review: true, cultural: null },
{ week: 13, day: 2, num: 124, type: 'conversation', title: 'Rollenspiel - Amt, Arzt, Einkauf', desc: 'Mehrere reale Alltagsszenen verbinden', targetMin: 22, targetScore: 78, review: false, cultural: null },
{ week: 13, day: 3, num: 125, type: 'review', title: 'Stabilisierungsblock 1 - Intensiv I', desc: 'Erste verdichtete Stabilisierungsrunde', targetMin: 30, targetScore: 82, review: false, cultural: null },
{ week: 13, day: 3, num: 126, type: 'vocab', title: 'Fehlerschwerpunkte Satzstellung', desc: 'Satzstellungsfehler gezielt reduzieren', targetMin: 20, targetScore: 85, review: true, cultural: null },
{ week: 13, day: 4, num: 127, type: 'conversation', title: 'Freies Erzählen - Familie, Arbeit, Termine', desc: 'Mehrere Themen freier verbinden', targetMin: 24, targetScore: 78, review: false, cultural: null },
{ week: 13, day: 4, num: 128, type: 'vocab', title: 'Mischtraining - Reale Situationen I', desc: 'Gemischtes Training realer Situationen', targetMin: 20, targetScore: 85, review: true, cultural: null },
{ week: 13, day: 5, num: 129, type: 'review', title: 'Stabilisierungsblock 1 - Intensiv II', desc: 'Zweite verdichtete Wiederholung des ersten Stabilisierungsblocks', targetMin: 30, targetScore: 82, review: false, cultural: null },
{ week: 13, day: 5, num: 130, type: 'vocab', title: 'Stabilisierungsblock 1 - Checkpoint', desc: 'Diagnose zum ersten Stabilisierungsblock', targetMin: 18, targetScore: 84, review: true, cultural: null },
{ week: 14, day: 1, num: 131, type: 'conversation', title: 'Dialogtag - Konflikt, Hilfe, Planung', desc: 'Konflikt, Hilfe und Planung in Dialogen verbinden', targetMin: 22, targetScore: 78, review: false, cultural: null },
{ week: 14, day: 1, num: 132, type: 'vocab', title: 'Mischtraining - Kernwortschatz II', desc: 'Zweite Kernwortschatzrunde über Alltagsthemen', targetMin: 20, targetScore: 85, review: true, cultural: null },
{ week: 14, day: 2, num: 133, type: 'grammar', title: 'Fehlertraining - Zeitformen & Modalverben', desc: 'Zeitformen und Modalverben gezielt kontrastieren', targetMin: 22, targetScore: 78, review: true, cultural: null },
{ week: 14, day: 2, num: 134, type: 'conversation', title: 'Rollenspiel - Missverständnisse lösen', desc: 'Missverständnisse ruhig und höflich klären', targetMin: 22, targetScore: 78, review: false, cultural: null },
{ week: 14, day: 3, num: 135, type: 'review', title: 'Stabilisierungsblock 2 - Intensiv I', desc: 'Erste verdichtete Wiederholung des zweiten Stabilisierungsblocks', targetMin: 30, targetScore: 82, review: false, cultural: null },
{ week: 14, day: 3, num: 136, type: 'vocab', title: 'Fehlerschwerpunkte Negation & Artikel', desc: 'Negation und Artikel gezielt zusammen trainieren', targetMin: 20, targetScore: 85, review: true, cultural: null },
{ week: 14, day: 4, num: 137, type: 'conversation', title: 'Freies Sprechen - Alltag ohne Stütze', desc: 'Mit wenig Stütze frei über Alltag sprechen', targetMin: 24, targetScore: 78, review: false, cultural: null },
{ week: 14, day: 4, num: 138, type: 'vocab', title: 'Mischtraining - Reale Situationen II', desc: 'Zweite große Mischrunde realer Situationen', targetMin: 20, targetScore: 85, review: true, cultural: null },
{ week: 14, day: 5, num: 139, type: 'review', title: 'Stabilisierungsblock 2 - Intensiv II', desc: 'Zweite verdichtete Wiederholung des zweiten Stabilisierungsblocks', targetMin: 30, targetScore: 82, review: false, cultural: null },
{ week: 14, day: 5, num: 140, type: 'vocab', title: 'Stabilisierungsblock 2 - Checkpoint', desc: 'Diagnose zum zweiten Stabilisierungsblock', targetMin: 18, targetScore: 84, review: true, cultural: null },
{ week: 15, day: 1, num: 141, type: 'review', title: 'Großes Mischreview I', desc: 'Breite Wiederholung des Gesamtpfads', targetMin: 30, targetScore: 82, review: false, cultural: null },
{ week: 15, day: 1, num: 142, type: 'vocab', title: 'Großes Mischreview II', desc: 'Zweite große Mischrunde mit höherer Dichte', targetMin: 20, targetScore: 85, review: true, cultural: null },
{ week: 15, day: 2, num: 143, type: 'grammar', title: 'Fehlertraining - letzte Schwächen', desc: 'Die letzten typischen Fehlerfelder gezielt bearbeiten', targetMin: 22, targetScore: 78, review: true, cultural: null },
{ week: 15, day: 2, num: 144, type: 'conversation', title: 'Freies Sprechen - längere Antworten', desc: 'Längere Antworten mit mehr Struktur geben', targetMin: 24, targetScore: 78, review: false, cultural: null },
{ week: 15, day: 3, num: 145, type: 'review', title: 'Langzeitreview I', desc: 'Frühe Inhalte gezielt gegen Vergessen absichern', targetMin: 30, targetScore: 82, review: false, cultural: null },
{ week: 15, day: 3, num: 146, type: 'vocab', title: 'Langzeitreview II', desc: 'Frühe und spätere Inhalte gemeinsam reaktivieren', targetMin: 20, targetScore: 85, review: true, cultural: null },
{ week: 15, day: 4, num: 147, type: 'conversation', title: 'Rollenspiele - echte Situationen', desc: 'Echte Situationen flexibel kombinieren', targetMin: 24, targetScore: 78, review: false, cultural: null },
{ week: 15, day: 4, num: 148, type: 'vocab', title: 'Abschlusstest - Stabilisierung', desc: 'Finaler Wortschatztest der Stabilisierungsphase', targetMin: 20, targetScore: 84, review: true, cultural: null },
{ week: 15, day: 5, num: 149, type: 'review', title: 'Abschlussprüfung - Gesamtpfad', desc: 'Große Abschlussprüfung über den gesamten Deutschpfad', targetMin: 32, targetScore: 84, review: false, cultural: 'Kommunikative Alltagssicherheit ist wichtiger als perfekte Formbeherrschung.' },
{ week: 15, day: 5, num: 150, type: 'culture', title: 'Kulturelle Orientierung in Deutschland vertieft', desc: 'Direktheit, Termine, Siezen und Alltagserwartungen vertiefen', targetMin: 16, targetScore: 0, review: false, cultural: 'Klare Aussagen, Termine und Pünktlichkeit werden im deutschen Alltag oft sehr ernst genommen.' }
];

View File

@@ -3542,6 +3542,7 @@ class FalukantService extends BaseService {
return {
relationshipId: r.id,
name: partner.firstName || 'Unknown',
age: partner.age != null ? partner.age : null,
gender: partner.gender || null,
title: partner.nobleTitle || '',
role: state.loverRole || 'lover',

View File

@@ -0,0 +1,493 @@
# Deutschkurs für Bisaya-Lernende: Umsetzungsdokument
## 1. Ziel
Der Deutschkurs für Bisaya-Muttersprachler soll nicht wie ein generischer A1-Wortschatzkurs aufgebaut sein, sondern gezielt auf die typischen Hürden von Bisaya-Lernenden reagieren.
Das Ziel ist:
- schnelle alltagsnahe Sprechfähigkeit
- frühes Verstehen typischer deutscher Satzmuster
- systematische Fehlerreduktion bei genau den Strukturen, die für Bisaya-Lernende schwer sind
- starke Wiederholung ohne stumpfes Kreisen
- schrittweise Entwicklung von freier Produktion
Der Kurs soll damit drei Dinge zugleich leisten:
- neuen Stoff effizient aufbauen
- alte Inhalte tief verankern
- typische Transferfehler aus der Erstsprache gezielt abfangen
## 2. Besondere Perspektive: Deutsch aus Sicht von Bisaya-Lernenden
Der Kurs muss didaktisch anders gebaut werden als ein allgemeiner Deutschkurs.
Typische Spannungsfelder:
- Deutsch hat Artikel, Genus und Kasus; Bisaya nicht in derselben Weise
- Deutsch markiert Zeitformen anders und oft expliziter
- deutsche Satzstellung ist viel rigider
- trennbare Verben, Verbzweitstellung und Nebensätze sind ungewohnt
- Funktionswörter wie `der`, `die`, `das`, `den`, `dem`, `ein`, `eine` wirken für Lernende anfangs wenig greifbar
- Höflichkeit, Direktheit und Standardreaktionen sind kulturell anders verteilt
Das heißt:
- der Kurs darf nicht nur Vokabel + Übersetzung sein
- er muss stark mit Mustern, Kontrasten und Minimalpaaren arbeiten
- Fehlertraining muss früh anfangen, nicht erst spät
## 3. Produktentscheidung
Der Deutschkurs wird als eigener Lernpfad konzipiert:
- `Deutsch für Bisaya-Lernende - Alltag & Stabilisierung`
Er soll wie beim Bisaya-Ausbau in feste Lernphasen aufgeteilt werden, aber die Inhalte speziell auf deutsche Hürden für Bisaya-Lernende zuschneiden.
## 4. Zielbild des Kursmodells
Der neue Deutschpfad besteht aus drei fachlichen Lernphasen.
### 4.1 Phase A: Schnellstart
Ziel:
- sofort auf elementare Alltagssituationen reagieren
- Begrüßung, Familie, Essen, Bedürfnisse, Wege und Hilfe ausdrücken
- erste deutsche Standardsätze ohne langes Nachdenken verwenden
Dauer:
- `6 Wochen`
Fokus:
- feste Alltagsmuster
- hochfrequente Sätze
- frühe Hör- und Sprechaktivierung
- noch reduzierte Grammatiklast
### 4.2 Phase B: Alltag
Ziel:
- Alltag auf Deutsch in mehr Bereichen tragen
- mit Schule, Arzt, Einkauf, Formularen, Nachbarschaft und Arbeit umgehen
- häufige Satzmuster produktiv variieren
Dauer:
- `8 bis 12 Wochen`
Fokus:
- deutsche Satzstellung
- Verbformen im Alltag
- Artikel und Pluralformen
- Fragen, Antworten, Bitten, Erklären
### 4.3 Phase C: Stabilisierung
Ziel:
- Langzeitverfügbarkeit
- automatische Reaktion auf Standardsituationen
- deutliche Reduktion typischer Bisaya-Deutsch-Fehler
- mehr freie und zusammenhängende Produktion
Dauer:
- `3 bis 6 Monate`
Fokus:
- Kontrasttraining
- gemischte Situationen
- Fehlerschwerpunkte
- freie Produktion
- langsame Langzeitwiederholung
## 5. Technische Phasenlabels
Wie beim Bisaya-Pfad werden drei feste Phasenlabels gespeichert:
- `quickstart`
- `daily_life`
- `stabilization`
## 6. Didaktische Grundprinzipien
### 6.1 Muster vor Einzelsammlung
Deutsch soll zuerst über verwendbare Muster gelernt werden:
- `Ich heiße ...`
- `Ich komme aus ...`
- `Ich habe ...`
- `Ich brauche ...`
- `Wo ist ...?`
- `Ich möchte ...`
- `Können Sie das bitte wiederholen?`
Nicht:
- lange Wortlisten ohne direkte Verwendbarkeit
### 6.2 Fehler früh sichtbar machen
Deutschfehler von Bisaya-Lernenden sollten nicht erst im Fortgeschrittenenbereich Thema werden.
Schon früh müssen Kontraste kommen wie:
- `ich bin` vs. `ich habe`
- `der / die / das`
- `ein / eine`
- `ich gehe` vs. `ich bin gegangen`
- `ich will` vs. `ich möchte`
- `wo` vs. `wohin`
- `nicht` vs. `kein`
### 6.3 Wiederholung in Wellen
Wie beim Bisaya-Kurs:
- kein reines Vokabel-Hämmern
- aber auch keine endlose Dauerschleife ohne Fortschritt
Stattdessen:
1. Mikro-Wiederholung innerhalb der Lektion
2. Kurzintervall-Wiederholung nach 1 / 3 / 7 Tagen
3. Intensiv-Wiederholungsphasen nach jedem Block
4. Spiral-Wiederholung alter Inhalte in neuen Kontexten
## 7. Typische Fehlerfelder für Bisaya-Lernende im Deutschen
Diese Fehlerfelder müssen eigene Lektions- und Reviewblöcke bekommen.
### 7.1 Artikel und Genus
Schwierigkeit:
- `der`, `die`, `das`
- `ein`, `eine`
- Artikel erscheinen oft willkürlich
Konsequenz:
- nicht isoliert lehren
- immer als Chunk:
- `der Tisch`
- `die Tasche`
- `das Kind`
### 7.2 Kasus im Alltag
Schwierigkeit:
- `ich sehe den Mann`
- `ich gebe dem Kind Wasser`
- `mit dem Bus`
Konsequenz:
- erst alltagsnah
- nicht über Grammatikdefinitionen, sondern über wiederkehrende Satzmuster
### 7.3 Satzstellung
Schwierigkeit:
- Verbzweitstellung
- Verbendstellung im Nebensatz
- Inversion nach Vorfeld
Konsequenz:
- sehr viele Mini-Kontraste
- Satzbau-Drills mit echten Alltagssätzen
### 7.4 Zeitformen
Schwierigkeit:
- Präsens, Perfekt, Modalverben
- deutsche Hilfsverben
Konsequenz:
- Präsens zuerst als Alltagsbasis
- Perfekt früh für häufige Erzählungen
- keine Überladung mit allen Formen gleichzeitig
### 7.5 Höflichkeit und Register
Schwierigkeit:
- `du` vs. `Sie`
- deutsche Direktheit
- höfliche Bitten
Konsequenz:
- soziale Szenarien mit klarer Registertrennung
### 7.6 Negation
Schwierigkeit:
- `nicht` vs. `kein`
Konsequenz:
- eigener Kontrastblock
- viele kurze Minimalpaare
## 8. Kursstruktur
### Phase 1: Schnellstart, 6 Wochen
Ziel:
- elementare mündliche Handlungsfähigkeit
Module:
1. Begrüßung, Name, Herkunft
2. Familie und Zuhause
3. Essen, Trinken, Fürsorge
4. Bedürfnisse und Gefühle
5. Orte, Wege, Verkehr
6. Zahlen, Geld, Preise
7. Gesundheit und Hilfe
8. Bitte, Danke, Entschuldigung
9. Tagesablauf
10. erste Wiederholungs- und Checkpointblöcke
### Phase 2: Alltag, 8 bis 12 Wochen
Module:
1. Kinder, Schule, Betreuung
2. Arzt, Apotheke, Termine
3. Einkauf, Markt, Mengen
4. Formulare, Amt, Dokumente
5. Nachbarschaft und Besuch
6. Hilfe, Bitte, Ablehnung
7. Arbeit und Aufgaben
8. Wohnung, Haushalt, Reparaturen
9. soziale Situationen und Konflikte
10. gemischte Alltagsszenarien
### Phase 3: Stabilisierung, 3 bis 6 Monate
Module:
1. Fehlerschwerpunkte Artikel
2. Fehlerschwerpunkte Satzstellung
3. Fehlerschwerpunkte Zeitformen
4. Mischtraining realer Situationen
5. freies Erzählen
6. Langzeitreview
7. große Abschlussdiagnosen
## 9. Lektionstypen
Die vorhandenen Typen können weiter genutzt werden:
- `vocab`
- `conversation`
- `grammar`
- `review`
- `culture`
Didaktisch sollten sie aber stärker spezialisiert werden:
- `core_input`
- `pattern_drill`
- `guided_dialogue`
- `contrast_training`
- `real_life_scenario`
- `intensive_review`
- `checkpoint`
## 10. Wiederholungsmodell
### 10.1 Verteilung von neuem und altem Stoff
- Start eines neuen Blocks:
- `70 % neu`
- `30 % alt`
- Mitte des Blocks:
- `50 % neu`
- `50 % alt`
- vor Intensivphase:
- `30 % neu`
- `70 % alt`
- Intensivphase:
- `10 % neu`
- `90 % alt`
### 10.2 Intensiv-Wiederholungsphasen
Nach jedem größeren Block:
- `2 bis 3` Lektionen ohne viel neuen Stoff
- Fokus auf:
- Abruf
- Kontrast
- typische Fehler
- gemischte Situationen
### 10.3 Langzeitreview
Frühe Inhalte müssen später wiederkehren, aber nicht in derselben Form.
Beispiel:
- früh:
- `Wo ist der Bahnhof?`
- später:
- `Entschuldigung, wo ist der Bahnhof?`
- `Wo ist der Bahnhof? Ich muss dorthin.`
- `Können Sie mir bitte sagen, wo der Bahnhof ist?`
## 11. UI- und Produktlogik
Die App sollte den Kurs nicht als lineare Liste von Lektionen darstellen, sondern als täglichen Lernfluss:
1. fällige Wiederholungen
2. aktueller Block
3. Intensivphase, wenn fällig
4. freie Sprech-/Anwendungsphase
Der Startscreen sollte zeigen:
- heute fällige Wiederholungen
- neuer Stoff verfügbar
- typische Fehler von gestern
- nächster Checkpoint
## 12. Konkrete Fehlertrainingsblöcke
Für Deutsch aus Bisaya-Sicht besonders wichtig:
1. `der / die / das`
2. `ein / eine`
3. `ich bin / ich habe`
4. `ich gehe / ich bin gegangen`
5. `wo / wohin`
6. `nicht / kein`
7. `du / Sie`
8. deutsche Wortstellung im Hauptsatz
9. Nebensatz mit `weil`, `dass`, `wenn`
10. Modalverben im Alltag
## 13. Phase-1-Umsetzungsvorschlag
Die erste technische Umsetzung sollte nicht sofort den ganzen Deutschkurs schreiben, sondern die Grundlage legen.
### Phase 1A
- Kursstruktur für `Deutsch für Bisaya-Lernende` definieren
- Phasen- und Blocklogik analog zum Bisaya-System übernehmen
- deutsche Didaktikfelder pro Lektion pflegen
### Phase 1B
- erste 4 bis 6 Wochen inhaltlich aufbauen
- frühe Fehlerkontraste schon einbauen
- Übungen für Begrüßung, Familie, Bedürfnisse, Wege, Hilfe
### Phase 1C
- spezielles Fehlertraining für:
- Artikel
- Satzstellung
- Negation
- dazu eigene `review`- und `grammar`-Lektionen
## 14. Empfohlene erste Module
Für die erste reale Bauphase:
1. `Begrüßung & Vorstellung`
2. `Familie & Zuhause`
3. `Essen & Trinken`
4. `Bedürfnisse & Gefühle`
5. `Weg & Verkehr`
6. `Bitte, Danke, Entschuldigung`
7. `Arzt & Hilfe`
8. `Zahlen, Geld, Preise`
9. `Tagesablauf`
10. `Intensivwiederholung Schnellstart`
## 15. Nächste Umsetzungsschritte
1. deutsches Kursziel und Titel festlegen
2. Wochen 1 bis 6 als echten Schnellstart definieren
3. deutsch-spezifische Fehlerblöcke pro Woche einplanen
4. Intensiv-Wiederholungsphasen pro Block festlegen
5. danach Übungen und Content-Skripte analog zum Bisaya-System aufbauen
## 15.1 Aktueller Implementierungsstand
Die Phasen 1 bis 5 sind jetzt als technische Struktur angelegt:
- [german-for-bisaya-phase1.js](/mnt/share/torsten/Programs/YourPart3/backend/scripts/german-for-bisaya-phase1.js)
- Wochen `1 bis 6`
- `60` Lektionen
- Schnellstart und erste Fehlerfelder
- [german-for-bisaya-phase2-pedagogy.js](/mnt/share/torsten/Programs/YourPart3/backend/scripts/german-for-bisaya-phase2-pedagogy.js)
- technische Phasen-/Blocklogik
- `quickstart`, `daily_life`, `stabilization`
- [german-for-bisaya-phase3-extension.js](/mnt/share/torsten/Programs/YourPart3/backend/scripts/german-for-bisaya-phase3-extension.js)
- Wochen `7 bis 9`
- Alltagsausbau
- [german-for-bisaya-phase4-extension.js](/mnt/share/torsten/Programs/YourPart3/backend/scripts/german-for-bisaya-phase4-extension.js)
- Wochen `10 bis 12`
- vertiefter Alltag und Fehlertraining
- [german-for-bisaya-phase5-extension.js](/mnt/share/torsten/Programs/YourPart3/backend/scripts/german-for-bisaya-phase5-extension.js)
- Wochen `13 bis 15`
- Stabilisierung, Mischtraining und Abschluss
- [create-german-for-bisaya-course.js](/mnt/share/torsten/Programs/YourPart3/backend/scripts/create-german-for-bisaya-course.js)
- erstellt direkt den kompletten `15-Wochen`-Pfad
- [create-german-for-bisaya-course-content.js](/mnt/share/torsten/Programs/YourPart3/backend/scripts/create-german-for-bisaya-course-content.js)
- erzeugt Übungen für den Gesamtpfad
- mit handgeschriebenen Kernlektionen und generischem Fallback
- [extend-german-for-bisaya-course-phase3.js](/mnt/share/torsten/Programs/YourPart3/backend/scripts/extend-german-for-bisaya-course-phase3.js)
- [extend-german-for-bisaya-course-phase4.js](/mnt/share/torsten/Programs/YourPart3/backend/scripts/extend-german-for-bisaya-course-phase4.js)
- [extend-german-for-bisaya-course-phase5.js](/mnt/share/torsten/Programs/YourPart3/backend/scripts/extend-german-for-bisaya-course-phase5.js)
### Neuer Kurs von Grund auf
```bash
node backend/scripts/create-german-for-bisaya-course.js <ownerHashedId>
node backend/scripts/create-german-for-bisaya-course-content.js
```
### Bestehenden Kurs stufenweise erweitern
```bash
node backend/scripts/extend-german-for-bisaya-course-phase3.js
node backend/scripts/extend-german-for-bisaya-course-phase4.js
node backend/scripts/extend-german-for-bisaya-course-phase5.js
node backend/scripts/create-german-for-bisaya-course-content.js
```
## 16. Ergebnis
Der Deutschkurs für Bisaya-Lernende sollte nicht einfach ein übersetzter Standardkurs sein.
Er muss:
- alltagsnah
- kontrastiv
- wiederholungsstark
- satzmusterorientiert
- fehlerbewusst
gebaut sein.
Dann entsteht kein bloßer Vokabelkurs, sondern ein echter Lernpfad, der auf die Ausgangssprache und die typischen Schwierigkeiten der Lernenden reagiert.

View File

@@ -677,6 +677,7 @@
"lovers": {
"title": "Liebhaber und Mätressen",
"none": "Keine Liebhaber vorhanden.",
"age": "Alter",
"affection": "Zuneigung",
"visibility": "Sichtbarkeit",
"discretion": "Diskretion",

View File

@@ -728,6 +728,7 @@
"lovers": {
"title": "Lovers and Mistresses",
"none": "No lovers present.",
"age": "Age",
"affection": "Affection",
"visibility": "Visibility",
"discretion": "Discretion",

View File

@@ -658,6 +658,7 @@
"lovers": {
"title": "Amantes y favoritas",
"none": "No hay amantes.",
"age": "Edad",
"affection": "Afecto",
"visibility": "Visibilidad",
"discretion": "Discreción",

View File

@@ -347,6 +347,9 @@
<div class="lover-card__header">
<div>
<strong>{{ $t('falukant.titles.' + lover.gender + '.' + lover.title) }} {{ lover.name }}</strong>
<div v-if="lover.age != null" class="lover-card__age">
{{ $t('falukant.family.lovers.age') }}: {{ lover.age }}
</div>
<div class="lover-card__role">
{{ $t('falukant.family.lovers.role.' + (lover.role || 'lover')) }}
</div>
@@ -421,7 +424,7 @@
<article v-for="candidate in possibleLovers" :key="candidate.characterId" class="lover-candidate-card">
<div class="lover-candidate-card__main">
<strong>{{ $t('falukant.titles.' + candidate.gender + '.' + candidate.title) }} {{ candidate.name }}</strong>
<span>{{ $t('falukant.family.spouse.age') }}: {{ candidate.age }}</span>
<span>{{ $t('falukant.family.lovers.age') }}: {{ candidate.age }}</span>
<span>{{ $t('falukant.family.lovers.statusFit') }}: {{ candidate.statusFit }}</span>
<span>{{ $t('falukant.family.lovers.monthlyCost') }}: {{ formatCost(candidate.estimatedMonthlyCost || 0) }}</span>
</div>
@@ -1276,6 +1279,12 @@ export default {
margin-bottom: 12px;
}
.lover-card__age {
font-size: 0.9rem;
color: rgba(0, 0, 0, 0.62);
margin-top: 4px;
}
.lover-card__role {
margin-top: 4px;
color: var(--color-text-secondary);