Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Python Quiz Generator</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <!-- Shop Modal --> | |
| <div id="shopModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden"> | |
| <div class="bg-gray-800 rounded-xl shadow-2xl p-8 max-w-2xl w-full max-h-[90vh] overflow-y-auto"> | |
| <div class="flex justify-between items-center mb-6"> | |
| <h2 class="text-3xl font-bold">Power-Up Shop</h2> | |
| <button id="closeShop" class="text-gray-400 hover:text-white text-2xl">×</button> | |
| </div> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-6"> | |
| <!-- Power-Up Items --> | |
| <div class="bg-gray-700 rounded-lg p-4 border-2 border-python-blue"> | |
| <div class="flex justify-between items-start mb-3"> | |
| <h3 class="text-xl font-bold">50/50</h3> | |
| <div class="flex items-center"> | |
| <i class="fas fa-coins text-python-yellow mr-1"></i> | |
| <span>100</span> | |
| </div> | |
| </div> | |
| <p class="text-gray-300 mb-4">Eliminates two wrong answers</p> | |
| <button class="buy-btn w-full bg-python-blue hover:bg-python-light text-white font-bold py-2 px-4 rounded-lg transition-all" data-powerup="5050" data-cost="100"> | |
| Buy | |
| </button> | |
| </div> | |
| <div class="bg-gray-700 rounded-lg p-4 border-2 border-python-yellow"> | |
| <div class="flex justify-between items-start mb-3"> | |
| <h3 class="text-xl font-bold">Time Freeze</h3> | |
| <div class="flex items-center"> | |
| <i class="fas fa-coins text-python-yellow mr-1"></i> | |
| <span>150</span> | |
| </div> | |
| </div> | |
| <p class="text-gray-300 mb-4">Gives you extra 30 seconds per question</p> | |
| <button class="buy-btn w-full bg-python-yellow hover:bg-yellow-400 text-gray-800 font-bold py-2 px-4 rounded-lg transition-all" data-powerup="timefreeze" data-cost="150"> | |
| Buy | |
| </button> | |
| </div> | |
| <div class="bg-gray-700 rounded-lg p-4 border-2 border-python-light"> | |
| <div class="flex justify-between items-start mb-3"> | |
| <h3 class="text-xl font-bold">Double Points</h3> | |
| <div class="flex items-center"> | |
| <i class="fas fa-coins text-python-yellow mr-1"></i> | |
| <span>200</span> | |
| </div> | |
| </div> | |
| <p class="text-gray-300 mb-4">Next correct answer gives double points</p> | |
| <button class="buy-btn w-full bg-python-light hover:bg-blue-400 text-white font-bold py-2 px-4 rounded-lg transition-all" data-powerup="doublepoints" data-cost="200"> | |
| Buy | |
| </button> | |
| </div> | |
| <div class="bg-gray-700 rounded-lg p-4 border-2 border-green-500"> | |
| <div class="flex justify-between items-start mb-3"> | |
| <h3 class="text-xl font-bold">Skip Question</h3> | |
| <div class="flex items-center"> | |
| <i class="fas fa-coins text-python-yellow mr-1"></i> | |
| <span>75</span> | |
| </div> | |
| </div> | |
| <p class="text-gray-300 mb-4">Skip the current question</p> | |
| <button class="buy-btn w-full bg-green-500 hover:bg-green-400 text-white font-bold py-2 px-4 rounded-lg transition-all" data-powerup="skip" data-cost="75"> | |
| Buy | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| tailwind.config = { | |
| theme: { | |
| extend: { | |
| colors: { | |
| 'python-blue': '#306998', | |
| 'python-yellow': '#FFD43B', | |
| 'python-light': '#4B8BBE', | |
| }, | |
| animation: { | |
| 'pulse-slow': 'pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite', | |
| 'bounce-slow': 'bounce 2s infinite', | |
| } | |
| } | |
| } | |
| } | |
| </script> | |
| <style> | |
| @import url('https://fonts.googleapis.com/css2?family=Source+Code+Pro:wght@400;500;600;700&display=swap'); | |
| body { | |
| font-family: 'Source Code Pro', monospace; | |
| background: linear-gradient(135deg, #1a2a6c, #2c3e50); | |
| min-height: 100vh; | |
| } | |
| .python-logo { | |
| animation: spin 20s linear infinite; | |
| } | |
| @keyframes spin { | |
| 0% { transform: rotate(0deg); } | |
| 100% { transform: rotate(360deg); } | |
| } | |
| .option-card { | |
| transition: all 0.3s ease; | |
| transform: scale(1); | |
| } | |
| .option-card:hover { | |
| transform: scale(1.03); | |
| box-shadow: 0 10px 25px rgba(0,0,0,0.2); | |
| } | |
| .correct-answer { | |
| animation: correct-pulse 0.5s ease; | |
| box-shadow: 0 0 0 4px rgba(72, 187, 120, 0.5); | |
| } | |
| .incorrect-answer { | |
| animation: shake 0.5s ease; | |
| box-shadow: 0 0 0 4px rgba(220, 38, 38, 0.5); | |
| } | |
| @keyframes correct-pulse { | |
| 0% { transform: scale(1); } | |
| 50% { transform: scale(1.05); } | |
| 100% { transform: scale(1); } | |
| } | |
| @keyframes shake { | |
| 0%, 100% { transform: translateX(0); } | |
| 25% { transform: translateX(-5px); } | |
| 75% { transform: translateX(5px); } | |
| } | |
| .progress-bar { | |
| transition: width 0.5s ease; | |
| } | |
| .snake-animation { | |
| animation: snake-move 8s linear infinite; | |
| } | |
| @keyframes snake-move { | |
| 0% { transform: translateX(-100%); } | |
| 100% { transform: translateX(100%); } | |
| } | |
| .code-block { | |
| font-family: 'Source Code Pro', monospace; | |
| background: #2d3748; | |
| border-left: 4px solid #4B8BBE; | |
| } | |
| </style> | |
| </head> | |
| <body class="text-gray-100"> | |
| <!-- Main Container --> | |
| <div class="container mx-auto px-4 py-8 max-w-4xl"> | |
| <!-- Header --> | |
| <header class="text-center mb-12"> | |
| <div class="flex justify-center mb-4"> | |
| <div class="python-logo bg-python-blue rounded-full w-24 h-24 flex items-center justify-center"> | |
| <div class="bg-python-yellow rounded-full w-16 h-16 flex items-center justify-center"> | |
| <i class="fas fa-code text-python-blue text-3xl"></i> | |
| </div> | |
| </div> | |
| </div> | |
| <h1 class="text-4xl md:text-5xl font-bold mb-2 bg-gradient-to-r from-python-yellow to-python-light bg-clip-text text-transparent"> | |
| Python Quiz Generator | |
| </h1> | |
| <p class="text-xl text-gray-300">Test your Python knowledge with interactive challenges!</p> | |
| </header> | |
| <!-- Currency Display --> | |
| <div class="bg-gray-800 rounded-xl shadow-2xl p-4 mb-4 flex justify-between items-center"> | |
| <div class="flex items-center"> | |
| <i class="fas fa-coins text-python-yellow text-2xl mr-2"></i> | |
| <span id="coinCount" class="text-xl font-bold">0</span> | |
| </div> | |
| <button id="shopBtn" class="bg-python-light hover:bg-python-blue text-white font-bold py-2 px-4 rounded-lg transition-all"> | |
| <i class="fas fa-store mr-2"></i> Shop | |
| </button> | |
| </div> | |
| <!-- Quiz Controls --> | |
| <div class="bg-gray-800 rounded-xl shadow-2xl p-6 mb-8"> | |
| <div class="flex flex-wrap justify-between items-center gap-4"> | |
| <div> | |
| <h2 class="text-2xl font-bold mb-2">Quiz Settings</h2> | |
| <p class="text-gray-400">Customize your quiz experience</p> | |
| </div> | |
| <div class="flex flex-wrap gap-3"> | |
| <div class="flex items-center"> | |
| <label class="mr-2">Questions:</label> | |
| <select id="questionCount" class="bg-gray-700 text-white rounded px-3 py-1"> | |
| <option>5</option> | |
| <option selected>10</option> | |
| <option>15</option> | |
| <option>20</option> | |
| </select> | |
| </div> | |
| <div class="flex items-center"> | |
| <label class="mr-2">Difficulty:</label> | |
| <select id="difficulty" class="bg-gray-700 text-white rounded px-3 py-1"> | |
| <option>Beginner</option> | |
| <option selected>Intermediate</option> | |
| <option>Advanced</option> | |
| </select> | |
| </div> | |
| <button id="generateBtn" class="bg-python-blue hover:bg-python-light text-white font-bold py-2 px-6 rounded-lg transition-all transform hover:scale-105 flex items-center"> | |
| <i class="fas fa-bolt mr-2"></i> Generate Quiz | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Quiz Container --> | |
| <div id="quizContainer" class="hidden"> | |
| <!-- Progress Bar --> | |
| <div class="mb-6"> | |
| <div class="flex justify-between mb-2"> | |
| <div class="text-lg font-bold"> | |
| Question <span id="currentQuestion">1</span> of <span id="totalQuestions">10</span> | |
| </div> | |
| <div class="text-lg font-bold"> | |
| Score: <span id="score">0</span> | |
| </div> | |
| </div> | |
| <div class="h-3 bg-gray-700 rounded-full overflow-hidden"> | |
| <div id="progressBar" class="h-full bg-python-blue rounded-full progress-bar" style="width: 10%"></div> | |
| </div> | |
| </div> | |
| <!-- Question Area --> | |
| <div class="bg-gray-800 rounded-xl shadow-2xl p-6 mb-6"> | |
| <div class="flex items-start mb-6"> | |
| <div class="bg-python-blue text-python-yellow rounded-full w-10 h-10 flex items-center justify-center mr-4 flex-shrink-0"> | |
| <i class="fas fa-question"></i> | |
| </div> | |
| <div> | |
| <h3 id="questionText" class="text-xl font-bold mb-2">What is the output of the following Python code?</h3> | |
| <div class="code-block p-4 rounded-lg mt-3"> | |
| <pre id="questionCode" class="text-green-400">print(2 + 2 * 3)</pre> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Options --> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mt-6"> | |
| <div class="option-card bg-gray-700 rounded-lg p-4 cursor-pointer"> | |
| <div class="flex items-center"> | |
| <div class="bg-gray-600 rounded-full w-8 h-8 flex items-center justify-center mr-3">A</div> | |
| <span class="option-text">8</span> | |
| </div> | |
| </div> | |
| <div class="option-card bg-gray-700 rounded-lg p-4 cursor-pointer"> | |
| <div class="flex items-center"> | |
| <div class="bg-gray-600 rounded-full w-8 h-8 flex items-center justify-center mr-3">B</div> | |
| <span class="option-text">10</span> | |
| </div> | |
| </div> | |
| <div class="option-card bg-gray-700 rounded-lg p-4 cursor-pointer"> | |
| <div class="flex items-center"> | |
| <div class="bg-gray-600 rounded-full w-8 h-8 flex items-center justify-center mr-3">C</div> | |
| <span class="option-text">12</span> | |
| </div> | |
| </div> | |
| <div class="option-card bg-gray-700 rounded-lg p-4 cursor-pointer"> | |
| <div class="flex items-center"> | |
| <div class="bg-gray-600 rounded-full w-8 h-8 flex items-center justify-center mr-3">D</div> | |
| <span class="option-text">6</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Explanation --> | |
| <div id="explanation" class="hidden bg-gray-800 rounded-xl shadow-2xl p-6 mb-6"> | |
| <div class="flex items-start"> | |
| <div class="bg-green-500 text-white rounded-full w-10 h-10 flex items-center justify-center mr-4 flex-shrink-0"> | |
| <i class="fas fa-lightbulb"></i> | |
| </div> | |
| <div> | |
| <h3 class="text-xl font-bold mb-2">Explanation</h3> | |
| <p id="explanationText" class="text-gray-300">In Python, multiplication has higher precedence than addition. So 2 * 3 is calculated first (resulting in 6), then 2 + 6 is calculated, giving 8.</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Navigation --> | |
| <div class="flex justify-between"> | |
| <button id="prevBtn" class="bg-gray-700 hover:bg-gray-600 text-white font-bold py-2 px-6 rounded-lg transition-all"> | |
| <i class="fas fa-arrow-left mr-2"></i> Previous | |
| </button> | |
| <button id="nextBtn" class="bg-python-blue hover:bg-python-light text-white font-bold py-2 px-6 rounded-lg transition-all transform hover:scale-105"> | |
| Next <i class="fas fa-arrow-right ml-2"></i> | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Snake Animation Decoration --> | |
| <div class="relative h-4 my-12 overflow-hidden"> | |
| <div class="snake-animation absolute top-0 left-0 w-full"> | |
| <div class="flex"> | |
| <div class="w-4 h-4 bg-python-blue rounded-full mx-1"></div> | |
| <div class="w-4 h-4 bg-python-yellow rounded-full mx-1"></div> | |
| <div class="w-4 h-4 bg-python-light rounded-full mx-1"></div> | |
| <div class="w-4 h-4 bg-python-blue rounded-full mx-1"></div> | |
| <div class="w-4 h-4 bg-python-yellow rounded-full mx-1"></div> | |
| <div class="w-4 h-4 bg-python-light rounded-full mx-1"></div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Results Container --> | |
| <div id="resultsContainer" class="hidden bg-gray-800 rounded-xl shadow-2xl p-8"> | |
| <div class="text-center mb-8"> | |
| <div class="flex justify-center mb-6"> | |
| <div class="bg-gradient-to-br from-python-blue to-python-light rounded-full w-24 h-24 flex items-center justify-center"> | |
| <i class="fas fa-trophy text-white text-4xl"></i> | |
| </div> | |
| </div> | |
| <h2 class="text-3xl font-bold mb-4">Quiz Completed!</h2> | |
| <div class="text-5xl font-bold mb-6 bg-gradient-to-r from-python-yellow to-python-light bg-clip-text text-transparent"> | |
| <span id="finalScore">8</span>/<span id="finalTotal">10</span> | |
| </div> | |
| <p id="resultMessage" class="text-xl mb-8">Great job! You have a solid understanding of Python fundamentals.</p> | |
| <!-- Analytics Section --> | |
| <div class="bg-gray-700 rounded-xl p-6 mb-8"> | |
| <h3 class="text-2xl font-bold mb-4 text-center">Your Performance Analysis</h3> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-6"> | |
| <!-- Weak Areas --> | |
| <div class="bg-gray-800 rounded-lg p-4"> | |
| <h4 class="text-xl font-bold mb-3 flex items-center"> | |
| <i class="fas fa-exclamation-triangle text-red-400 mr-2"></i> Weak Areas | |
| </h4> | |
| <ul id="weakAreas" class="space-y-2"> | |
| <!-- Dynamically populated --> | |
| </ul> | |
| </div> | |
| <!-- Progress Chart --> | |
| <div class="bg-gray-800 rounded-lg p-4"> | |
| <h4 class="text-xl font-bold mb-3 flex items-center"> | |
| <i class="fas fa-chart-line text-green-400 mr-2"></i> Progress | |
| </h4> | |
| <div class="h-48" id="progressChart"> | |
| <!-- Chart will be rendered here --> | |
| </div> | |
| </div> | |
| <!-- Mnemonics --> | |
| <div class="bg-gray-800 rounded-lg p-4"> | |
| <h4 class="text-xl font-bold mb-3 flex items-center"> | |
| <i class="fas fa-brain text-purple-400 mr-2"></i> Memory Aids | |
| </h4> | |
| <div id="mnemonics" class="space-y-3"> | |
| <!-- Dynamically populated --> | |
| </div> | |
| </div> | |
| <!-- Flashcards --> | |
| <div class="bg-gray-800 rounded-lg p-4"> | |
| <h4 class="text-xl font-bold mb-3 flex items-center"> | |
| <i class="fas fa-layer-group text-blue-400 mr-2"></i> Key Concepts | |
| </h4> | |
| <div id="flashcards" class="grid grid-cols-2 gap-3"> | |
| <!-- Dynamically populated --> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="flex justify-center gap-4"> | |
| <button id="restartBtn" class="bg-python-blue hover:bg-python-light text-white font-bold py-3 px-8 rounded-lg transition-all transform hover:scale-105"> | |
| <i class="fas fa-redo mr-2"></i> Try Again | |
| </button> | |
| <button id="newQuizBtn" class="bg-gray-700 hover:bg-gray-600 text-white font-bold py-3 px-8 rounded-lg transition-all"> | |
| <i class="fas fa-plus mr-2"></i> New Quiz | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| // Quiz questions database | |
| const questions = [ | |
| { | |
| question: "What is the output of the following Python code?", | |
| code: "print(2 + 2 * 3)", | |
| options: ["8", "10", "12", "6"], | |
| answer: 0, | |
| explanation: "In Python, multiplication has higher precedence than addition. So 2 * 3 is calculated first (resulting in 6), then 2 + 6 is calculated, giving 8." | |
| }, | |
| { | |
| question: "Which of the following is used to create a virtual environment in Python?", | |
| code: "", | |
| options: ["venv", "virtualenv", "pipenv", "All of the above"], | |
| answer: 3, | |
| explanation: "All of these tools can be used to create virtual environments in Python. venv is built into Python 3, virtualenv is a third-party tool, and pipenv combines virtual environment management with package management." | |
| }, | |
| { | |
| question: "What does the 'yield' keyword do in Python?", | |
| code: "", | |
| options: [ | |
| "Returns a value and terminates the function", | |
| "Pauses the function and returns a generator object", | |
| "Used for exception handling", | |
| "Defines a static method" | |
| ], | |
| answer: 1, | |
| explanation: "The yield keyword is used in generator functions to pause execution and return a value. When called again, the function resumes where it left off." | |
| }, | |
| { | |
| question: "What is the output of the following code?", | |
| code: "x = [1, 2, 3]\ny = x\ny.append(4)\nprint(x)", | |
| options: ["[1, 2, 3]", "[1, 2, 3, 4]", "[4]", "Error"], | |
| answer: 1, | |
| explanation: "When we assign y = x, both variables point to the same list in memory. So modifying y also modifies x." | |
| }, | |
| { | |
| question: "Which method would you use to remove the last element from a list?", | |
| code: "", | |
| options: ["list.remove()", "list.pop()", "list.delete()", "list.cut()"], | |
| answer: 1, | |
| explanation: "The pop() method removes and returns the last element by default. You can also specify an index to remove an element at a specific position." | |
| }, | |
| { | |
| question: "What is the purpose of __init__ in a Python class?", | |
| code: "", | |
| options: [ | |
| "To initialize the class object", | |
| "To create class methods", | |
| "To define class variables", | |
| "To terminate the class instance" | |
| ], | |
| answer: 0, | |
| explanation: "The __init__ method is called when a new instance of a class is created. It's used to initialize the object's attributes." | |
| }, | |
| { | |
| question: "What does the 'with' statement do?", | |
| code: "", | |
| options: [ | |
| "Creates a loop", | |
| "Handles exceptions", | |
| "Manages resources and ensures cleanup", | |
| "Defines a context for variable scope" | |
| ], | |
| answer: 2, | |
| explanation: "The 'with' statement simplifies resource management by ensuring that setup and cleanup operations are performed automatically." | |
| }, | |
| { | |
| question: "What is the output of the following code?", | |
| code: "print([i for i in range(10) if i % 2 == 0])", | |
| options: [ | |
| "[0, 2, 4, 6, 8]", | |
| "[2, 4, 6, 8]", | |
| "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]", | |
| "[1, 3, 5, 7, 9]" | |
| ], | |
| answer: 0, | |
| explanation: "This list comprehension generates numbers from 0 to 9, but only includes even numbers (where i % 2 == 0)." | |
| }, | |
| { | |
| question: "Which of these is NOT a valid variable name?", | |
| code: "", | |
| options: ["_private", "2nd_variable", "variable_name", "camelCase"], | |
| answer: 1, | |
| explanation: "Variable names cannot start with a number. They must start with a letter or underscore." | |
| }, | |
| { | |
| question: "What is the purpose of the 'pass' statement?", | |
| code: "", | |
| options: [ | |
| "To terminate the program", | |
| "To skip the current iteration in a loop", | |
| "As a placeholder where syntax requires a statement", | |
| "To pass arguments to a function" | |
| ], | |
| answer: 2, | |
| explanation: "The pass statement is a null operation - it does nothing. It's used when a statement is required syntactically but no action is needed." | |
| } | |
| ]; | |
| // DOM Elements | |
| const quizContainer = document.getElementById('quizContainer'); | |
| const resultsContainer = document.getElementById('resultsContainer'); | |
| const generateBtn = document.getElementById('generateBtn'); | |
| const questionText = document.getElementById('questionText'); | |
| const questionCode = document.getElementById('questionCode'); | |
| const optionElements = document.querySelectorAll('.option-card'); | |
| const optionTexts = document.querySelectorAll('.option-text'); | |
| const explanation = document.getElementById('explanation'); | |
| const explanationText = document.getElementById('explanationText'); | |
| const currentQuestionEl = document.getElementById('currentQuestion'); | |
| const totalQuestionsEl = document.getElementById('totalQuestions'); | |
| const scoreEl = document.getElementById('score'); | |
| const progressBar = document.getElementById('progressBar'); | |
| const prevBtn = document.getElementById('prevBtn'); | |
| const nextBtn = document.getElementById('nextBtn'); | |
| const finalScore = document.getElementById('finalScore'); | |
| const finalTotal = document.getElementById('finalTotal'); | |
| const resultMessage = document.getElementById('resultMessage'); | |
| const restartBtn = document.getElementById('restartBtn'); | |
| const newQuizBtn = document.getElementById('newQuizBtn'); | |
| // Enhanced quiz state | |
| let currentQuestionIndex = 0; | |
| let coins = 0; | |
| let powerups = { | |
| '5050': 0, | |
| 'timefreeze': 0, | |
| 'doublepoints': 0, | |
| 'skip': 0 | |
| }; | |
| let weakAreas = {}; | |
| let questionHistory = []; | |
| let score = 0; | |
| let userAnswers = []; | |
| let quizQuestions = []; | |
| // Initialize with new features | |
| document.addEventListener('DOMContentLoaded', () => { | |
| // Load saved coins from localStorage | |
| coins = parseInt(localStorage.getItem('pythonQuizCoins')) || 0; | |
| updateCoinDisplay(); | |
| // Shop functionality | |
| const shopBtn = document.getElementById('shopBtn'); | |
| const shopModal = document.getElementById('shopModal'); | |
| const closeShop = document.getElementById('closeShop'); | |
| shopBtn.addEventListener('click', () => shopModal.classList.remove('hidden')); | |
| closeShop.addEventListener('click', () => shopModal.classList.add('hidden')); | |
| // Handle powerup purchases | |
| document.querySelectorAll('.buy-btn').forEach(btn => { | |
| btn.addEventListener('click', function() { | |
| const powerup = this.dataset.powerup; | |
| const cost = parseInt(this.dataset.cost); | |
| if (coins >= cost) { | |
| coins -= cost; | |
| powerups[powerup]++; | |
| updateCoinDisplay(); | |
| localStorage.setItem('pythonQuizCoins', coins); | |
| alert(`Purchased ${powerup}! You now have ${powerups[powerup]}`); | |
| } else { | |
| alert("Not enough coins!"); | |
| } | |
| }); | |
| }); | |
| generateBtn.addEventListener('click', startQuiz); | |
| optionElements.forEach((option, index) => { | |
| option.addEventListener('click', () => selectAnswer(index)); | |
| }); | |
| nextBtn.addEventListener('click', nextQuestion); | |
| prevBtn.addEventListener('click', prevQuestion); | |
| restartBtn.addEventListener('click', restartQuiz); | |
| newQuizBtn.addEventListener('click', () => { | |
| resultsContainer.classList.add('hidden'); | |
| document.querySelector('.container').classList.remove('hidden'); | |
| }); | |
| }); | |
| // Start quiz | |
| function startQuiz() { | |
| const questionCount = parseInt(document.getElementById('questionCount').value); | |
| const difficulty = document.getElementById('difficulty').value; | |
| // Select random questions based on count | |
| quizQuestions = [...questions].sort(() => 0.5 - Math.random()).slice(0, questionCount); | |
| // Reset state | |
| currentQuestionIndex = 0; | |
| score = 0; | |
| userAnswers = []; | |
| // Update UI | |
| quizContainer.classList.remove('hidden'); | |
| document.querySelector('.container > div:nth-child(2)').classList.add('hidden'); // Hide settings | |
| totalQuestionsEl.textContent = quizQuestions.length; | |
| scoreEl.textContent = score; | |
| updateQuestion(); | |
| } | |
| // Update question display | |
| function updateQuestion() { | |
| const question = quizQuestions[currentQuestionIndex]; | |
| questionText.textContent = question.question; | |
| questionCode.textContent = question.code || ""; | |
| questionCode.parentElement.style.display = question.code ? "block" : "none"; | |
| optionTexts.forEach((option, index) => { | |
| option.textContent = question.options[index]; | |
| }); | |
| currentQuestionEl.textContent = currentQuestionIndex + 1; | |
| scoreEl.textContent = score; | |
| progressBar.style.width = `${((currentQuestionIndex + 1) / quizQuestions.length) * 100}%`; | |
| // Reset option styles | |
| optionElements.forEach(option => { | |
| option.classList.remove('correct-answer', 'incorrect-answer'); | |
| option.style.pointerEvents = 'auto'; | |
| }); | |
| explanation.classList.add('hidden'); | |
| prevBtn.disabled = currentQuestionIndex === 0; | |
| // Hide next button until answer is selected | |
| nextBtn.classList.add('hidden'); | |
| } | |
| // Update coin display | |
| function updateCoinDisplay() { | |
| document.getElementById('coinCount').textContent = coins; | |
| } | |
| // Award coins for correct answers | |
| function awardCoins(isCorrect, difficulty) { | |
| let amount = 0; | |
| if (isCorrect) { | |
| amount = difficulty === 'Beginner' ? 10 : | |
| difficulty === 'Intermediate' ? 20 : 30; | |
| coins += amount; | |
| updateCoinDisplay(); | |
| localStorage.setItem('pythonQuizCoins', coins); | |
| // Show coin animation | |
| const coinAnim = document.createElement('div'); | |
| coinAnim.className = 'absolute -top-2 -right-2 bg-python-yellow text-gray-800 font-bold rounded-full w-8 h-8 flex items-center justify-center animate-bounce'; | |
| coinAnim.innerHTML = `+${amount}`; | |
| document.getElementById('coinCount').parentNode.appendChild(coinAnim); | |
| setTimeout(() => coinAnim.remove(), 2000); | |
| } | |
| } | |
| // Handle answer selection with powerups | |
| function selectAnswer(selectedIndex) { | |
| const question = quizQuestions[currentQuestionIndex]; | |
| const correctIndex = question.answer; | |
| // Only allow one selection | |
| if (userAnswers[currentQuestionIndex] !== undefined) return; | |
| // Disable further selections | |
| optionElements.forEach(option => { | |
| option.style.pointerEvents = 'none'; | |
| }); | |
| // Mark correct answer | |
| optionElements[correctIndex].classList.add('correct-answer'); | |
| // Store user answer | |
| userAnswers[currentQuestionIndex] = selectedIndex; | |
| // Check if answer is correct | |
| if (selectedIndex === correctIndex) { | |
| score++; | |
| scoreEl.textContent = score; | |
| } else { | |
| // Mark incorrect answer | |
| optionElements[selectedIndex].classList.add('incorrect-answer'); | |
| } | |
| // Show explanation | |
| explanationText.textContent = question.explanation; | |
| explanation.classList.remove('hidden'); | |
| // Show next button if not last question | |
| if (currentQuestionIndex < quizQuestions.length - 1) { | |
| nextBtn.classList.remove('hidden'); | |
| } else { | |
| nextBtn.textContent = "Finish Quiz"; | |
| nextBtn.classList.remove('hidden'); | |
| } | |
| } | |
| // Navigate to next question | |
| function nextQuestion() { | |
| if (currentQuestionIndex < quizQuestions.length - 1) { | |
| currentQuestionIndex++; | |
| updateQuestion(); | |
| } else { | |
| // Only show results if all questions answered | |
| if (userAnswers.length === quizQuestions.length) { | |
| showResults(); | |
| } | |
| } | |
| } | |
| // Navigate to previous question | |
| function prevQuestion() { | |
| if (currentQuestionIndex > 0) { | |
| currentQuestionIndex--; | |
| updateQuestion(); | |
| // Reapply answer state if already answered | |
| if (userAnswers[currentQuestionIndex] !== undefined) { | |
| const question = quizQuestions[currentQuestionIndex]; | |
| const correctIndex = question.answer; | |
| const userAnswer = userAnswers[currentQuestionIndex]; | |
| optionElements.forEach(option => { | |
| option.style.pointerEvents = 'none'; | |
| }); | |
| optionElements[correctIndex].classList.add('correct-answer'); | |
| if (userAnswer !== correctIndex) { | |
| optionElements[userAnswer].classList.add('incorrect-answer'); | |
| } | |
| explanationText.textContent = question.explanation; | |
| explanation.classList.remove('hidden'); | |
| nextBtn.classList.remove('hidden'); | |
| } | |
| } | |
| } | |
| // Analyze weak areas | |
| function analyzeWeakAreas() { | |
| weakAreas = {}; | |
| quizQuestions.forEach((q, i) => { | |
| if (userAnswers[i] !== q.answer) { | |
| const category = q.question.split(' ')[0]; // Simple categorization | |
| weakAreas[category] = (weakAreas[category] || 0) + 1; | |
| } | |
| }); | |
| // Sort weak areas | |
| const sortedWeakAreas = Object.entries(weakAreas) | |
| .sort((a, b) => b[1] - a[1]) | |
| .slice(0, 3); | |
| // Display weak areas | |
| const weakAreasList = document.getElementById('weakAreas'); | |
| weakAreasList.innerHTML = sortedWeakAreas.map(([area, count]) => ` | |
| <li class="flex justify-between items-center"> | |
| <span>${area}</span> | |
| <span class="bg-red-500 text-white text-sm px-2 py-1 rounded-full">${count} mistakes</span> | |
| </li> | |
| `).join(''); | |
| // Generate mnemonics for weak areas | |
| const mnemonicsContainer = document.getElementById('mnemonics'); | |
| mnemonicsContainer.innerHTML = sortedWeakAreas.map(([area]) => { | |
| const mnemonic = generateMnemonic(area); | |
| return ` | |
| <div class="bg-gray-900 p-3 rounded-lg"> | |
| <div class="font-bold text-python-yellow mb-1">${area}</div> | |
| <div>${mnemonic}</div> | |
| </div> | |
| `; | |
| }).join(''); | |
| // Generate flashcards | |
| const flashcardsContainer = document.getElementById('flashcards'); | |
| flashcardsContainer.innerHTML = quizQuestions | |
| .filter((q, i) => userAnswers[i] !== q.answer) | |
| .slice(0, 4) | |
| .map(q => ` | |
| <div class="flashcard bg-gray-900 p-3 rounded-lg cursor-pointer transform transition hover:scale-105" onclick="this.classList.toggle('bg-gray-800')"> | |
| <div class="font-bold text-python-blue">Q: ${q.question.substring(0, 50)}...</div> | |
| <div class="hidden mt-2 text-sm">A: ${q.options[q.answer]}</div> | |
| </div> | |
| `).join(''); | |
| } | |
| // Simple mnemonic generator | |
| function generateMnemonic(topic) { | |
| const mnemonics = { | |
| "What": "When in doubt, PEMDAS rules them all (Parentheses, Exponents, Multiplication/Division, Addition/Subtraction)", | |
| "Which": "VENV is Very Essential for New Versions", | |
| "What does": "Yield gives you a generator - it 'yields' results one by one", | |
| "Which method": "POP goes the last element! (like popcorn popping out)" | |
| }; | |
| return mnemonics[topic] || "Practice makes perfect! Review this concept regularly."; | |
| } | |
| // Show enhanced results | |
| function showResults() { | |
| quizContainer.classList.add('hidden'); | |
| resultsContainer.classList.remove('hidden'); | |
| finalScore.textContent = score; | |
| finalTotal.textContent = quizQuestions.length; | |
| // Award bonus coins based on performance | |
| const bonus = Math.floor(score * 5); | |
| coins += bonus; | |
| updateCoinDisplay(); | |
| localStorage.setItem('pythonQuizCoins', coins); | |
| // Analyze performance | |
| analyzeWeakAreas(); | |
| // Custom message based on score | |
| const percentage = (score / quizQuestions.length) * 100; | |
| if (percentage >= 90) { | |
| resultMessage.textContent = "Python Master! Your skills are exceptional."; | |
| } else if (percentage >= 70) { | |
| resultMessage.textContent = "Great job! You have a strong understanding of Python."; | |
| } else if (percentage >= 50) { | |
| resultMessage.textContent = "Good effort! Keep practicing to improve your skills."; | |
| } else { | |
| resultMessage.textContent = "Keep learning! Review the basics and try again."; | |
| } | |
| } | |
| // Restart quiz | |
| function restartQuiz() { | |
| resultsContainer.classList.add('hidden'); | |
| quizContainer.classList.remove('hidden'); | |
| document.querySelector('.container > div:nth-child(2)').classList.remove('hidden'); | |
| // Reset to first question | |
| currentQuestionIndex = 0; | |
| score = 0; | |
| userAnswers = []; | |
| updateQuestion(); | |
| nextBtn.textContent = "Next"; | |
| } | |
| </script> | |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=casv/pythonquizgenerator" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |