feat(bisaya-course): add new 'Ort & Richtung' section with learning goals and practical tasks
All checks were successful
Deploy to production / deploy (push) Successful in 4m46s
All checks were successful
Deploy to production / deploy (push) Successful in 4m46s
- Introduced a new section for 'Ort & Richtung' in the Bisaya didactics, including learning goals, core patterns, grammar focus, speaking prompts, and practical tasks to enhance language learning. - Updated the lesson didactics to include the new section, ensuring comprehensive coverage of location and direction vocabulary.
This commit is contained in:
@@ -140,5 +140,49 @@ export const BISAYA_DIDACTICS_FRAGMENTS = {
|
|||||||
text: 'Baue einen Mini-Dialog mit Zielort, Uhrzeit und Rückkehr in mindestens vier Sätzen.'
|
text: 'Baue einen Mini-Dialog mit Zielort, Uhrzeit und Rückkehr in mindestens vier Sätzen.'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
'Ort & Richtung': {
|
||||||
|
learningGoals: [
|
||||||
|
'Fragen nach Ort und Richtung sicher stellen und beantworten.',
|
||||||
|
'„hier“, „dort“ und „unterwegs nach …“ im Alltag unterscheiden.',
|
||||||
|
'Kurze Weg- und Zielangaben mit bekannten Ortswörtern verbinden.'
|
||||||
|
],
|
||||||
|
corePatterns: [
|
||||||
|
{ target: 'Asa ka?', gloss: 'Wo bist du? / Wohin gehst du?' },
|
||||||
|
{ target: 'Asa ang merkado?', gloss: 'Wo ist der Markt?' },
|
||||||
|
{ target: 'Asa ang simbahan?', gloss: 'Wo ist die Kirche?' },
|
||||||
|
{ target: 'Dinhi ko.', gloss: 'Ich bin hier.' },
|
||||||
|
{ target: 'Naa ko dinhi.', gloss: 'Ich bin hier.' },
|
||||||
|
{ target: 'Didto siya.', gloss: 'Er/sie ist dort.' },
|
||||||
|
{ target: 'Adto ta didto.', gloss: 'Lass uns dorthin gehen.' },
|
||||||
|
{ target: 'Padulong ko sa merkado.', gloss: 'Ich bin auf dem Weg zum Markt.' },
|
||||||
|
{ target: 'Padulong ta didto.', gloss: 'Lass uns dorthin aufbrechen.' },
|
||||||
|
{ target: 'Naa ko sa balay.', gloss: 'Ich bin zu Hause.' }
|
||||||
|
],
|
||||||
|
grammarFocus: [
|
||||||
|
{
|
||||||
|
title: 'Asa = Wo / Wohin',
|
||||||
|
text: '„Asa“ fragt nach Ort oder Ziel. Mit „ang“ kannst du nach einem bestimmten Ort fragen.',
|
||||||
|
example: 'Asa ka? Asa ang merkado?'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'dinhi / didto',
|
||||||
|
text: '„dinhi“ = hier, „didto“ = dort (weg vom Sprecher).',
|
||||||
|
example: 'Naa ko dinhi. Didto ang simbahan.'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
speakingPrompts: [
|
||||||
|
{
|
||||||
|
title: 'Weg fragen',
|
||||||
|
prompt: 'Frage, wo der Markt ist, und sage dann, dass du dorthin unterwegs bist.',
|
||||||
|
cue: 'Asa ang merkado? Padulong ko sa merkado.'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
practicalTasks: [
|
||||||
|
{
|
||||||
|
title: 'Mini-Route',
|
||||||
|
text: 'Bilde drei Sätze: wo du bist, wohin du willst, und dass du unterwegs bist.'
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -166,6 +166,7 @@ export const LESSON_DIDACTICS = {
|
|||||||
'Alltagsgespräche - Teil 1': BISAYA_DIDACTICS_FRAGMENTS['Alltagsgespräche - Teil 1'],
|
'Alltagsgespräche - Teil 1': BISAYA_DIDACTICS_FRAGMENTS['Alltagsgespräche - Teil 1'],
|
||||||
'Haus & Familie': BISAYA_DIDACTICS_FRAGMENTS['Haus & Familie'],
|
'Haus & Familie': BISAYA_DIDACTICS_FRAGMENTS['Haus & Familie'],
|
||||||
'Alltagsgespräche - Teil 2': BISAYA_DIDACTICS_FRAGMENTS['Alltagsgespräche - Teil 2'],
|
'Alltagsgespräche - Teil 2': BISAYA_DIDACTICS_FRAGMENTS['Alltagsgespräche - Teil 2'],
|
||||||
|
'Ort & Richtung': BISAYA_DIDACTICS_FRAGMENTS['Ort & Richtung'],
|
||||||
'Gefühle & Zuneigung': {
|
'Gefühle & Zuneigung': {
|
||||||
learningGoals: [
|
learningGoals: [
|
||||||
'Wichtige Gefühle und Zuneigungsformeln sicher unterscheiden.',
|
'Wichtige Gefühle und Zuneigungsformeln sicher unterscheiden.',
|
||||||
|
|||||||
@@ -707,6 +707,8 @@
|
|||||||
"quickReviewIntro": "Kurze Session mit {count} Begriffen. Nach Abschluss wird die geplante Wiederholung als erledigt markiert.",
|
"quickReviewIntro": "Kurze Session mit {count} Begriffen. Nach Abschluss wird die geplante Wiederholung als erledigt markiert.",
|
||||||
"quickReviewDoneTitle": "Geschafft",
|
"quickReviewDoneTitle": "Geschafft",
|
||||||
"quickReviewDoneScore": "Richtig: {correct} / {total}",
|
"quickReviewDoneScore": "Richtig: {correct} / {total}",
|
||||||
|
"quickReviewNoTermsTitle": "Keine Begriffe für die Kurz-Wiederholung",
|
||||||
|
"quickReviewNoTermsBody": "Für diese Lektion sind keine Kernmuster (core patterns) hinterlegt oder sie konnten nicht geladen werden. Bitte Kursinhalt aktualisieren (Sync) oder die Lektion in der Vollansicht öffnen — danach sollte die Kurz-Wiederholung wieder funktionieren.",
|
||||||
"quickReviewBackToCourse": "Zurück zum Kurs",
|
"quickReviewBackToCourse": "Zurück zum Kurs",
|
||||||
"quickReviewProgress": "Begriff {current} von {total}",
|
"quickReviewProgress": "Begriff {current} von {total}",
|
||||||
"quickReviewPromptMeaning": "Was bedeutet \"{term}\"?",
|
"quickReviewPromptMeaning": "Was bedeutet \"{term}\"?",
|
||||||
|
|||||||
@@ -707,6 +707,8 @@
|
|||||||
"quickReviewIntro": "Short session with {count} terms. After completion, the scheduled review is marked as done.",
|
"quickReviewIntro": "Short session with {count} terms. After completion, the scheduled review is marked as done.",
|
||||||
"quickReviewDoneTitle": "Done",
|
"quickReviewDoneTitle": "Done",
|
||||||
"quickReviewDoneScore": "Correct: {correct} / {total}",
|
"quickReviewDoneScore": "Correct: {correct} / {total}",
|
||||||
|
"quickReviewNoTermsTitle": "No terms for quick review",
|
||||||
|
"quickReviewNoTermsBody": "This lesson has no core patterns loaded, or they could not be read. Please sync course content or open the full lesson — then quick review should work again.",
|
||||||
"quickReviewBackToCourse": "Back to course",
|
"quickReviewBackToCourse": "Back to course",
|
||||||
"quickReviewProgress": "Term {current} of {total}",
|
"quickReviewProgress": "Term {current} of {total}",
|
||||||
"quickReviewPromptMeaning": "What does \"{term}\" mean?",
|
"quickReviewPromptMeaning": "What does \"{term}\" mean?",
|
||||||
|
|||||||
@@ -15,7 +15,13 @@
|
|||||||
{{ $t('socialnetwork.vocab.courses.quickReviewIntro', { count: reviewQueue.length }) }}
|
{{ $t('socialnetwork.vocab.courses.quickReviewIntro', { count: reviewQueue.length }) }}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div v-if="reviewDone" class="review-done">
|
<div v-if="reviewDone && reviewEmptyNoPatterns" class="review-done review-done--empty">
|
||||||
|
<h3>{{ $t('socialnetwork.vocab.courses.quickReviewNoTermsTitle') }}</h3>
|
||||||
|
<p>{{ $t('socialnetwork.vocab.courses.quickReviewNoTermsBody') }}</p>
|
||||||
|
<button type="button" @click="backToCourse">{{ $t('socialnetwork.vocab.courses.quickReviewBackToCourse') }}</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-else-if="reviewDone" class="review-done">
|
||||||
<h3>{{ $t('socialnetwork.vocab.courses.quickReviewDoneTitle') }}</h3>
|
<h3>{{ $t('socialnetwork.vocab.courses.quickReviewDoneTitle') }}</h3>
|
||||||
<p>{{ $t('socialnetwork.vocab.courses.quickReviewDoneScore', { correct: correctCount, total: reviewQueue.length }) }}</p>
|
<p>{{ $t('socialnetwork.vocab.courses.quickReviewDoneScore', { correct: correctCount, total: reviewQueue.length }) }}</p>
|
||||||
<button type="button" @click="backToCourse">{{ $t('socialnetwork.vocab.courses.quickReviewBackToCourse') }}</button>
|
<button type="button" @click="backToCourse">{{ $t('socialnetwork.vocab.courses.quickReviewBackToCourse') }}</button>
|
||||||
@@ -91,6 +97,8 @@ export default {
|
|||||||
needsFeedbackAck: false,
|
needsFeedbackAck: false,
|
||||||
correctCount: 0,
|
correctCount: 0,
|
||||||
reviewDone: false,
|
reviewDone: false,
|
||||||
|
/** Keine Kernmuster geladen — nicht mit normalem Abschluss verwechseln */
|
||||||
|
reviewEmptyNoPatterns: false,
|
||||||
weakVocabMap: {}
|
weakVocabMap: {}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -280,6 +288,7 @@ export default {
|
|||||||
this.lesson = data;
|
this.lesson = data;
|
||||||
this.reviewQueue = this.buildQueue();
|
this.reviewQueue = this.buildQueue();
|
||||||
if (this.reviewQueue.length === 0) {
|
if (this.reviewQueue.length === 0) {
|
||||||
|
this.reviewEmptyNoPatterns = true;
|
||||||
this.reviewDone = true;
|
this.reviewDone = true;
|
||||||
} else {
|
} else {
|
||||||
this.setupCurrent();
|
this.setupCurrent();
|
||||||
|
|||||||
@@ -239,10 +239,18 @@
|
|||||||
<span v-if="previousVocab && previousVocab.length > 0" class="mode-badge" :class="{ 'mode-active': vocabTrainerPhase === 'mixed' }">
|
<span v-if="previousVocab && previousVocab.length > 0" class="mode-badge" :class="{ 'mode-active': vocabTrainerPhase === 'mixed' }">
|
||||||
{{ $t('socialnetwork.vocab.courses.mixedReview') }}
|
{{ $t('socialnetwork.vocab.courses.mixedReview') }}
|
||||||
</span>
|
</span>
|
||||||
<span class="mode-badge" :class="{ 'mode-active': vocabTrainerMode === 'multiple_choice', 'mode-completed': vocabTrainerMode === 'typing' }">
|
<span
|
||||||
|
class="mode-badge mode-clickable"
|
||||||
|
:class="{ 'mode-active': vocabTrainerMode === 'multiple_choice', 'mode-completed': vocabTrainerMode === 'typing' }"
|
||||||
|
@click="switchBackToMultipleChoice"
|
||||||
|
>
|
||||||
{{ $t('socialnetwork.vocab.courses.modeMultipleChoice') }}
|
{{ $t('socialnetwork.vocab.courses.modeMultipleChoice') }}
|
||||||
</span>
|
</span>
|
||||||
<span class="mode-badge" :class="{ 'mode-active': vocabTrainerMode === 'typing' }">
|
<span
|
||||||
|
class="mode-badge mode-clickable"
|
||||||
|
:class="{ 'mode-active': vocabTrainerMode === 'typing' }"
|
||||||
|
@click="switchToTyping"
|
||||||
|
>
|
||||||
{{ $t('socialnetwork.vocab.courses.modeTyping') }}
|
{{ $t('socialnetwork.vocab.courses.modeTyping') }}
|
||||||
</span>
|
</span>
|
||||||
<button @click="stopVocabTrainer" class="btn-stop-trainer">{{ $t('socialnetwork.vocab.courses.stopTrainer') }}</button>
|
<button @click="stopVocabTrainer" class="btn-stop-trainer">{{ $t('socialnetwork.vocab.courses.stopTrainer') }}</button>
|
||||||
@@ -280,7 +288,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- Texteingabe Modus -->
|
<!-- Texteingabe Modus -->
|
||||||
<div v-if="vocabTrainerMode === 'typing' && (!vocabTrainerAnswered || !vocabTrainerLastCorrect)" class="vocab-answer-area typing">
|
<div v-if="vocabTrainerMode === 'typing' && (!vocabTrainerAnswered || !vocabTrainerLastCorrect)" class="vocab-answer-area typing">
|
||||||
<div v-if="vocabTrainerAutoSwitchedToTyping" class="mode-switch-notice">
|
<div class="mode-switch-notice">
|
||||||
<button @click="switchBackToMultipleChoice" class="btn-switch-mode">
|
<button @click="switchBackToMultipleChoice" class="btn-switch-mode">
|
||||||
{{ $t('socialnetwork.vocab.courses.switchBackToMultipleChoice') }}
|
{{ $t('socialnetwork.vocab.courses.switchBackToMultipleChoice') }}
|
||||||
</button>
|
</button>
|
||||||
@@ -3396,9 +3404,9 @@ export default {
|
|||||||
const isReviewLesson = ['review', 'vocab_review'].includes(lessonType)
|
const isReviewLesson = ['review', 'vocab_review'].includes(lessonType)
|
||||||
|| ['review', 'vocab_review', 'intensive_review'].includes(didacticMode);
|
|| ['review', 'vocab_review', 'intensive_review'].includes(didacticMode);
|
||||||
const switchAfterAttempts = isReviewLesson
|
const switchAfterAttempts = isReviewLesson
|
||||||
? Math.max(8, Math.ceil(this.trainerExerciseUnlockAttempts * 0.35))
|
? Math.max(4, Math.ceil(this.trainerExerciseUnlockAttempts * 0.25))
|
||||||
: this.trainerExerciseUnlockAttempts;
|
: this.trainerExerciseUnlockAttempts;
|
||||||
const requiredSuccessRate = isReviewLesson ? 75 : 80;
|
const requiredSuccessRate = isReviewLesson ? 70 : 80;
|
||||||
|
|
||||||
if (this.vocabTrainerMode === 'multiple_choice' && this.vocabTrainerTotalAttempts >= switchAfterAttempts) {
|
if (this.vocabTrainerMode === 'multiple_choice' && this.vocabTrainerTotalAttempts >= switchAfterAttempts) {
|
||||||
const successRate = (this.vocabTrainerCorrect / this.vocabTrainerTotalAttempts) * 100;
|
const successRate = (this.vocabTrainerCorrect / this.vocabTrainerTotalAttempts) * 100;
|
||||||
@@ -3427,6 +3435,15 @@ export default {
|
|||||||
// Starte neue Frage im Multiple Choice Modus
|
// Starte neue Frage im Multiple Choice Modus
|
||||||
this.nextVocabQuestion();
|
this.nextVocabQuestion();
|
||||||
},
|
},
|
||||||
|
switchToTyping() {
|
||||||
|
if (!this.vocabTrainerActive || this.vocabTrainerMode === 'typing') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.vocabTrainerMode = 'typing';
|
||||||
|
this.vocabTrainerAutoSwitchedToTyping = false;
|
||||||
|
this.vocabTrainerPool = [...this.trainableLessonVocab, ...this.vocabTrainerMixedPool];
|
||||||
|
this.nextVocabQuestion();
|
||||||
|
},
|
||||||
getEquivalentVocabAnswers(prompt, direction, allVocabs) {
|
getEquivalentVocabAnswers(prompt, direction, allVocabs) {
|
||||||
const normalizedPrompt = this.normalizeVocab(prompt);
|
const normalizedPrompt = this.normalizeVocab(prompt);
|
||||||
const matches = [];
|
const matches = [];
|
||||||
@@ -5077,6 +5094,14 @@ export default {
|
|||||||
color: #6c757d;
|
color: #6c757d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mode-badge.mode-clickable {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mode-badge.mode-clickable:hover {
|
||||||
|
filter: brightness(0.98);
|
||||||
|
}
|
||||||
|
|
||||||
.mode-badge.mode-active {
|
.mode-badge.mode-active {
|
||||||
background: var(--color-primary);
|
background: var(--color-primary);
|
||||||
color: #2b1f14;
|
color: #2b1f14;
|
||||||
|
|||||||
Reference in New Issue
Block a user