feat: erweitere Didaktik-Fragmente und verbessere die Übersetzungen in mehreren Sprachen
All checks were successful
Deploy to production / deploy (push) Successful in 2m6s
All checks were successful
Deploy to production / deploy (push) Successful in 2m6s
This commit is contained in:
@@ -154,6 +154,7 @@ export const BISAYA_DIDACTICS_FRAGMENTS = {
|
|||||||
{ target: 'Dinhi ko.', gloss: 'Ich bin hier.' },
|
{ target: 'Dinhi ko.', gloss: 'Ich bin hier.' },
|
||||||
{ target: 'Naa ko dinhi.', gloss: 'Ich bin hier.' },
|
{ target: 'Naa ko dinhi.', gloss: 'Ich bin hier.' },
|
||||||
{ target: 'Didto siya.', gloss: 'Er/sie ist dort.' },
|
{ target: 'Didto siya.', gloss: 'Er/sie ist dort.' },
|
||||||
|
{ target: 'Adto ko sa merkado.', gloss: 'Ich gehe zum Markt.' },
|
||||||
{ target: 'Adto ta didto.', gloss: 'Lass uns dorthin gehen.' },
|
{ target: 'Adto ta didto.', gloss: 'Lass uns dorthin gehen.' },
|
||||||
{ target: 'Padulong ko sa merkado.', gloss: 'Ich bin auf dem Weg zum Markt.' },
|
{ target: 'Padulong ko sa merkado.', gloss: 'Ich bin auf dem Weg zum Markt.' },
|
||||||
{ target: 'Padulong ta didto.', gloss: 'Lass uns dorthin aufbrechen.' },
|
{ target: 'Padulong ta didto.', gloss: 'Lass uns dorthin aufbrechen.' },
|
||||||
@@ -169,6 +170,16 @@ export const BISAYA_DIDACTICS_FRAGMENTS = {
|
|||||||
title: 'dinhi / didto',
|
title: 'dinhi / didto',
|
||||||
text: '„dinhi“ = hier, „didto“ = dort (weg vom Sprecher).',
|
text: '„dinhi“ = hier, „didto“ = dort (weg vom Sprecher).',
|
||||||
example: 'Naa ko dinhi. Didto ang simbahan.'
|
example: 'Naa ko dinhi. Didto ang simbahan.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Naa + Person + Ort',
|
||||||
|
text: 'Mit „naa“ sagst du, dass jemand an einem Ort ist. Danach steht der Ort oder das Ortswort.',
|
||||||
|
example: 'Naa ko dinhi. Naa siya didto.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'adto vs. padulong',
|
||||||
|
text: '„adto“ ist gehen/fahren zu einem Ziel. „padulong“ betont, dass jemand bereits unterwegs in diese Richtung ist.',
|
||||||
|
example: 'Adto ko sa merkado. Padulong ko sa merkado.'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
speakingPrompts: [
|
speakingPrompts: [
|
||||||
|
|||||||
77
backend/scripts/count_corepatterns.js
Normal file
77
backend/scripts/count_corepatterns.js
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
import fs from 'fs';
|
||||||
|
import path from 'path';
|
||||||
|
|
||||||
|
function readFile(p) {
|
||||||
|
return fs.readFileSync(path.resolve(p), 'utf8');
|
||||||
|
}
|
||||||
|
|
||||||
|
const base = readFile('./backend/scripts/create-bisaya-course.js');
|
||||||
|
const bisaya = readFile('./backend/scripts/bisaya-course-plan-24-43.js');
|
||||||
|
|
||||||
|
function extractLessons(text) {
|
||||||
|
const lessons = new Map();
|
||||||
|
const re = /\{[\s\S]*?num:\s*(\d+),[\s\S]*?title:\s*'([^']+)'[\s\S]*?\}/g;
|
||||||
|
let m;
|
||||||
|
while ((m = re.exec(text))) {
|
||||||
|
const num = Number(m[1]);
|
||||||
|
const title = m[2];
|
||||||
|
if (num >= 1 && num <= 30) lessons.set(num, title);
|
||||||
|
}
|
||||||
|
return lessons;
|
||||||
|
}
|
||||||
|
|
||||||
|
function extractCorePatternsForTitle(title, text) {
|
||||||
|
// Try to find 'title': { ... corePatterns: [ ... ] }
|
||||||
|
const escTitle = title.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
|
||||||
|
const re = new RegExp("'" + escTitle + "'\\s*:\\s*\\{[\\s\\S]*?corePatterns\\s*:\\s*\\[([\\s\\S]*?)\\]", 'm');
|
||||||
|
const m = re.exec(text);
|
||||||
|
if (!m) return null;
|
||||||
|
const inside = m[1];
|
||||||
|
// Count entries: either objects { target: ... } or string entries
|
||||||
|
const lines = inside.split(/\r?\n/).map(l => l.trim()).filter(l => l.length > 0);
|
||||||
|
let count = 0;
|
||||||
|
for (const ln of lines) {
|
||||||
|
if (ln.startsWith('{') || ln.startsWith("'") || ln.startsWith('"')) count++;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
const lessons = extractLessons(base + '\n' + bisaya);
|
||||||
|
const results = [];
|
||||||
|
for (let i = 1; i <= 30; i++) {
|
||||||
|
const title = lessons.get(i);
|
||||||
|
if (!title) {
|
||||||
|
results.push({ num: i, title: null, count: 0, note: 'title not found' });
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let count = extractCorePatternsForTitle(title, base);
|
||||||
|
let source = 'create-bisaya-course.js';
|
||||||
|
if (count === null) {
|
||||||
|
count = extractCorePatternsForTitle(title, bisaya);
|
||||||
|
source = 'bisaya-course-plan-24-43.js';
|
||||||
|
}
|
||||||
|
if (count === null) {
|
||||||
|
// try relationship anchor
|
||||||
|
const relText = bisaya;
|
||||||
|
count = extractCorePatternsForTitle(title, relText);
|
||||||
|
source = 'bisaya-course-plan-24-43.js';
|
||||||
|
}
|
||||||
|
if (count === null) {
|
||||||
|
results.push({ num: i, title, count: 0, note: 'corePatterns not found' });
|
||||||
|
} else {
|
||||||
|
results.push({ num: i, title, count, source });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let total = 0;
|
||||||
|
for (const r of results) {
|
||||||
|
total += r.count || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Core pattern counts for lessons 1..30:');
|
||||||
|
results.forEach(r => {
|
||||||
|
console.log(`${r.num}. ${r.title || '<missing>'} -> ${r.count} ${r.source ? '('+r.source+')' : ''} ${r.note?'- '+r.note:''}`);
|
||||||
|
});
|
||||||
|
console.log('---');
|
||||||
|
console.log('Total core patterns (1..30):', total);
|
||||||
@@ -13,6 +13,7 @@ import VocabCourseLesson from '../models/community/vocab_course_lesson.js';
|
|||||||
import VocabGrammarExercise from '../models/community/vocab_grammar_exercise.js';
|
import VocabGrammarExercise from '../models/community/vocab_grammar_exercise.js';
|
||||||
import VocabCourse from '../models/community/vocab_course.js';
|
import VocabCourse from '../models/community/vocab_course.js';
|
||||||
import User from '../models/community/user.js';
|
import User from '../models/community/user.js';
|
||||||
|
import { BISAYA_DIDACTICS_FRAGMENTS, BISAYA_PHASE1_DIDACTICS } from './bisaya-course-phase1.js';
|
||||||
import { BISAYA_DIDACTICS_24_43, BISAYA_LESSONS_24_43_BY_NUMBER, BISAYA_RELATIONSHIP_ANCHOR_DIDACTICS } from './bisaya-course-plan-24-43.js';
|
import { BISAYA_DIDACTICS_24_43, BISAYA_LESSONS_24_43_BY_NUMBER, BISAYA_RELATIONSHIP_ANCHOR_DIDACTICS } from './bisaya-course-plan-24-43.js';
|
||||||
import { BISAYA_PHASE3_DIDACTICS, BISAYA_PHASE3_LESSONS } from './bisaya-course-phase3-extension.js';
|
import { BISAYA_PHASE3_DIDACTICS, BISAYA_PHASE3_LESSONS } from './bisaya-course-phase3-extension.js';
|
||||||
import { BISAYA_PHASE4_DIDACTICS, BISAYA_PHASE4_LESSONS } from './bisaya-course-phase4-extension.js';
|
import { BISAYA_PHASE4_DIDACTICS, BISAYA_PHASE4_LESSONS } from './bisaya-course-phase4-extension.js';
|
||||||
@@ -26,6 +27,8 @@ function withTypeName(exerciseTypeName, exercise) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const GENERATED_BISAYA_DIDACTICS = {
|
const GENERATED_BISAYA_DIDACTICS = {
|
||||||
|
...BISAYA_PHASE1_DIDACTICS,
|
||||||
|
...BISAYA_DIDACTICS_FRAGMENTS,
|
||||||
...BISAYA_RELATIONSHIP_ANCHOR_DIDACTICS,
|
...BISAYA_RELATIONSHIP_ANCHOR_DIDACTICS,
|
||||||
...BISAYA_DIDACTICS_24_43,
|
...BISAYA_DIDACTICS_24_43,
|
||||||
...BISAYA_PHASE3_DIDACTICS,
|
...BISAYA_PHASE3_DIDACTICS,
|
||||||
@@ -449,11 +452,23 @@ function rotateArray(values, offset) {
|
|||||||
|
|
||||||
function getLessonDidactics(lesson) {
|
function getLessonDidactics(lesson) {
|
||||||
const staticDidactics = GENERATED_BISAYA_DIDACTICS[lesson.title] || {};
|
const staticDidactics = GENERATED_BISAYA_DIDACTICS[lesson.title] || {};
|
||||||
const learningGoals = Array.isArray(lesson.learningGoals) ? lesson.learningGoals : (staticDidactics.learningGoals || []);
|
const learningGoals = Array.isArray(lesson.learningGoals) && lesson.learningGoals.length > 0
|
||||||
const corePatterns = Array.isArray(lesson.corePatterns) ? lesson.corePatterns : (staticDidactics.corePatterns || []);
|
? lesson.learningGoals
|
||||||
const grammarFocus = Array.isArray(lesson.grammarFocus) ? lesson.grammarFocus : (staticDidactics.grammarFocus || []);
|
: (staticDidactics.learningGoals || []);
|
||||||
const speakingPrompts = Array.isArray(lesson.speakingPrompts) ? lesson.speakingPrompts : (staticDidactics.speakingPrompts || []);
|
const corePatterns = [
|
||||||
const practicalTasks = Array.isArray(lesson.practicalTasks) ? lesson.practicalTasks : (staticDidactics.practicalTasks || []);
|
...(staticDidactics.corePatterns || []),
|
||||||
|
...(Array.isArray(lesson.corePatterns) ? lesson.corePatterns : [])
|
||||||
|
];
|
||||||
|
const grammarFocus = mergeGrammarFocusForLesson(
|
||||||
|
staticDidactics.grammarFocus || [],
|
||||||
|
Array.isArray(lesson.grammarFocus) ? lesson.grammarFocus : []
|
||||||
|
);
|
||||||
|
const speakingPrompts = Array.isArray(lesson.speakingPrompts) && lesson.speakingPrompts.length > 0
|
||||||
|
? lesson.speakingPrompts
|
||||||
|
: (staticDidactics.speakingPrompts || []);
|
||||||
|
const practicalTasks = Array.isArray(lesson.practicalTasks) && lesson.practicalTasks.length > 0
|
||||||
|
? lesson.practicalTasks
|
||||||
|
: (staticDidactics.practicalTasks || []);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
learningGoals,
|
learningGoals,
|
||||||
@@ -2361,14 +2376,14 @@ const BISAYA_EXERCISES = {
|
|||||||
instruction: 'Fülle die Lücken mit den richtigen Bisaya-Wörtern.',
|
instruction: 'Fülle die Lücken mit den richtigen Bisaya-Wörtern.',
|
||||||
questionData: {
|
questionData: {
|
||||||
type: 'gap_fill',
|
type: 'gap_fill',
|
||||||
text: '{gap} ko sa merkado. (Ich gehe zum Markt.) | {gap} ta didto. (Lass uns dorthin gehen.)',
|
text: '{gap} ko sa merkado. (Ich bin auf dem Weg zum Markt.) | {gap} ta didto. (Lass uns dorthin gehen.)',
|
||||||
gaps: 2
|
gaps: 2
|
||||||
},
|
},
|
||||||
answerData: {
|
answerData: {
|
||||||
type: 'gap_fill',
|
type: 'gap_fill',
|
||||||
answers: ['Padulong', 'Padulong']
|
answers: ['Padulong', 'Adto']
|
||||||
},
|
},
|
||||||
explanation: '\"Padulong\" beschreibt, dass man unterwegs zu einem Ziel ist.'
|
explanation: '„Padulong“ betont die Richtung/Bewegung; „Adto ta didto“ ist die natürliche Aufforderung, dorthin zu gehen.'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
exerciseTypeId: 4, // transformation
|
exerciseTypeId: 4, // transformation
|
||||||
@@ -2386,6 +2401,86 @@ const BISAYA_EXERCISES = {
|
|||||||
alternatives: ['Asa dapit ang simbahan?', 'Asa man ang simbahan?']
|
alternatives: ['Asa dapit ang simbahan?', 'Asa man ang simbahan?']
|
||||||
},
|
},
|
||||||
explanation: '\"simbahan\" = Kirche, \"Asa ang ...?\" = Wo ist ...?'
|
explanation: '\"simbahan\" = Kirche, \"Asa ang ...?\" = Wo ist ...?'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
exerciseTypeId: 4,
|
||||||
|
title: 'Nach der Person fragen',
|
||||||
|
instruction: 'Übersetze ins Bisaya.',
|
||||||
|
questionData: {
|
||||||
|
type: 'transformation',
|
||||||
|
text: 'Wo bist du?',
|
||||||
|
sourceLanguage: 'Deutsch',
|
||||||
|
targetLanguage: 'Bisaya'
|
||||||
|
},
|
||||||
|
answerData: {
|
||||||
|
type: 'transformation',
|
||||||
|
correct: 'Asa ka?',
|
||||||
|
alternatives: ['Asa man ka?']
|
||||||
|
},
|
||||||
|
explanation: '„Asa ka?“ kann je nach Kontext nach Ort oder Ziel fragen.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
exerciseTypeId: 4,
|
||||||
|
title: 'Hier antworten',
|
||||||
|
instruction: 'Übersetze ins Bisaya.',
|
||||||
|
questionData: {
|
||||||
|
type: 'transformation',
|
||||||
|
text: 'Ich bin hier.',
|
||||||
|
sourceLanguage: 'Deutsch',
|
||||||
|
targetLanguage: 'Bisaya'
|
||||||
|
},
|
||||||
|
answerData: {
|
||||||
|
type: 'transformation',
|
||||||
|
correct: 'Naa ko dinhi.',
|
||||||
|
alternatives: ['Dinhi ko.', 'Naa ko diri.', 'Diri ko.']
|
||||||
|
},
|
||||||
|
explanation: '„Naa ko dinhi“ und „Dinhi ko“ sind beide brauchbare Antworten.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
exerciseTypeId: 4,
|
||||||
|
title: 'Dort antworten',
|
||||||
|
instruction: 'Übersetze ins Bisaya.',
|
||||||
|
questionData: {
|
||||||
|
type: 'transformation',
|
||||||
|
text: 'Er ist dort.',
|
||||||
|
sourceLanguage: 'Deutsch',
|
||||||
|
targetLanguage: 'Bisaya'
|
||||||
|
},
|
||||||
|
answerData: {
|
||||||
|
type: 'transformation',
|
||||||
|
correct: 'Didto siya.',
|
||||||
|
alternatives: ['Naa siya didto.', 'Siya didto.']
|
||||||
|
},
|
||||||
|
explanation: '„siya“ kann er oder sie bedeuten; „didto“ markiert dort.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
exerciseTypeId: 3,
|
||||||
|
title: 'Mini-Route bauen',
|
||||||
|
instruction: 'Ordne die Sätze zu einer kurzen Route.',
|
||||||
|
questionData: {
|
||||||
|
type: 'sentence_building',
|
||||||
|
question: 'Baue: Wo ist der Markt? Ich bin hier. Ich bin auf dem Weg zum Markt.',
|
||||||
|
tokens: ['Asa ang merkado?', 'Naa ko dinhi.', 'Padulong ko sa merkado.']
|
||||||
|
},
|
||||||
|
answerData: {
|
||||||
|
correct: ['Asa ang merkado? Naa ko dinhi. Padulong ko sa merkado.']
|
||||||
|
},
|
||||||
|
explanation: 'Die Reihenfolge verbindet Ortsfrage, Standort und Richtung.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
exerciseTypeId: 10,
|
||||||
|
title: 'Weg im Alltag',
|
||||||
|
instruction: 'Antworte kurz mit Ort und Richtung.',
|
||||||
|
questionData: {
|
||||||
|
type: 'situational_response',
|
||||||
|
question: 'Jemand fragt, wo du bist und wohin du gehst. Sage, dass du hier bist und zum Markt unterwegs bist.',
|
||||||
|
keywords: ['naa', 'dinhi', 'padulong', 'merkado']
|
||||||
|
},
|
||||||
|
answerData: {
|
||||||
|
modelAnswer: 'Naa ko dinhi. Padulong ko sa merkado.',
|
||||||
|
keywords: ['naa', 'dinhi', 'padulong', 'merkado']
|
||||||
|
},
|
||||||
|
explanation: 'Die Antwort kombiniert Standort und Zielrichtung in zwei kurzen Sätzen.'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|||||||
@@ -931,7 +931,7 @@
|
|||||||
},
|
},
|
||||||
"mid": {
|
"mid": {
|
||||||
"label": "tunga-tunga nga kahimtang",
|
"label": "tunga-tunga nga kahimtang",
|
||||||
"effects": "Ang mga relasyon makaimpacto pag-iban sa reputasyon ug visibility; ang regular nga suporta makatabang sa pag-stabilize sa relasyon."
|
"effects": "May kombinadong epekto: ang maayo nga pag-atiman sa relasyon makahatag og dali nga pagtaas sa reputasyon ug mapuslanong koneksyon, apan ang pagtaas sa visibility ug taas o dili maayo nga pagdumala sa suporta makapataas sa risgo sa iskandalo ug politikal nga problema. Ang pagka-public nagdugang kaayo sa visibility; ang diskreto mas luwas apan makahatag og gamay nga reputasyon."
|
||||||
},
|
},
|
||||||
"high": {
|
"high": {
|
||||||
"label": "taas nga kahimtang",
|
"label": "taas nga kahimtang",
|
||||||
|
|||||||
@@ -808,7 +808,7 @@
|
|||||||
},
|
},
|
||||||
"mid": {
|
"mid": {
|
||||||
"label": "mittlerer Stand",
|
"label": "mittlerer Stand",
|
||||||
"effects": "Liebschaften können moderat Ansehen und Sichtbarkeit beeinflussen; regelmäßiger Unterhalt stabilisiert Beziehungen."
|
"effects": "Hat gemischte Effekte: gepflegte Liebschaften können kurzfristig Ansehen und nützliche Kontakte bringen, erhöhen aber bei wachsender Sichtbarkeit und schlecht verwaltetem Unterhalt das Skandalrisiko und politische Probleme. Öffentlich bekannte Beziehungen steigern die Sichtbarkeit deutlich; diskrete Beziehungen sind sicherer, liefern jedoch weniger Reputation."
|
||||||
},
|
},
|
||||||
"high": {
|
"high": {
|
||||||
"label": "hoher Stand",
|
"label": "hoher Stand",
|
||||||
|
|||||||
@@ -1007,7 +1007,7 @@
|
|||||||
},
|
},
|
||||||
"mid": {
|
"mid": {
|
||||||
"label": "middle stand",
|
"label": "middle stand",
|
||||||
"effects": "Affairs can moderately affect reputation and visibility; regular upkeep helps stabilise relations."
|
"effects": "Has mixed effects: well-maintained affairs can yield short-term reputation gains and useful contacts, but increased visibility and high or mismanaged upkeep raise scandal risk and political fallout. Public affairs greatly increase visibility; discreet affairs are safer but offer less reputation."
|
||||||
},
|
},
|
||||||
"high": {
|
"high": {
|
||||||
"label": "higher stand",
|
"label": "higher stand",
|
||||||
|
|||||||
@@ -808,7 +808,7 @@
|
|||||||
},
|
},
|
||||||
"mid": {
|
"mid": {
|
||||||
"label": "estamento medio",
|
"label": "estamento medio",
|
||||||
"effects": "Las relaciones pueden afectar moderadamente la reputación y la visibilidad; un mantenimiento regular estabiliza la relación."
|
"effects": "Efectos mixtos: las relaciones bien mantenidas pueden otorgar ganancias de reputación a corto plazo y contactos útiles, pero la mayor visibilidad y un mantenimiento alto o mal gestionado aumentan el riesgo de escándalo y las consecuencias políticas. Hacerla pública incrementa mucho la visibilidad; la discreción reduce riesgos pero ofrece menos reputación."
|
||||||
},
|
},
|
||||||
"high": {
|
"high": {
|
||||||
"label": "estamento alto",
|
"label": "estamento alto",
|
||||||
|
|||||||
@@ -806,7 +806,7 @@
|
|||||||
},
|
},
|
||||||
"mid": {
|
"mid": {
|
||||||
"label": "rang moyen",
|
"label": "rang moyen",
|
||||||
"effects": "Les relations peuvent modérément influencer réputation et visibilité ; un entretien régulier stabilise la relation."
|
"effects": "Effets mitigés : des relations bien entretenues peuvent apporter un gain d'image à court terme et des contacts utiles, mais une visibilité accrue et un entretien mal géré augmentent le risque de scandale et les répercussions politiques. Une relation publique augmente fortement la visibilité ; la discrétion réduit les risques mais rapporte moins de réputation."
|
||||||
},
|
},
|
||||||
"high": {
|
"high": {
|
||||||
"label": "rang élevé",
|
"label": "rang élevé",
|
||||||
|
|||||||
Reference in New Issue
Block a user