Files
renato97 a3360ec6e4 feat: fase 2+3 — expansion masiva multi-perfil + bug fixes + hardening
Fase 2 (expansion):
- Francesca: +6 etapas matematicas (5-10), +7 etapas lectura (3-9), +2 ortografia
- Sebastian: +8 etapas matematicas (4-11), +6 lectura, +3 historia, +3 geografia, +1 banderas
- Nuevas paginas: ortografia, lectura, geografia, matematicas
- ~900 ejercicios nuevos, paridad ~500 por perfil

Fase 3 (bug fixes + hardening):
- Fix: SessionLog auto-create en grade route
- Fix: engine cache (no borrar antes de revisar)
- Fix: FSRS cards actualizadas en flujo curriculum
- Fix: responseMs real (no hardcodeado 3000)
- Fix: options dentro de content en sebastian etapa-1
- Fix: trazo-letra consonantes crash
- Security: execFileSync anti-command-injection en TTS
- DB: 18 cascade deletes + indices + unique constraints
- APIs debug: reset, state, seed
- Docker: espeak-ng + prisma + user/group
- E2E: 23 tests nuevos (curriculum-flow.spec.ts)
- Code review: tailwind colors, middleware dev mode, eslint config

Verificado: tsc exit 0, build exit 0, 61 E2E tests pass
2026-07-25 22:07:28 -03:00

132 lines
7.1 KiB
TypeScript

