refactor(exercises): standardize answer language handling across exercise scripts
All checks were successful
Deploy to production / deploy (push) Successful in 2m48s

- Introduced a mechanism to infer answer language based on question phrasing in multiple exercise scripts, enhancing consistency in exercise data.
- Updated question formats to clarify the intent of exercises, improving user understanding and engagement.
- Streamlined the code for better maintainability and clarity in exercise generation processes.
This commit is contained in:
Torsten Schulz (local)
2026-04-07 14:32:44 +02:00
parent 160c9dafb2
commit ebb2283646
7 changed files with 107 additions and 6 deletions

View File

@@ -1251,9 +1251,53 @@ export default {
},
lessonVocab() {
const vocabByReference = new Map();
const targetTokenWeight = new Map();
const nativeTokenWeight = new Map();
const addTokens = (text, map, weight = 1) => {
const tokens = String(text || '')
.toLowerCase()
.normalize('NFKC')
.replace(/[\p{P}\p{S}]+/gu, ' ')
.split(/\s+/)
.map((t) => t.trim())
.filter((t) => t.length >= 2);
tokens.forEach((token) => {
map.set(token, (map.get(token) || 0) + weight);
});
};
const sideScore = (text, map) => {
const tokens = String(text || '')
.toLowerCase()
.normalize('NFKC')
.replace(/[\p{P}\p{S}]+/gu, ' ')
.split(/\s+/)
.map((t) => t.trim())
.filter((t) => t.length >= 2);
return tokens.reduce((sum, token) => sum + (map.get(token) || 0), 0);
};
(this.normalizedCorePatterns || []).forEach((p) => {
addTokens(p?.target, targetTokenWeight, 3);
addTokens(p?.gloss, nativeTokenWeight, 3);
});
(this.importantVocab || []).forEach((v) => {
addTokens(v?.reference, targetTokenWeight, 1);
addTokens(v?.learning, nativeTokenWeight, 1);
});
const orientPair = (learning, reference) => {
const l = String(learning || '').trim();
const r = String(reference || '').trim();
if (!l || !r) return { learning: l, reference: r };
const directScore = sideScore(r, targetTokenWeight) + sideScore(l, nativeTokenWeight);
const swappedScore = sideScore(l, targetTokenWeight) + sideScore(r, nativeTokenWeight);
if (swappedScore > directScore) {
return { learning: r, reference: l };
}
return { learning: l, reference: r };
};
const addEntry = (entry) => {
const reference = String(entry?.reference || '').trim();
const learning = String(entry?.learning || '').trim();
const oriented = orientPair(entry?.learning, entry?.reference);
const reference = String(oriented.reference || '').trim();
const learning = String(oriented.learning || '').trim();
if (!reference) return;
const key = this.normalizeLessonVocabTerm(reference);
if (!vocabByReference.has(key)) {