Bisaya kurs korrekturen
All checks were successful
Deploy to production / deploy (push) Successful in 2m41s

This commit is contained in:
Torsten Schulz (local)
2026-06-06 13:16:04 +02:00
parent bfec885a1f
commit 973fcaaf9e
5 changed files with 443 additions and 19 deletions

View File

@@ -156,6 +156,7 @@
<script>
import DialogWidget from '@/components/DialogWidget.vue';
import apiClient from '@/utils/axios.js';
import { normalizeComparableWithNumberWords } from '@/utils/numberAnswerVariants.js';
const PRACTICE_MIN_EXPOSURES = 3;
const SRS_SESSION_STORAGE_VERSION = 2;
@@ -630,14 +631,17 @@ export default {
}
},
normalize(s) {
const normalized = String(s || '')
.trim()
.toLowerCase()
.normalize('NFKC')
.replace(/[\p{P}\p{S}]+/gu, ' ')
.replace(/\s+/g, ' ')
.trim();
return normalized.replace(/\s+/g, '');
const baseNormalize = (value) => {
const normalized = String(value || '')
.trim()
.toLowerCase()
.normalize('NFKC')
.replace(/[\p{P}\p{S}]+/gu, ' ')
.replace(/\s+/g, ' ')
.trim();
return normalized.replace(/\s+/g, '');
};
return normalizeComparableWithNumberWords(s, baseNormalize);
},
isInstructionLikeText(value) {
const text = String(value || '').trim();

View File

@@ -0,0 +1,110 @@
const GERMAN_NUMBER_WORDS = new Map([
['null', '0'],
['ein', '1'],
['eins', '1'],
['eine', '1'],
['einen', '1'],
['einem', '1'],
['einer', '1'],
['zwei', '2'],
['drei', '3'],
['vier', '4'],
['fuenf', '5'],
['funf', '5'],
['fünf', '5'],
['sechs', '6'],
['sieben', '7'],
['acht', '8'],
['neun', '9'],
['zehn', '10'],
['elf', '11'],
['zwoelf', '12'],
['zwolf', '12'],
['zwölf', '12'],
['dreizehn', '13'],
['vierzehn', '14'],
['fuenfzehn', '15'],
['funfzehn', '15'],
['fünfzehn', '15'],
['sechzehn', '16'],
['siebzehn', '17'],
['achtzehn', '18'],
['neunzehn', '19'],
['zwanzig', '20'],
['dreissig', '30'],
['dreißig', '30'],
['vierzig', '40'],
['fuenfzig', '50'],
['funfzig', '50'],
['fünfzig', '50'],
['sechzig', '60'],
['siebzig', '70'],
['achtzig', '80'],
['neunzig', '90'],
['hundert', '100'],
['einhundert', '100'],
['tausend', '1000'],
['eintausend', '1000'],
['zweitausend', '2000']
]);
const GERMAN_ONES = [
['', ''],
['ein', 'eins'],
['zwei'],
['drei'],
['vier'],
['fuenf', 'funf', 'fünf'],
['sechs'],
['sieben'],
['acht'],
['neun']
];
const GERMAN_TENS = {
20: ['zwanzig'],
30: ['dreissig', 'dreißig'],
40: ['vierzig'],
50: ['fuenfzig', 'funfzig', 'fünfzig'],
60: ['sechzig'],
70: ['siebzig'],
80: ['achtzig'],
90: ['neunzig']
};
for (const [tensValue, tensWords] of Object.entries(GERMAN_TENS)) {
const tens = Number(tensValue);
for (let one = 1; one <= 9; one += 1) {
for (const oneWord of GERMAN_ONES[one]) {
for (const tenWord of tensWords) {
GERMAN_NUMBER_WORDS.set(`${oneWord}und${tenWord}`, String(tens + one));
}
}
}
}
function stripGermanNumberSeparators(value) {
return String(value || '')
.replace(/[\s.-]+/g, '');
}
export function canonicalizeNumberAnswer(value) {
const raw = String(value || '').trim().toLowerCase();
if (!raw) return '';
const compact = stripGermanNumberSeparators(raw);
if (/^\d+$/.test(compact)) {
return String(Number(compact));
}
return GERMAN_NUMBER_WORDS.get(compact) || '';
}
export function normalizeComparableWithNumberWords(value, baseNormalizer) {
const rawCanonical = canonicalizeNumberAnswer(value);
if (rawCanonical) return rawCanonical;
const normalized = baseNormalizer(String(value || ''));
const normalizedCanonical = canonicalizeNumberAnswer(normalized);
return normalizedCanonical || normalized;
}

View File

@@ -75,6 +75,7 @@
<script>
import apiClient from '@/utils/axios.js';
import { normalizeComparableWithNumberWords } from '@/utils/numberAnswerVariants.js';
export default {
name: 'VocabLessonReviewView',
@@ -119,9 +120,12 @@ export default {
},
methods: {
normalize(s) {
const base = String(s || '').trim().toLowerCase();
// Satzzeichen am Ende ignorieren (Punkt, Fragezeichen, Ausrufezeichen, Komma, Strichpunkt, Doppelpunkt)
return base.replace(/[.,!?;:]+$/g, '').replace(/\s+/g, ' ');
const baseNormalize = (value) => {
const base = String(value || '').trim().toLowerCase();
// Satzzeichen am Ende ignorieren (Punkt, Fragezeichen, Ausrufezeichen, Komma, Strichpunkt, Doppelpunkt)
return base.replace(/[.,!?;:]+$/g, '').replace(/\s+/g, ' ');
};
return normalizeComparableWithNumberWords(s, baseNormalize);
},
getItemKey(item) {
return `${String(item?.gloss || '').trim()}|${String(item?.target || '').trim()}`;

View File

@@ -1087,6 +1087,7 @@
<script>
import { mapGetters } from 'vuex';
import apiClient from '@/utils/axios.js';
import { normalizeComparableWithNumberWords } from '@/utils/numberAnswerVariants.js';
const debugLog = () => {};
const LESSON_STATE_VERSION = 1;
@@ -4271,14 +4272,17 @@ export default {
}
},
normalizeComparableText(value) {
const normalized = String(value || '')
.trim()
.toLowerCase()
.normalize('NFKC')
.replace(/[\p{P}\p{S}]+/gu, ' ')
.replace(/\s+/g, ' ')
.trim();
return normalized.replace(/\s+/g, '');
const baseNormalize = (source) => {
const normalized = String(source || '')
.trim()
.toLowerCase()
.normalize('NFKC')
.replace(/[\p{P}\p{S}]+/gu, ' ')
.replace(/\s+/g, ' ')
.trim();
return normalized.replace(/\s+/g, '');
};
return normalizeComparableWithNumberWords(value, baseNormalize);
},
stripTrailingParentheticalNotes(value) {
let text = String(value || '').trim();