feat(vocab): integrate fallback core patterns and enhance vocabulary display in VocabLessonView
All checks were successful
Deploy to production / deploy (push) Successful in 2m44s

- Added a new method in VocabService to merge core pattern glosses with fallback patterns, improving vocabulary clarity and consistency.
- Updated VocabLessonView to utilize the merged core patterns, ensuring a comprehensive vocabulary overview for users.
- Refactored vocabulary handling logic to enhance user experience during vocabulary lessons, including improved display of lesson vocabulary.
This commit is contained in:
Torsten Schulz (local)
2026-04-01 09:58:32 +02:00
parent 1328e4983e
commit 6d13965c76
6 changed files with 144 additions and 45 deletions

View File

@@ -0,0 +1,24 @@
export const BISAYA_PHASE1_DIDACTICS = {
'Begrüßungen & Höflichkeit': {
corePatterns: [
{ target: 'Kumusta ka?', gloss: 'Wie geht es dir?' },
{ target: 'Maayong buntag.', gloss: 'Guten Morgen.' },
{ target: 'Maayong adlaw.', gloss: 'Guten Tag.' },
{ target: 'Maayong gabii.', gloss: 'Guten Abend.' },
{ target: 'Maayong gabii, matulog na ta.', gloss: 'Guten Abend, wir legen uns schlafen.' },
{ target: 'Katulog og maayo.', gloss: 'Schlaf gut.' },
{ target: 'Kapoy na ka?', gloss: 'Bist du müde?' },
{ target: 'Matulog na ta.', gloss: 'Lass uns schlafen gehen.' },
{ target: 'Inom sa og tubig.', gloss: 'Trink Wasser.' },
{ target: 'Patya ang suga.', gloss: 'Mach das Licht aus.' },
{ target: 'Tabuni ang imong kaugalingon.', gloss: 'Deck dich zu.' },
{ target: 'Ugma nasad.', gloss: 'Bis morgen wieder.' },
{ target: 'Damgo og nindot.', gloss: 'Träum schön.' },
{ target: 'Amping.', gloss: 'Pass auf dich auf.' },
{ target: 'Babay.', gloss: 'Tschüss.' },
{ target: 'Maayo ko.', gloss: 'Mir geht es gut.' },
{ target: 'Salamat.', gloss: 'Danke.' },
{ target: 'Palihug.', gloss: 'Bitte.' }
]
}
};

View File

@@ -12,6 +12,7 @@ import UserParam from '../models/community/user_param.js';
import { sequelize } from '../utils/sequelize.js';
import { notifyUser } from '../utils/socket.js';
import { Op } from 'sequelize';
import { BISAYA_PHASE1_DIDACTICS } from '../scripts/bisaya-course-phase1.js';
export default class VocabService {
async _getUserByHashedId(hashedUserId) {
@@ -347,6 +348,27 @@ export default class VocabService {
});
}
_mergeCorePatternGlosses(primaryPatterns = [], fallbackPatterns = []) {
const fallbackByTarget = new Map(
fallbackPatterns
.map((entry) => this._normalizeCorePatternEntry(entry))
.filter(Boolean)
.map((entry) => [this._normalizeLexeme(entry.target), entry.gloss || ''])
);
return primaryPatterns.map((entry) => {
const normalized = this._normalizeCorePatternEntry(entry);
if (!normalized) {
return null;
}
if (normalized.gloss) {
return normalized;
}
const gloss = fallbackByTarget.get(this._normalizeLexeme(normalized.target)) || '';
return gloss ? { ...normalized, gloss } : normalized;
}).filter(Boolean);
}
_normalizeStructuredList(value, keys = ['title', 'text']) {
if (!value) return [];
if (Array.isArray(value)) {
@@ -560,9 +582,13 @@ export default class VocabService {
const learningGoals = this._normalizeStringList(plainLesson.learningGoals);
const extractedTrainerVocabs = this._extractTrainerVocabsFromExercises(grammarExercises);
const corePatterns = this._enrichCorePatternsWithGloss(
this._normalizeCorePatternList(plainLesson.corePatterns),
extractedTrainerVocabs
const phase1FallbackCorePatterns = BISAYA_PHASE1_DIDACTICS[plainLesson.title]?.corePatterns || [];
const corePatterns = this._mergeCorePatternGlosses(
this._enrichCorePatternsWithGloss(
this._normalizeCorePatternList(plainLesson.corePatterns),
extractedTrainerVocabs
),
phase1FallbackCorePatterns
);
const grammarFocus = this._normalizeStructuredList(plainLesson.grammarFocus, ['title', 'text', 'example']);
const explicitSpeakingPrompts = this._normalizeStructuredList(plainLesson.speakingPrompts, ['title', 'prompt', 'cue']);
@@ -578,9 +604,12 @@ export default class VocabService {
],
corePatterns: corePatterns.length > 0
? corePatterns
: this._enrichCorePatternsWithGloss(
uniquePatterns.slice(0, 5).map((s) => ({ target: String(s || '').trim(), gloss: '' })).filter((p) => p.target),
extractedTrainerVocabs
: this._mergeCorePatternGlosses(
this._enrichCorePatternsWithGloss(
uniquePatterns.slice(0, 5).map((s) => ({ target: String(s || '').trim(), gloss: '' })).filter((p) => p.target),
extractedTrainerVocabs
),
phase1FallbackCorePatterns
),
grammarFocus: grammarFocus.length > 0 ? grammarFocus : uniqueGrammarExplanations.slice(0, 4),
speakingPrompts: explicitSpeakingPrompts.length > 0 ? explicitSpeakingPrompts : speakingPrompts.slice(0, 4),