186 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			186 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
<!DOCTYPE html>
 | 
						|
<html lang="es">
 | 
						|
<head>
 | 
						|
    <meta charset="UTF-8">
 | 
						|
    <title>OpoQuizTiny - Copilot Fase 3</title>
 | 
						|
    <meta name="viewport" content="width=device-width,initial-scale=1">
 | 
						|
    <style>
 | 
						|
        body { font-family: system-ui, sans-serif; margin: 0; padding: 2em; background: #f8f9fa; }
 | 
						|
        h1 { font-size: 2em; margin-bottom: 0.5em; }
 | 
						|
        .file-input, .config-form { margin-bottom: 1em; }
 | 
						|
        .json-list { background: #fff; border: 1px solid #ccc; padding: 1em; border-radius: 6px; margin-top: 1em; }
 | 
						|
        pre { background: #f4f4f4; padding: 1em; border-radius: 4px; overflow-x: auto; }
 | 
						|
        .error { color: #b00; margin-top: 1em; }
 | 
						|
        .config-form label { display: block; margin-top: 0.5em; }
 | 
						|
        .config-form input, .config-form select { margin-top: 0.2em; }
 | 
						|
        .config-summary { background: #e9f7ef; border: 1px solid #b2dfdb; padding: 1em; border-radius: 6px; margin-top: 1em; }
 | 
						|
        .quiz-section { background: #fffde7; border: 1px solid #ffe082; padding: 1em; border-radius: 6px; margin-top: 1em; }
 | 
						|
        .question { margin-bottom: 1em; }
 | 
						|
        .answers { margin-bottom: 1em; }
 | 
						|
        .result { background: #e1f5fe; border: 1px solid #81d4fa; padding: 1em; border-radius: 6px; margin-top: 1em; }
 | 
						|
    </style>
 | 
						|
</head>
 | 
						|
<body>
 | 
						|
    <h1>OpoQuizTiny <small style="font-size:0.5em;">(Copilot Fase 3)</small></h1>
 | 
						|
    <form id="jsonForm" class="file-input">
 | 
						|
        <label for="jsonFiles">Cargar archivos JSON de temario:</label>
 | 
						|
        <input type="file" id="jsonFiles" name="jsonFiles" accept=".json" multiple>
 | 
						|
    </form>
 | 
						|
    <form id="configForm" class="config-form">
 | 
						|
        <label for="numQuestions">Número de preguntas:</label>
 | 
						|
        <input type="number" id="numQuestions" name="numQuestions" min="1" max="50" value="10">
 | 
						|
        <label for="questionType">Tipo de preguntas:</label>
 | 
						|
        <select id="questionType" name="questionType">
 | 
						|
            <option value="vf">Verdadero/Falso</option>
 | 
						|
            <option value="single">Opción única</option>
 | 
						|
            <option value="multi">Multiselección</option>
 | 
						|
        </select>
 | 
						|
        <label for="numAnswers">Número de respuestas por pregunta:</label>
 | 
						|
        <input type="number" id="numAnswers" name="numAnswers" min="2" max="10" value="4">
 | 
						|
        <label for="jsonSelect">Seleccionar temario cargado:</label>
 | 
						|
        <select id="jsonSelect" name="jsonSelect" multiple></select>
 | 
						|
        <button type="submit">Guardar configuración</button>
 | 
						|
    </form>
 | 
						|
    <div id="configSummary" class="config-summary" style="display:none;"></div>
 | 
						|
    <div id="quizSection" class="quiz-section" style="display:none;"></div>
 | 
						|
    <div id="output" class="json-list"></div>
 | 
						|
    <div id="error" class="error"></div>
 | 
						|
    <script>
 | 
						|
    let loadedJsons = {};
 | 
						|
    let quizConfig = null;
 | 
						|
    document.getElementById('jsonFiles').addEventListener('change', function (e) {
 | 
						|
        const files = Array.from(e.target.files);
 | 
						|
        const output = document.getElementById('output');
 | 
						|
        const error = document.getElementById('error');
 | 
						|
        const jsonSelect = document.getElementById('jsonSelect');
 | 
						|
        output.innerHTML = '';
 | 
						|
        error.textContent = '';
 | 
						|
        jsonSelect.innerHTML = '';
 | 
						|
        loadedJsons = {};
 | 
						|
        if (!files.length) return;
 | 
						|
        files.forEach(file => {
 | 
						|
            const reader = new FileReader();
 | 
						|
            reader.onload = function(evt) {
 | 
						|
                try {
 | 
						|
                    const json = JSON.parse(evt.target.result);
 | 
						|
                    loadedJsons[file.name] = json;
 | 
						|
                    output.innerHTML += `<h3>${file.name}</h3><pre>${JSON.stringify(json, null, 4)}</pre>`;
 | 
						|
                    const option = document.createElement('option');
 | 
						|
                    option.value = file.name;
 | 
						|
                    option.textContent = file.name;
 | 
						|
                    jsonSelect.appendChild(option);
 | 
						|
                } catch (err) {
 | 
						|
                    error.textContent = `Error en "${file.name}": ${err.message}`;
 | 
						|
                }
 | 
						|
            };
 | 
						|
            reader.onerror = function() {
 | 
						|
                error.textContent = `No se pudo leer el archivo "${file.name}".`;
 | 
						|
            };
 | 
						|
            reader.readAsText(file, 'utf-8');
 | 
						|
        });
 | 
						|
    });
 | 
						|
    document.getElementById('configForm').addEventListener('submit', function(e) {
 | 
						|
        e.preventDefault();
 | 
						|
        const numQuestions = parseInt(document.getElementById('numQuestions').value);
 | 
						|
        const questionType = document.getElementById('questionType').value;
 | 
						|
        const numAnswers = parseInt(document.getElementById('numAnswers').value);
 | 
						|
        const jsonSelect = document.getElementById('jsonSelect');
 | 
						|
        const selectedJsons = Array.from(jsonSelect.selectedOptions).map(opt => opt.value);
 | 
						|
        const configSummary = document.getElementById('configSummary');
 | 
						|
        if (selectedJsons.length === 0) {
 | 
						|
            configSummary.style.display = 'none';
 | 
						|
            alert('Selecciona al menos un temario cargado.');
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        quizConfig = { numQuestions, questionType, numAnswers, selectedJsons };
 | 
						|
        configSummary.innerHTML = `<strong>Configuración guardada:</strong><br>
 | 
						|
            Número de preguntas: ${numQuestions}<br>
 | 
						|
            Tipo de preguntas: ${questionType}<br>
 | 
						|
            Número de respuestas: ${numAnswers}<br>
 | 
						|
            Temarios seleccionados: ${selectedJsons.join(', ')}`;
 | 
						|
        configSummary.style.display = 'block';
 | 
						|
        generarQuiz();
 | 
						|
    });
 | 
						|
    function generarQuiz() {
 | 
						|
        const quizSection = document.getElementById('quizSection');
 | 
						|
        quizSection.innerHTML = '';
 | 
						|
        quizSection.style.display = 'block';
 | 
						|
        // Recopilar todos los nodos del temario seleccionado
 | 
						|
        let nodos = [];
 | 
						|
        quizConfig.selectedJsons.forEach(name => {
 | 
						|
            const json = loadedJsons[name];
 | 
						|
            if (Array.isArray(json)) {
 | 
						|
                nodos = nodos.concat(json);
 | 
						|
            } else if (typeof json === 'object') {
 | 
						|
                nodos.push(json);
 | 
						|
            }
 | 
						|
        });
 | 
						|
        // Generar preguntas aleatorias
 | 
						|
        const preguntas = [];
 | 
						|
        for (let i = 0; i < quizConfig.numQuestions; i++) {
 | 
						|
            const nodo = nodos[Math.floor(Math.random() * nodos.length)];
 | 
						|
            let pregunta = '';
 | 
						|
            let respuestas = [];
 | 
						|
            if (quizConfig.questionType === 'vf') {
 | 
						|
                pregunta = `¿${nodo.name ? (Array.isArray(nodo.name) ? nodo.name[0] : nodo.name) : 'Sin nombre'} es verdadero?`;
 | 
						|
                respuestas = ['Verdadero', 'Falso'];
 | 
						|
            } else if (quizConfig.questionType === 'single') {
 | 
						|
                pregunta = `¿Cuál es la descripción de ${nodo.name ? (Array.isArray(nodo.name) ? nodo.name[0] : nodo.name) : 'Sin nombre'}?`;
 | 
						|
                respuestas = [nodo.description ? (Array.isArray(nodo.description) ? nodo.description[0] : nodo.description) : 'Sin descripción'];
 | 
						|
                while (respuestas.length < quizConfig.numAnswers) {
 | 
						|
                    respuestas.push('Opción incorrecta ' + respuestas.length);
 | 
						|
                }
 | 
						|
            } else if (quizConfig.questionType === 'multi') {
 | 
						|
                pregunta = `Selecciona las opciones correctas sobre ${nodo.name ? (Array.isArray(nodo.name) ? nodo.name[0] : nodo.name) : 'Sin nombre'}`;
 | 
						|
                respuestas = [];
 | 
						|
                if (nodo.description) {
 | 
						|
                    if (Array.isArray(nodo.description)) {
 | 
						|
                        respuestas = respuestas.concat(nodo.description);
 | 
						|
                    } else {
 | 
						|
                        respuestas.push(nodo.description);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                while (respuestas.length < quizConfig.numAnswers) {
 | 
						|
                    respuestas.push('Opción incorrecta ' + respuestas.length);
 | 
						|
                }
 | 
						|
            }
 | 
						|
            preguntas.push({ pregunta, respuestas });
 | 
						|
        }
 | 
						|
        // Renderizar preguntas
 | 
						|
        preguntas.forEach((q, idx) => {
 | 
						|
            const div = document.createElement('div');
 | 
						|
            div.className = 'question';
 | 
						|
            div.innerHTML = `<strong>Pregunta ${idx + 1}:</strong> ${q.pregunta}`;
 | 
						|
            const answersDiv = document.createElement('div');
 | 
						|
            answersDiv.className = 'answers';
 | 
						|
            q.respuestas.forEach((ans, i) => {
 | 
						|
                let inputType = quizConfig.questionType === 'multi' ? 'checkbox' : 'radio';
 | 
						|
                answersDiv.innerHTML += `<label><input type="${inputType}" name="q${idx}" value="${ans}"> ${ans}</label><br>`;
 | 
						|
            });
 | 
						|
            div.appendChild(answersDiv);
 | 
						|
            quizSection.appendChild(div);
 | 
						|
        });
 | 
						|
        // Botón para corregir
 | 
						|
        const btn = document.createElement('button');
 | 
						|
        btn.textContent = 'Corregir';
 | 
						|
        btn.onclick = function() {
 | 
						|
            mostrarResultados(preguntas);
 | 
						|
        };
 | 
						|
        quizSection.appendChild(btn);
 | 
						|
    }
 | 
						|
    function mostrarResultados(preguntas) {
 | 
						|
        const quizSection = document.getElementById('quizSection');
 | 
						|
        let resultado = '<div class="result"><strong>Resultados:</strong><br>';
 | 
						|
        // Para demo, solo muestra las respuestas seleccionadas
 | 
						|
        preguntas.forEach((q, idx) => {
 | 
						|
            const inputs = quizSection.querySelectorAll(`[name="q${idx}"]:checked`);
 | 
						|
            const seleccionadas = Array.from(inputs).map(i => i.value);
 | 
						|
            resultado += `Pregunta ${idx + 1}: Seleccionaste: ${seleccionadas.join(', ') || 'Ninguna'}<br>`;
 | 
						|
        });
 | 
						|
        resultado += '</div>';
 | 
						|
        quizSection.innerHTML += resultado;
 | 
						|
    }
 | 
						|
    </script>
 | 
						|
</body>
 | 
						|
</html>
 |