|
<!DOCTYPE html> |
|
<html lang="en"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title>SmartLearn - Quiz Generation</title> |
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> |
|
<style> |
|
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600&display=swap'); |
|
|
|
body { |
|
font-family: 'Poppins', sans-serif; |
|
margin: 0; |
|
padding: 0; |
|
display: flex; |
|
justify-content: center; |
|
align-items: center; |
|
min-height: 100vh; |
|
background-image: url('../static/quiz.jpg'); |
|
background-size: cover; |
|
background-position: center; |
|
background-attachment: fixed; |
|
} |
|
|
|
.container { |
|
border-radius: 20px; |
|
padding: 40px; |
|
width: 90%; |
|
max-width: 500px; |
|
text-align: center; |
|
position: relative; |
|
z-index: 2; |
|
background: rgba(255, 255, 255, 0.1); |
|
backdrop-filter: blur(10px); |
|
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37); |
|
border: 1px solid rgba(255, 255, 255, 0.18); |
|
} |
|
|
|
.quiz-form { |
|
padding: 20px; |
|
border-radius: 10px; |
|
} |
|
|
|
.form-group { |
|
margin-bottom: 20px; |
|
text-align: left; |
|
} |
|
|
|
.form-group label { |
|
display: block; |
|
margin-bottom: 5px; |
|
color: #fff; |
|
font-weight: 600; |
|
} |
|
|
|
.form-group input, |
|
.form-group select { |
|
width: 100%; |
|
padding: 10px; |
|
border: none; |
|
border-radius: 5px; |
|
background: rgba(255, 255, 255, 0.8); |
|
color: #000; |
|
font-size: 16px; |
|
} |
|
|
|
.form-group select { |
|
appearance: none; |
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E"); |
|
background-repeat: no-repeat; |
|
background-position: right 10px center; |
|
background-size: 20px; |
|
} |
|
|
|
.btn { |
|
background-color: #3498db; |
|
color: white; |
|
border: none; |
|
padding: 12px 24px; |
|
border-radius: 30px; |
|
cursor: pointer; |
|
font-size: 18px; |
|
transition: all 0.3s ease; |
|
} |
|
|
|
.btn:hover { |
|
background-color: #2980b9; |
|
transform: translateY(-2px); |
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); |
|
} |
|
|
|
h1, h2, h3 { |
|
color: #fff; |
|
text-shadow: 2px 2px 4px rgba(0,0,0,0.5); |
|
} |
|
|
|
.score-circle { |
|
width: 150px; |
|
height: 150px; |
|
background-color: rgba(52, 152, 219, 0.8); |
|
border-radius: 50%; |
|
display: flex; |
|
justify-content: center; |
|
align-items: center; |
|
margin: 0 auto 30px; |
|
font-size: 36px; |
|
font-weight: bold; |
|
color: white; |
|
box-shadow: 0 5px 15px rgba(52, 152, 219, 0.3); |
|
} |
|
|
|
.areas-to-improve { |
|
background-color: rgba(248, 249, 250, 0.1); |
|
border-radius: 10px; |
|
padding: 20px; |
|
text-align: left; |
|
color: #fff; |
|
} |
|
|
|
.areas-to-improve ol { |
|
padding-left: 20px; |
|
} |
|
|
|
.areas-to-improve li { |
|
margin-bottom: 10px; |
|
} |
|
|
|
.validation-container { |
|
display: none; |
|
justify-content: center; |
|
align-items: center; |
|
flex-direction: column; |
|
} |
|
|
|
.loader { |
|
border: 5px solid rgba(255, 255, 255, 0.3); |
|
border-top: 5px solid #3498db; |
|
border-radius: 50%; |
|
width: 50px; |
|
height: 50px; |
|
animation: spin 1s linear infinite; |
|
} |
|
|
|
@keyframes spin { |
|
0% { transform: rotate(0deg); } |
|
100% { transform: rotate(360deg); } |
|
} |
|
|
|
.validation-text { |
|
margin-top: 20px; |
|
font-size: 18px; |
|
color: #fff; |
|
} |
|
|
|
.correct { color: #2ecc71; } |
|
.incorrect { color: #e74c3c; } |
|
#areas-to-improve { margin-top: 20px; } |
|
|
|
.options li { |
|
display: flex; |
|
align-items: center; |
|
margin-bottom: 10px; |
|
color: #fff; |
|
} |
|
|
|
.options li input { |
|
margin-right: 10px; |
|
} |
|
|
|
.back-button { |
|
position: absolute; |
|
top: 20px; |
|
left: 20px; |
|
background-color: #6c757d; |
|
color: white; |
|
border: none; |
|
padding: 10px 20px; |
|
border-radius: 30px; |
|
cursor: pointer; |
|
transition: background-color 0.3s; |
|
font-size: 16px; |
|
} |
|
|
|
.back-button:hover { |
|
background-color: #5a6268; |
|
} |
|
|
|
.fade-in { |
|
animation: fadeIn 0.5s ease-in-out; |
|
} |
|
|
|
@keyframes fadeIn { |
|
from { opacity: 0; transform: translateY(20px); } |
|
to { opacity: 1; transform: translateY(0); } |
|
} |
|
|
|
.icon { |
|
margin-right: 10px; |
|
} |
|
|
|
.loading-animation { |
|
display: flex; |
|
flex-direction: column; |
|
align-items: center; |
|
justify-content: center; |
|
margin-top: 20px; |
|
} |
|
|
|
.loading-animation p { |
|
margin-top: 10px; |
|
color: #fff; |
|
font-weight: 600; |
|
} |
|
|
|
@keyframes pulse { |
|
0% { transform: scale(1); } |
|
50% { transform: scale(1.1); } |
|
100% { transform: scale(1); } |
|
} |
|
|
|
.loading-icon { |
|
font-size: 48px; |
|
color: #3498db; |
|
animation: pulse 1.5s infinite; |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
<div class="container fade-in"> |
|
<button class="back-button" onclick="goBack()"><i class="fas fa-arrow-left"></i> Back</button> |
|
<h1><i class="fas fa-graduation-cap icon"></i>Generate Your Custom Quiz</h1> |
|
<form class="quiz-form"> |
|
<div class="form-group"> |
|
<label for="subject"><i class="fas fa-book icon"></i>Subject:</label> |
|
<input type="text" id="subject" name="subject" required> |
|
</div> |
|
<div class="form-group"> |
|
<label for="topic"><i class="fas fa-lightbulb icon"></i>Topic:</label> |
|
<input type="text" id="topic" name="topic" required> |
|
</div> |
|
<div class="form-group"> |
|
<label for="num-questions"><i class="fas fa-list-ol icon"></i>Number of Questions:</label> |
|
<select id="num-questions" name="num-questions"> |
|
<option value="2">2</option> |
|
<option value="5">5</option> |
|
<option value="10">10</option> |
|
<option value="15">15</option> |
|
<option value="20">20</option> |
|
</select> |
|
</div> |
|
<div class="form-group"> |
|
<label for="difficulty"><i class="fas fa-signal icon"></i>Difficulty Level:</label> |
|
<select id="difficulty" name="difficulty"> |
|
<option value="easy">Easy</option> |
|
<option value="medium">Medium</option> |
|
<option value="hard">Hard</option> |
|
</select> |
|
</div> |
|
<button type="submit" class="btn"><i class="fas fa-magic icon"></i>Generate Quiz</button> |
|
</form> |
|
|
|
<div id="loading-animation" class="loading-animation" style="display: none;"> |
|
<i class="fas fa-cog loading-icon"></i> |
|
<p id="loading-text">Generating Quiz...</p> |
|
</div> |
|
|
|
<div id="quiz-result" class="quiz-result" style="display: none;"> |
|
|
|
</div> |
|
<div id="validation-container" class="validation-container"> |
|
<div id="loader" class="loader"></div> |
|
<div id="validation-text" class="validation-text">Validating...</div> |
|
</div> |
|
<div id="quiz-score" style="display: none;"></div> |
|
<div id="areas-to-improve" class="areas-to-improve" style="display: none;"></div> |
|
</div> |
|
|
|
<script> |
|
let quizData = []; |
|
let studentId = 'alice.johnson@stateu.edu'; |
|
|
|
document.querySelector('.quiz-form').addEventListener('submit', function(e) { |
|
e.preventDefault(); |
|
const formData = new FormData(this); |
|
const data = { |
|
subject: formData.get('subject'), |
|
topic: formData.get('topic'), |
|
'num-questions': formData.get('num-questions'), |
|
difficulty: formData.get('difficulty') |
|
}; |
|
|
|
|
|
this.style.display = 'none'; |
|
document.getElementById('loading-animation').style.display = 'flex'; |
|
|
|
let loadingTexts = [ |
|
"Crafting challenging questions...", |
|
"Digging deep into the subject...", |
|
"Polishing the perfect quiz for you...", |
|
"Almost there, finalizing details..." |
|
]; |
|
let currentTextIndex = 0; |
|
|
|
|
|
const loadingInterval = setInterval(() => { |
|
document.getElementById('loading-text').textContent = loadingTexts[currentTextIndex]; |
|
currentTextIndex = (currentTextIndex + 1) % loadingTexts.length; |
|
}, 3000); |
|
|
|
fetch('/generate_quiz', { |
|
method: 'POST', |
|
headers: { |
|
'Content-Type': 'application/json', |
|
}, |
|
body: JSON.stringify(data) |
|
}) |
|
.then(response => response.json()) |
|
.then(data => { |
|
|
|
clearInterval(loadingInterval); |
|
|
|
|
|
document.getElementById('loading-animation').style.display = 'none'; |
|
|
|
quizData = parseQuizData(data.quiz); |
|
showQuiz(quizData); |
|
}) |
|
.catch(error => { |
|
console.error('Error:', error); |
|
|
|
clearInterval(loadingInterval); |
|
|
|
document.getElementById('loading-animation').style.display = 'none'; |
|
alert('An error occurred while generating the quiz. Please try again.'); |
|
}); |
|
}); |
|
|
|
function parseQuizData(quizString) { |
|
const questions = quizString.split('Question:').filter(q => q.trim() !== ''); |
|
return questions.map((question, index) => { |
|
const [questionText, ...options] = question.split('\n').filter(line => line.trim() !== ''); |
|
const answerLine = options.pop(); |
|
const correctAnswer = parseInt(answerLine.split(':')[1].trim()); |
|
return { |
|
id: index + 1, |
|
text: questionText.trim(), |
|
options: options.map(opt => opt.replace('<<o>>', '').trim()), |
|
correctAnswer: correctAnswer, |
|
concept: questionText.match(/\[(.*?)\]/)[1] |
|
}; |
|
}); |
|
} |
|
|
|
function showQuiz(questions) { |
|
const quizResult = document.getElementById('quiz-result'); |
|
let quizHtml = '<h2>Your Custom Quiz</h2>'; |
|
|
|
questions.forEach((question, index) => { |
|
quizHtml += ` |
|
<div class="question fade-in"> |
|
<h3>${question.id}. ${question.text}</h3> |
|
<ul class="options"> |
|
`; |
|
|
|
question.options.forEach((option, optionIndex) => { |
|
quizHtml += ` |
|
<li> |
|
<input type="radio" name="q${index}" value="${optionIndex + 1}" id="q${index}o${optionIndex}"> |
|
<label for="q${index}o${optionIndex}">${option}</label> |
|
</li> |
|
`; |
|
}); |
|
|
|
quizHtml += ` |
|
</ul> |
|
</div> |
|
`; |
|
}); |
|
|
|
quizHtml += '<button onclick="submitQuiz()" class="btn">Submit Quiz</button>'; |
|
|
|
quizResult.innerHTML = quizHtml; |
|
quizResult.style.display = 'block'; |
|
} |
|
|
|
function submitQuiz() { |
|
const validationContainer = document.getElementById('validation-container'); |
|
const quizResult = document.getElementById('quiz-result'); |
|
const quizScore = document.getElementById('quiz-score'); |
|
const areasToImprove = document.getElementById('areas-to-improve'); |
|
|
|
quizResult.style.display = 'none'; |
|
validationContainer.style.display = 'flex'; |
|
|
|
setTimeout(() => { |
|
validationContainer.style.display = 'none'; |
|
const score = calculateScore(); |
|
displayResults(score); |
|
|
|
|
|
let improveAreas = []; |
|
let incorrectQuestions = quizData.filter((question, index) => { |
|
const selectedAnswer = document.querySelector(`input[name="q${index}"]:checked`); |
|
return !selectedAnswer || parseInt(selectedAnswer.value) !== question.correctAnswer; |
|
}); |
|
|
|
if (incorrectQuestions.length > 0) { |
|
improveAreas = incorrectQuestions.map(question => question.concept); |
|
} |
|
|
|
|
|
fetch('/update_student_areas', { |
|
method: 'POST', |
|
headers: { |
|
'Content-Type': 'application/json', |
|
}, |
|
body: JSON.stringify({ student_id: studentId, areas_to_improve: improveAreas }) |
|
}) |
|
.then(response => response.json()) |
|
.then(data => { |
|
if (data.status === 'success') { |
|
console.log('Student areas to improve updated successfully.'); |
|
} else { |
|
console.error('Failed to update student areas to improve.'); |
|
} |
|
}) |
|
.catch(error => console.error('Error:', error)); |
|
|
|
}, 2000); |
|
} |
|
|
|
function calculateScore() { |
|
let score = 0; |
|
quizData.forEach((question, index) => { |
|
const selectedAnswer = document.querySelector(`input[name="q${index}"]:checked`); |
|
if (selectedAnswer && parseInt(selectedAnswer.value) === question.correctAnswer) { |
|
score++; |
|
} |
|
}); |
|
return score; |
|
} |
|
|
|
function displayResults(score) { |
|
const quizScore = document.getElementById('quiz-score'); |
|
const areasToImprove = document.getElementById('areas-to-improve'); |
|
|
|
quizScore.innerHTML = ` |
|
<div class="score-circle">${score}/${quizData.length}</div> |
|
<h3>You have scored</h3> |
|
<p>Performance: ${getPerformanceEvaluation(score, quizData.length)}</p> |
|
`; |
|
quizScore.style.display = 'block'; |
|
|
|
let incorrectQuestions = quizData.filter((question, index) => { |
|
const selectedAnswer = document.querySelector(`input[name="q${index}"]:checked`); |
|
return !selectedAnswer || parseInt(selectedAnswer.value) !== question.correctAnswer; |
|
}); |
|
|
|
if (incorrectQuestions.length > 0) { |
|
let improveHtml = '<h3>Areas to be improved</h3><ol>'; |
|
incorrectQuestions.forEach(question => { |
|
improveHtml += `<li>${question.concept}</li>`; |
|
}); |
|
improveHtml += '</ol>'; |
|
areasToImprove.innerHTML = improveHtml; |
|
areasToImprove.style.display = 'block'; |
|
} |
|
} |
|
|
|
function getPerformanceEvaluation(score, total) { |
|
const percentage = (score / total) * 100; |
|
if (percentage >= 80) return 'Excellent'; |
|
if (percentage >= 60) return 'Good'; |
|
if (percentage >= 40) return 'Average'; |
|
return 'Needs Improvement'; |
|
} |
|
|
|
function goBack() { |
|
window.history.back(); |
|
} |
|
</script> |
|
</body> |
|
</html> |