r

<!doctype html>
<html lang="es">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>RumanoDiario – aprende rumano jugando</title>
<style>
:root{
  --duo:#58cc02;--duo-dark:#4caf00;--wrong:#ea2b2b;--bg:#0d3b66;--card:#ffffff;--text:#1c1c1c;
  --shadow:0 4px 12px rgba(0,0,0,.25);
  font-family:Inter,system-ui,sans-serif;
}
* {box-sizing:border-box;margin:0;padding:0;}
body{background:var(--bg);color:#fff;display:flex;flex-direction:column;min-height:100vh;}
header{display:flex;justify-content:space-between;align-items:center;padding:1rem 1.2rem;}
header h1{font-size:1.4rem;}
#headerStats{display:flex;gap:1rem;font-size:1rem;}
main{flex:1;display:flex;align-items:center;justify-content:center;padding:1rem;}
.screen{display:none;width:100%;max-width:640px;}
.screen.active{display:block;}
#lessonGrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:1rem;}
.lessonCard{background:var(--card);color:var(--text);border-radius:12px;padding:1rem;text-align:center;cursor:pointer;transition:.2s;box-shadow:var(--shadow);}
.lessonCard:hover{transform:scale(1.05);}
.lessonCard.locked{opacity:.5;cursor:not-allowed;}
#progressBar{height:8px;background:#ffffff33;border-radius:4px;overflow:hidden;margin-bottom:1rem;}
#progressBar div{height:100%;background:var(--duo);width:0%;transition:width .3s;}
.btn{width:100%;border:none;padding:.9rem;font-size:1rem;border-radius:8px;cursor:pointer;font-weight:600;}
.primary{background:var(--duo);color:#fff;}
.primary:disabled{background:#888;}
.success{background:#2ecc71;color:#fff;}
.hidden{display:none;}
.tile{display:inline-block;background:var(--card);color:var(--text);padding:.6rem 1rem;margin:.25rem;border-radius:6px;cursor:pointer;user-select:none;}
.tile.selected{background:var(--duo);color:#fff;}
input[type=text]{width:100%;padding:.8rem;font-size:1rem;border-radius:6px;border:none;}
#exerciseArea{display:flex;flex-direction:column;gap:1rem;margin-bottom:1.2rem;}
.matchRow{display:flex;gap:1rem;flex-wrap:wrap;justify-content:center;}
.matchBtn{background:var(--card);color:var(--text);padding:.6rem 1rem;border-radius:6px;border:none;cursor:pointer;}
.matchBtn.on{background:var(--duo);color:#fff;}
.matchBtn.correct{background:#27ae60;color:#fff;pointer-events:none;}
.matchBtn.wrong{background:var(--wrong);color:#fff;}
</style>
</head>
<body>
<header>
  <h1>🇷🇴 RumanoDiario</h1>
  <div id="headerStats">
    <span id="streak">🔥 0</span>
    <span id="xp">⚡ 0 XP</span>
    <span id="level">Nivel <b>1</b></span>
  </div>
</header>

<main id="screens">
  <!-- MENÚ -->
  <section id="menu" class="screen active">
    <h2>Elige tu lección</h2>
    <div id="lessonGrid"></div>
  </section>

  <!-- LECCIÓN -->
  <section id="lesson" class="screen">
    <div id="progressBar"><div></div></div>
    <div id="questionCounter"></div>
    <div id="exerciseArea"></div>
    <button id="checkBtn" class="btn primary" disabled>Comprobar</button>
    <button id="continueBtn" class="btn success hidden">Continuar</button>
  </section>

  <!-- RESULTADOS -->
  <section id="results" class="screen">
    <h2>¡Lección completada!</h2>
    <p id="resultsText"></p>
    <button class="btn primary" onclick="showScreen('menu')">Menú</button>
    <button id="nextLessonBtn" class="btn success hidden">Siguiente lección →</button>
  </section>
</main>

<audio id="sndOk" preload="auto">
  <source src="data:audio/wav;base64,UklGRnoGAABXQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgAZGF0YQoGAACBhYqFbF1fdJivrJBhNjVgodDbq2EcBj+a2/LDciUFLIHO8tiJNwgZaLvt559NEAxQp+PwtmMcBjiR1/LMeSwFJHfH8N2QQAoUXrTp66hVFApGn+DyvmwhBSuBzvLZiTYIG2m98OScTgwOUarm7blmFgU7k9n1unEiBC13yO/eizEIHWq+8+OWT" type="audio/wav"/>
</audio>
<audio id="sndNo" preload="auto">
  <source src="data:audio/wav;base64,UklGRuICAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YcACAACBhYqFbF1fdJivrJBhNjVgodDbq2EcBj+a2/LDciUFLIHO8tiJNwgZaLvt559NEAxQp+PwtmMcBjiR1/LMeSwFJHfH8N2QQAoUXrTp66hVFApGn+DyvmwhBSuBzvLZiTYIG2m98OScTgwOUarm7blmFgU7k9n1unEiBC13yO/eizEIHWq+8+OWT" type="audio/wav"/>
</audio>

<script>
/*********************************************************************
 * BASE DE DATOS GRANDE
 *********************************************************************/
const LESSONS = [
  {
    id:1, title:"Saludos", locked:false,
    vocab:[
      {ro:"bună",es:"hola"},{ro:"salut",es:"hola (informal)"},{ro:"dimineața",es:"buenos días"},
      {ro:"ziua",es:"buenas tardes"},{ro:"seara",es:"buenas noches"},{ro:"noapte bună",es:"buenas noches (despedida)"},
      {ro:"la revedere",es:"adiós"},{ro:"pe mâine",es:"hasta mañana"},{ro:"cu plăcere",es:"con gusto"}
    ]
  },
  {
    id:2, title:"Presentaciones", locked:true,
    vocab:[
      {ro:"numele meu este",es:"mi nombre es"},{ro:"eu sunt",es:"yo soy"},{ro:"încântat",es:"encantado"},
      {ro:"ce mai faci?",es:"¿cómo estás?"},{ro:"bine, mulțumesc",es:"bien, gracias"},{ro:"și tu?",es:"¿y tú?"},
      {ro:"cât de ani ai?",es:"¿cuántos años tienes?"},{ro:"am 25 de ani",es:"tengo 25 años"}
    ]
  },
  {
    id:3, title:"Números 0-20", locked:true,
    vocab:[
      {ro:"zero",es:"cero"},{ro:"unu",es:"uno"},{ro:"doi",es:"dos"},{ro:"trei",es:"tres"},
      {ro:"patru",es:"cuatro"},{ro:"cinci",es:"cinco"},{ro:"șase",es:"seis"},{ro:"șapte",es:"siete"},
      {ro:"opt",es:"ocho"},{ro:"nouă",es:"nueve"},{ro:"zece",es:"diez"},{ro:"unsprezece",es:"once"},
      {ro:"douăsprezece",es:"doce"},{ro:"treisprezece",es:"trece"},{ro:"paisprezece",es:"catorce"},
      {ro:"cincisprezece",es:"quince"},{ro:"șaisprezece",es:"dieciséis"},{ro:"șaptesprezece",es:"diecisiete"},
      {ro:"optsprezece",es:"dieciocho"},{ro:"nouăsprezece",es:"diecinueve"},{ro:"douăzeci",es:"veinte"}
    ]
  },
  {
    id:4, title:"Colores", locked:true,
    vocab:[
      {ro:"roșu",es:"rojo"},{ro:"albastru",es:"azul"},{ro:"galben",es:"amarillo"},
      {ro:"verde",es:"verde"},{ro:"negru",es:"negro"},{ro:"alb",es:"blanco"},
      {ro:"roz",es:"rosa"},{ro:"mov",es:"morado"},{ro:"portocaliu",es:"naranja"},
      {ro:"maro",es:"marrón"},{ro:"gri",es:"gris"}
    ]
  },
  {
    id:5, title:"Familia", locked:true,
    vocab:[
      {ro:"mamă",es:"madre"},{ro:"tată",es:"padre"},{ro:"frate",es:"hermano"},
      {ro:"soră",es:"hermana"},{ro:"copil",es:"niño/hijo"},{ro:"fiu",es:"hijo"},
      {ro:"fiică",es:"hija"},{ro:"bunică",es:"abuela"},{ro:"bunic",es:"abuelo"},
      {ro:"soț",es:"esposo"},{ro:"soție",es:"esposa"}
    ]
  },
  {
    id:6, title:"Comida", locked:true,
    vocab:[
      {ro:"pâine",es:"pan"},{ro:"lapte",es:"leche"},{ro:"ouă",es:"huevos"},
      {ro:"brânză",es:"queso"},{ro:"carne",es:"carne"},{ro:"apa",es:"agua"},
      {ro:"vin",es:"vino"},{ro:"fructe",es:"frutas"},{ro:"legume",es:"verduras"},
      {ro:"dulce",es:"dulce"},{ro:"sare",es:"sal"},{ro:"piper",es:"pimienta"}
    ]
  },
  {
    id:7, title:"El tiempo", locked:true,
    vocab:[
      {ro:"soare",es:"sol"},{ro:"ploaie",es:"lluvia"},{ro:"zăpadă",es:"nieve"},
      {ro:"vânt",es:"viento"},{ro:"ceată",es:"niebla"},{ro:"cald",es:"calor"},
      {ro:"rece",es:"frío"},{ro:"umbrelă",es:"paraguas"},{ro:"temporatură",es:"temperatura"},
      {ro:"grade",es:"grados"},{ro:"astăzi",es:"hoy"},{ro:"mâine",es:"mañana"}
    ]
  },
  {
    id:8, title:"Verbos comunes", locked:true,
    vocab:[
      {ro:"a fi",es:"ser/estar"},{ro:"a avea",es:"tener"},{ro:"a face",es:"hacer"},
      {ro:"a merge",es:"ir"},{ro:"a veni",es:"venir"},{ro:"a spune",es:"decir"},
      {ro:"a vedea",es:"ver"},{ro:"a da",es:"dar"},{ro:"a lua",es:"tomar"},
      {ro:"a iubi",es:"amar"},{ro:"a mânca",es:"comer"},{ro:"a bea",es:"beber"}
    ]
  },
  {
    id:9, title:"Frases útiles", locked:true,
    vocab:[
      {ro:"unde este toaleta?",es:"¿dónde está el baño?"},{ro:"cât costă?",es:"¿cuánto cuesta?"},
      {ro:"nu înțeleg",es:"no entiendo"},{ro:"vorbiți engleză?",es:"¿habla inglés?"},
      {ro:"ajutor!",es:"¡ayuda!"},{ro:"sunt pierdut",es:"estoy perdido"},
      {ro:"cheia camerei",es:"la llave de la habitación"},{ro:"rezervare",es:"reserva"}
    ]
  },
  {
    id:10, title:"Viajes", locked:true,
    vocab:[
      {ro:"autobuz",es:"autobús"},{ro:"tren",es:"tren"},{ro:"avion",es:"avión"},
      {ro:"bicicletă",es:"bicicleta"},{ro:"mașină",es:"coche"},{ro:"hotel",es:"hotel"},
      {ro:"gară",es:"estación"},{ro:"aeroport",es:"aeropuerto"},{ro:"bilet",es:"billete"},
      {ro:"valiză",es:"maleta"},{ro:"hartă",es:"mapa"},{ro:"pașaport",es:"pasaporte"}
    ]
  }
];

/*********************************************************************
 * ESTADO
 *********************************************************************/
let state = {
  currentLesson:null,
  currentIndex:0,
  exercises:[],
  streak:Number(localStorage.getItem("streak")||0),
  xp:Number(localStorage.getItem("xp")||0),
  level:Number(localStorage.getItem("level")||1),
  lastDate:localStorage.getItem("lastDate")||null,
  unlocked:JSON.parse(localStorage.getItem("unlocked")||"[1]") // ids desbloqueados
};

/*********************************************************************
 * UTILS
 *********************************************************************/
const qs=s=>document.querySelector(s);
const qsa=s=>[...document.querySelectorAll(s)];
const rand=(arr)=>arr[Math.floor(Math.random()*arr.length)];
const shuffle=arr=>arr.sort(()=>Math.random()-.5);
function showScreen(name){qsa(".screen").forEach(sc=>sc.classList.remove("active"));qs("#"+name).classList.add("active");}
function play(id){const a=qs(id);a.currentTime=0;a.play();}
function speakRo(text){
  if(!('speechSynthesis' in window))return;
  const u=new SpeechSynthesisUtterance(text);u.lang="ro-RO";speechSynthesis.speak(u);
}
function saveState(){
  localStorage.setItem("streak",state.streak);
  localStorage.setItem("xp",state.xp);
  localStorage.setItem("level",state.level);
  localStorage.setItem("lastDate",state.lastDate);
  localStorage.setItem("unlocked",JSON.stringify(state.unlocked));
}

/*********************************************************************
 * MENÚ
 *********************************************************************/
function renderMenu(){
  const grid=qs("#lessonGrid");grid.innerHTML="";
  LESSONS.forEach(ls=>{
    const div=document.createElement("div");
    div.className="lessonCard"+(ls.locked?" locked":"");
    div.innerHTML=`<h3>${ls.title}</h3><small>${ls.vocab.length} términos</small>`;
    if(!ls.locked)div.onclick=()=>startLesson(ls);
    grid.appendChild(div);
  });
  updateHeader();
}
function updateHeader(){
  qs("#streak").textContent="🔥 "+state.streak;
  qs("#xp").textContent="⚡ "+state.xp+" XP";
  qs("#level b").textContent=state.level;
}

/*********************************************************************
 * LECCIÓN
 *********************************************************************/
function startLesson(lesson){
  state.currentLesson=lesson;
  state.currentIndex=0;
  buildExercises(lesson);
  showScreen("lesson");
  renderProgress();
  renderExercise();
}
function buildExercises(lesson){
  state.exercises=[];
  lesson.vocab.forEach(w=>{
    state.exercises.push({type:"pickEs",word:w,prompt:`¿Qué significa <b>${w.ro}</b>?`});
    state.exercises.push({type:"pickRo",word:w,prompt:`Traduce al rumano: <b>${w.es}</b>`});
    state.exercises.push({type:"listen",word:w,prompt:`Escucha y escribe lo que oyes`});
    state.exercises.push({type:"order",word:w,prompt:`Ordena la frase`});
    state.exercises.push({type:"fill",word:w,prompt:`Completa la palabra`});
  });
  shuffle(state.exercises);
}
function renderProgress(){
  const t=state.exercises.length,d=state.currentIndex;
  qs("#progressBar div").style.width=(d/t*100)+"%";
  qs("#questionCounter").textContent=`Pregunta ${d+1} de ${t}`;
}
function renderExercise(){
  const ex=state.exercises[state.currentIndex];
  const area=qs("#exerciseArea");area.innerHTML="";
  qs("#checkBtn").classList.remove("hidden");
  qs("#continueBtn").classList.add("hidden");
  qs("#checkBtn").disabled=true;
  const p=document.createElement("p");p.innerHTML=ex.prompt;area.appendChild(p);

  switch(ex.type){
    case "pickEs":case "pickRo":
      const choices=buildChoices(ex);
      choices.forEach(ch=>{
        const t=document.createElement("span");t.className="tile";t.textContent=ch;
        t.onclick=()=>{qsa("#exerciseArea .tile").forEach(x=>x.classList.remove("selected"));t.classList.add("selected");selectedAnswer=ch;qs("#checkBtn").disabled=false;};
        area.appendChild(t);
      });break;
    case "listen":
      speakRo(ex.word.ro);
      const inp=document.createElement("input");inp.type="text";inp.placeholder="Escribe en rumano…";
      inp.oninput=()=>qs("#checkBtn").disabled=!inp.value.trim();
      area.appendChild(inp);
      qs("#checkBtn").onclick=()=>checkWrite(inp.value.trim(),ex.word.ro);return;
    case "order":
      const letters=ex.word.ro.split("");shuffle(letters);
      const orderArea=document.createElement("div");orderArea.id="orderArea";
      letters.forEach(l=>{
        const b=document.createElement("button");b.className="matchBtn";b.textContent=l;
        b.onclick=()=>{orderAnswer=(orderAnswer||"")+l;b.classList.add("on");qs("#checkBtn").disabled=false;};
        orderArea.appendChild(b);
      });
      area.appendChild(orderArea);
      qs("#checkBtn").onclick=()=>checkWrite(orderAnswer,ex.word.ro);return;
    case "fill":
      const w=ex.word.ro;
      const hideIdx=Math.floor(w.length/2);
      const shown=w[hideIdx]===" "?w.replace(w.trim().split("")[hideIdx],"_"):w.replace(w[hideIdx],"_");
      const fillInp=document.createElement("input");fillInp.type="text";fillInp.placeholder="Completa…";
      fillInp.oninput=()=>qs("#checkBtn").disabled=!fillInp.value.trim();
      area.innerHTML+=`<p>${shown}</p>`;area.appendChild(fillInp);
      qs("#checkBtn").onclick=()=>checkWrite(fillInp.value.trim(),ex.word.ro);return;
  }
  qs("#checkBtn").onclick=()=>checkChoice(ex.answer);
}
let selectedAnswer=null,orderAnswer="";
function buildChoices(ex){
  const right=ex.type==="pickEs"?ex.word.es:ex.word.ro;
  const wrongs=LESSONS.flatMap(l=>l.vocab).filter(v=>v.ro!==ex.word.ro).map(v=>ex.type==="pickEs"?v.es:v.ro);
  const picks=[right];while(picks.length<4)picks.push(rand(wrongs));return shuffle(picks);
}
function checkChoice(correct){feedback(selectedAnswer===correct);}
function checkWrite(value,correct){feedback(value.toLowerCase()===correct.toLowerCase());}
function feedback(ok){
  play(ok?"#sndOk":"#sndNo");
  qs("#checkBtn").classList.add("hidden");
  qs("#continueBtn").classList.remove("hidden");
  if(ok){state.xp+=10;saveState();updateHeader();}
}
qs("#continueBtn").onclick=()=>{
  state.currentIndex++;
  if(state.currentIndex>=state.exercises.length){
    finishLesson();
  }else{
    renderProgress();
    renderExercise();
  }
};
function finishLesson(){
  const today=new Date().toISOString().slice(0,10);
  if(state.lastDate!==today){state.streak++;state.lastDate=today;}
  const newLevel=Math.floor(state.xp/100)+1;
  if(newLevel>state.level)state.level=newLevel;
  saveState();
  qs("#resultsText").innerHTML=`¡Bien hecho! Ganaste <b>${state.exercises.length*10} XP</b>. Racha: <b>${state.streak} días</b>.`;
  // desbloquear siguiente
  const next=LESSONS.find(l=>l.id===state.currentLesson.id+1);
  if(next&&!state.unlocked.includes(next.id)){state.unlocked.push(next.id);next.locked=false;saveState();}
  qs("#nextLessonBtn").classList.toggle("hidden",!next);
  qs("#nextLessonBtn").onclick=()=>startLesson(next);
  showScreen("results");
}

/*********************************************************************
 * INIT
 *********************************************************************/
(function init(){
  LESSONS.forEach(ls=>ls.locked=!state.unlocked.includes(ls.id));
  renderMenu();
})();
</script>
</body>
</html>

Entradas populares de este blog

CALCULADORA C1 Y C2 (TCAE, TF, Aux Advo/a, Advo/a, TER, TEL, TEAP,TEDS, Celador/a-Conductor/a, TEMEII, Cocinero/a, Telefonista)

CALCULADORA Grupo E: Celador/a, Pinche, Limpiador/a, Peón, P. Lavanderia Planchado, etc.

CALCULADORA GRUPOS A1 Y A2: FEA, Medicina, Cuerpo A4, T Social, TFA, TMGFA, Enfermería, Fisioterapia, etc.