// Escalera — climb levels, 3 lives, difficulty grows const Escalera = ({ profile, onFinish, onQuit }) => { const t = window.MP_I18N.t; const diff = window.MP_DATA.difficultyForGrade(profile.grade); const [phase, setPhase] = React.useState('count'); const [lives, setLives] = React.useState(3); const [level, setLevel] = React.useState(1); const [score, setScore] = React.useState(0); const [correct, setCorrect] = React.useState(0); const [total, setTotal] = React.useState(0); const [problem, setProblem] = React.useState(null); const [choices, setChoices] = React.useState([]); const [picked, setPicked] = React.useState(null); const [status, setStatus] = React.useState(null); const next = React.useCallback((lvl) => { const useLvl = lvl ?? level; const max = Math.min(diff.max, 4 + useLvl); const p = window.MP_DATA.genProblem({ tables: diff.tables, max }); setProblem(p); setChoices(window.MP_DATA.genOptions(p.answer, 4)); setPicked(null); setStatus(null); }, [level]); React.useEffect(() => { if (phase === 'play') next(level); }, [phase]); const finish = (livesLeft) => { onFinish({ mode: 'escalera', score, correct, total, perfect: livesLeft === 3 && total > 5 }); }; const pick = (c) => { if (picked != null) return; setPicked(c); setTotal(x => x + 1); if (c === problem.answer) { window.MP_SOUND.correct(); setStatus('right'); setCorrect(x => x + 1); const earned = 5 + level * 2; setScore(s => s + earned); setTimeout(() => { const nl = level + 1; setLevel(nl); next(nl); }, 450); } else { window.MP_SOUND.wrong(); setStatus('wrong'); const nl = lives - 1; setLives(nl); setTimeout(() => { if (nl <= 0) finish(nl); else next(level); }, 800); } }; if (phase === 'count') { return ( setPhase('play')} /> ); } return (
{t('level')} {level}
{problem && }
); }; window.Escalera = Escalera;