Neurolingua commited on
Commit
37c46bc
1 Parent(s): 879327a

Update templates/student_quiz.html

Browse files
Files changed (1) hide show
  1. templates/student_quiz.html +481 -442
templates/student_quiz.html CHANGED
@@ -1,443 +1,482 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>SmartLearn - Quiz Generation</title>
7
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
8
- <style>
9
- @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600&display=swap');
10
-
11
- body {
12
- font-family: 'Poppins', sans-serif;
13
- margin: 0;
14
- padding: 0;
15
- display: flex;
16
- justify-content: center;
17
- align-items: center;
18
- min-height: 100vh;
19
- background-image: url('../static/quiz.jpg');
20
- background-size: cover;
21
- background-position: center;
22
- background-attachment: fixed;
23
- }
24
-
25
- .container {
26
- border-radius: 20px;
27
- padding: 40px;
28
- width: 90%;
29
- max-width: 500px;
30
- text-align: center;
31
- position: relative;
32
- z-index: 2;
33
- background: rgba(255, 255, 255, 0.1);
34
- backdrop-filter: blur(10px);
35
- box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37);
36
- border: 1px solid rgba(255, 255, 255, 0.18);
37
- }
38
-
39
- .quiz-form {
40
- padding: 20px;
41
- border-radius: 10px;
42
- }
43
-
44
- .form-group {
45
- margin-bottom: 20px;
46
- text-align: left;
47
- }
48
-
49
- .form-group label {
50
- display: block;
51
- margin-bottom: 5px;
52
- color: #fff;
53
- font-weight: 600;
54
- }
55
-
56
- .form-group input,
57
- .form-group select {
58
- width: 100%;
59
- padding: 10px;
60
- border: none;
61
- border-radius: 5px;
62
- background: rgba(255, 255, 255, 0.8);
63
- color: #000;
64
- font-size: 16px;
65
- }
66
-
67
- .form-group select {
68
- appearance: none;
69
- 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");
70
- background-repeat: no-repeat;
71
- background-position: right 10px center;
72
- background-size: 20px;
73
- }
74
-
75
- .btn {
76
- background-color: #3498db;
77
- color: white;
78
- border: none;
79
- padding: 12px 24px;
80
- border-radius: 30px;
81
- cursor: pointer;
82
- font-size: 18px;
83
- transition: all 0.3s ease;
84
- }
85
-
86
- .btn:hover {
87
- background-color: #2980b9;
88
- transform: translateY(-2px);
89
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
90
- }
91
-
92
- h1, h2, h3 {
93
- color: #fff;
94
- text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
95
- }
96
-
97
- .score-circle {
98
- width: 150px;
99
- height: 150px;
100
- background-color: rgba(52, 152, 219, 0.8);
101
- border-radius: 50%;
102
- display: flex;
103
- justify-content: center;
104
- align-items: center;
105
- margin: 0 auto 30px;
106
- font-size: 36px;
107
- font-weight: bold;
108
- color: white;
109
- box-shadow: 0 5px 15px rgba(52, 152, 219, 0.3);
110
- }
111
-
112
- .areas-to-improve {
113
- background-color: rgba(248, 249, 250, 0.1);
114
- border-radius: 10px;
115
- padding: 20px;
116
- text-align: left;
117
- color: #fff;
118
- }
119
-
120
- .areas-to-improve ol {
121
- padding-left: 20px;
122
- }
123
-
124
- .areas-to-improve li {
125
- margin-bottom: 10px;
126
- }
127
-
128
- .validation-container {
129
- display: none;
130
- justify-content: center;
131
- align-items: center;
132
- flex-direction: column;
133
- }
134
-
135
- .loader {
136
- border: 5px solid rgba(255, 255, 255, 0.3);
137
- border-top: 5px solid #3498db;
138
- border-radius: 50%;
139
- width: 50px;
140
- height: 50px;
141
- animation: spin 1s linear infinite;
142
- }
143
-
144
- @keyframes spin {
145
- 0% { transform: rotate(0deg); }
146
- 100% { transform: rotate(360deg); }
147
- }
148
-
149
- .validation-text {
150
- margin-top: 20px;
151
- font-size: 18px;
152
- color: #fff;
153
- }
154
-
155
- .correct { color: #2ecc71; }
156
- .incorrect { color: #e74c3c; }
157
- #areas-to-improve { margin-top: 20px; }
158
-
159
- .options li {
160
- display: flex;
161
- align-items: center;
162
- margin-bottom: 10px;
163
- color: #fff;
164
- }
165
-
166
- .options li input {
167
- margin-right: 10px;
168
- }
169
-
170
- .back-button {
171
- position: absolute;
172
- top: 20px;
173
- left: 20px;
174
- background-color: #6c757d;
175
- color: white;
176
- border: none;
177
- padding: 10px 20px;
178
- border-radius: 30px;
179
- cursor: pointer;
180
- transition: background-color 0.3s;
181
- font-size: 16px;
182
- }
183
-
184
- .back-button:hover {
185
- background-color: #5a6268;
186
- }
187
-
188
- .fade-in {
189
- animation: fadeIn 0.5s ease-in-out;
190
- }
191
-
192
- @keyframes fadeIn {
193
- from { opacity: 0; transform: translateY(20px); }
194
- to { opacity: 1; transform: translateY(0); }
195
- }
196
-
197
- .icon {
198
- margin-right: 10px;
199
- }
200
-
201
- .loading-animation {
202
- display: flex;
203
- flex-direction: column;
204
- align-items: center;
205
- justify-content: center;
206
- margin-top: 20px;
207
- }
208
-
209
- .loading-animation p {
210
- margin-top: 10px;
211
- color: #fff;
212
- font-weight: 600;
213
- }
214
- </style>
215
- </head>
216
- <body>
217
- <div class="container fade-in">
218
- <button class="back-button" onclick="goBack()"><i class="fas fa-arrow-left"></i> Back</button>
219
- <h1><i class="fas fa-graduation-cap icon"></i>Generate Your Custom Quiz</h1>
220
- <form class="quiz-form">
221
- <div class="form-group">
222
- <label for="subject"><i class="fas fa-book icon"></i>Subject:</label>
223
- <input type="text" id="subject" name="subject" required>
224
- </div>
225
- <div class="form-group">
226
- <label for="topic"><i class="fas fa-lightbulb icon"></i>Topic:</label>
227
- <input type="text" id="topic" name="topic" required>
228
- </div>
229
- <div class="form-group">
230
- <label for="num-questions"><i class="fas fa-list-ol icon"></i>Number of Questions:</label>
231
- <select id="num-questions" name="num-questions">
232
- <option value="5">5</option>
233
- <option value="10">10</option>
234
- <option value="15">15</option>
235
- <option value="20">20</option>
236
- </select>
237
- </div>
238
- <div class="form-group">
239
- <label for="difficulty"><i class="fas fa-signal icon"></i>Difficulty Level:</label>
240
- <select id="difficulty" name="difficulty">
241
- <option value="easy">Easy</option>
242
- <option value="medium">Medium</option>
243
- <option value="hard">Hard</option>
244
- </select>
245
- </div>
246
- <button type="submit" class="btn"><i class="fas fa-magic icon"></i>Generate Quiz</button>
247
- </form>
248
-
249
- <div id="loading-animation" class="loading-animation" style="display: none;">
250
- <div class="loader"></div>
251
- <p>Generating Quiz...</p>
252
- </div>
253
-
254
- <div id="quiz-result" class="quiz-result" style="display: none;">
255
- <!-- Quiz questions will be dynamically inserted here -->
256
- </div>
257
- <div id="validation-container" class="validation-container">
258
- <div id="loader" class="loader"></div>
259
- <div id="validation-text" class="validation-text">Validating...</div>
260
- </div>
261
- <div id="quiz-score" style="display: none;"></div>
262
- <div id="areas-to-improve" class="areas-to-improve" style="display: none;"></div>
263
- </div>
264
-
265
-
266
- <script>
267
- let quizData = [];
268
- let studentId = ''; // Assume you set this variable with the logged-in student's ID.
269
-
270
- document.querySelector('.quiz-form').addEventListener('submit', function(e) {
271
- e.preventDefault();
272
- const formData = new FormData(this);
273
- const data = {
274
- subject: formData.get('subject'),
275
- topic: formData.get('topic'),
276
- 'num-questions': formData.get('num-questions'),
277
- difficulty: formData.get('difficulty')
278
- };
279
- fetch('/generate_quiz', {
280
- method: 'POST',
281
- headers: {
282
- 'Content-Type': 'application/json',
283
- },
284
- body: JSON.stringify(data)
285
- })
286
- .then(response => response.json())
287
- .then(data => {
288
- quizData = parseQuizData(data.quiz);
289
- showQuiz(quizData);
290
- })
291
- .catch(error => console.error('Error:', error));
292
- });
293
-
294
- function parseQuizData(quizString) {
295
- const questions = quizString.split('Question:').filter(q => q.trim() !== '');
296
- return questions.map((question, index) => {
297
- const [questionText, ...options] = question.split('\n').filter(line => line.trim() !== '');
298
- const answerLine = options.pop();
299
- const correctAnswer = parseInt(answerLine.split(':')[1].trim());
300
- return {
301
- id: index + 1,
302
- text: questionText.trim(),
303
- options: options.map(opt => opt.replace('<<o>>', '').trim()),
304
- correctAnswer: correctAnswer,
305
- concept: questionText.match(/\[(.*?)\]/)[1]
306
- };
307
- });
308
- }
309
-
310
- function showQuiz(questions) {
311
- const quizResult = document.getElementById('quiz-result');
312
- let quizHtml = '<h2>Your Custom Quiz</h2>';
313
-
314
- questions.forEach((question, index) => {
315
- quizHtml += `
316
- <div class="question fade-in">
317
- <h3>${question.id}. ${question.text}</h3>
318
- <ul class="options">
319
- `;
320
-
321
- question.options.forEach((option, optionIndex) => {
322
- quizHtml += `
323
- <li>
324
- <input type="radio" name="q${index}" value="${optionIndex + 1}" id="q${index}o${optionIndex}">
325
- <label for="q${index}o${optionIndex}">${option}</label>
326
- </li>
327
- `;
328
- });
329
-
330
- quizHtml += `
331
- </ul>
332
- </div>
333
- `;
334
- });
335
-
336
- quizHtml += '<button onclick="submitQuiz()" class="btn">Submit Quiz</button>';
337
-
338
- quizResult.innerHTML = quizHtml;
339
- quizResult.style.display = 'block';
340
- }
341
-
342
- function submitQuiz() {
343
- const validationContainer = document.getElementById('validation-container');
344
- const quizResult = document.getElementById('quiz-result');
345
- const quizScore = document.getElementById('quiz-score');
346
- const areasToImprove = document.getElementById('areas-to-improve');
347
-
348
- quizResult.style.display = 'none';
349
- validationContainer.style.display = 'block';
350
-
351
- setTimeout(() => {
352
- validationContainer.style.display = 'none';
353
- const score = calculateScore();
354
- displayResults(score);
355
-
356
- // Get areas to improve
357
- let improveAreas = [];
358
- let incorrectQuestions = quizData.filter((question, index) => {
359
- const selectedAnswer = document.querySelector(`input[name="q${index}"]:checked`);
360
- return !selectedAnswer || parseInt(selectedAnswer.value) !== question.correctAnswer;
361
- });
362
-
363
- if (incorrectQuestions.length > 0) {
364
- improveAreas = incorrectQuestions.map(question => question.concept);
365
- }
366
-
367
- // Ensure studentId is set correctly
368
- const studentId = '[email protected]'; // Replace with actual student ID
369
-
370
- // Send areas to improve to the backend
371
- fetch('/update_student_areas', {
372
- method: 'POST',
373
- headers: {
374
- 'Content-Type': 'application/json',
375
- },
376
- body: JSON.stringify({ student_id: studentId, areas_to_improve: improveAreas })
377
- })
378
- .then(response => response.json())
379
- .then(data => {
380
- if (data.status === 'success') {
381
- console.log('Student areas to improve updated successfully.');
382
- } else {
383
- console.error('Failed to update student areas to improve.');
384
- }
385
- })
386
- .catch(error => console.error('Error:', error));
387
-
388
- }, 2000);
389
- }
390
-
391
-
392
- function calculateScore() {
393
- let score = 0;
394
- quizData.forEach((question, index) => {
395
- const selectedAnswer = document.querySelector(`input[name="q${index}"]:checked`);
396
- if (selectedAnswer && parseInt(selectedAnswer.value) === question.correctAnswer) {
397
- score++;
398
- }
399
- });
400
- return score;
401
- }
402
-
403
- function displayResults(score) {
404
- const quizScore = document.getElementById('quiz-score');
405
- const areasToImprove = document.getElementById('areas-to-improve');
406
-
407
- quizScore.innerHTML = `
408
- <div class="score-circle">${score}/${quizData.length}</div>
409
- <h3>You have scored</h3>
410
- <p>Performance: ${getPerformanceEvaluation(score, quizData.length)}</p>
411
- `;
412
- quizScore.style.display = 'block';
413
-
414
- let incorrectQuestions = quizData.filter((question, index) => {
415
- const selectedAnswer = document.querySelector(`input[name="q${index}"]:checked`);
416
- return !selectedAnswer || parseInt(selectedAnswer.value) !== question.correctAnswer;
417
- });
418
-
419
- if (incorrectQuestions.length > 0) {
420
- let improveHtml = '<h3>Areas to be improved</h3><ol>';
421
- incorrectQuestions.forEach(question => {
422
- improveHtml += `<li>${question.concept}</li>`;
423
- });
424
- improveHtml += '</ol>';
425
- areasToImprove.innerHTML = improveHtml;
426
- areasToImprove.style.display = 'block';
427
- }
428
- }
429
-
430
- function getPerformanceEvaluation(score, total) {
431
- const percentage = (score / total) * 100;
432
- if (percentage >= 80) return 'Excellent';
433
- if (percentage >= 60) return 'Good';
434
- if (percentage >= 40) return 'Average';
435
- return 'Needs Improvement';
436
- }
437
-
438
- function goBack() {
439
- window.history.back();
440
- }
441
- </script>
442
- </body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
443
  </html>
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>SmartLearn - Quiz Generation</title>
7
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
8
+ <style>
9
+ @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600&display=swap');
10
+
11
+ body {
12
+ font-family: 'Poppins', sans-serif;
13
+ margin: 0;
14
+ padding: 0;
15
+ display: flex;
16
+ justify-content: center;
17
+ align-items: center;
18
+ min-height: 100vh;
19
+ background-image: url('../static/quiz.jpg');
20
+ background-size: cover;
21
+ background-position: center;
22
+ background-attachment: fixed;
23
+ }
24
+
25
+ .container {
26
+ border-radius: 20px;
27
+ padding: 40px;
28
+ width: 90%;
29
+ max-width: 500px;
30
+ text-align: center;
31
+ position: relative;
32
+ z-index: 2;
33
+ background: rgba(255, 255, 255, 0.1);
34
+ backdrop-filter: blur(10px);
35
+ box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37);
36
+ border: 1px solid rgba(255, 255, 255, 0.18);
37
+ }
38
+
39
+ .quiz-form {
40
+ padding: 20px;
41
+ border-radius: 10px;
42
+ }
43
+
44
+ .form-group {
45
+ margin-bottom: 20px;
46
+ text-align: left;
47
+ }
48
+
49
+ .form-group label {
50
+ display: block;
51
+ margin-bottom: 5px;
52
+ color: #fff;
53
+ font-weight: 600;
54
+ }
55
+
56
+ .form-group input,
57
+ .form-group select {
58
+ width: 100%;
59
+ padding: 10px;
60
+ border: none;
61
+ border-radius: 5px;
62
+ background: rgba(255, 255, 255, 0.8);
63
+ color: #000;
64
+ font-size: 16px;
65
+ }
66
+
67
+ .form-group select {
68
+ appearance: none;
69
+ 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");
70
+ background-repeat: no-repeat;
71
+ background-position: right 10px center;
72
+ background-size: 20px;
73
+ }
74
+
75
+ .btn {
76
+ background-color: #3498db;
77
+ color: white;
78
+ border: none;
79
+ padding: 12px 24px;
80
+ border-radius: 30px;
81
+ cursor: pointer;
82
+ font-size: 18px;
83
+ transition: all 0.3s ease;
84
+ }
85
+
86
+ .btn:hover {
87
+ background-color: #2980b9;
88
+ transform: translateY(-2px);
89
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
90
+ }
91
+
92
+ h1, h2, h3 {
93
+ color: #fff;
94
+ text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
95
+ }
96
+
97
+ .score-circle {
98
+ width: 150px;
99
+ height: 150px;
100
+ background-color: rgba(52, 152, 219, 0.8);
101
+ border-radius: 50%;
102
+ display: flex;
103
+ justify-content: center;
104
+ align-items: center;
105
+ margin: 0 auto 30px;
106
+ font-size: 36px;
107
+ font-weight: bold;
108
+ color: white;
109
+ box-shadow: 0 5px 15px rgba(52, 152, 219, 0.3);
110
+ }
111
+
112
+ .areas-to-improve {
113
+ background-color: rgba(248, 249, 250, 0.1);
114
+ border-radius: 10px;
115
+ padding: 20px;
116
+ text-align: left;
117
+ color: #fff;
118
+ }
119
+
120
+ .areas-to-improve ol {
121
+ padding-left: 20px;
122
+ }
123
+
124
+ .areas-to-improve li {
125
+ margin-bottom: 10px;
126
+ }
127
+
128
+ .validation-container {
129
+ display: none;
130
+ justify-content: center;
131
+ align-items: center;
132
+ flex-direction: column;
133
+ }
134
+
135
+ .loader {
136
+ border: 5px solid rgba(255, 255, 255, 0.3);
137
+ border-top: 5px solid #3498db;
138
+ border-radius: 50%;
139
+ width: 50px;
140
+ height: 50px;
141
+ animation: spin 1s linear infinite;
142
+ }
143
+
144
+ @keyframes spin {
145
+ 0% { transform: rotate(0deg); }
146
+ 100% { transform: rotate(360deg); }
147
+ }
148
+
149
+ .validation-text {
150
+ margin-top: 20px;
151
+ font-size: 18px;
152
+ color: #fff;
153
+ }
154
+
155
+ .correct { color: #2ecc71; }
156
+ .incorrect { color: #e74c3c; }
157
+ #areas-to-improve { margin-top: 20px; }
158
+
159
+ .options li {
160
+ display: flex;
161
+ align-items: center;
162
+ margin-bottom: 10px;
163
+ color: #fff;
164
+ }
165
+
166
+ .options li input {
167
+ margin-right: 10px;
168
+ }
169
+
170
+ .back-button {
171
+ position: absolute;
172
+ top: 20px;
173
+ left: 20px;
174
+ background-color: #6c757d;
175
+ color: white;
176
+ border: none;
177
+ padding: 10px 20px;
178
+ border-radius: 30px;
179
+ cursor: pointer;
180
+ transition: background-color 0.3s;
181
+ font-size: 16px;
182
+ }
183
+
184
+ .back-button:hover {
185
+ background-color: #5a6268;
186
+ }
187
+
188
+ .fade-in {
189
+ animation: fadeIn 0.5s ease-in-out;
190
+ }
191
+
192
+ @keyframes fadeIn {
193
+ from { opacity: 0; transform: translateY(20px); }
194
+ to { opacity: 1; transform: translateY(0); }
195
+ }
196
+
197
+ .icon {
198
+ margin-right: 10px;
199
+ }
200
+
201
+ .loading-animation {
202
+ display: flex;
203
+ flex-direction: column;
204
+ align-items: center;
205
+ justify-content: center;
206
+ margin-top: 20px;
207
+ }
208
+
209
+ .loading-animation p {
210
+ margin-top: 10px;
211
+ color: #fff;
212
+ font-weight: 600;
213
+ }
214
+
215
+ @keyframes pulse {
216
+ 0% { transform: scale(1); }
217
+ 50% { transform: scale(1.1); }
218
+ 100% { transform: scale(1); }
219
+ }
220
+
221
+ .loading-icon {
222
+ font-size: 48px;
223
+ color: #3498db;
224
+ animation: pulse 1.5s infinite;
225
+ }
226
+ </style>
227
+ </head>
228
+ <body>
229
+ <div class="container fade-in">
230
+ <button class="back-button" onclick="goBack()"><i class="fas fa-arrow-left"></i> Back</button>
231
+ <h1><i class="fas fa-graduation-cap icon"></i>Generate Your Custom Quiz</h1>
232
+ <form class="quiz-form">
233
+ <div class="form-group">
234
+ <label for="subject"><i class="fas fa-book icon"></i>Subject:</label>
235
+ <input type="text" id="subject" name="subject" required>
236
+ </div>
237
+ <div class="form-group">
238
+ <label for="topic"><i class="fas fa-lightbulb icon"></i>Topic:</label>
239
+ <input type="text" id="topic" name="topic" required>
240
+ </div>
241
+ <div class="form-group">
242
+ <label for="num-questions"><i class="fas fa-list-ol icon"></i>Number of Questions:</label>
243
+ <select id="num-questions" name="num-questions">
244
+ <option value="5">5</option>
245
+ <option value="10">10</option>
246
+ <option value="15">15</option>
247
+ <option value="20">20</option>
248
+ </select>
249
+ </div>
250
+ <div class="form-group">
251
+ <label for="difficulty"><i class="fas fa-signal icon"></i>Difficulty Level:</label>
252
+ <select id="difficulty" name="difficulty">
253
+ <option value="easy">Easy</option>
254
+ <option value="medium">Medium</option>
255
+ <option value="hard">Hard</option>
256
+ </select>
257
+ </div>
258
+ <button type="submit" class="btn"><i class="fas fa-magic icon"></i>Generate Quiz</button>
259
+ </form>
260
+
261
+ <div id="loading-animation" class="loading-animation" style="display: none;">
262
+ <i class="fas fa-cog loading-icon"></i>
263
+ <p id="loading-text">Generating Quiz...</p>
264
+ </div>
265
+
266
+ <div id="quiz-result" class="quiz-result" style="display: none;">
267
+ <!-- Quiz questions will be dynamically inserted here -->
268
+ </div>
269
+ <div id="validation-container" class="validation-container">
270
+ <div id="loader" class="loader"></div>
271
+ <div id="validation-text" class="validation-text">Validating...</div>
272
+ </div>
273
+ <div id="quiz-score" style="display: none;"></div>
274
+ <div id="areas-to-improve" class="areas-to-improve" style="display: none;"></div>
275
+ </div>
276
+
277
+ <script>
278
+ let quizData = [];
279
+ let studentId = '[email protected]'; // Assume you set this variable with the logged-in student's ID.
280
+
281
+ document.querySelector('.quiz-form').addEventListener('submit', function(e) {
282
+ e.preventDefault();
283
+ const formData = new FormData(this);
284
+ const data = {
285
+ subject: formData.get('subject'),
286
+ topic: formData.get('topic'),
287
+ 'num-questions': formData.get('num-questions'),
288
+ difficulty: formData.get('difficulty')
289
+ };
290
+
291
+ // Hide the form and show loading animation
292
+ this.style.display = 'none';
293
+ document.getElementById('loading-animation').style.display = 'flex';
294
+
295
+ let loadingTexts = [
296
+ "Crafting challenging questions...",
297
+ "Digging deep into the subject...",
298
+ "Polishing the perfect quiz for you...",
299
+ "Almost there, finalizing details..."
300
+ ];
301
+ let currentTextIndex = 0;
302
+
303
+ // Start the loading text animation
304
+ const loadingInterval = setInterval(() => {
305
+ document.getElementById('loading-text').textContent = loadingTexts[currentTextIndex];
306
+ currentTextIndex = (currentTextIndex + 1) % loadingTexts.length;
307
+ }, 3000);
308
+
309
+ fetch('/generate_quiz', {
310
+ method: 'POST',
311
+ headers: {
312
+ 'Content-Type': 'application/json',
313
+ },
314
+ body: JSON.stringify(data)
315
+ })
316
+ .then(response => response.json())
317
+ .then(data => {
318
+ // Clear the loading interval
319
+ clearInterval(loadingInterval);
320
+
321
+ // Hide loading animation
322
+ document.getElementById('loading-animation').style.display = 'none';
323
+
324
+ quizData = parseQuizData(data.quiz);
325
+ showQuiz(quizData);
326
+ })
327
+ .catch(error => {
328
+ console.error('Error:', error);
329
+ // Clear the loading interval
330
+ clearInterval(loadingInterval);
331
+ // Hide loading animation and show error message
332
+ document.getElementById('loading-animation').style.display = 'none';
333
+ alert('An error occurred while generating the quiz. Please try again.');
334
+ });
335
+ });
336
+
337
+ function parseQuizData(quizString) {
338
+ const questions = quizString.split('Question:').filter(q => q.trim() !== '');
339
+ return questions.map((question, index) => {
340
+ const [questionText, ...options] = question.split('\n').filter(line => line.trim() !== '');
341
+ const answerLine = options.pop();
342
+ const correctAnswer = parseInt(answerLine.split(':')[1].trim());
343
+ return {
344
+ id: index + 1,
345
+ text: questionText.trim(),
346
+ options: options.map(opt => opt.replace('<<o>>', '').trim()),
347
+ correctAnswer: correctAnswer,
348
+ concept: questionText.match(/\[(.*?)\]/)[1]
349
+ };
350
+ });
351
+ }
352
+
353
+ function showQuiz(questions) {
354
+ const quizResult = document.getElementById('quiz-result');
355
+ let quizHtml = '<h2>Your Custom Quiz</h2>';
356
+
357
+ questions.forEach((question, index) => {
358
+ quizHtml += `
359
+ <div class="question fade-in">
360
+ <h3>${question.id}. ${question.text}</h3>
361
+ <ul class="options">
362
+ `;
363
+
364
+ question.options.forEach((option, optionIndex) => {
365
+ quizHtml += `
366
+ <li>
367
+ <input type="radio" name="q${index}" value="${optionIndex + 1}" id="q${index}o${optionIndex}">
368
+ <label for="q${index}o${optionIndex}">${option}</label>
369
+ </li>
370
+ `;
371
+ });
372
+
373
+ quizHtml += `
374
+ </ul>
375
+ </div>
376
+ `;
377
+ });
378
+
379
+ quizHtml += '<button onclick="submitQuiz()" class="btn">Submit Quiz</button>';
380
+
381
+ quizResult.innerHTML = quizHtml;
382
+ quizResult.style.display = 'block';
383
+ }
384
+
385
+ function submitQuiz() {
386
+ const validationContainer = document.getElementById('validation-container');
387
+ const quizResult = document.getElementById('quiz-result');
388
+ const quizScore = document.getElementById('quiz-score');
389
+ const areasToImprove = document.getElementById('areas-to-improve');
390
+
391
+ quizResult.style.display = 'none';
392
+ validationContainer.style.display = 'flex';
393
+
394
+ setTimeout(() => {
395
+ validationContainer.style.display = 'none';
396
+ const score = calculateScore();
397
+ displayResults(score);
398
+
399
+ // Get areas to improve
400
+ let improveAreas = [];
401
+ let incorrectQuestions = quizData.filter((question, index) => {
402
+ const selectedAnswer = document.querySelector(`input[name="q${index}"]:checked`);
403
+ return !selectedAnswer || parseInt(selectedAnswer.value) !== question.correctAnswer;
404
+ });
405
+
406
+ if (incorrectQuestions.length > 0) {
407
+ improveAreas = incorrectQuestions.map(question => question.concept);
408
+ }
409
+
410
+ // Send areas to improve to the backend
411
+ fetch('/update_student_areas', {
412
+ method: 'POST',
413
+ headers: {
414
+ 'Content-Type': 'application/json',
415
+ },
416
+ body: JSON.stringify({ student_id: studentId, areas_to_improve: improveAreas })
417
+ })
418
+ .then(response => response.json())
419
+ .then(data => {
420
+ if (data.status === 'success') {
421
+ console.log('Student areas to improve updated successfully.');
422
+ } else {
423
+ console.error('Failed to update student areas to improve.');
424
+ }
425
+ })
426
+ .catch(error => console.error('Error:', error));
427
+
428
+ }, 2000);
429
+ }
430
+
431
+ function calculateScore() {
432
+ let score = 0;
433
+ quizData.forEach((question, index) => {
434
+ const selectedAnswer = document.querySelector(`input[name="q${index}"]:checked`);
435
+ if (selectedAnswer && parseInt(selectedAnswer.value) === question.correctAnswer) {
436
+ score++;
437
+ }
438
+ });
439
+ return score;
440
+ }
441
+
442
+ function displayResults(score) {
443
+ const quizScore = document.getElementById('quiz-score');
444
+ const areasToImprove = document.getElementById('areas-to-improve');
445
+
446
+ quizScore.innerHTML = `
447
+ <div class="score-circle">${score}/${quizData.length}</div>
448
+ <h3>You have scored</h3>
449
+ <p>Performance: ${getPerformanceEvaluation(score, quizData.length)}</p>
450
+ `;
451
+ quizScore.style.display = 'block';
452
+
453
+ let incorrectQuestions = quizData.filter((question, index) => {
454
+ const selectedAnswer = document.querySelector(`input[name="q${index}"]:checked`);
455
+ return !selectedAnswer || parseInt(selectedAnswer.value) !== question.correctAnswer;
456
+ });
457
+
458
+ if (incorrectQuestions.length > 0) {
459
+ let improveHtml = '<h3>Areas to be improved</h3><ol>';
460
+ incorrectQuestions.forEach(question => {
461
+ improveHtml += `<li>${question.concept}</li>`;
462
+ });
463
+ improveHtml += '</ol>';
464
+ areasToImprove.innerHTML = improveHtml;
465
+ areasToImprove.style.display = 'block';
466
+ }
467
+ }
468
+
469
+ function getPerformanceEvaluation(score, total) {
470
+ const percentage = (score / total) * 100;
471
+ if (percentage >= 80) return 'Excellent';
472
+ if (percentage >= 60) return 'Good';
473
+ if (percentage >= 40) return 'Average';
474
+ return 'Needs Improvement';
475
+ }
476
+
477
+ function goBack() {
478
+ window.history.back();
479
+ }
480
+ </script>
481
+ </body>
482
  </html>