feat(cards): multiple-choice Card-Type mit dynamischen Distractors
- CardTypeSchema: 'multiple-choice' (Felder: front + answer, distractor_pool optional) - subIndexCount: 'multiple-choice' → 1 - GET /api/v1/decks/:deckId/distractors: N zufällige Feldwerte anderer Karten im Deck; field-Allowlist (front/back/answer/question); RANDOM() ORDER; Fallback auf distractor_pool wenn Deck < 4 Karten - fetchDistractors(): Frontend-Client-Funktion - MultipleChoiceView.svelte: lädt Distractors on mount, shuffelt 4 Optionen, zeigt Sofort-Feedback (correct/wrong/neutral), Keyboard 1–4 + Space; auto-grade correct→good, wrong→again - Study-Page: isMultipleChoice + multipleChoiceData derived, Action-Bar ausgeblendet, onKey delegiert Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
0791436107
commit
2b36990e43
6 changed files with 351 additions and 4 deletions
|
|
@ -153,6 +153,8 @@ export function subIndexCount(type: string): number {
|
|||
return 1;
|
||||
case 'multiple-choice':
|
||||
return 1;
|
||||
case 'multiple-choice':
|
||||
return 1;
|
||||
case 'cloze':
|
||||
throw new Error(
|
||||
'subIndexCount("cloze") not supported — use subIndexCountForCloze(text) from @cards/domain'
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ export const CardTypeSchema = z.enum([
|
|||
'image-occlusion',
|
||||
'audio-front',
|
||||
'typing',
|
||||
'multiple-choice',
|
||||
]);
|
||||
export type CardType = z.infer<typeof CardTypeSchema>;
|
||||
|
||||
|
|
@ -50,7 +51,7 @@ export function validateFieldsForType(
|
|||
'image-occlusion': ['image_ref', 'mask_regions'],
|
||||
'audio-front': ['audio_ref', 'back'],
|
||||
typing: ['front', 'answer'],
|
||||
'multiple-choice': ['question', 'options', 'correct_index'],
|
||||
'multiple-choice': ['front', 'answer'],
|
||||
};
|
||||
const need = required[type] ?? [];
|
||||
const missing = need.filter((k) => !(k in fields));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue