diff --git a/frontend/src/dialogues/socialnetwork/VocabPracticeDialog.vue b/frontend/src/dialogues/socialnetwork/VocabPracticeDialog.vue index 7341c00..8f563e2 100644 --- a/frontend/src/dialogues/socialnetwork/VocabPracticeDialog.vue +++ b/frontend/src/dialogues/socialnetwork/VocabPracticeDialog.vue @@ -543,11 +543,52 @@ export default { const itemPrompt = direction === 'L2R' ? item.learning : item.reference; if (this.normalize(itemPrompt) === p) { const a = direction === 'L2R' ? item.reference : item.learning; - answers.add(a); + this.expandAnswerVariants(a).forEach((variant) => answers.add(variant)); } } return Array.from(answers); }, + expandAnswerVariants(answer) { + const base = String(answer || '').trim(); + if (!base) return []; + + const words = base.split(/\s+/).map((word) => { + if (!word.includes('/')) { + return [word]; + } + + const match = word.match(/^([([{„"'“‘]*)(.*?)([)\]}.,!?;:»"'”’]*)$/); + const prefix = match?.[1] || ''; + const core = match?.[2] || word; + const suffix = match?.[3] || ''; + const parts = core + .split('/') + .map((part) => part.trim()) + .filter(Boolean); + + if (parts.length < 2 || parts.length > 4) { + return [word]; + } + + return parts.map((part) => `${prefix}${part}${suffix}`); + }); + + const variants = ['']; + for (const options of words) { + const next = []; + for (const current of variants) { + for (const option of options) { + next.push(`${current}${current ? ' ' : ''}${option}`); + } + } + if (next.length > 24) { + return [base]; + } + variants.splice(0, variants.length, ...next); + } + + return [...new Set([base, ...variants])]; + }, computeWeight(item) { const st = this.perId[item.id] || { c: 0, w: 0, streak: 0, lastAsked: 0 }; let w = 1;