python-quiz / index.html
karaltan's picture
Add 2 files
e483e55 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Python Quiz with Code Editor</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">
<style>
.question-card {
transition: all 0.3s ease;
}
.question-card:hover {
transform: translateY(-3px);
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
}
.progress-bar {
transition: width 0.5s ease-in-out;
}
.fade-in {
animation: fadeIn 0.5s ease-in-out;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.code-block {
font-family: 'Courier New', Courier, monospace;
background-color: #f8f8f8;
border-radius: 4px;
padding: 10px;
border-left: 3px solid #3b82f6;
}
#editorContainer {
height: 300px;
border: 1px solid #e5e7eb;
border-radius: 0.375rem;
overflow: hidden;
}
.output-container {
background-color: #1e1e1e;
color: #d4d4d4;
font-family: monospace;
padding: 10px;
border-radius: 0.375rem;
height: 100px;
overflow-y: auto;
}
</style>
</head>
<body class="bg-gray-50 min-h-screen">
<div class="container mx-auto px-4 py-8">
<header class="text-center mb-12">
<h1 class="text-4xl font-bold text-blue-800 mb-2">Python Code Quiz</h1>
<p class="text-lg text-gray-600">Write, test and submit your Python code directly in the editor</p>
<div class="w-24 h-1 bg-blue-500 mx-auto mt-4 rounded-full"></div>
</header>
<div class="max-w-5xl mx-auto">
<div id="quizContainer" class="bg-white rounded-xl shadow-lg p-6 mb-8 question-card">
<div class="flex justify-between items-center mb-6">
<h2 class="text-xl font-semibold text-gray-800">Question</h2>
<span id="questionCounter" class="bg-blue-100 text-blue-800 text-sm font-medium px-3 py-1 rounded-full">1/10</span>
</div>
<div id="questionContent" class="mb-6">
<p id="questionText" class="text-gray-700 mb-4"></p>
<div id="codeExample" class="code-block mb-4 hidden">
<pre id="codeContent" class="whitespace-pre-wrap"></pre>
</div>
</div>
<div class="mb-4">
<div class="flex justify-between items-center mb-2">
<label class="block text-sm font-medium text-gray-700">Code Editor:</label>
<button id="runCodeBtn" class="px-3 py-1 bg-green-600 text-white text-sm rounded-md hover:bg-green-700 transition-colors duration-300">
<i class="fas fa-play mr-1"></i> Run Code
</button>
</div>
<div id="editorContainer"></div>
</div>
<div class="mb-4">
<label class="block text-sm font-medium text-gray-700 mb-2">Output:</label>
<div id="outputContainer" class="output-container">
<div id="outputContent">Output will appear here...</div>
</div>
</div>
<div class="flex justify-between">
<button id="skipBtn" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 hover:bg-gray-50 transition-colors duration-300">
<i class="fas fa-forward mr-2"></i>Skip
</button>
<button id="submitBtn" class="px-6 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors duration-300">
<i class="fas fa-paper-plane mr-2"></i>Submit
</button>
</div>
</div>
<div id="resultContainer" class="bg-white rounded-xl shadow-lg p-6 mb-8 hidden fade-in">
<div class="text-center mb-6">
<h2 class="text-2xl font-bold text-gray-800 mb-2">Your Result</h2>
<p id="resultMessage" class="text-gray-600"></p>
</div>
<div class="mb-6">
<div class="flex justify-between mb-1">
<span class="text-sm font-medium text-gray-700">Answer Similarity</span>
<span id="similarityPercent" class="text-sm font-medium text-gray-700">0%</span>
</div>
<div class="w-full bg-gray-200 rounded-full h-2.5">
<div id="similarityBar" class="progress-bar h-2.5 rounded-full bg-blue-600" style="width: 0%"></div>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
<div>
<h3 class="font-medium text-gray-700 mb-2">Your Solution:</h3>
<div class="code-block">
<pre id="displayStudentAnswer" class="whitespace-pre-wrap"></pre>
</div>
</div>
<div>
<h3 class="font-medium text-gray-700 mb-2">Expected Solution:</h3>
<div class="code-block">
<pre id="displayCorrectAnswer" class="whitespace-pre-wrap"></pre>
</div>
</div>
</div>
<div id="feedbackTips" class="bg-blue-50 border-l-4 border-blue-500 p-4 mb-6 hidden">
<h3 class="font-medium text-blue-800 mb-2">Tips for improvement:</h3>
<p id="improvementTips" class="text-blue-700"></p>
</div>
<div class="text-center">
<button id="nextQuestionBtn" class="px-6 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors duration-300">
<i class="fas fa-arrow-right mr-2"></i>Next Question
</button>
</div>
</div>
<div id="quizComplete" class="bg-white rounded-xl shadow-lg p-8 text-center hidden fade-in">
<div class="mb-6">
<i class="fas fa-trophy text-yellow-500 text-6xl mb-4"></i>
<h2 class="text-2xl font-bold text-gray-800 mb-2">Quiz Complete!</h2>
<p class="text-gray-600 mb-4">You've answered all the questions.</p>
</div>
<div class="bg-blue-50 rounded-lg p-6 mb-6 max-w-md mx-auto">
<h3 class="font-medium text-blue-800 mb-2">Your Final Score</h3>
<div class="text-4xl font-bold text-blue-600 mb-2" id="finalScore">0%</div>
<div class="w-full bg-gray-200 rounded-full h-2.5">
<div id="finalScoreBar" class="progress-bar h-2.5 rounded-full bg-blue-600" style="width: 0%"></div>
</div>
</div>
<div class="flex justify-center gap-4">
<button id="restartQuizBtn" class="px-6 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors duration-300">
<i class="fas fa-redo mr-2"></i>Restart Quiz
</button>
<button id="reviewAnswersBtn" class="px-6 py-2 border border-blue-600 text-blue-600 rounded-md hover:bg-blue-50 transition-colors duration-300">
<i class="fas fa-list-ul mr-2"></i>Review Answers
</button>
</div>
</div>
</div>
</div>
<!-- Load Monaco Editor -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.36.1/min/vs/loader.min.js"></script>
<script>
// Python questions database
const pythonQuestions = [
{
question: "Write a function to calculate the factorial of a number.",
codeExample: "def factorial(n):\n # Your code here",
answer: "def factorial(n):\n if n == 0:\n return 1\n else:\n return n * factorial(n-1)",
tips: "Remember that factorial of 0 is 1. Use recursion for an elegant solution.",
testCase: "print(factorial(5)) # Expected output: 120"
},
{
question: "How would you reverse a string in Python?",
codeExample: "my_string = 'hello'\n# Your code here",
answer: "my_string = 'hello'\nreversed_string = my_string[::-1]",
tips: "Python slicing is powerful. [::-1] means start at end of string and move backwards.",
testCase: "print(reversed_string) # Expected output: olleh"
},
{
question: "Write a list comprehension to get squares of even numbers from 1 to 10.",
codeExample: "# Your list comprehension here",
answer: "[x**2 for x in range(1, 11) if x % 2 == 0]",
tips: "List comprehensions have three parts: output expression, input sequence, and optional condition.",
testCase: "print(squares) # Expected output: [4, 16, 36, 64, 100]"
},
{
question: "How do you check if a key exists in a dictionary?",
codeExample: "my_dict = {'a': 1, 'b': 2}\n# Your code here",
answer: "my_dict = {'a': 1, 'b': 2}\nif 'a' in my_dict:\n print('Key exists')",
tips: "The 'in' keyword is the Pythonic way to check for key existence in dictionaries.",
testCase: "# Should print 'Key exists' if 'a' is in my_dict"
},
{
question: "Write a lambda function to add 10 to a given number.",
codeExample: "# Your lambda function here",
answer: "add_ten = lambda x: x + 10",
tips: "Lambda functions are anonymous functions defined with the lambda keyword.",
testCase: "print(add_ten(5)) # Expected output: 15"
},
{
question: "How would you handle exceptions in Python?",
codeExample: "# Your exception handling code here",
answer: "try:\n # Code that might raise an exception\n x = 1 / 0\nexcept ZeroDivisionError:\n print('Cannot divide by zero')\nexcept Exception as e:\n print(f'An error occurred: {e}')",
tips: "Always catch specific exceptions before more general ones. Use 'as' to access the exception object.",
testCase: "# Should print 'Cannot divide by zero'"
},
{
question: "Write a function to check if a number is prime.",
codeExample: "def is_prime(n):\n # Your code here",
answer: "def is_prime(n):\n if n <= 1:\n return False\n for i in range(2, int(n**0.5) + 1):\n if n % i == 0:\n return False\n return True",
tips: "Optimize by checking divisors only up to the square root of the number.",
testCase: "print(is_prime(7)) # Expected output: True\nprint(is_prime(4)) # Expected output: False"
},
{
question: "How would you merge two dictionaries in Python?",
codeExample: "dict1 = {'a': 1, 'b': 2}\ndict2 = {'c': 3, 'd': 4}\n# Your code here",
answer: "dict1 = {'a': 1, 'b': 2}\ndict2 = {'c': 3, 'd': 4}\nmerged = {**dict1, **dict2}",
tips: "In Python 3.5+, you can use the ** operator to unpack dictionaries. For older versions, use the update() method.",
testCase: "print(merged) # Expected output: {'a': 1, 'b': 2, 'c': 3, 'd': 4}"
},
{
question: "Write a generator function to yield Fibonacci numbers.",
codeExample: "def fibonacci():\n # Your code here",
answer: "def fibonacci():\n a, b = 0, 1\n while True:\n yield a\n a, b = b, a + b",
tips: "Generators use yield instead of return. They maintain their state between calls.",
testCase: "fib = fibonacci()\nprint([next(fib) for _ in range(10)]) # Expected output: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]"
},
{
question: "How would you remove duplicates from a list while preserving order?",
codeExample: "my_list = [1, 2, 2, 3, 4, 4, 5]\n# Your code here",
answer: "my_list = [1, 2, 2, 3, 4, 4, 5]\nunique_list = []\nseen = set()\nfor item in my_list:\n if item not in seen:\n unique_list.append(item)\n seen.add(item)",
tips: "Using a set for tracking seen items provides O(1) lookup time, making the solution efficient.",
testCase: "print(unique_list) # Expected output: [1, 2, 3, 4, 5]"
}
];
// Quiz state variables
let currentQuestionIndex = 0;
let shuffledQuestions = [];
let userAnswers = [];
let scores = [];
let editor = null;
// DOM elements
const quizContainer = document.getElementById('quizContainer');
const resultContainer = document.getElementById('resultContainer');
const quizComplete = document.getElementById('quizComplete');
const questionText = document.getElementById('questionText');
const codeExample = document.getElementById('codeExample');
const codeContent = document.getElementById('codeContent');
const submitBtn = document.getElementById('submitBtn');
const skipBtn = document.getElementById('skipBtn');
const nextQuestionBtn = document.getElementById('nextQuestionBtn');
const questionCounter = document.getElementById('questionCounter');
const displayStudentAnswer = document.getElementById('displayStudentAnswer');
const displayCorrectAnswer = document.getElementById('displayCorrectAnswer');
const similarityPercent = document.getElementById('similarityPercent');
const similarityBar = document.getElementById('similarityBar');
const feedbackTips = document.getElementById('feedbackTips');
const improvementTips = document.getElementById('improvementTips');
const resultMessage = document.getElementById('resultMessage');
const finalScore = document.getElementById('finalScore');
const finalScoreBar = document.getElementById('finalScoreBar');
const restartQuizBtn = document.getElementById('restartQuizBtn');
const reviewAnswersBtn = document.getElementById('reviewAnswersBtn');
const runCodeBtn = document.getElementById('runCodeBtn');
const outputContent = document.getElementById('outputContent');
// Initialize Monaco Editor
function initEditor() {
require.config({ paths: { 'vs': 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.36.1/min/vs' }});
require(['vs/editor/editor.main'], function() {
editor = monaco.editor.create(document.getElementById('editorContainer'), {
value: '',
language: 'python',
theme: 'vs-dark',
automaticLayout: true,
minimap: {
enabled: false
},
fontSize: 14,
scrollBeyondLastLine: false,
renderWhitespace: 'selection',
roundedSelection: true,
autoIndent: 'full',
tabSize: 4
});
});
}
// Initialize the quiz
function initQuiz() {
// Shuffle questions
shuffledQuestions = [...pythonQuestions].sort(() => Math.random() - 0.5);
currentQuestionIndex = 0;
userAnswers = [];
scores = [];
// Show first question
showQuestion();
quizContainer.classList.remove('hidden');
resultContainer.classList.add('hidden');
quizComplete.classList.add('hidden');
// Initialize editor if not already done
if (!editor) {
initEditor();
}
}
// Display current question
function showQuestion() {
if (currentQuestionIndex >= shuffledQuestions.length) {
showQuizComplete();
return;
}
const question = shuffledQuestions[currentQuestionIndex];
questionText.textContent = question.question;
if (question.codeExample) {
codeExample.classList.remove('hidden');
codeContent.textContent = question.codeExample;
} else {
codeExample.classList.add('hidden');
}
// Set initial editor content
if (editor) {
editor.setValue(question.codeExample || '# Write your solution here');
}
// Clear output
outputContent.textContent = 'Output will appear here...';
questionCounter.textContent = `${currentQuestionIndex + 1}/${shuffledQuestions.length}`;
}
// Run Python code in the editor
function runPythonCode() {
if (!editor) return;
const code = editor.getValue();
outputContent.textContent = 'Running code...';
// In a real implementation, you would send this to a Python backend
// For this demo, we'll simulate execution with the test case
setTimeout(() => {
const question = shuffledQuestions[currentQuestionIndex];
if (question.testCase) {
outputContent.textContent = `>>> ${question.testCase}\n${getExpectedOutput(question)}`;
} else {
outputContent.textContent = "Code executed (simulated). Check your solution against the expected output when you submit.";
}
}, 1000);
}
// Helper function to get expected output for demo purposes
function getExpectedOutput(question) {
switch(currentQuestionIndex) {
case 0: return "120";
case 1: return "olleh";
case 2: return "[4, 16, 36, 64, 100]";
case 3: return "Key exists";
case 4: return "15";
case 5: return "Cannot divide by zero";
case 6: return "True\nFalse";
case 7: return "{'a': 1, 'b': 2, 'c': 3, 'd': 4}";
case 8: return "[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]";
case 9: return "[1, 2, 3, 4, 5]";
default: return "Expected output";
}
}
// Calculate similarity between two strings (simple version)
function calculateSimilarity(str1, str2) {
// Remove whitespace and make lowercase for comparison
const cleanStr1 = str1.replace(/\s+/g, '').toLowerCase();
const cleanStr2 = str2.replace(/\s+/g, '').toLowerCase();
// If strings are identical
if (cleanStr1 === cleanStr2) return 100;
// If one string is empty
if (cleanStr1.length === 0 || cleanStr2.length === 0) return 0;
// Calculate Levenshtein distance
const distance = levenshteinDistance(cleanStr1, cleanStr2);
// Calculate similarity percentage
const maxLength = Math.max(cleanStr1.length, cleanStr2.length);
const similarity = (1 - distance / maxLength) * 100;
return Math.max(0, Math.min(100, similarity.toFixed(1)));
}
// Levenshtein distance algorithm
function levenshteinDistance(a, b) {
const matrix = [];
// Increment along the first column of each row
for (let i = 0; i <= b.length; i++) {
matrix[i] = [i];
}
// Increment each column in the first row
for (let j = 0; j <= a.length; j++) {
matrix[0][j] = j;
}
// Fill in the rest of the matrix
for (let i = 1; i <= b.length; i++) {
for (let j = 1; j <= a.length; j++) {
if (b.charAt(i - 1) === a.charAt(j - 1)) {
matrix[i][j] = matrix[i - 1][j - 1];
} else {
matrix[i][j] = Math.min(
matrix[i - 1][j - 1] + 1, // substitution
matrix[i][j - 1] + 1, // insertion
matrix[i - 1][j] + 1 // deletion
);
}
}
}
return matrix[b.length][a.length];
}
// Show result after submission
function showResult() {
if (!editor) return;
const question = shuffledQuestions[currentQuestionIndex];
const userAnswer = editor.getValue().trim();
const correctAnswer = question.answer;
// Calculate similarity score
const similarityScore = calculateSimilarity(userAnswer, correctAnswer);
// Store user answer and score
userAnswers.push({
question: question.question,
userAnswer: userAnswer,
correctAnswer: correctAnswer,
score: similarityScore,
output: outputContent.textContent
});
scores.push(similarityScore);
// Display results
displayStudentAnswer.textContent = userAnswer || "No answer provided";
displayCorrectAnswer.textContent = correctAnswer;
similarityPercent.textContent = `${similarityScore}%`;
similarityBar.style.width = `${similarityScore}%`;
// Set color based on score
if (similarityScore >= 80) {
similarityBar.classList.remove('bg-red-600', 'bg-yellow-500');
similarityBar.classList.add('bg-green-500');
resultMessage.textContent = "Excellent! Your answer is very close to the expected solution.";
} else if (similarityScore >= 50) {
similarityBar.classList.remove('bg-green-500', 'bg-red-600');
similarityBar.classList.add('bg-yellow-500');
resultMessage.textContent = "Good try! Your answer has some similarities with the expected solution.";
} else {
similarityBar.classList.remove('bg-green-500', 'bg-yellow-500');
similarityBar.classList.add('bg-red-600');
resultMessage.textContent = "Keep practicing! Review the expected solution to improve.";
}
// Show improvement tips if available
if (question.tips) {
improvementTips.textContent = question.tips;
feedbackTips.classList.remove('hidden');
} else {
feedbackTips.classList.add('hidden');
}
// Switch to result view
quizContainer.classList.add('hidden');
resultContainer.classList.remove('hidden');
}
// Move to next question
function nextQuestion() {
currentQuestionIndex++;
if (currentQuestionIndex < shuffledQuestions.length) {
showQuestion();
quizContainer.classList.remove('hidden');
resultContainer.classList.add('hidden');
} else {
showQuizComplete();
}
}
// Show quiz completion screen
function showQuizComplete() {
// Calculate average score
const averageScore = scores.reduce((a, b) => a + b, 0) / scores.length;
// Display final score
finalScore.textContent = `${averageScore.toFixed(1)}%`;
finalScoreBar.style.width = `${averageScore}%`;
// Set color based on score
if (averageScore >= 80) {
finalScoreBar.classList.remove('bg-red-600', 'bg-yellow-500');
finalScoreBar.classList.add('bg-green-500');
} else if (averageScore >= 50) {
finalScoreBar.classList.remove('bg-green-500', 'bg-red-600');
finalScoreBar.classList.add('bg-yellow-500');
} else {
finalScoreBar.classList.remove('bg-green-500', 'bg-yellow-500');
finalScoreBar.classList.add('bg-red-600');
}
// Show completion screen
quizContainer.classList.add('hidden');
resultContainer.classList.add('hidden');
quizComplete.classList.remove('hidden');
}
// Event listeners
submitBtn.addEventListener('click', showResult);
skipBtn.addEventListener('click', nextQuestion);
nextQuestionBtn.addEventListener('click', nextQuestion);
restartQuizBtn.addEventListener('click', initQuiz);
runCodeBtn.addEventListener('click', runPythonCode);
// Review answers button would typically show a summary of all questions and answers
reviewAnswersBtn.addEventListener('click', () => {
let reviewContent = "Review of your answers:\n\n";
userAnswers.forEach((answer, index) => {
reviewContent += `Question ${index + 1}: ${answer.question}\n`;
reviewContent += `Your Answer:\n${answer.userAnswer}\n\n`;
reviewContent += `Score: ${answer.score}%\n\n`;
reviewContent += "--------------------------------\n\n";
});
alert(reviewContent);
});
// Initialize the quiz when page loads
document.addEventListener('DOMContentLoaded', () => {
initEditor();
initQuiz();
});
</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=karaltan/python-quiz" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>