import type { Stage } from "../types"
const lecturas = [
{
text: "Martín dejó la campera en el patio de la escuela. Cuando volvió a buscarla, ya no estaba. Lloró todo el camino a casa.",
preguntas: [
{ q: "¿Por qué lloró Martín?", op: ["Perdió su campera", "Se lastimó", "Terminó la escuela"], correcta: "Perdió su campera" },
{ q: "¿Dónde dejó la campera?", op: ["En el patio de la escuela", "En el aula", "En su casa"], correcta: "En el patio de la escuela" },
{ q: "¿Qué pasó cuando volvió a buscarla?", op: ["Ya no estaba", "Estaba ahí", "Se la habían lavado"], correcta: "Ya no estaba" },
],
emoji: "😢",
},
{
text: "El lunes Lucía no fue a la escuela. El martes sus amigos le contaron que hubo una obra de teatro. Lucía se puso triste.",
preguntas: [
{ q: "¿Por qué se puso triste Lucía?", op: ["Se perdió la obra de teatro", "No le gusta el teatro", "Sus amigos no le hablaron"], correcta: "Se perdió la obra de teatro" },
{ q: "¿Qué día no fue a la escuela?", op: ["El lunes", "El martes", "El viernes"], correcta: "El lunes" },
{ q: "¿Cómo se enteró Lucía?", op: ["Sus amigos le contaron", "Vio un cartel", "Se lo dijo la maestra"], correcta: "Sus amigos le contaron" },
],
emoji: "🎭",
},
{
text: "Había muchas nubes grises. La mamá de Pedro le dijo que llevara el paraguas. Pedro dijo que no. Cuando salió, se mojó todo.",
preguntas: [
{ q: "¿Qué pasó después de que Pedro salió sin paraguas?", op: ["Se mojó", "Hizo sol", "Encontró un paraguas"], correcta: "Se mojó" },
{ q: "¿Qué le dijo la mamá a Pedro?", op: ["Que llevara el paraguas", "Que no saliera", "Que se abrigara"], correcta: "Que llevara el paraguas" },
{ q: "¿Por qué la mamá le dijo que llevara el paraguas?", op: ["Porque había nubes grises", "Porque ella lo necesitaba", "Porque estaba lloviendo"], correcta: "Porque había nubes grises" },
],
emoji: "☔",
},
{
text: "La maestra preguntó quién hizo la tarea. Todos levantaron la mano menos Tomás. Él había estado jugando a la pelota toda la tarde.",
preguntas: [
{ q: "¿Por qué Tomás no hizo la tarea?", op: ["Estuvo jugando a la pelota", "No entendió la tarea", "Estaba enfermo"], correcta: "Estuvo jugando a la pelota" },
{ q: "¿Quiénes hicieron la tarea?", op: ["Todos menos Tomás", "Nadie", "Solo Tomás"], correcta: "Todos menos Tomás" },
{ q: "¿Qué hizo la maestra?", op: ["Preguntó quién hizo la tarea", "Se enojó", "Los castigó"], correcta: "Preguntó quién hizo la tarea" },
],
emoji: "⚽",
},
{
text: "Valentina encontró un pájaro en el jardín que no podía volar. Le dio agua y semillas. Al día siguiente el pájaro se fue volando.",
preguntas: [
{ q: "¿Qué hizo Valentina con el pájaro?", op: ["Le dio agua y semillas", "Lo guardó en una jaula", "Lo asustó"], correcta: "Le dio agua y semillas" },
{ q: "¿Dónde encontró al pájaro?", op: ["En el jardín", "En la calle", "En la escuela"], correcta: "En el jardín" },
{ q: "¿Qué pasó al día siguiente?", op: ["El pájaro se fue volando", "El pájaro se quedó", "El pájaro se enfermó"], correcta: "El pájaro se fue volando" },
],
emoji: "🐦",
},
{
text: "Sofía estudió mucho para la prueba de matemáticas. Cuando la maestra dio los resultados, Sofía tenía un 10. Saltó de alegría.",
preguntas: [
{ q: "¿Cómo se sintió Sofía con su resultado?", op: ["Alegre", "Triste", "Enojada"], correcta: "Alegre" },
{ q: "¿Qué nota sacó Sofía?", op: ["10", "5", "8"], correcta: "10" },
{ q: "¿Por qué Sofía sacó esa nota?", op: ["Porque estudió mucho", "Porque tuvo suerte", "Porque la prueba era fácil"], correcta: "Porque estudió mucho" },
],
emoji: "🎉",
},
{
text: "El perro de Juan se escapó por la puerta abierta. Juan lo buscó por todo el barrio. Finalmente lo encontró en la plaza.",
preguntas: [
{ q: "¿Dónde encontró Juan a su perro?", op: ["En la plaza", "En su casa", "En la escuela"], correcta: "En la plaza" },
{ q: "¿Por qué se escapó el perro?", op: ["Por la puerta abierta", "Por la ventana", "Por el jardín"], correcta: "Por la puerta abierta" },
{ q: "¿Dónde buscó Juan?", op: ["Por todo el barrio", "Solo en su casa", "En la veterinaria"], correcta: "Por todo el barrio" },
],
emoji: "🐕",
},
{
text: "La mamá de Nico le pidió que ordenara su habitación. Nico puso los juguetes en el baúl y los libros en el estante. La mamá sonrió.",
preguntas: [
{ q: "¿Por qué sonrió la mamá de Nico?", op: ["Porque Nico ordenó su cuarto", "Porque Nico terminó la tarea", "Porque Nico se bañó"], correcta: "Porque Nico ordenó su cuarto" },
{ q: "¿Dónde puso los juguetes Nico?", op: ["En el baúl", "En el estante", "En la cama"], correcta: "En el baúl" },
{ q: "¿Dónde puso los libros?", op: ["En el estante", "En el baúl", "En el piso"], correcta: "En el estante" },
],
emoji: "🧹",
},
{
text: "Había una fila para el tobogán. Lola llegó después que Mateo pero se quería colar. Mateo le dijo que esperara su turno.",
preguntas: [
{ q: "¿Qué quería hacer Lola?", op: ["Colarse en la fila", "Irse a su casa", "Jugar a otra cosa"], correcta: "Colarse en la fila" },
{ q: "¿Quién llegó primero?", op: ["Mateo", "Lola", "Los dos igual"], correcta: "Mateo" },
{ q: "¿Qué le dijo Mateo a Lola?", op: ["Que esperara su turno", "Que se colara", "Que se fuera"], correcta: "Que esperara su turno" },
],
emoji: "🛝",
},
{
text: "El abuelo de Ana plantó una semilla en una maceta. Todos los días la regaba. Una mañana salió una planta verde. Ana aplaudió.",
preguntas: [
{ q: "¿Qué salió de la semilla?", op: ["Una planta verde", "Una flor roja", "Un árbol grande"], correcta: "Una planta verde" },
{ q: "¿Qué hacía el abuelo todos los días?", op: ["Regaba la semilla", "Le cantaba", "La movía"], correcta: "Regaba la semilla" },
{ q: "¿Cómo reaccionó Ana?", op: ["Aplaudió", "Se enojó", "Se fue"], correcta: "Aplaudió" },
],
emoji: "🌱",
},
]
const exercises: any[] = []
let idx = 0
for (const l of lecturas) {
for (const p of l.preguntas) {
exercises.push({
id: `fra7-inferencia-${idx}`,
stage: 7,
skillCode: `lectura-inferencia-${idx}`,
type: "lectura",
prerequisites: idx === 0 ? [`fra6-escuela-29`] : [`fra7-inferencia-${idx - 1}`],
content: {
instruction: p.q,
text: l.text,
audioText: l.text,
emoji: l.emoji,
options: p.op.map((o) => ({
label: o,
correct: o === p.correcta,
id: o.toLowerCase().slice(0, 12),
})),
},
functionalContext: "Comprensión inferencial Decroly: deducir información no explícita en textos narrativos cortos.",
errorType: "omision-letra",
})
idx++
}
}
const stage: Stage = {
id: 7,
name: "Comprensión inferencial",
description: "Deducir información no explícita en textos cortos con preguntas de inferencia (método Decroly).",
exercises,
}
export default stage