|
|
<!DOCTYPE html> |
|
|
<html lang="en"> |
|
|
<head> |
|
|
<meta charset="UTF-8"> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
|
<title>QuizCraft Pro - Quiz</title> |
|
|
<link rel="icon" type="image/x-icon" href="/static/favicon.ico"> |
|
|
<script src="https://cdn.tailwindcss.com"></script> |
|
|
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script> |
|
|
<script src="https://unpkg.com/feather-icons"></script> |
|
|
<script src="https://cdn.jsdelivr.net/npm/animejs/lib/anime.min.js"></script> |
|
|
<style> |
|
|
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap'); |
|
|
body { |
|
|
font-family: 'Poppins', sans-serif; |
|
|
} |
|
|
.glass-card { |
|
|
background: rgba(255, 255, 255, 0.1); |
|
|
backdrop-filter: blur(10px); |
|
|
border: 1px solid rgba(255, 255, 255, 0.2); |
|
|
} |
|
|
.btn-primary { |
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
|
|
transition: all 0.3s ease; |
|
|
} |
|
|
.btn-primary:hover { |
|
|
transform: translateY(-2px); |
|
|
box-shadow: 0 10px 20px rgba(0,0,0,0.2); |
|
|
} |
|
|
.option-card { |
|
|
transition: all 0.3s ease; |
|
|
cursor: pointer; |
|
|
} |
|
|
.option-card:hover { |
|
|
transform: translateY(-2px); |
|
|
background: rgba(255, 255, 255, 0.15); |
|
|
} |
|
|
.option-card.selected { |
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
|
|
} |
|
|
.progress-bar { |
|
|
transition: width 0.5s ease-in-out; |
|
|
} |
|
|
</style> |
|
|
</head> |
|
|
<body class="min-h-screen bg-gradient-to-br from-purple-900 via-blue-900 to-indigo-900 text-white"> |
|
|
|
|
|
<nav class="glass-card rounded-lg m-4 p-4"> |
|
|
<div class="container mx-auto flex justify-between items-center"> |
|
|
<div class="flex items-center space-x-2"> |
|
|
<i data-feather="award" class="text-purple-400"></i> |
|
|
<span class="text-xl font-bold">QuizCraft Pro</span> |
|
|
</div> |
|
|
<div class="flex space-x-6"> |
|
|
<a href="index.html" class="hover:text-purple-300 transition-colors">Home</a> |
|
|
<a href="quiz.html" class="hover:text-purple-300 transition-colors">Quiz</a> |
|
|
<a href="history.html" class="hover:text-purple-300 transition-colors">History</a> |
|
|
</div> |
|
|
</div> |
|
|
</nav> |
|
|
|
|
|
|
|
|
<div class="container mx-auto px-4 py-8 max-w-4xl"> |
|
|
|
|
|
<div id="category-selection" class="glass-card p-8 rounded-xl mb-8"> |
|
|
<h2 class="text-3xl font-bold mb-6 text-center">Choose Your Challenge</h2> |
|
|
<div class="grid grid-cols-2 md:grid-cols-4 gap-4"> |
|
|
<div class="option-card p-4 rounded-lg text-center border-2 border-purple-500" data-category="9"> |
|
|
<i data-feather="brain" class="w-8 h-8 mx-auto mb-2"></i> |
|
|
<span>General Knowledge</span> |
|
|
</div> |
|
|
<div class="option-card p-4 rounded-lg text-center border-2 border-blue-500" data-category="17"> |
|
|
<i data-feather="atom" class="w-8 h-8 mx-auto mb-2"></i> |
|
|
<span>Science</span> |
|
|
</div> |
|
|
<div class="option-card p-4 rounded-lg text-center border-2 border-green-500" data-category="22"> |
|
|
<i data-feather="map" class="w-8 h-8 mx-auto mb-2"></i> |
|
|
<span>Geography</span> |
|
|
</div> |
|
|
<div class="option-card p-4 rounded-lg text-center border-2 border-yellow-500" data-category="23"> |
|
|
<i data-feather="book" class="w-8 h-8 mx-auto mb-2"></i> |
|
|
<span>History</span> |
|
|
</div> |
|
|
</div> |
|
|
<div class="text-center mt-6"> |
|
|
<button id="start-quiz" class="btn-primary px-8 py-3 rounded-full font-semibold"> |
|
|
Start Quiz <i data-feather="arrow-right" class="inline ml-2"></i> |
|
|
</button> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div id="quiz-interface" class="hidden"> |
|
|
|
|
|
<div class="glass-card p-4 rounded-xl mb-6"> |
|
|
<div class="flex justify-between items-center mb-2"> |
|
|
<span class="text-sm">Question <span id="current-question">1</span> of 10</span> |
|
|
<span id="score" class="text-sm">Score: 0</span> |
|
|
</div> |
|
|
<div class="w-full bg-gray-700 rounded-full h-2"> |
|
|
<div id="progress-bar" class="progress-bar h-2 rounded-full bg-gradient-to-r from-purple-400 to-pink-400" style="width: 10%"></div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div id="question-card" class="glass-card p-8 rounded-xl mb-6"> |
|
|
<h2 id="question-text" class="text-2xl font-semibold mb-6 text-center"></h2> |
|
|
<div id="options-container" class="grid gap-4"> |
|
|
|
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="flex justify-between"> |
|
|
<button id="prev-question" class="glass-card px-6 py-3 rounded-full font-semibold opacity-50 cursor-not-allowed"> |
|
|
<i data-feather="arrow-left" class="inline mr-2"></i>Previous |
|
|
</button> |
|
|
<button id="next-question" class="btn-primary px-6 py-3 rounded-full font-semibold"> |
|
|
Next <i data-feather="arrow-right" class="inline ml-2"></i> |
|
|
</button> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div id="results-screen" class="hidden glass-card p-8 rounded-xl text-center"> |
|
|
<i data-feather="award" class="w-16 h-16 mx-auto mb-4 text-yellow-400"></i> |
|
|
<h2 class="text-4xl font-bold mb-4">Quiz Complete!</h2> |
|
|
<div id="final-score" class="text-6xl font-bold mb-4 bg-gradient-to-r from-purple-400 to-pink-400 bg-clip-text text-transparent"></div> |
|
|
<p id="performance-message" class="text-xl mb-6"></p> |
|
|
<div class="flex flex-col sm:flex-row gap-4 justify-center"> |
|
|
<button id="play-again" class="btn-primary px-6 py-3 rounded-full font-semibold"> |
|
|
<i data-feather="refresh-cw" class="inline mr-2"></i>Play Again |
|
|
</button> |
|
|
<a href="history.html" class="btn-secondary px-6 py-3 rounded-full font-semibold"> |
|
|
<i data-feather="bar-chart-2" class="inline mr-2"></i>View History |
|
|
</a> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<script> |
|
|
feather.replace(); |
|
|
|
|
|
|
|
|
let currentCategory = null; |
|
|
let currentQuestionIndex = 0; |
|
|
let score = 0; |
|
|
let questions = []; |
|
|
let selectedOptions = new Array(10).fill(null); |
|
|
|
|
|
|
|
|
const categorySelection = document.getElementById('category-selection'); |
|
|
const quizInterface = document.getElementById('quiz-interface'); |
|
|
const resultsScreen = document.getElementById('results-screen'); |
|
|
const startQuizBtn = document.getElementById('start-quiz'); |
|
|
const questionText = document.getElementById('question-text'); |
|
|
const optionsContainer = document.getElementById('options-container'); |
|
|
const currentQuestionSpan = document.getElementById('current-question'); |
|
|
const scoreSpan = document.getElementById('score'); |
|
|
const progressBar = document.getElementById('progress-bar'); |
|
|
const prevQuestionBtn = document.getElementById('prev-question'); |
|
|
const nextQuestionBtn = document.getElementById('next-question'); |
|
|
const finalScore = document.getElementById('final-score'); |
|
|
const performanceMessage = document.getElementById('performance-message'); |
|
|
const playAgainBtn = document.getElementById('play-again'); |
|
|
|
|
|
|
|
|
document.querySelectorAll('.option-card').forEach(card => { |
|
|
card.addEventListener('click', function() { |
|
|
document.querySelectorAll('.option-card').forEach(c => { |
|
|
c.classList.remove('selected', 'border-white'); |
|
|
c.classList.add('border-opacity-50'); |
|
|
}); |
|
|
this.classList.add('selected', 'border-white'); |
|
|
this.classList.remove('border-opacity-50'); |
|
|
currentCategory = this.dataset.category; |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
startQuizBtn.addEventListener('click', async function() { |
|
|
if (!currentCategory) { |
|
|
alert('Please select a category first!'); |
|
|
return; |
|
|
} |
|
|
|
|
|
try { |
|
|
const response = await fetch(`https://opentdb.com/api.php?amount=10&category=${currentCategory}&type=multiple`); |
|
|
const data = await response.json(); |
|
|
questions = data.results; |
|
|
|
|
|
categorySelection.classList.add('hidden'); |
|
|
quizInterface.classList.remove('hidden'); |
|
|
loadQuestion(0); |
|
|
} catch (error) { |
|
|
console.error('Error fetching questions:', error); |
|
|
alert('Failed to load questions. Please try again.'); |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
function loadQuestion(index) { |
|
|
const question = questions[index]; |
|
|
currentQuestionIndex = index; |
|
|
|
|
|
|
|
|
currentQuestionSpan.textContent = index + 1; |
|
|
scoreSpan.textContent = `Score: ${score}`; |
|
|
progressBar.style.width = `${((index + 1) / 10) * 100}%`; |
|
|
|
|
|
|
|
|
questionText.textContent = decodeHTML(question.question); |
|
|
|
|
|
|
|
|
const allOptions = [...question.incorrect_answers, question.correct_answer] |
|
|
.sort(() => Math.random() - 0.5); |
|
|
|
|
|
optionsContainer.innerHTML = ''; |
|
|
allOptions.forEach((option, optionIndex) => { |
|
|
const optionDiv = document.createElement('div'); |
|
|
optionDiv.className = `option-card p-4 rounded-lg border-2 border-gray-600 ${ |
|
|
selectedOptions[index] === option ? 'selected' : '' |
|
|
}`; |
|
|
optionDiv.innerHTML = ` |
|
|
<div class="flex items-center justify-between"> |
|
|
<span>${decodeHTML(option)}</span> |
|
|
${selectedOptions[index] === option ? '<i data-feather="check" class="w-5 h-5"></i>' : ''} |
|
|
</div> |
|
|
`; |
|
|
|
|
|
optionDiv.addEventListener('click', () => selectOption(option, index)); |
|
|
optionsContainer.appendChild(optionDiv); |
|
|
}); |
|
|
|
|
|
|
|
|
prevQuestionBtn.disabled = index === 0; |
|
|
prevQuestionBtn.classList.toggle('opacity-50', index === 0); |
|
|
prevQuestionBtn.classList.toggle('cursor-not-allowed', index === 0); |
|
|
|
|
|
if (index === 9) { |
|
|
nextQuestionBtn.textContent = 'Finish Quiz'; |
|
|
nextQuestionBtn.innerHTML = 'Finish Quiz <i data-feather="check" class="inline ml-2"></i>'; |
|
|
} else { |
|
|
nextQuestionBtn.textContent = 'Next'; |
|
|
nextQuestionBtn.innerHTML = 'Next <i data-feather="arrow-right" class="inline ml-2"></i>'; |
|
|
} |
|
|
|
|
|
feather.replace(); |
|
|
} |
|
|
|
|
|
|
|
|
function selectOption(option, index) { |
|
|
selectedOptions[index] = option; |
|
|
const isCorrect = option === questions[index].correct_answer; |
|
|
|
|
|
|
|
|
if (isCorrect && selectedOptions[index] !== option) { |
|
|
score += 10; |
|
|
} |
|
|
|
|
|
loadQuestion(index); |
|
|
} |
|
|
|
|
|
|
|
|
prevQuestionBtn.addEventListener('click', () => { |
|
|
if (currentQuestionIndex > 0) { |
|
|
loadQuestion(currentQuestionIndex - 1); |
|
|
} |
|
|
}); |
|
|
|
|
|
nextQuestionBtn.addEventListener('click', () => { |
|
|
if (currentQuestionIndex < 9) { |
|
|
loadQuestion(currentQuestionIndex + 1); |
|
|
} else { |
|
|
|
|
|
showResults(); |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
function showResults() { |
|
|
quizInterface.classList.add('hidden'); |
|
|
resultsScreen.classList.remove('hidden'); |
|
|
|
|
|
finalScore.textContent = `${score}/100`; |
|
|
|
|
|
if (score >= 90) { |
|
|
performanceMessage.textContent = 'Outstanding! You are a quiz master! π'; |
|
|
} else if (score >= 70) { |
|
|
performanceMessage.textContent = 'Great job! You know your stuff! πͺ'; |
|
|
} else if (score >= 50) { |
|
|
performanceMessage.textContent = 'Good effort! Keep learning! π'; |
|
|
} else { |
|
|
performanceMessage.textContent = 'Nice try! Practice makes perfect! π'; |
|
|
} |
|
|
|
|
|
|
|
|
const quizResult = { |
|
|
category: document.querySelector('.selected span').textContent, |
|
|
score: score, |
|
|
date: new Date().toISOString(), |
|
|
totalQuestions: 10 |
|
|
}; |
|
|
|
|
|
let history = JSON.parse(localStorage.getItem('quizHistory') || '[]'); |
|
|
history.unshift(quizResult); |
|
|
localStorage.setItem('quizHistory', JSON.stringify(history)); |
|
|
} |
|
|
|
|
|
|
|
|
playAgainBtn.addEventListener('click', () => { |
|
|
location.reload(); |
|
|
}); |
|
|
|
|
|
|
|
|
function decodeHTML(html) { |
|
|
const txt = document.createElement('textarea'); |
|
|
txt.innerHTML = html; |
|
|
return txt.value; |
|
|
} |
|
|
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', function() { |
|
|
anime({ |
|
|
targets: '.glass-card', |
|
|
translateY: [30, 0], |
|
|
opacity: [0, 1], |
|
|
duration: 800, |
|
|
delay: anime.stagger(100) |
|
|
}); |
|
|
}); |
|
|
</script> |
|
|
</body> |
|
|
</html> |
|
|
|