feat(falukant): add age information to lovers in family view
All checks were successful
Deploy to production / deploy (push) Successful in 3m7s
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:
735
backend/scripts/create-german-for-bisaya-course-content.js
Normal file
735
backend/scripts/create-german-for-bisaya-course-content.js
Normal 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);
|
||||
});
|
||||
145
backend/scripts/create-german-for-bisaya-course.js
Normal file
145
backend/scripts/create-german-for-bisaya-course.js
Normal 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);
|
||||
});
|
||||
}
|
||||
84
backend/scripts/extend-german-for-bisaya-course-phase3.js
Normal file
84
backend/scripts/extend-german-for-bisaya-course-phase3.js
Normal 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);
|
||||
});
|
||||
}
|
||||
84
backend/scripts/extend-german-for-bisaya-course-phase4.js
Normal file
84
backend/scripts/extend-german-for-bisaya-course-phase4.js
Normal 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);
|
||||
});
|
||||
}
|
||||
84
backend/scripts/extend-german-for-bisaya-course-phase5.js
Normal file
84
backend/scripts/extend-german-for-bisaya-course-phase5.js
Normal 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);
|
||||
});
|
||||
}
|
||||
345
backend/scripts/german-for-bisaya-phase1.js
Normal file
345
backend/scripts/german-for-bisaya-phase1.js
Normal 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.' }
|
||||
]
|
||||
})
|
||||
};
|
||||
40
backend/scripts/german-for-bisaya-phase2-pedagogy.js
Normal file
40
backend/scripts/german-for-bisaya-phase2-pedagogy.js
Normal 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'
|
||||
};
|
||||
}
|
||||
75
backend/scripts/german-for-bisaya-phase3-extension.js
Normal file
75
backend/scripts/german-for-bisaya-phase3-extension.js
Normal 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 }
|
||||
];
|
||||
75
backend/scripts/german-for-bisaya-phase4-extension.js
Normal file
75
backend/scripts/german-for-bisaya-phase4-extension.js
Normal 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 }
|
||||
];
|
||||
75
backend/scripts/german-for-bisaya-phase5-extension.js
Normal file
75
backend/scripts/german-for-bisaya-phase5-extension.js
Normal 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.' }
|
||||
];
|
||||
@@ -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',
|
||||
|
||||
493
docs/GERMAN_FOR_BISAYA_IMPLEMENTATION_SPEC.md
Normal file
493
docs/GERMAN_FOR_BISAYA_IMPLEMENTATION_SPEC.md
Normal 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.
|
||||
@@ -677,6 +677,7 @@
|
||||
"lovers": {
|
||||
"title": "Liebhaber und Mätressen",
|
||||
"none": "Keine Liebhaber vorhanden.",
|
||||
"age": "Alter",
|
||||
"affection": "Zuneigung",
|
||||
"visibility": "Sichtbarkeit",
|
||||
"discretion": "Diskretion",
|
||||
|
||||
@@ -728,6 +728,7 @@
|
||||
"lovers": {
|
||||
"title": "Lovers and Mistresses",
|
||||
"none": "No lovers present.",
|
||||
"age": "Age",
|
||||
"affection": "Affection",
|
||||
"visibility": "Visibility",
|
||||
"discretion": "Discretion",
|
||||
|
||||
@@ -658,6 +658,7 @@
|
||||
"lovers": {
|
||||
"title": "Amantes y favoritas",
|
||||
"none": "No hay amantes.",
|
||||
"age": "Edad",
|
||||
"affection": "Afecto",
|
||||
"visibility": "Visibilidad",
|
||||
"discretion": "Discreción",
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user