// Practice Mode Module class PracticeMode extends BaseModule { constructor() { super(); this.sessionStats = { correct: 0, incorrect: 0, total: 0 }; this.answered = false; this.init(); } init() { this.setupEventListeners(); } setupEventListeners() { document.getElementById('start-practice')?.addEventListener('click', () => { this.startPractice(); }); document.getElementById('new-session')?.addEventListener('click', () => { this.resetSession(); }); document.getElementById('skip-question')?.addEventListener('click', () => { this.nextQuestion(); }); document.getElementById('next-question')?.addEventListener('click', () => { this.nextQuestion(); }); document.getElementById('practice-again')?.addEventListener('click', () => { this.resetSession(); this.startPractice(); }); } async startPractice() { const count = parseInt(document.getElementById('question-count').value); this.showLoading(); BaseModule.hide('welcome-message'); BaseModule.hide('practice-content'); BaseModule.hide('practice-complete'); try { const data = await this.fetchQuestions({ mode: 'random', count: count }); this.questions = data; this.currentIndex = 0; this.resetSession(); this.displayQuestion(); this.hideLoading(); BaseModule.show('practice-content'); } catch (error) { this.hideLoading(); console.error('Error in startPractice:', error); } } displayQuestion() { if (this.currentIndex >= this.questions.length) { this.showResults(); return; } const question = this.questions[this.currentIndex]; this.answered = false; let html = `
Pregunta ${question.id}
${this.currentIndex + 1} de ${this.questions.length}
`; if (question.has_image && question.image) { html += `Imagen de la pregunta`; } html += `

${question.question}

`; html += '
'; question.options.forEach((option, index) => { const letter = String.fromCharCode(97 + index); // a, b, c, d html += ` `; }); html += '
'; html += ''; html += '
'; document.getElementById('question-container').innerHTML = html; document.getElementById('question-counter').textContent = `${this.currentIndex + 1} de ${this.questions.length}`; // Setup option click handlers this.setupOptionHandlers(question); BaseModule.show('skip-question'); BaseModule.hide('next-question'); // Setup keyboard shortcuts this.setupKeyboardHandlers(); } setupOptionHandlers(question) { const optionButtons = document.querySelectorAll('.option-enhanced'); optionButtons.forEach(button => { button.addEventListener('click', () => { if (this.answered) return; this.playSound('click'); button.classList.add('selected'); const selectedAnswer = button.getAttribute('data-answer'); this.checkAnswer(selectedAnswer, question); }); }); } setupKeyboardHandlers() { document.removeEventListener('keydown', this.practiceKeyHandler); document.addEventListener('keydown', this.practiceKeyHandler.bind(this)); } practiceKeyHandler(e) { if (this.answered) return; const key = e.key.toLowerCase(); if (['a', 'b', 'c', 'd'].includes(key)) { e.preventDefault(); const optionButton = document.querySelector(`.option-enhanced[data-answer="${key}"]`); if (optionButton) { optionButton.click(); } } } checkAnswer(selectedAnswer, question) { if (this.answered) return; this.answered = true; const isCorrect = selectedAnswer === question.correct; // Update session stats this.sessionStats.total++; if (isCorrect) { this.sessionStats.correct++; this.playSound('correct'); } else { this.sessionStats.incorrect++; this.playSound('incorrect'); } this.updateSessionStats(); // Update global stats if (window.statsManager) { window.statsManager.updateStats(isCorrect); } // Show feedback this.showFeedback(isCorrect, question); BaseModule.hide('skip-question'); BaseModule.show('next-question'); } showFeedback(isCorrect, question) { const optionButtons = document.querySelectorAll('.option-enhanced'); optionButtons.forEach(button => { const answer = button.getAttribute('data-answer'); if (answer === question.correct) { button.classList.add('correct'); } else if (button.classList.contains('selected') && !isCorrect) { button.classList.add('incorrect'); } button.style.pointerEvents = 'none'; }); let feedbackHtml = ''; if (isCorrect) { feedbackHtml = `
¡Excelente!

Has seleccionado la respuesta correcta.

`; } else { feedbackHtml = `
Respuesta incorrecta

La respuesta correcta es: ${question.correct.toUpperCase()})

`; } const feedbackElement = document.getElementById('feedback'); feedbackElement.innerHTML = feedbackHtml; feedbackElement.style.display = 'none'; feedbackElement.style.opacity = '0'; feedbackElement.style.display = 'block'; // Fade in effect setTimeout(() => { feedbackElement.style.transition = 'opacity 0.3s ease'; feedbackElement.style.opacity = '1'; }, 10); } nextQuestion() { document.removeEventListener('keydown', this.practiceKeyHandler); this.currentIndex++; this.displayQuestion(); } updateSessionStats() { document.getElementById('session-correct').textContent = this.sessionStats.correct; document.getElementById('session-incorrect').textContent = this.sessionStats.incorrect; const accuracy = this.sessionStats.total > 0 ? Math.round((this.sessionStats.correct / this.sessionStats.total) * 100) : 0; document.getElementById('session-accuracy').textContent = accuracy + '%'; // Update progress bar const progressBar = document.getElementById('session-progress'); progressBar.style.width = accuracy + '%'; // Change bar color based on accuracy progressBar.classList.remove('bg-danger', 'bg-warning', 'bg-success', 'bg-light'); if (accuracy >= 80) { progressBar.classList.add('bg-success'); } else if (accuracy >= 60) { progressBar.classList.add('bg-warning'); } else if (accuracy > 0) { progressBar.classList.add('bg-danger'); } else { progressBar.classList.add('bg-light'); } } resetSession() { this.sessionStats = { correct: 0, incorrect: 0, total: 0 }; this.updateSessionStats(); } showResults() { const accuracy = this.sessionStats.total > 0 ? Math.round((this.sessionStats.correct / this.sessionStats.total) * 100) : 0; document.getElementById('final-correct').textContent = this.sessionStats.correct; document.getElementById('final-incorrect').textContent = this.sessionStats.incorrect; document.getElementById('final-accuracy').textContent = accuracy + '%'; const finalProgress = document.getElementById('final-progress'); finalProgress.style.width = accuracy + '%'; // Change final progress bar color finalProgress.classList.remove('bg-danger', 'bg-warning', 'bg-success'); if (accuracy >= 80) { finalProgress.classList.add('bg-success'); if (window.Utils) { Utils.createConfetti(); Utils.playSound('complete'); Utils.showNotification('¡Excelente trabajo! Has obtenido una puntuación sobresaliente.', 'success'); } } else if (accuracy >= 60) { finalProgress.classList.add('bg-warning'); if (window.Utils) { Utils.playSound('complete'); Utils.showNotification('¡Buen trabajo! Sigue practicando para mejorar.', 'warning'); } } else { finalProgress.classList.add('bg-danger'); if (window.Utils) { Utils.showNotification('Sigue estudiando. La práctica hace al maestro.', 'info'); } } BaseModule.hide('practice-content'); BaseModule.show('practice-complete'); } } // Auto-initialize when DOM is ready document.addEventListener('DOMContentLoaded', function() { if (document.getElementById('practice-content')) { window.practiceMode = new PracticeMode(); } }); // Export for global use window.PracticeMode = PracticeMode;