const state = { selectedTopic: null, selectedDifficulty: 1, selectedCount: 10, practice: { questions: [], index: 0, awaitingNext: false, currentProblem: null, topic: null, difficulty: 1, count: 0 }, quiz: { questions: [], index: 0, score: 0, timer: null, timeLeft: 0, active: false } }; function navigate(view) { if (view === 'home' && state.quiz.active) { clearInterval(state.quiz.timer); state.quiz.active = false; } document.querySelectorAll('.view').forEach(v => v.classList.remove('active')); const el = document.getElementById('view-' + view); if (el) el.classList.add('active'); updateHeader(); if (view === 'progress') renderProgress(); if (view === 'home') renderHome(); if (view === 'topics' || view === 'quiz-setup') resetSelection(view); window.scrollTo(0, 0); } function updateHeader() { const data = ProgressStore.load(); document.getElementById('points-header').textContent = data.points; document.getElementById('streak-header').textContent = data.streak; } function renderHome() { updateHeader(); } function resetSelection(view) { const container = document.getElementById('view-' + view); container.querySelectorAll('.topic-card').forEach(c => c.classList.remove('selected')); container.querySelectorAll('.diff-btn').forEach(b => b.classList.remove('active')); container.querySelector('.diff-btn[data-level="1"]')?.classList.add('active'); state.selectedTopic = null; state.selectedDifficulty = 1; const startBtn = document.getElementById(view === 'topics' ? 'start-practice' : 'start-quiz'); if (startBtn) startBtn.disabled = true; } document.addEventListener('click', function(e) { const topicCard = e.target.closest('.topic-card'); if (topicCard) { const view = topicCard.closest('.view'); if (!view) return; view.querySelectorAll('.topic-card').forEach(c => c.classList.remove('selected')); topicCard.classList.add('selected'); state.selectedTopic = topicCard.dataset.topic; const isQuiz = view.id === 'view-quiz-setup'; const btn = document.getElementById(isQuiz ? 'start-quiz' : 'start-practice'); if (btn) btn.disabled = false; return; } const diffBtn = e.target.closest('.diff-btn'); if (diffBtn) { const view = diffBtn.closest('.view'); view.querySelectorAll('.diff-btn').forEach(b => b.classList.remove('active')); diffBtn.classList.add('active'); state.selectedDifficulty = parseInt(diffBtn.dataset.level); return; } const countBtn = e.target.closest('.count-btn'); if (countBtn) { countBtn.closest('.quiz-count-selector').querySelectorAll('.count-btn').forEach(b => b.classList.remove('active')); countBtn.classList.add('active'); state.selectedCount = parseInt(countBtn.dataset.count); return; } }); document.getElementById('start-practice')?.addEventListener('click', function() { if (!state.selectedTopic) return; startPractice(); }); document.getElementById('start-quiz')?.addEventListener('click', function() { if (!state.selectedTopic) return; startQuiz(); }); function startPractice() { state.practice.topic = state.selectedTopic; state.practice.difficulty = state.selectedDifficulty; state.practice.count = 0; nextPracticeProblem(); } function nextPracticeProblem() { const topic = state.practice.topic; const diff = state.practice.difficulty; const problem = MathEngine.generateProblem(topic, diff); state.practice.currentProblem = problem; state.practice.awaitingNext = false; state.practice.count++; navigate('practice'); showPracticeProblem(); } function showPracticeProblem() { const q = state.practice.currentProblem; document.getElementById('practice-problem').textContent = q.display; document.getElementById('practice-counter').textContent = `#${state.practice.count}`; document.getElementById('practice-topic-label').textContent = q.type.replace('-', ' '); document.getElementById('practice-input').value = ''; document.getElementById('practice-input').disabled = false; document.getElementById('practice-check').disabled = false; document.getElementById('practice-feedback').className = ''; document.getElementById('practice-feedback').textContent = ''; document.getElementById('practice-steps').style.display = 'none'; document.getElementById('practice-steps').innerHTML = ''; document.getElementById('practice-actions').style.display = 'none'; document.getElementById('practice-input').focus(); } document.getElementById('practice-check')?.addEventListener('click', checkPracticeAnswer); document.getElementById('practice-input')?.addEventListener('keydown', function(e) { if (e.key === 'Enter') { if (state.practice.awaitingNext) { nextPracticeProblem(); } else { checkPracticeAnswer(); } } }); function checkPracticeAnswer() { if (state.practice.awaitingNext) return; const input = document.getElementById('practice-input'); const answer = parseFloat(input.value); const problem = state.practice.currentProblem; if (isNaN(answer)) return; const correct = answer === problem.answer; const fb = document.getElementById('practice-feedback'); const steps = document.getElementById('practice-steps'); if (correct) { fb.className = 'feedback-correct'; fb.textContent = '✅ Correct!'; } else { fb.className = 'feedback-incorrect'; fb.textContent = `❌ Not quite. The answer is ${problem.answerDisplay || problem.answer}`; } ProgressStore.recordAnswer(problem.type, correct); updateHeader(); input.disabled = true; document.getElementById('practice-check').disabled = true; state.practice.awaitingNext = true; document.getElementById('practice-actions').style.display = 'flex'; } document.getElementById('practice-show-steps')?.addEventListener('click', function() { const problem = state.practice.currentProblem; const steps = document.getElementById('practice-steps'); if (steps.style.display === 'none') { steps.innerHTML = problem.steps.map(s => `
${s}
`).join(''); steps.style.display = 'block'; this.textContent = 'Hide Steps'; } else { steps.style.display = 'none'; this.textContent = 'Show Steps'; } }); document.getElementById('practice-next')?.addEventListener('click', function() { nextPracticeProblem(); }); function startQuiz() { const topic = state.selectedTopic; const diff = state.selectedDifficulty; const count = state.selectedCount; state.quiz.questions = MathEngine.generateQuizQuestions(topic, diff, count); state.quiz.index = 0; state.quiz.score = 0; state.quiz.timeLeft = count * 15; state.quiz.active = true; navigate('quiz'); showQuizProblem(); startQuizTimer(); } function showQuizProblem() { const q = state.quiz.questions[state.quiz.index]; document.getElementById('quiz-problem').textContent = q.display; document.getElementById('quiz-question-num').textContent = `Question ${state.quiz.index + 1} of ${state.quiz.questions.length}`; document.getElementById('quiz-score').textContent = state.quiz.score; document.getElementById('quiz-total').textContent = state.quiz.questions.length; document.getElementById('quiz-input').value = ''; document.getElementById('quiz-input').disabled = false; document.getElementById('quiz-submit').disabled = false; document.getElementById('quiz-feedback').className = ''; document.getElementById('quiz-feedback').textContent = ''; document.getElementById('quiz-input').focus(); updateQuizProgress(); } function updateQuizProgress() { const pct = (state.quiz.index / state.quiz.questions.length) * 100; document.getElementById('quiz-progress-fill').style.width = pct + '%'; } function startQuizTimer() { updateTimerDisplay(); state.quiz.timer = setInterval(function() { state.quiz.timeLeft--; updateTimerDisplay(); if (state.quiz.timeLeft <= 0) { clearInterval(state.quiz.timer); endQuiz(); } }, 1000); } function updateTimerDisplay() { const minutes = Math.floor(state.quiz.timeLeft / 60); const seconds = state.quiz.timeLeft % 60; document.getElementById('quiz-timer').textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`; const timerEl = document.querySelector('.quiz-timer'); if (state.quiz.timeLeft <= 15) { timerEl.style.color = '#e74c3c'; } else if (state.quiz.timeLeft <= 30) { timerEl.style.color = '#f5a623'; } else { timerEl.style.color = '#2c3e50'; } } document.getElementById('quiz-submit')?.addEventListener('click', submitQuizAnswer); document.getElementById('quiz-input')?.addEventListener('keydown', function(e) { if (e.key === 'Enter') submitQuizAnswer(); }); function submitQuizAnswer() { const input = document.getElementById('quiz-input'); const answer = parseFloat(input.value); const problem = state.quiz.questions[state.quiz.index]; if (isNaN(answer)) return; const correct = answer === problem.answer; const fb = document.getElementById('quiz-feedback'); if (correct) { state.quiz.score++; fb.className = 'feedback-correct'; fb.textContent = '✅ Correct!'; ProgressStore.recordAnswer(problem.type, true); } else { fb.className = 'feedback-incorrect'; const display = problem.answerDisplay || problem.answer; fb.textContent = `❌ Answer: ${display}`; ProgressStore.recordAnswer(problem.type, false); } updateHeader(); input.disabled = true; document.getElementById('quiz-submit').disabled = true; setTimeout(function() { if (!state.quiz.active) return; state.quiz.index++; if (state.quiz.index >= state.quiz.questions.length) { clearInterval(state.quiz.timer); endQuiz(); } else { showQuizProblem(); } }, 800); } function endQuiz() { state.quiz.active = false; const total = state.quiz.questions.length; const score = state.quiz.score; const pct = Math.round((score / total) * 100); const data = ProgressStore.recordQuiz(state.selectedTopic, score, total, state.selectedDifficulty); updateHeader(); let stars = '⭐'; if (pct >= 100) stars = '⭐⭐⭐'; else if (pct >= 80) stars = '⭐⭐'; document.getElementById('results-stars').textContent = stars; document.getElementById('results-correct').textContent = score; document.getElementById('results-total').textContent = total; document.getElementById('results-pct').textContent = pct + '%'; if (pct >= 100) document.getElementById('results-title').textContent = '🎉 Perfect Score!'; else if (pct >= 80) document.getElementById('results-title').textContent = 'Great Job! 🌟'; else if (pct >= 60) document.getElementById('results-title').textContent = 'Good Effort! 💪'; else document.getElementById('results-title').textContent = 'Keep Practicing! 📚'; const pointsEarned = pct >= 80 ? 30 : pct >= 60 ? 15 : 5; document.getElementById('results-points').textContent = pointsEarned; document.getElementById('results-streak').textContent = data.streak; navigate('results'); } function renderProgress() { const data = ProgressStore.load(); const attempted = data.totalAttempted || 1; document.getElementById('stat-points').textContent = data.points; document.getElementById('stat-streak').textContent = data.bestStreak; document.getElementById('stat-accuracy').textContent = Math.round((data.totalCorrect / attempted) * 100) + '%'; const topics = ['addition', 'subtraction', 'multiplication', 'division', 'word-problems']; const labels = { 'addition': '➕ Add', 'subtraction': '➖ Sub', 'multiplication': '✖️ Mul', 'division': '➗ Div', 'word-problems': '📖 Word' }; const breakdown = document.getElementById('topic-breakdown'); breakdown.innerHTML = ''; topics.forEach(t => { const stats = ProgressStore.getTopicStats(t); const pct = stats.attempted > 0 ? Math.round((stats.correct / stats.attempted) * 100) : 0; const row = document.createElement('div'); row.className = 'topic-row'; row.innerHTML = ` ${labels[t] || t} ${pct}% `; breakdown.appendChild(row); }); const hist = document.getElementById('quiz-history'); hist.innerHTML = ''; if (data.quizHistory.length === 0) { hist.innerHTML = 'No quizzes yet. Take one to see it here!
'; } else { const recent = [...data.quizHistory].reverse().slice(0, 10); recent.forEach(h => { const div = document.createElement('div'); div.className = 'quiz-history-item'; const date = new Date(h.date); const dateStr = date.toLocaleDateString(); const pct = Math.round((h.score / h.total) * 100); div.innerHTML = ` ${h.topic} (Lv${h.difficulty}) ${h.score}/${h.total} (${pct}%) - ${dateStr} `; hist.appendChild(div); }); } } document.addEventListener('DOMContentLoaded', function() { navigate('home'); });