270 lines
8.6 KiB
TypeScript
270 lines
8.6 KiB
TypeScript
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<string, string> = { 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<string, { gesto: string, palabra: string, fonema: string, emoji: string }> = {
|
|
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
|