Update app.py
Browse files
app.py
CHANGED
|
@@ -108,31 +108,10 @@ class QuizApp:
|
|
| 108 |
<div style="max-width: 800px; margin: 0 auto; padding: 20px; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;">
|
| 109 |
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px; border-radius: 15px; text-align: center; margin-bottom: 30px; box-shadow: 0 10px 30px rgba(0,0,0,0.2);">
|
| 110 |
<h1 style="margin: 0; font-size: 2.5em; font-weight: 300;">π Multiple Choice Quiz</h1>
|
| 111 |
-
<p style="margin: 10px 0
|
| 112 |
-
<button type="button" onclick="openQuizModal()"
|
| 113 |
-
style="background: rgba(255,255,255,0.2); color: white; border: 2px solid white; padding: 12px 30px; font-size: 1.1em; border-radius: 25px; cursor: pointer; transition: all 0.3s ease; font-weight: 500; backdrop-filter: blur(10px);"
|
| 114 |
-
onmouseover="this.style.background='white'; this.style.color='#667eea';"
|
| 115 |
-
onmouseout="this.style.background='rgba(255,255,255,0.2)'; this.style.color='white';">
|
| 116 |
-
π Start Quiz
|
| 117 |
-
</button>
|
| 118 |
</div>
|
| 119 |
|
| 120 |
-
<
|
| 121 |
-
<div id="quizModal" style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.8); z-index: 10000; backdrop-filter: blur(5px);">
|
| 122 |
-
<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 90%; max-width: 900px; max-height: 90%; background: white; border-radius: 20px; box-shadow: 0 20px 60px rgba(0,0,0,0.3); overflow: hidden;">
|
| 123 |
-
|
| 124 |
-
<!-- Modal Header -->
|
| 125 |
-
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 20px 30px; display: flex; justify-content: space-between; align-items: center;">
|
| 126 |
-
<div>
|
| 127 |
-
<h2 style="margin: 0; font-size: 1.8em; font-weight: 300;">π Quiz in Progress</h2>
|
| 128 |
-
<p style="margin: 5px 0 0 0; opacity: 0.9;" id="progressText">Question 1 of {len(self.questions)}</p>
|
| 129 |
-
</div>
|
| 130 |
-
<button onclick="closeQuizModal()" style="background: none; border: none; color: white; font-size: 1.5em; cursor: pointer; padding: 5px; border-radius: 50%; transition: background 0.3s;" onmouseover="this.style.background='rgba(255,255,255,0.2)';" onmouseout="this.style.background='none';">β</button>
|
| 131 |
-
</div>
|
| 132 |
-
|
| 133 |
-
<!-- Modal Body -->
|
| 134 |
-
<div style="padding: 0; max-height: 70vh; overflow-y: auto;">
|
| 135 |
-
<form id="quizForm" style="padding: 30px;">
|
| 136 |
"""
|
| 137 |
|
| 138 |
for i, q in enumerate(self.questions):
|
|
@@ -164,99 +143,23 @@ class QuizApp:
|
|
| 164 |
"""
|
| 165 |
|
| 166 |
html += f"""
|
| 167 |
-
|
| 168 |
-
<
|
| 169 |
-
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
onmouseover="this.style.transform='translateY(-2px)'; this.style.boxShadow='0 8px 25px rgba(102, 126, 234, 0.6)';"
|
| 175 |
-
onmouseout="this.style.transform='translateY(0)'; this.style.boxShadow='0 5px 15px rgba(102, 126, 234, 0.4)';">
|
| 176 |
-
π Submit Quiz
|
| 177 |
-
</button>
|
| 178 |
-
<button type="button" onclick="closeQuizModal()"
|
| 179 |
-
style="background: #6c757d; color: white; border: none; padding: 15px 30px; font-size: 1.1em; border-radius: 25px; cursor: pointer; transition: all 0.3s ease;"
|
| 180 |
-
onmouseover="this.style.background='#5a6268';"
|
| 181 |
-
onmouseout="this.style.background='#6c757d';">
|
| 182 |
-
Cancel
|
| 183 |
-
</button>
|
| 184 |
-
</div>
|
| 185 |
</div>
|
| 186 |
-
</
|
| 187 |
|
| 188 |
-
<
|
| 189 |
-
<div id="resultsModal" style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.8); z-index: 10001; backdrop-filter: blur(5px);">
|
| 190 |
-
<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 90%; max-width: 900px; max-height: 90%; background: white; border-radius: 20px; box-shadow: 0 20px 60px rgba(0,0,0,0.3); overflow: hidden;">
|
| 191 |
-
|
| 192 |
-
<!-- Results Header -->
|
| 193 |
-
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 20px 30px; display: flex; justify-content: space-between; align-items: center;">
|
| 194 |
-
<div>
|
| 195 |
-
<h2 style="margin: 0; font-size: 1.8em; font-weight: 300;">π Quiz Results</h2>
|
| 196 |
-
<p style="margin: 5px 0 0 0; opacity: 0.9;">Your performance summary</p>
|
| 197 |
-
</div>
|
| 198 |
-
<button onclick="closeResultsModal()" style="background: none; border: none; color: white; font-size: 1.5em; cursor: pointer; padding: 5px; border-radius: 50%; transition: background 0.3s;" onmouseover="this.style.background='rgba(255,255,255,0.2)';" onmouseout="this.style.background='none';">β</button>
|
| 199 |
-
</div>
|
| 200 |
-
|
| 201 |
-
<!-- Results Body -->
|
| 202 |
-
<div id="resultsContent" style="padding: 0; max-height: 70vh; overflow-y: auto;">
|
| 203 |
-
<!-- Results will be populated here -->
|
| 204 |
-
</div>
|
| 205 |
-
|
| 206 |
-
<!-- Results Footer -->
|
| 207 |
-
<div style="background: #f8f9ff; padding: 20px 30px; border-top: 1px solid #e1e5e9; text-align: center;">
|
| 208 |
-
<button onclick="restartQuiz()"
|
| 209 |
-
style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border: none; padding: 12px 30px; font-size: 1.1em; border-radius: 25px; cursor: pointer; box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4); margin-right: 15px;">
|
| 210 |
-
π Take Quiz Again
|
| 211 |
-
</button>
|
| 212 |
-
<button onclick="closeResultsModal()"
|
| 213 |
-
style="background: #6c757d; color: white; border: none; padding: 12px 30px; font-size: 1.1em; border-radius: 25px; cursor: pointer; transition: all 0.3s ease;"
|
| 214 |
-
onmouseover="this.style.background='#5a6268';"
|
| 215 |
-
onmouseout="this.style.background='#6c757d';">
|
| 216 |
-
Close
|
| 217 |
-
</button>
|
| 218 |
-
</div>
|
| 219 |
-
</div>
|
| 220 |
-
</div>
|
| 221 |
</div>
|
| 222 |
|
| 223 |
<script>
|
| 224 |
// Store quiz data
|
| 225 |
const quizData = JSON.parse("{quiz_data_json}".replace(/"/g, '"'));
|
| 226 |
|
| 227 |
-
function openQuizModal() {{
|
| 228 |
-
document.getElementById('quizModal').style.display = 'block';
|
| 229 |
-
document.body.style.overflow = 'hidden'; // Prevent background scrolling
|
| 230 |
-
}}
|
| 231 |
-
|
| 232 |
-
function closeQuizModal() {{
|
| 233 |
-
if (confirm('Are you sure you want to close the quiz? Your progress will be lost.')) {{
|
| 234 |
-
document.getElementById('quizModal').style.display = 'none';
|
| 235 |
-
document.body.style.overflow = 'auto';
|
| 236 |
-
}}
|
| 237 |
-
}}
|
| 238 |
-
|
| 239 |
-
function closeResultsModal() {{
|
| 240 |
-
document.getElementById('resultsModal').style.display = 'none';
|
| 241 |
-
document.body.style.overflow = 'auto';
|
| 242 |
-
}}
|
| 243 |
-
|
| 244 |
-
function restartQuiz() {{
|
| 245 |
-
// Reset form
|
| 246 |
-
document.getElementById('quizForm').reset();
|
| 247 |
-
|
| 248 |
-
// Clear visual selections
|
| 249 |
-
const labels = document.querySelectorAll('#quizForm label');
|
| 250 |
-
labels.forEach(label => {{
|
| 251 |
-
label.style.borderColor = '#e1e5e9';
|
| 252 |
-
label.style.backgroundColor = 'white';
|
| 253 |
-
}});
|
| 254 |
-
|
| 255 |
-
// Close results and open quiz
|
| 256 |
-
closeResultsModal();
|
| 257 |
-
openQuizModal();
|
| 258 |
-
}}
|
| 259 |
-
|
| 260 |
function selectAnswer(labelElement) {{
|
| 261 |
// Remove previous selections from this question
|
| 262 |
const questionDiv = labelElement.closest('div[style*="margin-bottom: 35px"]');
|
|
@@ -325,27 +228,23 @@ class QuizApp:
|
|
| 325 |
console.log('Final score:', score);
|
| 326 |
console.log('Feedback:', feedback);
|
| 327 |
|
| 328 |
-
// Close quiz modal and show results
|
| 329 |
-
document.getElementById('quizModal').style.display = 'none';
|
| 330 |
displayResults(score, totalQuestions, feedback);
|
| 331 |
}}
|
| 332 |
|
| 333 |
function displayResults(score, total, feedback) {{
|
| 334 |
const percentage = Math.round((score / total) * 100);
|
| 335 |
let resultsHtml = `
|
| 336 |
-
<div style="padding: 30px;
|
| 337 |
-
<div style="margin-bottom: 30px;">
|
| 338 |
-
<
|
| 339 |
-
|
| 340 |
-
<div style="font-size:
|
| 341 |
-
<div style="font-size: 1.
|
| 342 |
-
${{percentage >= 80 ? 'Excellent! π' : percentage >= 60 ? 'Good Job! π' : 'Keep Practicing! πͺ'}}
|
| 343 |
-
</div>
|
| 344 |
</div>
|
| 345 |
</div>
|
| 346 |
|
| 347 |
-
<div style="
|
| 348 |
-
<h3 style="color: #333; margin-bottom: 20px; text-align: center;
|
| 349 |
`;
|
| 350 |
|
| 351 |
feedback.forEach((item, index) => {{
|
|
@@ -355,54 +254,42 @@ class QuizApp:
|
|
| 355 |
|
| 356 |
resultsHtml += `
|
| 357 |
<div style="margin-bottom: 20px; padding: 20px; background: ${{bgColor}}; border-left: 5px solid ${{borderColor}}; border-radius: 8px;">
|
| 358 |
-
<div style="font-weight: bold; color: #333; margin-bottom: 10px;
|
| 359 |
${{icon}} Question ${{index + 1}}
|
| 360 |
</div>
|
| 361 |
-
<div style="color: #666; margin-bottom:
|
| 362 |
"${{item.question}}"
|
| 363 |
</div>
|
| 364 |
-
<div style="margin-bottom:
|
| 365 |
-
<strong
|
| 366 |
-
<span style="color: ${{item.isCorrect ? '#4caf50' : '#f44336'}}; font-weight: 500;">${{item.userAnswer}}</span>
|
| 367 |
</div>
|
| 368 |
<div>
|
| 369 |
-
<strong
|
| 370 |
-
<span style="color: #4caf50; font-weight: 500;">${{item.correctAnswer}}</span>
|
| 371 |
</div>
|
| 372 |
</div>
|
| 373 |
`;
|
| 374 |
}});
|
| 375 |
|
| 376 |
-
resultsHtml += `
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 377 |
|
| 378 |
-
document.getElementById('
|
| 379 |
-
document.getElementById('
|
| 380 |
-
|
| 381 |
-
|
| 382 |
-
// Close modal when clicking outside
|
| 383 |
-
window.onclick = function(event) {{
|
| 384 |
-
const quizModal = document.getElementById('quizModal');
|
| 385 |
-
const resultsModal = document.getElementById('resultsModal');
|
| 386 |
|
| 387 |
-
|
| 388 |
-
|
| 389 |
-
}}
|
| 390 |
-
if (event.target === resultsModal) {{
|
| 391 |
-
closeResultsModal();
|
| 392 |
-
}}
|
| 393 |
}}
|
| 394 |
|
| 395 |
-
// Keyboard shortcuts
|
| 396 |
-
document.addEventListener('keydown', function(event) {{
|
| 397 |
-
if (event.key === 'Escape') {{
|
| 398 |
-
if (document.getElementById('resultsModal').style.display === 'block') {{
|
| 399 |
-
closeResultsModal();
|
| 400 |
-
}} else if (document.getElementById('quizModal').style.display === 'block') {{
|
| 401 |
-
closeQuizModal();
|
| 402 |
-
}}
|
| 403 |
-
}}
|
| 404 |
-
}});
|
| 405 |
-
|
| 406 |
// Add some debugging
|
| 407 |
console.log('Quiz script loaded');
|
| 408 |
console.log('Quiz data available:', typeof quizData !== 'undefined');
|
|
|
|
| 108 |
<div style="max-width: 800px; margin: 0 auto; padding: 20px; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;">
|
| 109 |
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px; border-radius: 15px; text-align: center; margin-bottom: 30px; box-shadow: 0 10px 30px rgba(0,0,0,0.2);">
|
| 110 |
<h1 style="margin: 0; font-size: 2.5em; font-weight: 300;">π Multiple Choice Quiz</h1>
|
| 111 |
+
<p style="margin: 10px 0 0 0; font-size: 1.2em; opacity: 0.9;">Test your knowledge with {len(self.questions)} questions</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 112 |
</div>
|
| 113 |
|
| 114 |
+
<form id="quizForm" style="background: white; padding: 30px; border-radius: 15px; box-shadow: 0 5px 20px rgba(0,0,0,0.1);">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 115 |
"""
|
| 116 |
|
| 117 |
for i, q in enumerate(self.questions):
|
|
|
|
| 143 |
"""
|
| 144 |
|
| 145 |
html += f"""
|
| 146 |
+
<div style="text-align: center; margin-top: 40px;">
|
| 147 |
+
<button type="button" onclick="submitQuiz()"
|
| 148 |
+
style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border: none; padding: 15px 40px; font-size: 1.2em; border-radius: 30px; cursor: pointer; box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4); transition: all 0.3s ease; font-weight: 500;"
|
| 149 |
+
onmouseover="this.style.transform='translateY(-2px)'; this.style.boxShadow='0 8px 25px rgba(102, 126, 234, 0.6)';"
|
| 150 |
+
onmouseout="this.style.transform='translateY(0)'; this.style.boxShadow='0 5px 15px rgba(102, 126, 234, 0.4)';">
|
| 151 |
+
π Submit Quiz
|
| 152 |
+
</button>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 153 |
</div>
|
| 154 |
+
</form>
|
| 155 |
|
| 156 |
+
<div id="results" style="margin-top: 30px; display: none;"></div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 157 |
</div>
|
| 158 |
|
| 159 |
<script>
|
| 160 |
// Store quiz data
|
| 161 |
const quizData = JSON.parse("{quiz_data_json}".replace(/"/g, '"'));
|
| 162 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 163 |
function selectAnswer(labelElement) {{
|
| 164 |
// Remove previous selections from this question
|
| 165 |
const questionDiv = labelElement.closest('div[style*="margin-bottom: 35px"]');
|
|
|
|
| 228 |
console.log('Final score:', score);
|
| 229 |
console.log('Feedback:', feedback);
|
| 230 |
|
|
|
|
|
|
|
| 231 |
displayResults(score, totalQuestions, feedback);
|
| 232 |
}}
|
| 233 |
|
| 234 |
function displayResults(score, total, feedback) {{
|
| 235 |
const percentage = Math.round((score / total) * 100);
|
| 236 |
let resultsHtml = `
|
| 237 |
+
<div style="background: white; padding: 30px; border-radius: 15px; box-shadow: 0 5px 20px rgba(0,0,0,0.1);">
|
| 238 |
+
<div style="text-align: center; margin-bottom: 30px;">
|
| 239 |
+
<h2 style="color: #333; margin-bottom: 15px;">π Quiz Complete!</h2>
|
| 240 |
+
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 20px; border-radius: 15px; display: inline-block; min-width: 200px;">
|
| 241 |
+
<div style="font-size: 3em; font-weight: bold; margin-bottom: 10px;">${{score}}/${{total}}</div>
|
| 242 |
+
<div style="font-size: 1.5em;">${{percentage}}%</div>
|
|
|
|
|
|
|
| 243 |
</div>
|
| 244 |
</div>
|
| 245 |
|
| 246 |
+
<div style="margin-top: 30px;">
|
| 247 |
+
<h3 style="color: #333; margin-bottom: 20px; text-align: center;">π Detailed Results</h3>
|
| 248 |
`;
|
| 249 |
|
| 250 |
feedback.forEach((item, index) => {{
|
|
|
|
| 254 |
|
| 255 |
resultsHtml += `
|
| 256 |
<div style="margin-bottom: 20px; padding: 20px; background: ${{bgColor}}; border-left: 5px solid ${{borderColor}}; border-radius: 8px;">
|
| 257 |
+
<div style="font-weight: bold; color: #333; margin-bottom: 10px;">
|
| 258 |
${{icon}} Question ${{index + 1}}
|
| 259 |
</div>
|
| 260 |
+
<div style="color: #666; margin-bottom: 10px; font-style: italic;">
|
| 261 |
"${{item.question}}"
|
| 262 |
</div>
|
| 263 |
+
<div style="margin-bottom: 5px;">
|
| 264 |
+
<strong>Your answer:</strong> ${{item.userAnswer}}
|
|
|
|
| 265 |
</div>
|
| 266 |
<div>
|
| 267 |
+
<strong>Correct answer:</strong> ${{item.correctAnswer}}
|
|
|
|
| 268 |
</div>
|
| 269 |
</div>
|
| 270 |
`;
|
| 271 |
}});
|
| 272 |
|
| 273 |
+
resultsHtml += `
|
| 274 |
+
</div>
|
| 275 |
+
|
| 276 |
+
<div style="text-align: center; margin-top: 30px;">
|
| 277 |
+
<button onclick="location.reload()"
|
| 278 |
+
style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border: none; padding: 12px 30px; font-size: 1.1em; border-radius: 25px; cursor: pointer; box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);">
|
| 279 |
+
π Take Quiz Again
|
| 280 |
+
</button>
|
| 281 |
+
</div>
|
| 282 |
+
</div>
|
| 283 |
+
`;
|
| 284 |
|
| 285 |
+
document.getElementById('results').innerHTML = resultsHtml;
|
| 286 |
+
document.getElementById('results').style.display = 'block';
|
| 287 |
+
document.getElementById('quizForm').style.display = 'none';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 288 |
|
| 289 |
+
// Scroll to results
|
| 290 |
+
document.getElementById('results').scrollIntoView({{ behavior: 'smooth' }});
|
|
|
|
|
|
|
|
|
|
|
|
|
| 291 |
}}
|
| 292 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 293 |
// Add some debugging
|
| 294 |
console.log('Quiz script loaded');
|
| 295 |
console.log('Quiz data available:', typeof quizData !== 'undefined');
|