import type { Stage } from '../types' function vocalChoice(vocal: string, correctLabel: string, distractors: string[], emoji: string, instruction: string, audioText?: string) { const options = [ { label: correctLabel, correct: true, id: vocal }, ...distractors.map((d) => ({ label: d, correct: false, id: d })), ].sort(() => Math.random() - 0.5) return { stage: 3, skillCode: `vocal-${vocal}`, type: 'eleccion' as const, prerequisites: getVocalPrereqs(vocal), content: { instruction, text: correctLabel, options, audioText: audioText || `${correctLabel}`, emoji, color: getVocalColor(vocal), }, functionalContext: `Identificar la vocal ${vocal.toUpperCase()} en diferentes contextos.`, errorType: 'confusion-letra' as const, } } function getVocalColor(vocal: string): string { const colors: Record = { a: '#FF6B6B', o: '#4ECDC4', i: '#45B7D1', e: '#96CEB4', u: '#DDA0DD' } return colors[vocal] || '#FF6B6B' } function getVocalPrereqs(vocal: string): string[] { const order = ['a', 'o', 'i', 'e', 'u'] const idx = order.indexOf(vocal) if (idx === 0) return ['lec2-segmentar-pato'] return [`vocal-${order[idx - 1]}-completa`] } const gestos: Record = { a: { gesto: 'Abrí la mano como una boca grande', palabra: 'ÁRBOL', fonema: 'AAA', emoji: '🌳' }, o: { gesto: 'Redondeá la mano como una O', palabra: 'OJO', fonema: 'OOO', emoji: '👁️' }, i: { gesto: 'Señalá el cielo con el dedo', palabra: 'INDIO', fonema: 'III', emoji: '🪶' }, e: { gesto: 'Estirá la mano como una trompa de elefante', palabra: 'ELEFANTE', fonema: 'EEE', emoji: '🐘' }, u: { gesto: 'Señalá el suelo con la mano', palabra: 'UNO', fonema: 'UUU', emoji: '1️⃣' }, } function buildVocalExercises(vocal: string, index: number): any[] { const g = gestos[vocal] const exs: any[] = [] // Ejercicio de gesto (sensibilizacion) exs.push({ id: `lec3-${vocal}-gesto`, stage: 3, skillCode: `vocal-${vocal}`, type: 'sensibilizacion', prerequisites: getVocalPrereqs(vocal), content: { instruction: `Hacé así para la ${vocal.toUpperCase()}: ${g.gesto}`, audioText: `Esta es la letra ${vocal.toUpperCase()}. ${g.palabra}. ${g.fonema}`, emoji: g.emoji, color: getVocalColor(vocal), }, functionalContext: `Aprender el gesto Borel-Maisonny para la vocal ${vocal.toUpperCase()}.`, }) // Reconocer la vocal entre otras exs.push(vocalChoice( vocal, vocal.toUpperCase(), ['A', 'O', 'I', 'E', 'U'].filter((v) => v !== vocal.toUpperCase()), g.emoji, `Señalá la letra ${vocal.toUpperCase()}`, )) // ¿Con qué vocal empieza? exs.push({ id: `lec3-${vocal}-inicial`, stage: 3, skillCode: `vocal-${vocal}`, type: 'eleccion', prerequisites: [`lec3-${vocal}-gesto`], content: { instruction: `¿Con qué vocal empieza ${g.palabra}?`, text: g.palabra, audioText: `${g.palabra} empieza con ${vocal.toUpperCase()}`, options: [ { label: vocal.toUpperCase(), correct: true, id: vocal }, ...['A', 'O', 'I', 'E', 'U'].filter((v) => v !== vocal.toUpperCase()).slice(0, 2).map((v) => ({ label: v, correct: false, id: v })), ], emoji: g.emoji, }, functionalContext: `Reconocer la vocal inicial en palabras.`, errorType: 'discriminacion-auditiva', }) // Emparejar imagen con vocal exs.push({ id: `lec3-${vocal}-emparejar`, stage: 3, skillCode: `vocal-${vocal}`, type: 'conciencia', prerequisites: [`lec3-${vocal}-inicial`], content: { instruction: `¿Cuál empieza con ${vocal.toUpperCase()}?`, audioText: `¿Qué empieza con ${vocal.toUpperCase()}?`, options: [ { label: g.emoji, correct: true, id: vocal }, ...Object.entries(gestos) .filter(([k]) => k !== vocal) .slice(0, 2) .map(([k, v]) => ({ label: v.emoji, correct: false, id: k })), ], }, functionalContext: `Asociar la vocal con imágenes que empiezan con ella.`, errorType: 'confusion-letra', }) // Discriminación auditiva exs.push({ id: `lec3-${vocal}-auditiva`, stage: 3, skillCode: `vocal-${vocal}`, type: 'conciencia', prerequisites: [`lec3-${vocal}-emparejar`], content: { instruction: `Escuchá bien. ¿Cuál suena como ${vocal.toUpperCase()}?`, audioText: `${g.fonema}... ${g.fonema}... como ${g.palabra}`, options: [ { label: vocal.toUpperCase(), correct: true, id: vocal }, ...['A', 'O', 'I', 'E', 'U'].filter((v) => v !== vocal.toUpperCase()).slice(0, 2).map((v) => ({ label: v, correct: false, id: v })), ], emoji: '👂', }, functionalContext: `Discriminar auditivamente la vocal ${vocal.toUpperCase()}.`, errorType: 'discriminacion-auditiva', }) // Escribir con el dedo (trazo) exs.push({ id: `lec3-${vocal}-trazo`, stage: 3, skillCode: `vocal-${vocal}`, type: 'trazo', prerequisites: [`lec3-${vocal}-auditiva`], content: { instruction: `Trazá la letra ${vocal.toUpperCase()} con tu dedo`, text: vocal.toUpperCase(), audioText: `Trazá la ${vocal.toUpperCase()}`, color: getVocalColor(vocal), emoji: g.emoji, }, functionalContext: `Desarrollar memoria motriz de la vocal ${vocal.toUpperCase()}.`, errorType: 'confusion-letra', }) // Repaso final exs.push({ id: `lec3-${vocal}-completa`, stage: 3, skillCode: `vocal-${vocal}`, type: 'eleccion', prerequisites: [`lec3-${vocal}-trazo`], content: { instruction: `¡Repaso! Señalá la letra ${vocal.toUpperCase()}`, audioText: `Buscá la ${vocal.toUpperCase()}`, options: [ { label: vocal.toUpperCase(), correct: true, id: vocal }, ...['A', 'O', 'I', 'E', 'U'].filter((v) => v !== vocal.toUpperCase()).map((v) => ({ label: v, correct: false, id: v })), ], emoji: g.emoji, color: getVocalColor(vocal), }, functionalContext: `Consolidar reconocimiento de la vocal ${vocal.toUpperCase()}.`, errorType: 'confusion-letra', }) return exs } // Additional cross-vowel discrimination exercises const mixedExercises: any[] = [ { id: 'lec3-mix-ae', stage: 3, skillCode: 'vocal-discriminacion', type: 'eleccion', prerequisites: ['lec3-a-completa', 'lec3-e-completa'], content: { instruction: '¿Cuál es la A y cuál es la E? Señalá la A', options: [ { label: 'A', correct: true, id: 'a' }, { label: 'E', correct: false, id: 'e' }, { label: 'O', correct: false, id: 'o' }, ], emoji: '🔤', }, functionalContext: 'Discriminar entre A y E.', errorType: 'confusion-letra', }, { id: 'lec3-mix-iu', stage: 3, skillCode: 'vocal-discriminacion', type: 'eleccion', prerequisites: ['lec3-i-completa', 'lec3-u-completa'], content: { instruction: '¿Cuál es la I y cuál es la U? Señalá la I', options: [ { label: 'I', correct: true, id: 'i' }, { label: 'U', correct: false, id: 'u' }, { label: 'A', correct: false, id: 'a' }, ], emoji: '🔤', }, functionalContext: 'Discriminar entre I y U.', errorType: 'confusion-letra', }, { id: 'lec3-mix-ao', stage: 3, skillCode: 'vocal-discriminacion', type: 'eleccion', prerequisites: ['lec3-a-completa', 'lec3-o-completa'], content: { instruction: 'Señalá la letra O', options: [ { label: 'A', correct: false, id: 'a' }, { label: 'O', correct: true, id: 'o' }, { label: 'U', correct: false, id: 'u' }, ], emoji: '🔤', }, functionalContext: 'Discriminar entre A y O.', errorType: 'confusion-letra', }, { id: 'lec3-mix-ei', stage: 3, skillCode: 'vocal-discriminacion', type: 'eleccion', prerequisites: ['lec3-e-completa', 'lec3-i-completa'], content: { instruction: 'Señalá la E', options: [ { label: 'I', correct: false, id: 'i' }, { label: 'E', correct: true, id: 'e' }, { label: 'U', correct: false, id: 'u' }, ], emoji: '🔤', }, functionalContext: 'Discriminar entre E e I.', errorType: 'confusion-letra', }, ] const exercises: any[] = [] for (const [i, vocal] of ['a', 'o', 'i', 'e', 'u'].entries()) { exercises.push(...buildVocalExercises(vocal, i)) } exercises.push(...mixedExercises) const stage: Stage = { id: 3, name: 'Vocales A-O-I-E-U', description: 'Aprender las 5 vocales con gestos Borel-Maisonny, discriminación auditiva y visual, trazo y reconocimiento.', exercises, } export default stage