const SUBJECTS=[ {id:"lengua",name:"Lengua",games:[ {id:"acentos",glyph:"á",name:"Aguda, llana o esdrújula",area:"Sílaba tónica y acentuación",t:1}, {id:"gramatica",glyph:"Sust.",name:"Clases de palabras",area:"Sustantivo, verbo, adjetivo…",t:0}]}, {id:"mates",name:"Matemáticas",games:[ {id:"calculo",glyph:"×10",name:"Cálculo mental",area:"Tablas, ×10, ÷10, fracción de un número",t:1}, {id:"problemas",glyph:"?",name:"Problemas",area:"Una y dos operaciones",t:0}, {id:"fracciones",glyph:"¾",name:"Fracciones",area:"Leer fracciones en una figura",t:2}, {id:"decimales",glyph:"0,5",name:"Números decimales",area:"Comparar y ordenar",t:2}]}, {id:"naturales",name:"Ciencias de la Naturaleza",games:[ {id:"reinos",glyph:"🍄",name:"Los cinco reinos",area:"Clasificación de los seres vivos",t:1}]}, {id:"sociales",name:"Ciencias Sociales",games:[ {id:"universo",glyph:"🪐",name:"El sistema solar",area:"El universo y la Tierra",t:1}]}, {id:"english",name:"English",games:[ {id:"grammar",glyph:"En",name:"Grammar practice",area:"A1-A2",t:0}]} ]; const HELP={acentos:"Busca la sílaba tónica y clasifica la palabra.",gramatica:"¿Qué clase de palabra es la marcada?",calculo:"Calcula de cabeza y toca el resultado.",problemas:"Lee el problema y toca la solución.", fracciones:"¿Qué fracción está coloreada?",decimales:"Toca el número que se pide.",reinos:"¿A qué reino pertenece este ser vivo?",universo:"Toca la respuesta correcta.",grammar:"Choose the correct word."}; const GRAM=[ ["El *perro* ladra muy fuerte.","sustantivo"],["La *profesora* explica la lección.","sustantivo"],["El *río* baja con mucha agua.","sustantivo"], ["La casa *azul* es de mi abuela.","adjetivo"],["Hoy hace un día *precioso*.","adjetivo"],["El agua de la piscina está *fría*.","adjetivo"], ["Mi hermana *canta* muy bien.","verbo"],["Los niños *juegan* en el patio.","verbo"],["Ayer *escribimos* una carta.","verbo"], ["*Ellos* llegaron tarde a clase.","pronombre"],["*Nosotros* preparamos la obra de teatro.","pronombre"],["¿*Quién* ha llamado a la puerta?","pronombre"], ["Marta corre muy *deprisa*.","adverbio"],["Lo terminaremos *mañana*.","adverbio"],["*Siempre* desayuno fruta.","adverbio"],["Lucía es *muy* simpática.","adverbio"], ["El libro está *sobre* la mesa.","preposición"],["Iremos al museo *con* mis primos.","preposición"],["Salimos *hacia* el parque.","preposición"], ["*Aquellos* árboles son muy altos.","determinante"],["*Mis* zapatillas son nuevas.","determinante"],["*Este* cuaderno es de Pablo.","determinante"] ]; const CATS=["sustantivo","adjetivo","verbo","pronombre","adverbio","preposición","determinante"]; /* La sílaba en MAYÚSCULAS es la tónica */ const ACENTOS=["can-CIÓN","ÁR-bol","MÚ-si-ca","re-LOJ","LÁ-piz","PÁ-ja-ro","so-FÁ","ca-FÉ","ME-sa","te-LÉ-fo-no","ra-TÓN","CÁR-cel","e-XA-men","mur-CIÉ-la-go","pa-PEL","a-ZÚ-car","BRÚ-ju-la","ciu-DAD","CÉS-ped","SÁ-ba-do","ca-MIÓN","FÁ-cil","NÚ-me-ro","co-ra-ZÓN","ven-TA-na","ju-GAR","MÉ-di-co","a-ZUL","LI-bro","PLÁ-ta-no","RE-gla","ma-ri-PO-sa","pan-ta-LÓN","CÓ-mo-da"]; const REINOS=["animales","plantas","hongos","protoctistas","moneras"]; const SERES=[["Perro","🐶","animales"],["Águila","🦅","animales"],["Mariposa","🦋","animales"],["Rosal","🌹","plantas"],["Pino","🌲","plantas"],["Helecho","🌿","plantas"], ["Champiñón","🍄","hongos"],["Levadura del pan","🍞","hongos"],["Moho del pan","🦠","hongos"],["Ameba","🔬","protoctistas"],["Paramecio","🔬","protoctistas"],["Alga unicelular","🔬","protoctistas"],["Bacteria","🦠","moneras"]]; const UNIVERSO=[["¿Cuál es el planeta más cercano al Sol?","Mercurio","Venus","Marte"],["¿Cuál es el planeta más grande?","Júpiter","Saturno","La Tierra"],["¿Qué planeta es conocido como el planeta rojo?","Marte","Venus","Júpiter"], ["¿Qué es el Sol?","Una estrella","Un planeta","Un satélite"],["¿Cuál es el satélite de la Tierra?","La Luna","Marte","El Sol"],["¿Cuánto tarda la Tierra en dar una vuelta alrededor del Sol?","Un año","Un día","Un mes"], ["¿Qué movimiento produce el día y la noche?","La rotación","La traslación","Las mareas"],["¿Cuántos planetas tiene el sistema solar?","8","9","7"],["¿Cuál es el planeta más alejado del Sol?","Neptuno","Urano","Saturno"], ["¿Cómo se llama nuestra galaxia?","La Vía Láctea","Andrómeda","La Osa Mayor"],["¿Qué planeta tiene los anillos más visibles?","Saturno","Mercurio","Marte"],["¿Cuánto tarda la Tierra en girar sobre sí misma?","Un día","Un año","Una semana"]]; const GRAMMAR=[["I ___ a shower every morning.","have",["has","having"]],["There isn't ___ milk in the fridge.","any",["some","a"]],["Where ___ you yesterday?","were",["was","are"]],["He ___ watching TV at the moment.","is",["are","does"]], ["My sister is ___ than me.","older",["oldest","more old"]],["We ___ to the zoo last week.","went",["go","goed"]],["___ often do you play tennis?","How",["What","Who"]],["I'm good ___ maths.","at",["in","on"]], ["She doesn't ___ coffee.","like",["likes","liking"]],["Can you ___ me the salt, please?","pass",["passing","passes"]],["They have never ___ to Paris.","been",["be","went"]],["It's ___ cold today!","very",["much","many"]]]; const $=s=>document.querySelector(s); const board=$("#board"); const rand=(a,b)=>a+Math.floor(Math.random()*(b-a+1)); const pick=a=>a[rand(0,a.length-1)]; const shuffle=a=>{a=[...a];for(let i=a.length-1;i>0;i--){const j=Math.floor(Math.random()*(i+1));[a[i],a[j]]=[a[j],a[i]]}return a}; const esc=s=>String(s).replace(/[&<>"]/g,c=>({"&":"&","<":"<",">":">",'"':"""}[c])); const fmt=n=>{const r=Math.round(n*1000)/1000;let [i,d]=String(r).split(".");if(i.length>4)i=i.replace(/\B(?=(\d{3})+(?!\d))/g,".");return d?i+","+d:i}; const ALL=SUBJECTS.flatMap(s=>s.games.map(g=>({...g,subject:s}))); const TRIM=["Todo el curso","1.er trimestre","2.º trimestre","3.er trimestre"]; let current="acentos", soundOn=true, actx=null, trim=0; function tone(ok){ if(!soundOn) return; try{ actx=actx||new (window.AudioContext||window.webkitAudioContext)(); (ok?[660,880]:[220]).forEach((f,i)=>{const o=actx.createOscillator(),g=actx.createGain();o.type="sine";o.frequency.value=f; const t=actx.currentTime+i*.11;g.gain.setValueAtTime(.0001,t);g.gain.exponentialRampToValueAtTime(.16,t+.02);g.gain.exponentialRampToValueAtTime(.0001,t+.25); o.connect(g).connect(actx.destination);o.start(t);o.stop(t+.27)}); }catch(e){} } function shake(el){el.classList.remove("shake");void el.offsetWidth;el.classList.add("shake")} function renderNav(){ $("#trims").innerHTML=TRIM.map((t,k)=>``).join(""); document.querySelectorAll("#trims button").forEach(b=>b.onclick=()=>{trim=+b.dataset.t;renderNav()}); $("#games").innerHTML=SUBJECTS.map(s=>{const gs=s.games.filter(g=>!trim||g.t===0||g.t===trim).sort((a,b)=>a.t-b.t); return `
Nada este trimestre
`}${e}
${esc(n)}
`,answer:"reino "+r,opts:REINOS.map(x=>"reino "+x),txt:true}; } if(id==="universo"){ const [q,ok,...bad]=pick(UNIVERSO.filter(x=>!used.has(x[0]))); used.add(q); return {scene:`${esc(q)}
`,answer:ok,opts:shuffle([ok,...bad]),txt:true}; } if(id==="grammar"){ const [s,ok,bad]=pick(GRAMMAR.filter(x=>!used.has(x[0]))); used.add(s); return {scene:`${esc(s).replace("___",' ? ')}
`,answer:ok,opts:shuffle([ok,...bad]),txt:true, after:()=>`${esc(s).replace("___",`${esc(ok)}`)}
`}; } if(id==="fracciones"){ const n=pick([3,4,5,6,8,10,12]), k=rand(1,n-1); const cells=shuffle(Array.from({length:n},(_,i)=>i¿Cuál es el número ${big?"MAYOR":"MENOR"}?
`,answer:fmt(t),opts:shuffle(vals.map(fmt)), why:"Compara primero la parte entera, luego las décimas, después las centésimas… ¡Más cifras no significa más grande!"}; } if(id==="calculo"){ const k=rand(0,5); let txt,r,ex=[]; if(k===0){const a=rand(3,9),b=rand(3,9);txt=`${a} × ${b}`;r=a*b;ex=[a*b+a,a*b-b];} else if(k===1){const a=rand(11,99)/10,m=pick([10,100,1000]);txt=`${fmt(a)} × ${m}`;r=a*m;ex=[a*m/10,a*m*10];} else if(k===2){const a=rand(2,99)*10,m=pick([10,100]);const aa=m===100?a*10:a;txt=`${aa} : ${m}`;r=aa/m;ex=[r*10,r/10];} else if(k===3){const d=pick([2,3,4,5,10]),n=d*rand(3,12);txt=`1/${d} de ${n}`;r=n/d;ex=[n-d,n*d/10];} else if(k===4){const a=pick([25,50,125]),b=a===125?8:a===25?pick([4,8,12]):pick([2,4,6]);txt=`${a} × ${b}`;r=a*b;ex=[r+a,r-a];} else {const p=pick([10,50,25]),n=pick([20,40,60,80,120,200,400]);txt=`${p} % de ${n}`;r=n*p/100;ex=[n-r,r*2];} return {scene:`${txt.replace(/1\/(\d+)/,(m,d)=>`1${d}`)} = ?
`,answer:fmt(r),opts:numOpts(r,ex)}; } if(id==="problemas"){ const k=rand(0,5); if(k===0){const a=rand(6,12),b=rand(4,8),c=rand(10,a*b-5),r=a*b-c; return {scene:`En el comedor hay ${a} mesas con ${b} sillas cada una. Se sientan ${c} alumnos. ¿Cuántas sillas quedan libres?
`,answer:fmt(r),opts:numOpts(r,[a*b,a*b+c]),why:`${a} × ${b} = ${a*b} sillas; ${a*b} − ${c} = ${r}.`};} if(k===1){const b=rand(8,15),d=rand(6,12),a=b*d; return {scene:`Un libro tiene ${a} páginas. Marta lee ${b} páginas cada día. ¿Cuántos días tarda en terminarlo?
`,answer:fmt(d),opts:numOpts(d,[a-b,d+2]),why:`${a} : ${b} = ${d} días.`};} if(k===2){const a=rand(3,6),p=rand(2,5),m=a*p<20?20:50,r=m-a*p; return {scene:`Compramos ${a} cuadernos a ${p} € cada uno y pagamos con un billete de ${m} €. ¿Cuántos euros nos devuelven?
`,answer:fmt(r),opts:numOpts(r,[a*p,m-a-p]),why:`${a} × ${p} = ${a*p} €; ${m} − ${a*p} = ${r} €.`};} if(k===3){const a=rand(12,25),b=rand(20,28),r=a*b; return {scene:`La excursión cuesta ${a} € por alumno y van ${b} alumnos. ¿Cuánto se paga en total?
`,answer:fmt(r),opts:numOpts(r,[a+b,r+a]),why:`${a} × ${b} = ${r} €.`};} if(k===4){const d=pick([3,4,5]),n=d*rand(5,12),r=n/d; return {scene:`En una caja hay ${n} canicas. 1${d} de ellas son rojas. ¿Cuántas canicas rojas hay?
`,answer:fmt(r),opts:numOpts(r,[n-r,n-d]),why:`${n} : ${d} = ${r}.`};} const a=rand(120,480),b=rand(60,180),c=rand(40,a+b-30),r=a+b-c; return {scene:`Una biblioteca tenía ${a} libros. Compró ${b} más y prestó ${c}. ¿Cuántos libros quedan en la biblioteca?
`,answer:fmt(r),opts:numOpts(r,[a+b,a-c]),why:`${a} + ${b} = ${a+b}; ${a+b} − ${c} = ${r}.`}; } if(id==="gramatica"){ const [s,c]=pick(GRAM.filter(x=>!used.has(x[0]))); used.add(s); const html=esc(s).replace(/\*(.+?)\*/,"$1"); return {scene:`${html}
`,answer:c,opts:shuffle([c,...shuffle(CATS.filter(x=>x!==c)).slice(0,2)]),txt:true}; } /* acentos */ const w=pick(ACENTOS.filter(x=>x&&!used.has(x))); used.add(w); const sy=w.split("-"), ti=sy.findIndex(x=>x===x.toUpperCase()), fromEnd=sy.length-1-ti; const type=["aguda","llana","esdrújula"][fromEnd]; const word=sy.join("").toLowerCase(); return {scene:`${esc(word)}
`,answer:type,opts:["aguda","llana","esdrújula"],txt:true, after:()=>`${HELP[g.id]}
${msg}