Harshal V commited on
Commit
9630b25
·
0 Parent(s):

Initial Commit

Browse files
Files changed (7) hide show
  1. .gitignore +3 -0
  2. db.py +535 -0
  3. file_upload_vectorize.py +105 -0
  4. main.py +134 -0
  5. session_page.py +270 -0
  6. utils/helpers.py +83 -0
  7. utils/sample_data.py +226 -0
.gitignore ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ # Ignore .env file
2
+ .env
3
+ __pycache__/
db.py ADDED
@@ -0,0 +1,535 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Setup for MongoDB
2
+ from pymongo import MongoClient
3
+ from datetime import datetime
4
+ from werkzeug.security import generate_password_hash
5
+ import os
6
+ from dotenv import load_dotenv
7
+
8
+ load_dotenv()
9
+ MONGO_URI = os.getenv('MONGO_URI')
10
+
11
+ client = MongoClient(MONGO_URI)
12
+ try:
13
+ client.admin.command('ping')
14
+ print("MongoDB connection successful")
15
+ except Exception as e:
16
+ print(f"MongoDB connection failed: {e}")
17
+
18
+ db = client['novascholar_db']
19
+
20
+ # Define the course schema
21
+ course_schema = {
22
+ "bsonType": "object",
23
+ "required": ["course_id", "title", "description", "faculty", "faculty_id", "duration", "created_at"],
24
+ "properties": {
25
+ "course_id": {
26
+ "bsonType": "string",
27
+ "description": "Unique identifier for the course"
28
+ },
29
+ "title": {
30
+ "bsonType": "string",
31
+ "description": "Title of the course"
32
+ },
33
+ "description": {
34
+ "bsonType": "string",
35
+ "description": "Description of the course"
36
+ },
37
+ "faculty": {
38
+ "bsonType": "string",
39
+ "description": "Name of the faculty"
40
+ },
41
+ "duration": {
42
+ "bsonType": "string",
43
+ "description": "Duration of the course"
44
+ },
45
+ "created_at": {
46
+ "bsonType": "date",
47
+ "description": "Date when the course was created"
48
+ },
49
+ "sessions": {
50
+ "bsonType": "array",
51
+ "description": "List of sessions associated with the course",
52
+ "items": {
53
+ "bsonType": "object",
54
+ "required": ["session_id", "title", "date", "status", "created_at"],
55
+ "properties": {
56
+ "session_id": {
57
+ "bsonType": "string",
58
+ "description": "Unique identifier for the session"
59
+ },
60
+ "title": {
61
+ "bsonType": "string",
62
+ "description": "Title of the session"
63
+ },
64
+ "date": {
65
+ "bsonType": "date",
66
+ "description": "Date of the session"
67
+ },
68
+ "status": {
69
+ "bsonType": "string",
70
+ "description": "Status of the session (e.g., completed, upcoming)"
71
+ },
72
+ "created_at": {
73
+ "bsonType": "date",
74
+ "description": "Date when the session was created"
75
+ },
76
+ "pre_class": {
77
+ "bsonType": "object",
78
+ "description": "Pre-class segment data",
79
+ "properties": {
80
+ "resources": {
81
+ "bsonType": "array",
82
+ "description": "List of pre-class resources",
83
+ "items": {
84
+ "bsonType": "object",
85
+ "required": ["type", "title", "url"],
86
+ "properties": {
87
+ "type": {
88
+ "bsonType": "string",
89
+ "description": "Type of resource (e.g., pdf, video)"
90
+ },
91
+ "title": {
92
+ "bsonType": "string",
93
+ "description": "Title of the resource"
94
+ },
95
+ "url": {
96
+ "bsonType": "string",
97
+ "description": "URL of the resource"
98
+ },
99
+ "vector": {
100
+ "bsonType": "array",
101
+ "description": "Vector representation of the resource",
102
+ "items": {
103
+ "bsonType": "double"
104
+ }
105
+ }
106
+ }
107
+ }
108
+ },
109
+ "completion_required": {
110
+ "bsonType": "bool",
111
+ "description": "Indicates if completion of pre-class resources is required"
112
+ }
113
+ }
114
+ },
115
+ "in_class": {
116
+ "bsonType": "object",
117
+ "description": "In-class segment data",
118
+ "properties": {
119
+ "topics": {
120
+ "bsonType": "array",
121
+ "description": "List of topics covered in the session",
122
+ "items": {
123
+ "bsonType": "string"
124
+ }
125
+ },
126
+ "quiz": {
127
+ "bsonType": "object",
128
+ "description": "Quiz data",
129
+ "properties": {
130
+ "title": {
131
+ "bsonType": "string",
132
+ "description": "Title of the quiz"
133
+ },
134
+ "questions": {
135
+ "bsonType": "int",
136
+ "description": "Number of questions in the quiz"
137
+ },
138
+ "duration": {
139
+ "bsonType": "int",
140
+ "description": "Duration of the quiz in minutes"
141
+ }
142
+ }
143
+ },
144
+ "polls": {
145
+ "bsonType": "array",
146
+ "description": "List of polls conducted during the session",
147
+ "items": {
148
+ "bsonType": "object",
149
+ "required": ["question", "options"],
150
+ "properties": {
151
+ "question": {
152
+ "bsonType": "string",
153
+ "description": "Poll question"
154
+ },
155
+ "options": {
156
+ "bsonType": "array",
157
+ "description": "List of poll options",
158
+ "items": {
159
+ "bsonType": "string"
160
+ }
161
+ },
162
+ "responses": {
163
+ "bsonType": "object",
164
+ "description": "Responses to the poll",
165
+ "additionalProperties": {
166
+ "bsonType": "int"
167
+ }
168
+ }
169
+ }
170
+ }
171
+ }
172
+ }
173
+ },
174
+ "post_class": {
175
+ "bsonType": "object",
176
+ "description": "Post-class segment data",
177
+ "properties": {
178
+ "assignments": {
179
+ "bsonType": "array",
180
+ "description": "List of assignments",
181
+ "items": {
182
+ "bsonType": "object",
183
+ "required": ["id", "title", "due_date", "status"],
184
+ "properties": {
185
+ "id": {
186
+ "bsonType": "int",
187
+ "description": "Assignment ID"
188
+ },
189
+ "title": {
190
+ "bsonType": "string",
191
+ "description": "Title of the assignment"
192
+ },
193
+ "due_date": {
194
+ "bsonType": "date",
195
+ "description": "Due date of the assignment"
196
+ },
197
+ "status": {
198
+ "bsonType": "string",
199
+ "description": "Status of the assignment (e.g., pending, completed)"
200
+ },
201
+ "submissions": {
202
+ "bsonType": "array",
203
+ "description": "List of submissions",
204
+ "items": {
205
+ "bsonType": "object",
206
+ "required": ["student_id", "file_url", "submitted_at"],
207
+ "properties": {
208
+ "student_id": {
209
+ "bsonType": "string",
210
+ "description": "ID of the student who submitted the assignment"
211
+ },
212
+ "file_url": {
213
+ "bsonType": "string",
214
+ "description": "URL of the submitted file"
215
+ },
216
+ "submitted_at": {
217
+ "bsonType": "date",
218
+ "description": "Date when the assignment was submitted"
219
+ }
220
+ }
221
+ }
222
+ }
223
+ }
224
+ }
225
+ }
226
+ }
227
+ }
228
+ }
229
+ }
230
+ }
231
+ }
232
+ }
233
+
234
+ # Create the collection with the schema
235
+ # db.create_collection("courses_collection2", validator={"$jsonSchema": course_schema})
236
+
237
+ # sample_course = {
238
+ # "course_id": "CS101",
239
+ # "title": "Introduction to Computer Science",
240
+ # "description": "This course covers the basics of computer science and programming.",
241
+ # "faculty": "Dr. John Doe",
242
+ # "faculty_id": "F101",
243
+ # "duration": "10 weeks",
244
+ # "created_at": datetime.utcnow(),
245
+ # "sessions": [
246
+ # {
247
+ # "session_id": "S101",
248
+ # "title": "Introduction to Programming Fundamentals",
249
+ # "date": datetime.utcnow() - timedelta(days=7),
250
+ # "status": "completed",
251
+ # "created_at": datetime.utcnow() - timedelta(days=7),
252
+ # "pre_class": {
253
+ # "resources": [
254
+ # {
255
+ # "type": "pdf",
256
+ # "title": "Introduction to Python Basics",
257
+ # "url": "/assets/python_basics.pdf",
258
+ # "vector": [0.1, 0.2, 0.3] # Example vector
259
+ # }
260
+ # ],
261
+ # "completion_required": True
262
+ # },
263
+ # "in_class": {
264
+ # "topics": ["Variables", "Data Types", "Basic Operations"],
265
+ # "quiz": {
266
+ # "title": "Python Basics Quiz",
267
+ # "questions": 5,
268
+ # "duration": 15
269
+ # },
270
+ # "polls": [
271
+ # {
272
+ # "question": "How comfortable are you with Python syntax?",
273
+ # "options": ["Very", "Somewhat", "Not at all"],
274
+ # "responses": {"Very": 10, "Somewhat": 5, "Not at all": 2}
275
+ # }
276
+ # ]
277
+ # },
278
+ # "post_class": {
279
+ # "assignments": [
280
+ # {
281
+ # "id": 1,
282
+ # "title": "Basic Python Programs",
283
+ # "due_date": datetime.utcnow() + timedelta(days=2),
284
+ # "status": "pending",
285
+ # "submissions": []
286
+ # }
287
+ # ]
288
+ # }
289
+ # },
290
+ # {
291
+ # "session_id": "S102",
292
+ # "title": "Control Flow and Functions",
293
+ # "date": datetime.utcnow() - timedelta(days=3),
294
+ # "status": "completed",
295
+ # "created_at": datetime.utcnow() - timedelta(days=3),
296
+ # "pre_class": {
297
+ # "resources": [
298
+ # {
299
+ # "type": "pdf",
300
+ # "title": "Control Flow in Python",
301
+ # "url": "/assets/control_flow.pdf",
302
+ # "vector": [0.4, 0.5, 0.6] # Example vector
303
+ # }
304
+ # ],
305
+ # "completion_required": True
306
+ # },
307
+ # "in_class": {
308
+ # "topics": ["If-else statements", "Loops", "Function definitions"],
309
+ # "quiz": {
310
+ # "title": "Control Flow Quiz",
311
+ # "questions": 8,
312
+ # "duration": 20
313
+ # },
314
+ # "polls": [
315
+ # {
316
+ # "question": "Which loop type do you find more intuitive?",
317
+ # "options": ["For loops", "While loops", "Both"],
318
+ # "responses": {"For loops": 12, "While loops": 8, "Both": 10}
319
+ # }
320
+ # ]
321
+ # },
322
+ # "post_class": {
323
+ # "assignments": [
324
+ # {
325
+ # "id": 2,
326
+ # "title": "Function Implementation Exercise",
327
+ # "due_date": datetime.utcnow() + timedelta(days=4),
328
+ # "status": "pending",
329
+ # "submissions": []
330
+ # }
331
+ # ]
332
+ # }
333
+ # }
334
+ # ]
335
+ # }
336
+ courses_collection2 = db['courses_collection2']
337
+
338
+ # courses_collection2.insert_one(sample_course)
339
+ # print("Sample course inserted successfully!")
340
+
341
+
342
+ # sessions_collection.insert_one(session_data)
343
+ # sessions_collection.delete_one({"session_id": "S101"})
344
+
345
+ # course_id = "C101"
346
+ # sessions = sessions_collection.find({"course_id": course_id})
347
+ # for session in sessions:
348
+ # print(session)
349
+
350
+
351
+ # Define the users schema
352
+ users_schema = {
353
+ "bsonType": "object",
354
+ "required": ["user_id", "username", "password", "role", "created_at"],
355
+ "properties": {
356
+ "user_id": {
357
+ "bsonType": "string",
358
+ "description": "Unique identifier for the user"
359
+ },
360
+ "username": {
361
+ "bsonType": "string",
362
+ "description": "Name of the User"
363
+ },
364
+ "password": {
365
+ "bsonType": "string",
366
+ "description": "Password of the user"
367
+ },
368
+ "role": {
369
+ "bsonType": "string",
370
+ "description": "Type of user (e.g., student, faculty)"
371
+ },
372
+ "created_at": {
373
+ "bsonType": "date",
374
+ "description": "Date when the user was created"
375
+ }
376
+ }
377
+ }
378
+ # Create the collection with the schema
379
+ # db.create_collection("users", validator={"$jsonSchema": users_schema})
380
+ users_collection = db['users']
381
+
382
+ # sample_user = {
383
+ # "user_id": "U103",
384
+ # "username": "Yash Desai",
385
+ # "password": generate_password_hash("yash"),
386
+ # "role": "Faculty",
387
+ # "created_at": datetime.utcnow()
388
+ # }
389
+ # users_collection.insert_one(sample_user)
390
+ # print("Sample user inserted successfully!")
391
+
392
+ # Defining the Student Collection
393
+ student_schema = {
394
+ "bsonType": "object",
395
+ "required": ["SID", "full_name", "password", "enrolled_courses", "created_at"],
396
+ "properties": {
397
+ "SID": {
398
+ "bsonType": "string",
399
+ "description": "Unique identifier for the student"
400
+ },
401
+ "full_name": {
402
+ "bsonType": "string",
403
+ "description": "Full name of the student"
404
+ },
405
+ "password": {
406
+ "bsonType": "string",
407
+ "description": "Hashed password of the student"
408
+ },
409
+ "enrolled_courses": {
410
+ "bsonType": "array",
411
+ "description": "List of courses the student is enrolled in",
412
+ "items": {
413
+ "bsonType": "object",
414
+ "required": ["course_id", "title"],
415
+ "properties": {
416
+ "course_id": {
417
+ "bsonType": "string",
418
+ "description": "Unique identifier for the course"
419
+ },
420
+ "title": {
421
+ "bsonType": "string",
422
+ "description": "Title of the course"
423
+ }
424
+ }
425
+ }
426
+ },
427
+ "created_at": {
428
+ "bsonType": "date",
429
+ "description": "Date when the student was created"
430
+ }
431
+ }
432
+ }
433
+ # Defining the Faculty Collection
434
+ faculty_schema = {
435
+ "bsonType": "object",
436
+ "required": ["TID", "full_name", "password", "courses_taught", "created_at"],
437
+ "properties": {
438
+ "TID": {
439
+ "bsonType": "string",
440
+ "description": "Unique identifier for the faculty"
441
+ },
442
+ "full_name": {
443
+ "bsonType": "string",
444
+ "description": "Full name of the faculty"
445
+ },
446
+ "password": {
447
+ "bsonType": "string",
448
+ "description": "Hashed password of the faculty"
449
+ },
450
+ "courses_taught": {
451
+ "bsonType": "array",
452
+ "description": "List of courses the faculty is teaching",
453
+ "items": {
454
+ "bsonType": "object",
455
+ "required": ["course_id", "title"],
456
+ "properties": {
457
+ "course_id": {
458
+ "bsonType": "string",
459
+ "description": "Unique identifier for the course"
460
+ },
461
+ "title": {
462
+ "bsonType": "string",
463
+ "description": "Title of the course"
464
+ }
465
+ }
466
+ }
467
+ },
468
+ "created_at": {
469
+ "bsonType": "date",
470
+ "description": "Date when the faculty was created"
471
+ }
472
+ }
473
+ }
474
+ # Creating the Collections
475
+ # db.create_collection("students", validator={"$jsonSchema": student_schema})
476
+ # db.create_collection("faculty", validator={"$jsonSchema": faculty_schema})
477
+
478
+ students_collection = db['students']
479
+ faculty_collection = db['faculty']
480
+
481
+ # Inserting Sample Student Data
482
+ # sample_student = {
483
+ # "SID": "S102",
484
+ # "full_name": "Omkar Surve",
485
+ # "password": generate_password_hash("omkar"),
486
+ # "enrolled_courses": [
487
+ # {"course_id": "CS101", "title": "Introduction to Computer Science"}
488
+ # ],
489
+ # "created_at": datetime.utcnow()
490
+ # }
491
+ # # students_collection.insert_one(sample_student)
492
+ # print("Sample student inserted successfully!")
493
+
494
+ # Inserting Sample Faculty Data
495
+ # sample_faculty = {
496
+ # "TID": "F101",
497
+ # "full_name": "Dr. John Doe",
498
+ # "password": generate_password_hash("john"),
499
+ # "courses_taught": [
500
+ # {"course_id": "CS101", "title": "Introduction to Computer Science"}
501
+ # ],
502
+ # "created_at": datetime.utcnow()
503
+ # }
504
+ # faculty_collection.insert_one(sample_faculty)
505
+ # print("Sample faculty inserted successfully!")
506
+
507
+ # Defining the Vector Collection Schema
508
+ vector_schema = {
509
+ "bsonType": "object",
510
+ "required": ["resource_id", "vector"],
511
+ "properties": {
512
+ "resource_id": {
513
+ "bsonType": "objectId",
514
+ "description": "Unique identifier for the resource"
515
+ },
516
+ "vector": {
517
+ "bsonType": "array",
518
+ "description": "Vector representation of the resource",
519
+ "items": {
520
+ "bsonType": "double"
521
+ }
522
+ },
523
+ "text": {
524
+ "bsonType": "string",
525
+ "description": "Text content of the resource"
526
+ },
527
+ "created_at": {
528
+ "bsonType": "date",
529
+ "description": "Date when the vector was created"
530
+ }
531
+ }
532
+ }
533
+ # Creating the Vector Collection
534
+ # db.create_collection("vectors", validator={"$jsonSchema": vector_schema})
535
+ vectors_collection = db['vectors']
file_upload_vectorize.py ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pymongo import MongoClient
2
+ from datetime import datetime
3
+ import openai
4
+ import google.generativeai as genai
5
+ import streamlit as st
6
+ from db import courses_collection2, faculty_collection, students_collection, vectors_collection
7
+ from PIL import Image
8
+ import PyPDF2, docx, io
9
+ from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Document
10
+ from bson import ObjectId
11
+ from dotenv import load_dotenv
12
+ import os
13
+
14
+ load_dotenv()
15
+ MONGO_URI = os.getenv('MONGO_URI')
16
+ OPENAI_KEY = os.getenv('OPENAI_KEY')
17
+ GEMINI_KEY = os.getenv('GEMINI_KEY')
18
+
19
+
20
+ client = MongoClient(MONGO_URI)
21
+ db = client['novascholar_db']
22
+ resources_collection = db['resources']
23
+
24
+ # Configure APIs
25
+ openai.api_key = OPENAI_KEY
26
+ genai.configure(api_key=GEMINI_KEY)
27
+ model = genai.GenerativeModel('gemini-pro')
28
+
29
+ def upload_resource(course_id, session_id, file_name, file_content, material_type):
30
+ # material_data = {
31
+ # "session_id": session_id,
32
+ # "course_id": course_id,
33
+ # "file_name": file_name,
34
+ # "file_content": file_content,
35
+ # "material_type": material_type,
36
+ # "uploaded_at": datetime.utcnow()
37
+ # }
38
+ # return resources_collection.insert_one(material_data)
39
+ resource_id = ObjectId()
40
+
41
+ # Extract text content from the file
42
+ text_content = extract_text_from_file(file_content)
43
+
44
+ # Read the file content
45
+ file_content.seek(0) # Reset the file pointer to the beginning
46
+ original_file_content = file_content.read()
47
+
48
+
49
+ resource_data = {
50
+ "resource_id": resource_id,
51
+ "course_id": course_id,
52
+ "session_id": session_id,
53
+ "file_name": file_name,
54
+ "file_type": file_content.type,
55
+ "text_content": text_content,
56
+ "file_content": original_file_content, # Store the original file content
57
+ "material_type": material_type,
58
+ "uploaded_at": datetime.utcnow()
59
+ }
60
+
61
+ resources_collection.insert_one(resource_data)
62
+ return resource_id
63
+
64
+ def extract_text_from_file(uploaded_file):
65
+ text = ""
66
+ file_type = uploaded_file.type
67
+
68
+ try:
69
+ if file_type == "text/plain":
70
+ text = uploaded_file.getvalue().decode("utf-8")
71
+ elif file_type == "application/pdf":
72
+ pdf_reader = PyPDF2.PdfReader(io.BytesIO(uploaded_file.getvalue()))
73
+ for page in pdf_reader.pages:
74
+ text += page.extract_text() + "\n"
75
+ elif file_type == "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
76
+ doc = docx.Document(io.BytesIO(uploaded_file.getvalue()))
77
+ for para in doc.paragraphs:
78
+ text += para.text + "\n"
79
+ return text
80
+ except Exception as e:
81
+ st.error(f"Error processing file: {str(e)}")
82
+ return None
83
+
84
+ def get_embedding(text):
85
+ response = openai.embeddings.create(
86
+ model="text-embedding-ada-002",
87
+ input=text
88
+ )
89
+ return response.data[0].embedding
90
+
91
+ def create_vector_store(text, resource_id):
92
+ resource_object_id = ObjectId(resource_id)
93
+ document = Document(text=text)
94
+ embedding = get_embedding(text)
95
+
96
+ vector_data = {
97
+ "resource_id": resource_object_id,
98
+ "vector": embedding,
99
+ "text": text,
100
+ "created_at": datetime.utcnow()
101
+ }
102
+
103
+ vectors_collection.insert_one(vector_data)
104
+
105
+ return VectorStoreIndex.from_documents([document])
main.py ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import datetime
3
+ from pathlib import Path
4
+ from utils.sample_data import SAMPLE_COURSES, SAMPLE_SESSIONS
5
+ from session_page import display_session_content
6
+ from db import courses_collection2, faculty_collection, students_collection
7
+ from werkzeug.security import generate_password_hash, check_password_hash
8
+ import hashlib
9
+
10
+ def init_session_state():
11
+ """Initialize session state variables"""
12
+ if 'authenticated' not in st.session_state:
13
+ st.session_state.authenticated = False
14
+ if 'user_type' not in st.session_state:
15
+ st.session_state.user_type = None
16
+ if 'username' not in st.session_state:
17
+ st.session_state.username = None
18
+ if 'selected_course' not in st.session_state:
19
+ st.session_state.selected_course = None
20
+
21
+ def login_user(username, password, user_type):
22
+ """Login user based on credentials"""
23
+ if user_type == "student":
24
+ user = students_collection.find_one({"full_name": username})
25
+ else:
26
+ user = faculty_collection.find_one({"full_name": username})
27
+
28
+ if user and check_password_hash(user['password'], password):
29
+ st.session_state.authenticated = True
30
+ st.session_state.user_type = user_type
31
+ st.session_state.username = username
32
+ return True
33
+ return False
34
+
35
+
36
+ def login_form():
37
+ """Display login form"""
38
+ st.title("Welcome to NOVAScholar")
39
+
40
+ with st.form("login_form"):
41
+ user_type = st.selectbox("Select User Type", ["student", "faculty"])
42
+ username = st.text_input("Username")
43
+ password = st.text_input("Password", type="password")
44
+ submit = st.form_submit_button("Login")
45
+
46
+ if submit:
47
+ if login_user(username, password, user_type):
48
+ st.success("Login successful!")
49
+ st.rerun()
50
+ else:
51
+ st.error("Invalid credentials!")
52
+
53
+ def get_courses(username, user_type):
54
+ if user_type == "student":
55
+ student = students_collection.find_one({"full_name": username})
56
+ if student:
57
+ enrolled_course_ids = [course['course_id'] for course in student.get('enrolled_courses', [])]
58
+ courses = courses_collection2.find({"course_id": {"$in": enrolled_course_ids}})
59
+ # course_titles = [course['title'] for course in courses]
60
+ print(courses)
61
+ return list(courses)
62
+ elif user_type == "faculty":
63
+ faculty = faculty_collection.find_one({"full_name": username})
64
+ if faculty:
65
+ course_ids = [course['course_id'] for course in faculty.get('courses_taught', [])]
66
+ courses = courses_collection2.find({"course_id": {"$in": course_ids}})
67
+ return list(courses)
68
+ else:
69
+ return []
70
+
71
+ def get_course_ids():
72
+ """Get course IDs for sample courses"""
73
+ return [course['course_id'] for course in SAMPLE_COURSES]
74
+
75
+ def get_sessions(course_id):
76
+ """Get sessions for a given course ID"""
77
+ course = courses_collection2.find_one({"course_id": course_id})
78
+ if course:
79
+ return course.get('sessions', [])
80
+ return []
81
+
82
+ def main_dashboard():
83
+ # st.title(f"Welcome, {st.session_state.username}")
84
+ selected_course_id = None
85
+ with st.sidebar:
86
+ st.title("Courses")
87
+
88
+ # Course selection
89
+ enrolled_courses = get_courses(st.session_state.username, st.session_state.user_type)
90
+ course_titles = [course['title'] for course in enrolled_courses]
91
+ course_ids = [course['course_id'] for course in enrolled_courses]
92
+
93
+ selected_course = st.selectbox("Select Course", course_titles)
94
+ selected_course_id = course_ids[course_titles.index(selected_course)]
95
+ print(selected_course_id)
96
+
97
+ st.session_state.selected_course = selected_course
98
+ st.session_state.selected_course_id = selected_course_id
99
+
100
+ # Display course sessions
101
+ sessions = get_sessions(selected_course_id)
102
+ print(sessions)
103
+
104
+ st.title("Sessions")
105
+ for i, session in enumerate(sessions, start=1):
106
+ if st.button(f"Session {i}", key=f"session_{i}", use_container_width=True):
107
+ st.session_state.selected_session = session
108
+
109
+ if st.button("Logout", use_container_width=True):
110
+ for key in st.session_state.keys():
111
+ del st.session_state[key]
112
+ st.rerun()
113
+
114
+ # Main content
115
+ if 'selected_session' in st.session_state:
116
+ display_session_content(selected_course_id, st.session_state.selected_session, st.session_state.username)
117
+
118
+
119
+ def main():
120
+ st.set_page_config(
121
+ page_title="NOVAScholar",
122
+ page_icon="📚",
123
+ layout="wide"
124
+ )
125
+ init_session_state()
126
+
127
+ if not st.session_state.authenticated:
128
+ login_form()
129
+ else:
130
+ main_dashboard()
131
+
132
+ if __name__ == "__main__":
133
+ main()
134
+
session_page.py ADDED
@@ -0,0 +1,270 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from datetime import datetime
3
+ from utils.sample_data import SAMPLE_CHAT_HISTORY, SAMPLE_STUDENT_PROGRESS
4
+ from utils.helpers import display_progress_bar, create_notification, format_datetime
5
+ from utils.sample_data import SAMPLE_SESSIONS, SAMPLE_COURSES
6
+ from file_upload_vectorize import upload_resource, extract_text_from_file, create_vector_store, resources_collection
7
+ from db import courses_collection2
8
+ def display_preclass_content(session, username):
9
+ """Display pre-class materials for a session"""
10
+ st.subheader("Pre-class Materials")
11
+
12
+ # Display progress bar
13
+ # progress = SAMPLE_STUDENT_PROGRESS.get(st.session_state.username, {}).get(session['session_id'], {}).get('pre_class', 0)
14
+ # display_progress_bar(progress, 100, "Pre-class completion")
15
+
16
+ # for resource in session['pre_class']['resources']:
17
+ # with st.expander(f"{resource['title']} ({resource['type'].upper()})"):
18
+ # if resource['type'] == 'pdf':
19
+ # st.markdown(f"📑 [Open PDF Document]({resource['url']})")
20
+ # if st.button("Mark PDF as Read", key=f"pdf_{resource['title']}"):
21
+ # create_notification("PDF marked as read!", "success")
22
+
23
+ # elif resource['type'] == 'video':
24
+ # st.markdown(f"🎥 Video Duration: {resource['duration']}")
25
+ # col1, col2 = st.columns([3, 1])
26
+ # with col1:
27
+ # st.video("https://example.com/placeholder.mp4")
28
+ # with col2:
29
+ # if st.button("Mark Video Complete", key=f"video_{resource['title']}"):
30
+ # create_notification("Video marked as complete!", "success")
31
+
32
+ # elif resource['type'] == 'reading':
33
+ # st.markdown(f"📖 Reading Assignment: Pages {resource['pages']}")
34
+ # if st.button("Mark Reading Complete", key=f"reading_{resource['title']}"):
35
+ # create_notification("Reading marked as complete!", "success")
36
+
37
+ # st.markdown("---")
38
+ # st.markdown("**Notes:**")
39
+ # notes = st.text_area("Add your notes here", key=f"notes_{resource['title']}")
40
+ # if st.button("Save Notes", key=f"save_notes_{resource['title']}"):
41
+ # create_notification("Notes saved successfully!", "success")
42
+
43
+ # Display pre-class materials
44
+ materials = resources_collection.find({"session_id": session['session_id']})
45
+ for material in materials:
46
+ # with st.expander(f"{material['file_name']} ({material['material_type'].upper()})"):
47
+ # if material['material_type'] == 'pdf':
48
+ # # st.markdown(f"📑 [Open PDF Document]({material['url']})")
49
+ # if st.button("Mark PDF as Read", key=f"pdf_{material['file_name']}"):
50
+ # create_notification("PDF marked as read!", "success")
51
+ with st.expander(f"{material['file_name']} ({material['material_type'].upper()})"):
52
+ file_type = material.get('file_type', 'unknown')
53
+ if file_type == 'application/pdf':
54
+ st.markdown(f"📑 [Open PDF Document]({material['file_name']})")
55
+ if st.button("View PDF", key=f"view_pdf_{material['file_name']}"):
56
+ st.text_area("PDF Content", material['text_content'], height=300)
57
+ if st.button("Download PDF", key=f"download_pdf_{material['file_name']}"):
58
+ st.download_button(
59
+ label="Download PDF",
60
+ data=material['file_content'],
61
+ file_name=material['file_name'],
62
+ mime='application/pdf'
63
+ )
64
+ if st.button("Mark PDF as Read", key=f"pdf_{material['file_name']}"):
65
+ create_notification("PDF marked as read!", "success")
66
+
67
+ def display_in_class_content(session):
68
+ """Display in-class activities and interactions"""
69
+ st.header("In-class Activities")
70
+
71
+ # Topics covered
72
+ with st.expander("Topics Covered", expanded=True):
73
+ for topic in session['in_class']['topics']:
74
+ st.markdown(f"- {topic}")
75
+
76
+ # Live Quiz section
77
+ st.subheader("Session Quiz")
78
+ quiz = session['in_class']['quiz']
79
+ with st.expander(f"Quiz: {quiz['title']}"):
80
+ st.markdown(f"- Number of questions: {quiz['questions']}")
81
+ st.markdown(f"- Time allowed: {quiz['duration']} minutes")
82
+ if session['status'] == 'in_progress':
83
+ if st.button("Start Quiz"):
84
+ create_notification("Quiz will begin shortly!", "info")
85
+ else:
86
+ st.info("Quiz not available at this time")
87
+
88
+ # Live Polls
89
+ st.subheader("Interactive Polls")
90
+ for idx, poll in enumerate(session['in_class']['polls']):
91
+ with st.expander(f"Poll {idx + 1}: {poll['question']}"):
92
+ selected_option = st.radio(
93
+ "Your response:",
94
+ options=poll['options'],
95
+ key=f"poll_{session['session_id']}_{idx}"
96
+ )
97
+ if st.button("Submit Response", key=f"submit_poll_{idx}"):
98
+ create_notification("Poll response recorded!", "success")
99
+
100
+ # Chat Interface
101
+ st.subheader("Class Discussion")
102
+ chat_container = st.container()
103
+ with chat_container:
104
+ # Display existing messages
105
+ messages = SAMPLE_CHAT_HISTORY.get(session['session_id'], [])
106
+ for msg in messages:
107
+ with st.chat_message(msg['user']):
108
+ st.write(msg['message'])
109
+
110
+ # New message input
111
+ if session['status'] == 'in_progress':
112
+ if prompt := st.chat_input("Ask a question..."):
113
+ if len(messages) < 20:
114
+ with st.chat_message("user"):
115
+ st.write(prompt)
116
+ with st.chat_message("assistant"):
117
+ st.write("This is a sample response to your question.")
118
+ else:
119
+ create_notification("Message limit (20) reached for this session.", "warning")
120
+
121
+ def display_post_class_content(session):
122
+ """Display post-class assignments and submissions"""
123
+ st.header("Post-class Work")
124
+
125
+ # Display assignments
126
+ for assignment in session['post_class']['assignments']:
127
+ with st.expander(f"Assignment: {assignment['title']}", expanded=True):
128
+ st.markdown(f"**Due Date:** {format_datetime(assignment['due_date'])}")
129
+ st.markdown(f"**Status:** {assignment['status'].replace('_', ' ').title()}")
130
+
131
+ # Assignment details
132
+ st.markdown("### Instructions")
133
+ st.markdown("Complete the assignment according to the provided guidelines.")
134
+
135
+ # File submission
136
+ st.markdown("### Submission")
137
+ uploaded_file = st.file_uploader(
138
+ "Upload your work",
139
+ type=['pdf', 'py', 'ipynb'],
140
+ key=f"upload_{assignment['id']}"
141
+ )
142
+
143
+ if uploaded_file is not None:
144
+ st.success("File uploaded successfully!")
145
+ if st.button("Submit Assignment", key=f"submit_{assignment['id']}"):
146
+ create_notification("Assignment submitted successfully!", "success")
147
+
148
+ # Feedback section (if assignment is completed)
149
+ if assignment['status'] == 'completed':
150
+ st.markdown("### Feedback")
151
+ st.info("Feedback will be provided here once the assignment is graded.")
152
+
153
+ def display_preclass_analytics(session):
154
+ """Display pre-class analytics for faculty"""
155
+ st.subheader("Pre-class Analytics")
156
+
157
+ # Display pre-class resource completion rates
158
+ for resource in session['pre_class']['resources']:
159
+ progress = SAMPLE_STUDENT_PROGRESS.get(resource['title'], 0)
160
+ display_progress_bar(progress, 100, resource['title'])
161
+
162
+ def display_inclass_analytics(session):
163
+ """Display in-class analytics for faculty"""
164
+ st.subheader("In-class Analytics")
165
+
166
+ # Display chat usage metrics
167
+ chat_messages = SAMPLE_CHAT_HISTORY.get(session['session_id'], [])
168
+ st.metric("Total Chat Messages", len(chat_messages))
169
+
170
+ # Display live quiz/poll results
171
+ # for poll in session['in_class']['polls']:
172
+ # st.subheader(poll['question'])
173
+ # for option, count in poll['responses'].items():
174
+ # st.metric(option, count)
175
+ for poll in session.get('in_class', {}).get('polls', []):
176
+ st.text(poll.get('question', 'No question available'))
177
+ responses = poll.get('responses', {})
178
+ if responses:
179
+ for option, count in responses.items():
180
+ st.metric(option, count)
181
+ else:
182
+ st.warning("No responses available for this poll")
183
+
184
+ def display_postclass_analytics(session):
185
+ """Display post-class analytics for faculty"""
186
+ st.subheader("Post-class Analytics")
187
+
188
+ # Display assignment completion rates
189
+ for assignment in session['post_class']['assignments']:
190
+ progress = SAMPLE_STUDENT_PROGRESS.get(assignment['id'], 0)
191
+ display_progress_bar(progress, 100, assignment['title'])
192
+
193
+
194
+ def upload_preclass_materials(session_id, course_id):
195
+ """Upload pre-class materials for a session"""
196
+ st.subheader("Upload Pre-class Materials")
197
+
198
+ # File upload section
199
+ uploaded_file = st.file_uploader("Upload Material", type=['txt', 'pdf', 'docx'])
200
+ if uploaded_file is not None:
201
+ with st.spinner("Processing document..."):
202
+ file_name = uploaded_file.name
203
+ file_content = extract_text_from_file(uploaded_file)
204
+ if file_content:
205
+ material_type = st.selectbox("Select Material Type", ["pdf", "docx", "txt"])
206
+ if st.button("Upload Material"):
207
+ upload_resource(course_id, session_id, file_name, uploaded_file, material_type)
208
+
209
+ # Search for the newly uploaded resource's _id in resources_collection
210
+ resource_id = resources_collection.find_one({"file_name": file_name})["_id"]
211
+ create_vector_store(file_content, resource_id)
212
+ st.success("Material uploaded successfully!")
213
+
214
+ # Display existing materials
215
+ materials = resources_collection.find({"course_id": course_id, "session_id": session_id})
216
+ for material in materials:
217
+ st.markdown(f"""
218
+ * **{material['file_name']}** ({material['material_type']})
219
+ Uploaded on: {material['uploaded_at'].strftime('%Y-%m-%d %H:%M')}
220
+ """)
221
+
222
+
223
+
224
+
225
+ def display_session_content(course_id, session, username):
226
+ st.title(f"Session {session['session_id']}: {session['title']}")
227
+ st.markdown(f"**Date:** {format_datetime(session['date'])}")
228
+ st.markdown(f"**Status:** {session['status'].replace('_', ' ').title()}")
229
+
230
+ # Find the course_id of the session in
231
+
232
+ if st.session_state.user_type == 'student':
233
+ tabs = (["Pre-class Work", "In-class Work", "Post-class Work"])
234
+ else:
235
+ tabs = (["Pre-class Analytics", "In-class Analytics", "Post-class Analytics"])
236
+
237
+ # Create tabs for different sections
238
+ # pre_class_tab, in_class_tab, post_class_tab, faculty_tab = st.tabs([
239
+ # "Pre-class Work",
240
+ # "In-class Work",
241
+ # "Post-class Work",
242
+ # "Faculty Analytics"
243
+ # ])
244
+
245
+ if st.session_state.user_type == 'student':
246
+ pre_class_tab, in_class_tab, post_class_tab = st.tabs(["Pre-class Work", "In-class Work", "Post-class Work"])
247
+ else:
248
+ pre_class_work, in_class_work, post_class_work, preclass_analytics, inclass_analytics, postclass_analytics = st.tabs(["Pre-class Work", "In-class Work", "Post-class Work", "Pre-class Analytics", "In-class Analytics", "Post-class Analytics"])
249
+
250
+ # Display pre-class materials
251
+ if st.session_state.user_type == 'student':
252
+ with pre_class_tab:
253
+ display_preclass_content(session, username)
254
+
255
+ with in_class_tab:
256
+ display_in_class_content(session)
257
+
258
+ # Post-class Content
259
+ with post_class_tab:
260
+ display_post_class_content(session)
261
+
262
+ if st.session_state.user_type == 'faculty':
263
+ with pre_class_work:
264
+ upload_preclass_materials(session['session_id'], course_id)
265
+ with preclass_analytics:
266
+ display_preclass_analytics(session)
267
+ with inclass_analytics:
268
+ display_inclass_analytics(session)
269
+ with postclass_analytics:
270
+ display_postclass_analytics(session)
utils/helpers.py ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from datetime import datetime, timedelta
2
+ import streamlit as st
3
+
4
+ def format_datetime(dt):
5
+ """Format datetime for display"""
6
+ return dt.strftime("%Y-%m-%d %H:%M")
7
+
8
+ def get_session_progress(username, course_id, session_id):
9
+ """
10
+ Get user's progress for a specific session
11
+ Returns dict with pre_class, in_class, and post_class completion status
12
+ """
13
+ # Demo implementation - replace with actual database queries
14
+ return {
15
+ 'pre_class': {
16
+ 'completed': True,
17
+ 'last_access': datetime.now() - timedelta(days=1),
18
+ 'resources_viewed': 3,
19
+ 'total_resources': 3
20
+ },
21
+ 'in_class': {
22
+ 'completed': False,
23
+ 'attendance': True,
24
+ 'quiz_completed': False,
25
+ 'questions_asked': 5
26
+ },
27
+ 'post_class': {
28
+ 'completed': False,
29
+ 'assignments_submitted': 1,
30
+ 'total_assignments': 2,
31
+ 'grade': None
32
+ }
33
+ }
34
+
35
+ def get_course_sessions(course_id):
36
+ """Get all sessions for a course"""
37
+ # Demo implementation - replace with database query
38
+ return [
39
+ {
40
+ 'id': 1,
41
+ 'title': 'Introduction to Programming Concepts',
42
+ 'date': datetime.now() + timedelta(days=i),
43
+ 'status': 'completed' if i < 0 else 'upcoming'
44
+ }
45
+ for i in range(-2, 5)
46
+ ]
47
+
48
+ def display_progress_bar(completed, total, text=""):
49
+ """Display a progress bar with text"""
50
+ progress = completed / total if total > 0 else 0
51
+ st.progress(progress)
52
+ st.text(f"{text}: {completed}/{total} ({progress*100:.1f}%)")
53
+
54
+ def create_notification(message, type="info"):
55
+ """Create a notification message"""
56
+ if type == "success":
57
+ st.success(message)
58
+ elif type == "error":
59
+ st.error(message)
60
+ elif type == "warning":
61
+ st.warning(message)
62
+ else:
63
+ st.info(message)
64
+
65
+ class SessionManager:
66
+ """Manage session state and navigation"""
67
+ @staticmethod
68
+ def get_current_session():
69
+ """Get current session information"""
70
+ if 'current_session' not in st.session_state:
71
+ st.session_state.current_session = 1
72
+ return st.session_state.current_session
73
+
74
+ @staticmethod
75
+ def set_current_session(session_id):
76
+ """Set current session"""
77
+ st.session_state.current_session = session_id
78
+
79
+ @staticmethod
80
+ def clear_session():
81
+ """Clear session state"""
82
+ for key in list(st.session_state.keys()):
83
+ del st.session_state[key]
utils/sample_data.py ADDED
@@ -0,0 +1,226 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from datetime import datetime, timedelta
2
+
3
+ SAMPLE_COURSES = [
4
+ {
5
+ 'course_id': 'CS101',
6
+ 'title': 'Introduction to Computer Science',
7
+ 'description': 'This course covers the basics of computer science and programming.',
8
+ 'instructor': 'Dr. John Doe',
9
+ 'duration': '10 weeks'
10
+ },
11
+ {
12
+ 'course_id': 'CS102',
13
+ 'title': 'Data Structures and Algorithms',
14
+ 'description': 'This course introduces data structures and algorithms for efficient data processing.',
15
+ 'instructor': 'Dr. Jane Smith',
16
+ 'duration': '12 weeks'
17
+ },
18
+ {
19
+ 'course_id': 'CS103',
20
+ 'title': 'Advanced Python Programming',
21
+ 'description': 'This course covers advanced topics in Python programming, including file handling and exception management.',
22
+ 'instructor': 'Dr. Emily Johnson',
23
+ 'duration': '8 weeks'
24
+ }
25
+ ]
26
+
27
+ SAMPLE_SESSIONS = [
28
+ {
29
+ 'id': 1,
30
+ 'course_id': 'CS101',
31
+ 'title': 'Introduction to Programming Fundamentals',
32
+ 'date': datetime.now() - timedelta(days=7),
33
+ 'status': 'completed',
34
+ 'pre_class': {
35
+ 'resources': [
36
+ {'type': 'pdf', 'title': 'Introduction to Python Basics', 'url': '/assets/python_basics.pdf'},
37
+ {'type': 'video', 'title': 'Programming Fundamentals', 'duration': '15:00'},
38
+ {'type': 'reading', 'title': 'Chapter 1: Getting Started', 'pages': '1-15'}
39
+ ],
40
+ 'completion_required': True
41
+ },
42
+ 'in_class': {
43
+ 'topics': ['Variables', 'Data Types', 'Basic Operations'],
44
+ 'quiz': {
45
+ 'title': 'Python Basics Quiz',
46
+ 'questions': 5,
47
+ 'duration': 15
48
+ },
49
+ 'polls': [
50
+ {'question': 'How comfortable are you with Python syntax?', 'options': ['Very', 'Somewhat', 'Not at all']}
51
+ ]
52
+ },
53
+ 'post_class': {
54
+ 'assignments': [
55
+ {
56
+ 'id': 1,
57
+ 'title': 'Basic Python Programs',
58
+ 'due_date': datetime.now() + timedelta(days=2),
59
+ 'status': 'pending'
60
+ }
61
+ ]
62
+ }
63
+ },
64
+ {
65
+ 'id': 2,
66
+ 'course_id': 'CS101',
67
+ 'title': 'Control Flow and Functions',
68
+ 'date': datetime.now() - timedelta(days=3),
69
+ 'status': 'completed',
70
+ 'pre_class': {
71
+ 'resources': [
72
+ {'type': 'pdf', 'title': 'Control Flow in Python', 'url': '/assets/control_flow.pdf'},
73
+ {'type': 'video', 'title': 'Functions and Methods', 'duration': '20:00'}
74
+ ],
75
+ 'completion_required': True
76
+ },
77
+ 'in_class': {
78
+ 'topics': ['If-else statements', 'Loops', 'Function definitions'],
79
+ 'quiz': {
80
+ 'title': 'Control Flow Quiz',
81
+ 'questions': 8,
82
+ 'duration': 20
83
+ },
84
+ 'polls': [
85
+ {'question': 'Which loop type do you find more intuitive?', 'options': ['For loops', 'While loops', 'Both']}
86
+ ]
87
+ },
88
+ 'post_class': {
89
+ 'assignments': [
90
+ {
91
+ 'id': 2,
92
+ 'title': 'Function Implementation Exercise',
93
+ 'due_date': datetime.now() + timedelta(days=4),
94
+ 'status': 'pending'
95
+ }
96
+ ]
97
+ }
98
+ },
99
+ {
100
+ 'id': 3,
101
+ 'course_id': 'CS102',
102
+ 'title': 'Data Structures',
103
+ 'date': datetime.now(),
104
+ 'status': 'in_progress',
105
+ 'pre_class': {
106
+ 'resources': [
107
+ {'type': 'pdf', 'title': 'Python Data Structures', 'url': '/assets/data_structures.pdf'},
108
+ {'type': 'video', 'title': 'Lists and Dictionaries', 'duration': '25:00'}
109
+ ],
110
+ 'completion_required': True
111
+ },
112
+ 'in_class': {
113
+ 'topics': ['Lists', 'Tuples', 'Dictionaries', 'Sets'],
114
+ 'quiz': {
115
+ 'title': 'Data Structures Quiz',
116
+ 'questions': 10,
117
+ 'duration': 25
118
+ },
119
+ 'polls': [
120
+ {'question': 'Which data structure do you use most often?', 'options': ['Lists', 'Dictionaries', 'Sets', 'Tuples']}
121
+ ]
122
+ },
123
+ 'post_class': {
124
+ 'assignments': [
125
+ {
126
+ 'id': 3,
127
+ 'title': 'Data Structure Implementation',
128
+ 'due_date': datetime.now() + timedelta(days=7),
129
+ 'status': 'not_started'
130
+ }
131
+ ]
132
+ }
133
+ },
134
+ {
135
+ 'id': 4,
136
+ 'course_id': 'CS101',
137
+ 'title': 'Object-Oriented Programming',
138
+ 'date': datetime.now() + timedelta(days=4),
139
+ 'status': 'upcoming',
140
+ 'pre_class': {
141
+ 'resources': [
142
+ {'type': 'pdf', 'title': 'OOP Concepts', 'url': '/assets/oop_concepts.pdf'},
143
+ {'type': 'video', 'title': 'Classes and Objects', 'duration': '30:00'}
144
+ ],
145
+ 'completion_required': True
146
+ },
147
+ 'in_class': {
148
+ 'topics': ['Classes', 'Objects', 'Inheritance', 'Polymorphism'],
149
+ 'quiz': {
150
+ 'title': 'OOP Concepts Quiz',
151
+ 'questions': 12,
152
+ 'duration': 30
153
+ },
154
+ 'polls': [
155
+ {'question': 'Have you used OOP before?', 'options': ['Yes', 'No', 'Not sure'], 'responses': {'For loops': 12, 'While loops': 8, 'Both': 10}}
156
+ ]
157
+ },
158
+ 'post_class': {
159
+ 'assignments': [
160
+ {
161
+ 'id': 4,
162
+ 'title': 'Class Implementation Project',
163
+ 'due_date': datetime.now() + timedelta(days=11),
164
+ 'status': 'not_started'
165
+ }
166
+ ]
167
+ }
168
+ },
169
+ {
170
+ 'id': 5,
171
+ 'course_id': 'CS103',
172
+ 'title': 'File Handling and Exception Management',
173
+ 'date': datetime.now() + timedelta(days=7),
174
+ 'status': 'upcoming',
175
+ 'pre_class': {
176
+ 'resources': [
177
+ {'type': 'pdf', 'title': 'File Operations in Python', 'url': '/assets/file_ops.pdf'},
178
+ {'type': 'video', 'title': 'Exception Handling', 'duration': '20:00'}
179
+ ],
180
+ 'completion_required': True
181
+ },
182
+ 'in_class': {
183
+ 'topics': ['File Operations', 'Exception Handling', 'Context Managers'],
184
+ 'quiz': {
185
+ 'title': 'File Operations Quiz',
186
+ 'questions': 8,
187
+ 'duration': 20
188
+ },
189
+ 'polls': [
190
+ {'question': 'How often do you handle exceptions in your code?',
191
+ 'options': ['Always', 'Sometimes', 'Rarely', 'Never'],
192
+ 'responses': {'Very': 10, 'Somewhat': 15, 'Not at all': 5}
193
+ }
194
+ ]
195
+ },
196
+ 'post_class': {
197
+ 'assignments': [
198
+ {
199
+ 'id': 5,
200
+ 'title': 'File Processing Application',
201
+ 'due_date': datetime.now() + timedelta(days=14),
202
+ 'status': 'not_started'
203
+ }
204
+ ]
205
+ }
206
+ }
207
+ ]
208
+
209
+ # Chatbot message history
210
+ SAMPLE_CHAT_HISTORY = {
211
+ 1: [
212
+ {'user': 'student1', 'message': 'What is the difference between list and tuple?', 'timestamp': datetime.now()},
213
+ {'user': 'chatbot', 'message': 'Lists are mutable (can be modified) while tuples are immutable (cannot be modified after creation).', 'timestamp': datetime.now()}
214
+ ]
215
+ }
216
+
217
+ # Student progress data
218
+ SAMPLE_STUDENT_PROGRESS = {
219
+ 'user1': {
220
+ 1: {'pre_class': 50, 'in_class': 80, 'post_class': 90},
221
+ 2: {'pre_class': 100, 'in_class': 75, 'post_class': 85},
222
+ 3: {'pre_class': 50, 'in_class': 0, 'post_class': 0},
223
+ 4: {'pre_class': 0, 'in_class': 0, 'post_class': 0},
224
+ 5: {'pre_class': 0, 'in_class': 0, 'post_class': 0}
225
+ }
226
+ }