From b5b4d722932a120f6440efdce95335b24b11751c Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Thu, 27 Aug 2026 15:21:40 +0200 Subject: [PATCH] feat(bisaya): enhance speaking prompts and practical tasks for lesson 46 --- ...02-fix-bisaya-lesson-46-question-chain.cjs | 21 +++++++++++ ...00003-clarify-bisaya-lesson-46-prompts.cjs | 35 +++++++++++++++++++ .../scripts/bisaya-course-phase3-extension.js | 2 +- .../scripts/create-bisaya-course-content.js | 20 +++++++++-- 4 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 backend/migrations-active/20260827000002-fix-bisaya-lesson-46-question-chain.cjs create mode 100644 backend/migrations-active/20260827000003-clarify-bisaya-lesson-46-prompts.cjs diff --git a/backend/migrations-active/20260827000002-fix-bisaya-lesson-46-question-chain.cjs b/backend/migrations-active/20260827000002-fix-bisaya-lesson-46-question-chain.cjs new file mode 100644 index 0000000..d2d83d2 --- /dev/null +++ b/backend/migrations-active/20260827000002-fix-bisaya-lesson-46-question-chain.cjs @@ -0,0 +1,21 @@ +'use strict'; + +/** Aligns the generated word order task with its promised three-question scene. */ +module.exports = { + async up(queryInterface) { + await queryInterface.sequelize.query(` + UPDATE community.vocab_grammar_exercise AS exercise + SET question_data = '{"type":"sentence_building","question":"Baue eine natürliche Fragekette mit drei kurzen Fragen.","tokens":["Asa","ka","padulong","Kanus-a","ka","moadto","Kinsa","imong","kuyog"]}'::jsonb, + answer_data = '{"correct":["Asa ka padulong? Kanus-a ka moadto? Kinsa imong kuyog?"]}'::jsonb, + explanation = 'Die Fragekette lautet: "Asa ka padulong? Kanus-a ka moadto? Kinsa imong kuyog?"' + FROM community.vocab_course_lesson AS lesson + WHERE exercise.lesson_id = lesson.id + AND lesson.lesson_number = 46 + AND lesson.title = 'Fragen im Alltag vertiefen' + AND exercise.title = 'Fragen im Alltag vertiefen: Satz aus dem Alltag bauen'; + `); + }, + async down() { + // Do not restore the mismatched single-sentence task. + } +}; diff --git a/backend/migrations-active/20260827000003-clarify-bisaya-lesson-46-prompts.cjs b/backend/migrations-active/20260827000003-clarify-bisaya-lesson-46-prompts.cjs new file mode 100644 index 0000000..e27ea5d --- /dev/null +++ b/backend/migrations-active/20260827000003-clarify-bisaya-lesson-46-prompts.cjs @@ -0,0 +1,35 @@ +'use strict'; + +/** Makes the production tasks explicit instead of naming only grammar categories. */ +module.exports = { + async up(queryInterface) { + await queryInterface.sequelize.query(` + UPDATE community.vocab_grammar_exercise AS exercise + SET question_data = jsonb_set( + exercise.question_data, + '{question}', + to_jsonb('Ordne die Wortkarten als drei Fragen: Wohin geht die Person? Wann geht sie los? Mit wem ist sie unterwegs?'::text) + ) + FROM community.vocab_course_lesson AS lesson + WHERE exercise.lesson_id = lesson.id + AND lesson.lesson_number = 46 + AND lesson.title = 'Fragen im Alltag vertiefen' + AND exercise.title = 'Fragen im Alltag vertiefen: Satz aus dem Alltag bauen'; + + UPDATE community.vocab_grammar_exercise AS exercise + SET question_data = jsonb_set( + exercise.question_data, + '{question}', + to_jsonb('Eine Person geht gleich los. Frage sie auf Bisaya nacheinander: Wohin geht sie? Wann geht sie los? Mit wem ist sie unterwegs? Sprich oder schreibe alle drei Fragen.'::text) + ) + FROM community.vocab_course_lesson AS lesson + WHERE exercise.lesson_id = lesson.id + AND lesson.lesson_number = 46 + AND lesson.title = 'Fragen im Alltag vertiefen' + AND exercise.title = 'Fragen im Alltag vertiefen: Laut sprechen'; + `); + }, + async down() { + // The older prompts were less specific and are deliberately not restored. + } +}; diff --git a/backend/scripts/bisaya-course-phase3-extension.js b/backend/scripts/bisaya-course-phase3-extension.js index 84720eb..231c33c 100755 --- a/backend/scripts/bisaya-course-phase3-extension.js +++ b/backend/scripts/bisaya-course-phase3-extension.js @@ -78,7 +78,7 @@ export const BISAYA_PHASE3_DIDACTICS = { { title: 'ka und imong', text: 'ka bezieht sich auf du als Person, imong auf dein/deine.', example: 'Asa ka padulong? Unsa imong buhaton?' } ], speakingPrompts: [ - { title: 'Drei-Fragen-Kette', prompt: 'Frage nach Ziel, Zeit und Begleitung.', cue: 'Asa ka padulong? Kanus-a ka moadto? Kinsa imong kuyog?' }, + { title: 'Ausgehpläne klären', prompt: 'Eine Person geht gleich los. Frage sie nacheinander, wohin sie geht, wann sie losgeht und mit wem sie unterwegs ist. Sprich oder schreibe alle drei Bisaya-Fragen.', cue: 'Asa ka padulong? Kanus-a ka moadto? Kinsa imong kuyog?' }, { title: 'Reparaturfrage', prompt: 'Sage, dass du fragen möchtest, bitte um Wiederholung und frage nach Bedeutung.', cue: 'Pwede ko mangutana? Palihug ka mubalik? Unsay pasabot ani?' } ], practicalTasks: [ diff --git a/backend/scripts/create-bisaya-course-content.js b/backend/scripts/create-bisaya-course-content.js index cacfd61..edcf6ab 100755 --- a/backend/scripts/create-bisaya-course-content.js +++ b/backend/scripts/create-bisaya-course-content.js @@ -645,14 +645,28 @@ function buildSentenceExercise(lessonTitle, pattern) { } function buildTaskSentenceExercise(lesson, didactics, pattern) { - const sentenceExercise = buildSentenceExercise(lesson.title, pattern); - if (!sentenceExercise) return null; - const practicalTask = Array.isArray(didactics.practicalTasks) ? didactics.practicalTasks[0] : null; + const speakingPrompt = Array.isArray(didactics.speakingPrompts) ? didactics.speakingPrompts[0] : null; + const taskText = normalizeText(practicalTask?.text || ''); + const scenarioCue = normalizeText(speakingPrompt?.cue || ''); + // When the transfer task explicitly asks for a chain or scene, build that + // whole cue. Using an unrelated single core pattern makes the UI promise + // something different from the words it offers. + const sentenceTarget = scenarioCue && /drei kurze fragen|fragekette|szene|dialog/i.test(taskText) + ? scenarioCue + : pattern; + const sentenceExercise = buildSentenceExercise(lesson.title, sentenceTarget); + if (!sentenceExercise) return null; return { ...sentenceExercise, title: `${lesson.title}: Satz aus dem Alltag bauen`, + questionData: { + ...sentenceExercise.questionData, + question: sentenceTarget === scenarioCue + ? 'Ordne die Wortkarten als drei Fragen: Wohin geht die Person? Wann geht sie los? Mit wem ist sie unterwegs?' + : sentenceExercise.questionData.question + }, instruction: practicalTask?.text ? `Baue die passende Formulierung für diese Aufgabe: ${practicalTask.text}` : 'Ordne die Wörter zu einem natürlichen Bisaya-Satz aus dem Alltag.'