feat: Puente Mayúscula-Minúscula + TTS SpeechSynthesis + E2E fixes

This commit is contained in:
renato97
2026-07-21 15:31:46 -03:00
commit fa8e0c58ce
120 changed files with 16013 additions and 0 deletions
+235
View File
@@ -0,0 +1,235 @@
import type { Stage } from '../types'
type ConInfo = {
letra: string
palabra: string
emoji: string
silabas: string[]
gesto: string
}
const consonantes: ConInfo[] = [
{ letra: 'M', palabra: 'MAMÁ', emoji: '👩', silabas: ['MA', 'ME', 'MI', 'MO', 'MU'], gesto: 'Manos en la boca como mmm' },
{ letra: 'P', palabra: 'PAPÁ', emoji: '👨', silabas: ['PA', 'PE', 'PI', 'PO', 'PU'], gesto: 'Manos que abren y cierran como pompa' },
{ letra: 'L', palabra: 'LUNA', emoji: '🌙', silabas: ['LA', 'LE', 'LI', 'LO', 'LU'], gesto: 'Lengua arriba como lámpara' },
{ letra: 'S', palabra: 'SOL', emoji: '☀️', silabas: ['SA', 'SE', 'SI', 'SO', 'SU'], gesto: 'Dedos como serpiente sss' },
{ letra: 'T', palabra: 'TASA', emoji: '☕', silabas: ['TA', 'TE', 'TI', 'TO', 'TU'], gesto: 'Golpecito con la mano' },
{ letra: 'N', palabra: 'NIDO', emoji: '🪺', silabas: ['NA', 'NE', 'NI', 'NO', 'NU'], gesto: 'Nariz como nido' },
{ letra: 'D', palabra: 'DEDO', emoji: '👉', silabas: ['DA', 'DE', 'DI', 'DO', 'DU'], gesto: 'Dedo señalando' },
{ letra: 'R', palabra: 'RATÓN', emoji: '🐭', silabas: ['RA', 'RE', 'RI', 'RO', 'RU'], gesto: 'Lengua que vibra como rrr' },
]
const exercises: any[] = []
for (const con of consonantes) {
// 1. Presentación con gesto
exercises.push({
id: `lec4-${con.letra.toLowerCase()}-gesto`,
stage: 4,
skillCode: `consonante-${con.letra.toLowerCase()}`,
type: 'sensibilizacion',
prerequisites: con.letra === 'M' ? ['lec3-u-completa'] : [`lec4-${consonantes[consonantes.indexOf(con) - 1].letra.toLowerCase()}-completa`],
content: {
instruction: `Hacé así para la ${con.letra}: ${con.gesto}`,
audioText: `Esta es la letra ${con.letra}. ${con.palabra}. ${con.silabas[0].toLowerCase()}`,
emoji: con.emoji,
},
functionalContext: `Conocer el gesto asociado a la consonante ${con.letra}.`,
})
// 2. Reconocer la consonante
exercises.push({
id: `lec4-${con.letra.toLowerCase()}-reconocer`,
stage: 4,
skillCode: `consonante-${con.letra.toLowerCase()}`,
type: 'eleccion',
prerequisites: [`lec4-${con.letra.toLowerCase()}-gesto`],
content: {
instruction: `Señalá la letra ${con.letra}`,
text: `Buscá la ${con.letra}`,
audioText: `¿Dónde está la ${con.letra}?`,
options: [
{ label: con.letra, correct: true, id: con.letra.toLowerCase() },
...consonantes.filter(c => c.letra !== con.letra).slice(0, 3).map(c => ({ label: c.letra, correct: false, id: c.letra.toLowerCase() })),
],
emoji: con.emoji,
},
functionalContext: `Reconocer visualmente la consonante ${con.letra}.`,
errorType: 'confusion-letra',
})
// 3. Discriminación auditiva de la sílaba
exercises.push({
id: `lec4-${con.letra.toLowerCase()}-auditiva`,
stage: 4,
skillCode: `consonante-${con.letra.toLowerCase()}`,
type: 'conciencia',
prerequisites: [`lec4-${con.letra.toLowerCase()}-reconocer`],
content: {
instruction: `Escuchá. ¿Cuál suena como ${con.silabas[0]}?`,
audioText: `${con.silabas[0]}... ${con.silabas[0]}... como ${con.palabra}`,
options: [
{ label: con.silabas[0], correct: true, id: con.silabas[0].toLowerCase() },
...consonantes.filter(c => c.letra !== con.letra).slice(0, 2).map(c => ({ label: c.silabas[0], correct: false, id: c.silabas[0].toLowerCase() })),
],
emoji: '👂',
},
functionalContext: `Discriminar auditivamente la sílaba ${con.silabas[0]}.`,
errorType: 'discriminacion-auditiva',
})
// 4. Emparejar sílaba con vocal
for (let vi = 1; vi < con.silabas.length; vi++) {
const sil = con.silabas[vi]
const vocal = sil[1]
const vocales = ['A', 'E', 'I', 'O', 'U'].filter(v => v !== vocal)
exercises.push({
id: `lec4-${con.letra.toLowerCase()}-silaba-${sil.toLowerCase()}`,
stage: 4,
skillCode: `consonante-${con.letra.toLowerCase()}-silabas`,
type: 'eleccion',
prerequisites: [`lec4-${con.letra.toLowerCase()}-auditiva`, `lec4-${con.letra.toLowerCase()}-silaba-${con.silabas[vi - 1].toLowerCase()}`],
content: {
instruction: `¿Cuál es ${sil}?`,
text: sil,
audioText: `${sil}... como ${con.palabra.toLowerCase()}`,
options: [
{ label: sil, correct: true, id: sil.toLowerCase() },
{ label: `${con.letra}${vocales[0]}`, correct: false, id: `${con.letra}${vocales[0]}`.toLowerCase() },
{ label: `${con.letra}${vocales[1]}`, correct: false, id: `${con.letra}${vocales[1]}`.toLowerCase() },
],
emoji: con.emoji,
},
functionalContext: `Leer la sílaba ${sil}.`,
errorType: 'confusion-letra',
})
}
// 5. Palabra con la consonante
exercises.push({
id: `lec4-${con.letra.toLowerCase()}-palabra`,
stage: 4,
skillCode: `consonante-${con.letra.toLowerCase()}`,
type: 'palabra',
prerequisites: [`lec4-${con.letra.toLowerCase()}-silaba-${con.silabas[con.silabas.length - 1].toLowerCase()}`],
content: {
instruction: `¿Cuál palabra empieza con ${con.letra}?`,
audioText: `${con.palabra} empieza con ${con.letra}`,
imageEmoji: con.emoji,
options: [
{ label: con.palabra, correct: true, id: con.palabra.toLowerCase() },
{ label: 'CASA', correct: false, id: 'casa' },
{ label: 'GATO', correct: false, id: 'gato' },
{ label: 'Escuchar 👂', correct: false, id: 'escuchar' },
],
},
functionalContext: `Asociar la consonante ${con.letra} con una palabra significativa.`,
errorType: 'discriminacion-auditiva',
})
// 6. Final: repaso completo
exercises.push({
id: `lec4-${con.letra.toLowerCase()}-completa`,
stage: 4,
skillCode: `consonante-${con.letra.toLowerCase()}`,
type: 'eleccion',
prerequisites: [`lec4-${con.letra.toLowerCase()}-palabra`],
content: {
instruction: `¡Repaso! Señalá la letra ${con.letra}`,
audioText: `Buscá la ${con.letra}`,
options: [
{ label: con.letra, correct: true, id: con.letra.toLowerCase() },
...consonantes.filter(c => c.letra !== con.letra).slice(0, 3).map(c => ({ label: c.letra, correct: false, id: c.letra.toLowerCase() })),
],
emoji: con.emoji,
},
functionalContext: `Consolidar reconocimiento de la consonante ${con.letra}.`,
errorType: 'confusion-letra',
})
}
// Cross-consonant discrimination exercises
exercises.push({
id: 'lec4-mix-mp',
stage: 4,
skillCode: 'consonante-discriminacion',
type: 'eleccion',
prerequisites: ['lec4-m-completa', 'lec4-p-completa'],
content: {
instruction: 'Señalá la M',
options: [
{ label: 'M', correct: true, id: 'm' },
{ label: 'P', correct: false, id: 'p' },
{ label: 'L', correct: false, id: 'l' },
],
emoji: '🔤',
},
functionalContext: 'Discriminar entre M y P.',
errorType: 'confusion-letra',
})
exercises.push({
id: 'lec4-mix-st',
stage: 4,
skillCode: 'consonante-discriminacion',
type: 'eleccion',
prerequisites: ['lec4-s-completa', 'lec4-t-completa'],
content: {
instruction: 'Señalá la T',
options: [
{ label: 'S', correct: false, id: 's' },
{ label: 'T', correct: true, id: 't' },
{ label: 'N', correct: false, id: 'n' },
],
emoji: '🔤',
},
functionalContext: 'Discriminar entre S y T.',
errorType: 'confusion-letra',
})
exercises.push({
id: 'lec4-mix-ld',
stage: 4,
skillCode: 'consonante-discriminacion',
type: 'eleccion',
prerequisites: ['lec4-l-completa', 'lec4-d-completa'],
content: {
instruction: 'Señalá la D',
options: [
{ label: 'L', correct: false, id: 'l' },
{ label: 'D', correct: true, id: 'd' },
{ label: 'R', correct: false, id: 'r' },
],
emoji: '🔤',
},
functionalContext: 'Discriminar entre L y D.',
errorType: 'confusion-letra',
})
exercises.push({
id: 'lec4-mix-nr',
stage: 4,
skillCode: 'consonante-discriminacion',
type: 'eleccion',
prerequisites: ['lec4-n-completa', 'lec4-r-completa'],
content: {
instruction: 'Señalá la R',
options: [
{ label: 'N', correct: false, id: 'n' },
{ label: 'R', correct: true, id: 'r' },
{ label: 'M', correct: false, id: 'm' },
],
emoji: '🔤',
},
functionalContext: 'Discriminar entre N y R.',
errorType: 'confusion-letra',
})
const stage: Stage = {
id: 4,
name: 'Consonantes M-P-L-S-T-N-D-R',
description: 'Aprender las consonantes M, P, L, S, T, N, D, R con gestos, sílabas, y palabras significativas.',
exercises,
}
export default stage