// Misión diaria — fixed seed by date, 5 problems const Mision = ({ profile, onFinish, onQuit }) => { const t = window.MP_I18N.t; const diff = window.MP_DATA.difficultyForGrade(profile.grade); const TOTAL = 5; // Seeded RNG so all kids get same daily challenge const seedRNG = React.useMemo(() => { const s = window.MP_DATA.todayStr(); let h = 0; for (let i = 0; i < s.length; i++) h = (h * 31 + s.charCodeAt(i)) >>> 0; return () => { h = (h * 1103515245 + 12345) >>> 0; return (h % 1000) / 1000; }; }, []); const problems = React.useMemo(() => { const arr = []; for (let i = 0; i < TOTAL; i++) { const a = diff.tables[Math.floor(seedRNG() * diff.tables.length)]; const b = Math.floor(seedRNG() * diff.max) + 1; arr.push({ a, b, answer: a * b }); } return arr; }, []); const [idx, setIdx] = React.useState(0); const [score, setScore] = React.useState(0); const [correct, setCorrect] = React.useState(0); const [picked, setPicked] = React.useState(null); const [status, setStatus] = React.useState(null); const problem = problems[idx]; const choices = React.useMemo(() => problem ? window.MP_DATA.genOptions(problem.answer, 4) : [], [idx]); const pick = (c) => { if (picked != null) return; setPicked(c); if (c === problem.answer) { window.MP_SOUND.correct(); setStatus('right'); setCorrect(x => x + 1); setScore(s => s + 15); } else { window.MP_SOUND.wrong(); setStatus('wrong'); } setTimeout(() => { if (idx + 1 >= TOTAL) { onFinish({ mode: 'mision', score: score + (c === problem.answer ? 15 : 0) + (correct + (c === problem.answer ? 1 : 0) === TOTAL ? 50 : 0), correct: correct + (c === problem.answer ? 1 : 0), total: TOTAL, perfect: correct + (c === problem.answer ? 1 : 0) === TOTAL }); } else { setIdx(i => i + 1); setPicked(null); setStatus(null); } }, 700); }; return (
⭐ +50 bonus {idx + 1} / {TOTAL}
{problem && } ); }; window.Mision = Mision;