/** * cuestionarios/js/quiz.js * Lógica del cuestionario TAI con fórmula de corrección AGE. * Fórmula: Nota = (Aciertos - Fallos/3) / TotalPreguntas * 10 */ // ── Estado ────────────────────────────────────────────────── let preguntas = []; let supuestosData = {}; // { "Supuesto I": [...], "Supuesto II": [...] } let faseActual = 'test'; // 'test' | 'supuesto' let indice = 0; let aciertos = 0; let fallos = 0; let respondida = false; let preguntasFalladas = []; // { pregunta, elegida } // ── Mapa de temas y palabras clave ────────────────────────── const TEMAS_KW = [ { id:'const', label:'Constitución Española', link:'../curso.html?bloque=1', kw:['constitución','constitucional','rey ','cortes generales','senado','congreso','diputad','tribunal constitucional','defensor del pueblo','artículo 62','artículo 63','título i','título ii','artículo 1 ','capítulo'] }, { id:'p39', label:'Procedimiento Adm. (Ley 39/2015)', link:'../curso.html?bloque=1', kw:['ley 39','procedimiento administrativo','recurso de alzada','silencio administrativo','notificación','expediente administrativo','recurso potestativo','recurso extraordinario'] }, { id:'p40', label:'Régimen Jurídico (Ley 40/2015)', link:'../curso.html?bloque=1', kw:['ley 40','órgano colegiado','delegación de competencia','avocación','administración general del estado','convenio interadministrativo'] }, { id:'lcsp', label:'Contratación Pública (LCSP)', link:'../curso.html?bloque=1', kw:['contratos del sector público','lcsp','licitación','adjudicación','pliego','contrato menor','concesión de servicios','poder adjudicador'] }, { id:'trebep', label:'Función Pública (TREBEP)', link:'../curso.html?bloque=1', kw:['trebep','funcionario','empleado público','oposición','provisión de puestos','situaciones administrativas','excedencia','régimen disciplinario','carrera profesional'] }, { id:'hac', label:'Hacienda Pública / Presupuestos', link:'../curso.html?bloque=1', kw:['presupuesto','hacienda pública','igae','tribunal de cuentas','crédito presupuestario','gasto público','control financiero','intervención general'] }, { id:'html', label:'HTML / CSS / JavaScript', link:'../curso.html?bloque=3', kw:['html','css','javascript','dom',' t.includes(k))) return tema; } return { id:'otro', label:'Otros / Material general', link:'../curso.html' }; } // ── Elementos DOM ──────────────────────────────────────────── const selExamen = document.getElementById('sel-examen'); const btnIniciar = document.getElementById('btn-iniciar'); const btnSiguiente = document.getElementById('btn-siguiente'); const seccionQuiz = document.getElementById('seccion-quiz'); const seccionFinal = document.getElementById('seccion-final'); const seccionEmpty = document.getElementById('seccion-empty'); const seccionSupSel = document.getElementById('seccion-supuesto-sel'); const supCardsWrap = document.getElementById('sup-cards'); const contextoPanel = document.getElementById('contexto-pregunta'); const examPdfsPanel = document.getElementById('exam-pdfs'); // ── Mapa de PDFs por examen ─────────────────────────────────── const EXAM_PDFS = { 'data/TAI_2019.json': [ { label: 'Cuestionario oficial', icon: 'fa-file-alt', url: 'pdfs/cues_1er_ejer_TAI-L_oep19_154AB89SD658.pdf' }, { label: 'Plantilla definitiva', icon: 'fa-check-square', url: 'pdfs/Plantilla_defTAI-L1ejer_154AB89SD658.pdf' }, { label: 'Plantilla provisional', icon: 'fa-clipboard', url: 'pdfs/plant_prov_1er_ejer_TAI-L_oep19_154AB89SD658.pdf' }, { label: 'Material adicional (supuesto)', icon: 'fa-book-open', url: 'pdfs/07TAIL_154AB89SD658.pdf' }, ], 'data/TAI_2023.json': [ { label: 'Cuestionario oficial', icon: 'fa-file-alt', url: 'pdfs/Cuestionario TAI-L_2023.pdf' }, { label: 'Plantilla de respuestas', icon: 'fa-check-square', url: 'pdfs/PlantillaRespuestas TAI-L_2023.pdf' }, ], 'data/TAI_2024A.json': [ { label: 'Cuestionario oficial', icon: 'fa-file-alt', url: 'pdfs/Cuestionario_TAI_LI_2024_A_M8L91VL1CL_154AB89SD658.pdf' }, { label: 'Plantilla de respuestas', icon: 'fa-check-square', url: 'pdfs/Plantilla_Respuestas_PROV_TAI_LI_2024_A_6J5MFQ8OEN_154AB89SD658.pdf' }, { label: 'Material supuesto II', icon: 'fa-book-open', url: 'data/tai_2024A_supuesto2.md' }, ], 'data/TAI_2024B.json': [ { label: 'Cuestionario oficial', icon: 'fa-file-alt', url: 'pdfs/Cuestionario_TAI_LI_2024_B_DNFGFEK45R_154AB89SD658.pdf' }, { label: 'Plantilla de respuestas', icon: 'fa-check-square', url: 'pdfs/Plantilla_Respuestas_PROV_TAI_LI_2024_B_JQE95HBC1R_154AB89SD658.pdf' }, ], }; const elPreguntaNum = document.getElementById('pregunta-num'); const elPreguntaTxt = document.getElementById('pregunta-txt'); const elOpciones = document.getElementById('opciones'); const elFeedback = document.getElementById('feedback'); const elAciertos = document.getElementById('val-aciertos'); const elFallos = document.getElementById('val-fallos'); const elProgreso = document.getElementById('val-progreso'); const elNota = document.getElementById('val-nota'); // ── Eventos ────────────────────────────────────────────────── btnIniciar.addEventListener('click', iniciarExamen); btnSiguiente.addEventListener('click', siguiente); selExamen.addEventListener('change', () => { btnIniciar.disabled = !selExamen.value; renderExamPdfs(selExamen.value); }); function renderExamPdfs(url) { const pdfs = EXAM_PDFS[url]; if (!pdfs || !pdfs.length) { examPdfsPanel.style.display = 'none'; return; } examPdfsPanel.innerHTML = ' Documentos INAP:' + pdfs.map(p => `` + ` ${escHtml(p.label)}` ).join(''); examPdfsPanel.style.display = 'flex'; } // ── Funciones ──────────────────────────────────────────────── async function iniciarExamen() { const url = selExamen.value; if (!url) return; btnIniciar.disabled = true; btnIniciar.innerHTML = ' Cargando…'; try { const datos = await fetch(url).then(r => r.json()); const todas = Array.isArray(datos) ? datos : (datos.preguntas || []); // Separar preguntas tipo test de supuestos prácticos const testQs = todas.filter(p => !p.contexto?.supuesto); const supuestoQs = todas.filter(p => p.contexto?.supuesto); preguntas = mezclar(testQs); supuestosData = {}; for (const p of supuestoQs) { const nombre = p.contexto.supuesto; if (!supuestosData[nombre]) supuestosData[nombre] = []; supuestosData[nombre].push(p); } } catch (e) { alert('Error cargando el examen. Comprueba la ruta del fichero.'); btnIniciar.disabled = false; btnIniciar.innerHTML = ' Iniciar'; return; } faseActual = 'test'; indice = 0; aciertos = 0; fallos = 0; respondida = false; preguntasFalladas = []; mostrarSolo('quiz'); actualizarMarcador(); mostrarPregunta(); btnIniciar.disabled = false; btnIniciar.innerHTML = ' Reiniciar'; } function mostrarSolo(seccion) { seccionEmpty.style.display = seccion === 'empty' ? 'block' : 'none'; seccionQuiz.style.display = seccion === 'quiz' ? 'block' : 'none'; seccionFinal.style.display = seccion === 'final' ? 'block' : 'none'; seccionSupSel.style.display = seccion === 'supsel' ? 'block' : 'none'; } function mostrarSelectorSupuesto() { supCardsWrap.innerHTML = ''; for (const [nombre, pregs] of Object.entries(supuestosData)) { const ctx = pregs[0]?.contexto || {}; const ref = ctx.referencia_diagrama || ctx.referencia || null; const esImg = ref && /\.(png|jpg|jpeg|gif|webp)$/i.test(ref); const esPdf = ref && /\.pdf$/i.test(ref); const card = document.createElement('div'); card.className = 'sup-card'; card.innerHTML = `
${escHtml(ctx.descripcion || '')}
${esImg ? `¡Sin fallos! Dominas todo el temario de este examen.
'; wrap.style.display = 'block'; return; } // Agrupar fallos por tema detectado const grupos = {}; for (const { pregunta, elegida } of preguntasFalladas) { const tema = detectarTema(pregunta.pregunta); if (!grupos[tema.id]) grupos[tema.id] = { tema, items: [] }; grupos[tema.id].items.push({ pregunta, elegida }); } const n = preguntasFalladas.length; wrap.innerHTML = `Has fallado ${n} pregunta${n > 1 ? 's' : ''}. Estos son los temas donde debes reforzar:
${Object.values(grupos).map(g => `${escHtml(p.pregunta.length > 140 ? p.pregunta.slice(0,140)+'…' : p.pregunta)}