Fixed bisaya course
All checks were successful
Deploy to production / deploy (push) Successful in 2m8s

This commit is contained in:
Torsten Schulz (local)
2026-06-15 16:17:02 +02:00
parent b22e1923cd
commit fc4b607ac2
3 changed files with 194 additions and 10 deletions

View File

@@ -225,9 +225,25 @@ export default {
return Math.round((this.wrongCount / this.totalCount) * 100);
},
currentPrompt() {
if (!this.current) return '';
return this.currentDisplayPrompt || this.currentAnswerPrompt;
},
currentAnswerPrompt() {
if (!this.current) return '';
return this.direction === 'L2R' ? this.current.learning : this.current.reference;
},
currentDisplayPrompt() {
if (!this.current || this.direction !== 'L2R') return '';
const learning = this.normalizeSpacedText(this.current.learning);
const reference = this.normalizeSpacedText(this.current.reference);
if ((learning === 'wo' || learning === 'wo wohin' || learning === 'wohin') && reference === 'asa') {
return '_______(wo/wohin) ka padulong?';
}
if (learning === 'was' && reference === 'unsa') {
return '_______(was) imong plano?';
}
return '';
},
directionLabel() {
return this.direction === 'L2R'
? this.$t('socialnetwork.vocab.practice.dirLearningToRef')
@@ -650,13 +666,13 @@ export default {
if (wordCount < 3) return false;
const normalized = text.toLowerCase().normalize('NFKC');
const startsWithTaskVerb = /^(sage|sag|frage|frag|bitte|stelle|sprich|erzähle|erzaehle|beschreibe|bilde|wähle|waehle|ordne|übersetze|uebersetze|nenne|nenn|beginne|verwende|nutze|reagiere|kombiniere|spiele|löse|loese|beantworte|ergänze|ergaenze|formuliere|lies|entscheide|zeige)\b/i.test(normalized);
const startsWithTaskVerb = /^(sage|sag|frage|frag|bitte|stelle|sprich|erzähle|erzaehle|beschreibe|bilde|wähle|waehle|ordne|übersetze|uebersetze|nenne|nenn|beginne|verwende|nutze|reagiere|kombiniere|spiele|löse|loese|beantworte|ergänze|ergaenze|formuliere|lies|entscheide|zeige|begrüße|begruesse|grüße|gruesse|drücke|druecke)\b/i.test(normalized);
const startsWithTakeTask = /^nimm\b/i.test(normalized)
&& (
/\b(ein|eine|einen|zwei|drei|vier|fünf|fuenf|sechs|sieben|acht|neun|zehn|\d+)\b/i.test(normalized)
|| /\b(w[oö]rter|verben|gegenstände|gegenstaende|sätze|saetze|muster|beispiele)\b/i.test(normalized)
);
const containsTaskChain = /\b(und|,)\s*(sage|sag|frage|frag|bitte|stelle|sprich|erzähle|erzaehle|beschreibe|bilde|wähle|waehle|ordne|übersetze|uebersetze|nenne|nenn|verwende|nutze|reagiere|kombiniere|spiele|löse|loese|beantworte|ergänze|ergaenze|formuliere|lies|entscheide|zeige)\b/i.test(normalized);
const containsTaskChain = /\b(und|,)\s*(sage|sag|frage|frag|bitte|stelle|sprich|erzähle|erzaehle|beschreibe|bilde|wähle|waehle|ordne|übersetze|uebersetze|nenne|nenn|verwende|nutze|reagiere|kombiniere|spiele|löse|loese|beantworte|ergänze|ergaenze|formuliere|lies|entscheide|zeige|begrüße|begruesse|grüße|gruesse|drücke|druecke)\b/i.test(normalized);
const containsPracticeMarker = /\b(laut|jeweils|zu jedem|zu jeder|umgebung|alltagsszene|rollenspiel|mini-dialog|szene)\b/i.test(normalized);
return startsWithTaskVerb || startsWithTakeTask || (containsTaskChain && containsPracticeMarker);
@@ -678,6 +694,37 @@ export default {
.filter(Boolean)
.length;
},
normalizeSpacedText(value) {
return String(value || '')
.trim()
.toLowerCase()
.normalize('NFKC')
.replace(/[\p{P}\p{S}]+/gu, ' ')
.replace(/\s+/g, ' ')
.trim();
},
isGermanQuestionCue(value) {
return new Set(['wo', 'wo wohin', 'wohin', 'was', 'wer', 'wann', 'warum', 'wieso', 'wie'])
.has(this.normalizeSpacedText(value));
},
firstWordOfQuestion(value) {
const text = String(value || '').trim();
if (!/\?\s*$/.test(text) || this.wordCount(text) < 2) return '';
return text.split(/\s+/).find(Boolean) || '';
},
normalizeQuestionCuePair(item) {
const learning = String(item?.learning || '').trim();
const reference = String(item?.reference || '').trim();
if (this.isGermanQuestionCue(learning)) {
const firstWord = this.firstWordOfQuestion(reference);
if (firstWord) return { ...item, learning, reference: firstWord };
}
if (this.isGermanQuestionCue(reference)) {
const firstWord = this.firstWordOfQuestion(learning);
if (firstWord) return { ...item, learning: firstWord, reference };
}
return { ...item, learning, reference };
},
looksLikeFragmentMismatch(left, right) {
const leftWords = this.wordCount(left);
const rightWords = this.wordCount(right);
@@ -730,14 +777,15 @@ export default {
const mapped = expanded
.map(({ candidate, index, altIndex }) => {
const learning = String(candidate?.learning || '').trim();
const reference = String(candidate?.reference || '').trim();
const normalizedCandidate = this.normalizeQuestionCuePair(candidate);
const learning = String(normalizedCandidate?.learning || '').trim();
const reference = String(normalizedCandidate?.reference || '').trim();
if (!this.isTrainablePair(learning, reference)) return null;
const key = `${this.normalize(learning)}|${this.normalize(reference)}`;
if (seen.has(key)) return null;
seen.add(key);
return {
...candidate,
...normalizedCandidate,
id: candidate?.id || candidate?.itemKey || candidate?.key || `${key}|${index}|${altIndex}`,
learning,
reference
@@ -782,7 +830,7 @@ export default {
}
// Aktuelle Frage behalten, nur UI/Antwortmodus neu aufbauen
const prompt = this.currentPrompt;
const prompt = this.currentAnswerPrompt;
this.acceptableAnswers = this.getAnswersForPrompt(prompt, this.direction);
if (this.simpleMode) {
this.buildChoices();
@@ -1067,7 +1115,7 @@ export default {
return items[items.length - 1];
},
buildChoices() {
const prompt = this.currentPrompt;
const prompt = this.currentAnswerPrompt;
const acceptable = this.getAnswersForPrompt(prompt, this.direction);
this.acceptableAnswers = acceptable;
@@ -1290,7 +1338,7 @@ export default {
}
}
if (!this.current) return;
const prompt = this.currentPrompt;
const prompt = this.currentAnswerPrompt;
this.acceptableAnswers = this.getAnswersForPrompt(prompt, this.direction);
if (this.simpleMode) this.buildChoices();
this.$nextTick(() => {