Harshal Vhatkar commited on
Commit
cf5bc29
·
1 Parent(s): 2008141

add question_bank in pre_class_quiz

Browse files
Files changed (2) hide show
  1. gen_mcqs.py +108 -1
  2. session_page.py +394 -98
gen_mcqs.py CHANGED
@@ -225,7 +225,7 @@ GEMINI_KEY = os.getenv('GEMINI_KEY')
225
  # Configure APIs
226
  openai.api_key = OPENAI_KEY
227
  genai.configure(api_key=GEMINI_KEY)
228
- model = genai.GenerativeModel('gemini-pro')
229
 
230
  # Connect to MongoDB
231
  client = MongoClient(MONGO_URI)
@@ -306,6 +306,113 @@ def generate_mcqs(context, num_questions, session_title, session_description):
306
  print(f"Error generating MCQs: , error: {e}")
307
  return None
308
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
309
  def save_pre_class_quiz(course_id: str, session_id: str, title: str, questions: List[Dict], user_id: str, duration: int):
310
  """Save pre-class quiz to database"""
311
  try:
 
225
  # Configure APIs
226
  openai.api_key = OPENAI_KEY
227
  genai.configure(api_key=GEMINI_KEY)
228
+ model = genai.GenerativeModel('gemini-1.5-flash')
229
 
230
  # Connect to MongoDB
231
  client = MongoClient(MONGO_URI)
 
306
  print(f"Error generating MCQs: , error: {e}")
307
  return None
308
 
309
+ def generate_pre_class_question_bank(context: str, session_title: str, session_description: str) -> List[Dict]:
310
+ """Generate a bank of 40 MCQ questions for pre-class quiz"""
311
+ try:
312
+ prompt = f"""
313
+ Based on the following content, generate 50 multiple choice questions for a question bank.
314
+ Format each question as a Python dictionary with this exact structure:
315
+ {{
316
+ "question": "Question text here",
317
+ "options": ["A) option1", "B) option2", "C) option3", "D) option4"],
318
+ "correct_option": "A) option1" or "B) option2" or "C) option3" or "D) option4",
319
+ "difficulty": "easy|medium|hard",
320
+ "topic": "specific topic from content"
321
+ }}
322
+
323
+ Content:
324
+ {context}
325
+
326
+ Session Title: {session_title}
327
+ Description: {session_description}
328
+
329
+ Requirements:
330
+ 1. Questions should cover all important concepts
331
+ 2. Mix of easy (20%), medium (50%), and hard (30%) questions
332
+ 3. Clear and unambiguous questions
333
+ 4. Options should be plausible but only one correct answer
334
+ 5. Include topic tags for categorization
335
+ 6. **NUMBER OF QUESTIONS SHOULD BE GREATER THAN OR EQUAL TO 60**
336
+
337
+ Return ONLY the JSON array of questions.
338
+ """
339
+
340
+ response = model.generate_content(
341
+ prompt,
342
+ generation_config=genai.GenerationConfig(
343
+ # temperature=0.7,
344
+ response_mime_type="application/json"
345
+ )
346
+ )
347
+ response_text = response.text.strip()
348
+ modified_response_text = strip_code_markers(response_text)
349
+ question_bank = ast.literal_eval(modified_response_text)
350
+ print(question_bank)
351
+ # Validate question bank
352
+ if not isinstance(question_bank, list):
353
+ raise ValueError("Invalid question bank format or count")
354
+
355
+ return question_bank
356
+
357
+ except Exception as e:
358
+ print(f"Error generating question bank: {e}")
359
+ return None
360
+
361
+
362
+ def save_pre_class_quiz_with_bank(
363
+ course_id: str,
364
+ session_id: str,
365
+ title: str,
366
+ question_bank: List[Dict],
367
+ num_questions: int,
368
+ duration: int,
369
+ user_id: str
370
+ ) -> str:
371
+ """Save pre-class quiz with question bank to database"""
372
+ try:
373
+ quiz_data = {
374
+ "user_id": user_id,
375
+ "course_id": course_id,
376
+ "session_id": session_id,
377
+ "title": title,
378
+ "question_bank": question_bank,
379
+ "num_questions": num_questions,
380
+ "duration_minutes": duration,
381
+ "created_at": datetime.now(),
382
+ "status": "active",
383
+ "submissions": [],
384
+ "quiz_type": "pre_class"
385
+ }
386
+ result = quizzes_collection.insert_one(quiz_data)
387
+ return result.inserted_id
388
+ except Exception as e:
389
+ print(f"Error saving quiz with question bank: {e}")
390
+ return None
391
+
392
+ def get_randomized_questions(quiz_id) -> List[Dict]:
393
+ """Get randomly selected questions from question bank based on quiz settings"""
394
+ try:
395
+ quiz = quizzes_collection.find_one({"_id": quiz_id})
396
+ if not quiz:
397
+ return None
398
+
399
+ num_questions = quiz.get("num_questions", 0)
400
+ question_bank = quiz.get("question_bank", [])
401
+
402
+ if not question_bank or num_questions <= 0:
403
+ return None
404
+
405
+ # Randomly select questions
406
+ import random
407
+ selected_questions = random.sample(question_bank, num_questions)
408
+
409
+ return selected_questions
410
+
411
+ except Exception as e:
412
+ print(f"Error getting randomized questions: {e}")
413
+ return None
414
+
415
+
416
  def save_pre_class_quiz(course_id: str, session_id: str, title: str, questions: List[Dict], user_id: str, duration: int):
417
  """Save pre-class quiz to database"""
418
  try:
session_page.py CHANGED
@@ -17,7 +17,7 @@ import plotly.express as px
17
  from dotenv import load_dotenv
18
  import os
19
  from pymongo import MongoClient
20
- from gen_mcqs import generate_mcqs, save_pre_class_quiz, save_quiz, quizzes_collection, get_student_quiz_score, submit_quiz_answers
21
  from create_course import courses_collection
22
  # from pre_class_analytics import NovaScholarAnalytics
23
  from pre_class_analytics2 import NovaScholarAnalytics
@@ -831,56 +831,225 @@ def display_pre_class_quiz_tab(student_id, course_id, session_id):
831
  st.success(f"Quiz completed! Score: {existing_score:.1f}%")
832
 
833
  # Show review
834
- st.subheader("Quiz Review")
835
- for i, question in enumerate(quiz["questions"]):
836
- st.markdown(f"**Q{i+1}:** {question['question']}")
837
- for opt in question["options"]:
838
- if opt.startswith(question["correct_option"]):
839
- st.markdown(f"✅ {opt}")
840
- else:
841
- st.markdown(f"- {opt}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
842
 
843
  else:
844
- # Check time remaining
845
- start_time = quiz.get('start_time')
846
- if not start_time:
 
 
 
 
 
 
 
 
 
 
 
 
 
847
  if st.button("Start Quiz", key=f"start_{quiz['_id']}"):
848
- quizzes_collection.update_one(
849
- {"_id": quiz["_id"]},
850
- {"$set": {"start_time": datetime.now()}}
851
- )
852
- st.rerun()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
853
  else:
854
- time_remaining = (start_time + timedelta(minutes=quiz['duration_minutes'])) - datetime.now()
855
-
856
- if time_remaining.total_seconds() > 0:
857
- st.info(f"Time remaining: {int(time_remaining.total_seconds() // 60)}:{int(time_remaining.total_seconds() % 60):02d}")
 
 
 
 
 
858
 
859
- # Display quiz form
860
- with st.form(f"pre_class_quiz_{quiz['_id']}"):
861
- student_answers = {}
862
- for i, question in enumerate(quiz["questions"]):
863
- st.markdown(f"**Q{i+1}:** {question['question']}")
864
- options = [opt for opt in question["options"]]
865
- student_answers[str(i)] = st.radio(
866
- f"Select answer:",
867
- options=options,
868
- key=f"q_{quiz['_id']}_{i}"
869
- )
 
 
 
 
 
 
 
870
 
871
- if st.form_submit_button("Submit Quiz"):
872
- score = submit_quiz_answers(
873
- quiz["_id"],
874
- student_id,
875
- student_answers
876
- )
877
- if score is not None:
878
- st.success(f"Quiz submitted! Score: {score:.1f}%")
879
- st.rerun()
880
- else:
881
- st.error("Error submitting quiz")
882
- else:
883
- st.error("Quiz time expired")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
884
 
885
 
886
  def get_chat_context(session_id):
@@ -1389,13 +1558,76 @@ def upload_preclass_materials(session_id, course_id, student_id):
1389
  with pre_class_quiz:
1390
  if st.session_state.user_type == "faculty":
1391
  st.subheader("Create Pre-class Quiz")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1392
  with st.form("create_pre_class_quiz_form"):
1393
  quiz_title = st.text_input("Quiz Title")
1394
  num_questions = st.number_input(
1395
- "Number of Questions",
1396
- min_value=1,
1397
- max_value=20,
1398
- value=5
1399
  )
1400
  duration = st.number_input(
1401
  "Quiz Duration (minutes)",
@@ -1404,54 +1636,111 @@ def upload_preclass_materials(session_id, course_id, student_id):
1404
  value=15
1405
  )
1406
 
1407
- # Generate quiz button
1408
- if st.form_submit_button("Generate Pre-class Quiz"):
1409
- if not quiz_title:
1410
- st.error("Please enter a quiz title")
1411
- return
1412
-
1413
- # Get pre-class materials
1414
- materials = resources_collection.find({"session_id": session_id})
1415
- context = ""
1416
- for material in materials:
1417
- if 'text_content' in material:
1418
- context += material['text_content'] + "\n"
1419
-
1420
- if not context:
1421
- st.error("No pre-class materials found")
1422
- return
1423
 
1424
- # Generate questions
1425
- questions = generate_mcqs(
1426
- context=context,
1427
- num_questions=num_questions,
1428
- session_title=session['title'],
1429
- session_description=session.get('description', '')
1430
- )
1431
 
1432
- if questions:
1433
- # Preview questions
1434
- st.subheader("Preview Questions")
1435
- for i, q in enumerate(questions, 1):
1436
- st.markdown(f"**Q{i}:** {q['question']}")
1437
- for opt in q['options']:
1438
- st.markdown(f"- {opt}")
1439
- st.markdown(f"*Correct: {q['correct_option']}*")
1440
-
1441
- # Save quiz
1442
- quiz_id = save_pre_class_quiz(
1443
- course_id=course_id,
1444
- session_id=session_id,
1445
- title=quiz_title,
1446
- questions=questions,
1447
- user_id=st.session_state.user_id,
1448
- duration=duration
1449
- )
1450
 
1451
- if quiz_id:
1452
- st.success("Pre-class quiz created successfully!")
1453
- else:
1454
- st.error("Error saving quiz")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1455
 
1456
  def extract_external_content(url, content_type):
1457
  """Extract content from external resources based on their type"""
@@ -3440,13 +3729,19 @@ def display_session_analytics(session, course_id):
3440
  def display_quiz_tab(student_id, course_id, session_id):
3441
  """Display quizzes for students"""
3442
  st.header("Course Quizzes")
3443
-
3444
- # Get available quizzes for this session
3445
  quizzes = quizzes_collection.find({
3446
  "course_id": course_id,
3447
  "session_id": session_id,
3448
- "status": "active"
 
3449
  })
 
 
 
 
 
 
3450
 
3451
  quizzes = list(quizzes)
3452
  if not quizzes:
@@ -3570,7 +3865,8 @@ def display_session_content(student_id, course_id, session, username, user_type)
3570
  with tabs[2]:
3571
  display_post_class_content(session, student_id, course_id)
3572
  with tabs[3]:
3573
- display_preclass_analytics2(session, course_id)
 
3574
  with tabs[4]:
3575
  display_inclass_analytics(session, course_id)
3576
  with tabs[5]:
 
17
  from dotenv import load_dotenv
18
  import os
19
  from pymongo import MongoClient
20
+ from gen_mcqs import generate_mcqs, generate_pre_class_question_bank, get_randomized_questions, save_pre_class_quiz, save_pre_class_quiz_with_bank, save_quiz, quizzes_collection, get_student_quiz_score, submit_quiz_answers
21
  from create_course import courses_collection
22
  # from pre_class_analytics import NovaScholarAnalytics
23
  from pre_class_analytics2 import NovaScholarAnalytics
 
831
  st.success(f"Quiz completed! Score: {existing_score:.1f}%")
832
 
833
  # Show review
834
+ st.markdown("#### Quiz Review")
835
+ submission = next(
836
+ (sub for sub in quiz["submissions"] if sub["student_id"] == student_id),
837
+ None
838
+ )
839
+ # for i, question in enumerate(quiz["questions"]):
840
+ # st.markdown(f"**Q{i+1}:** {question['question']}")
841
+ # for opt in question["options"]:
842
+ # if opt.startswith(question["correct_option"]):
843
+ # st.markdown(f"✅ {opt}")
844
+ # else:
845
+ # st.markdown(f"- {opt}")
846
+ if submission:
847
+ questions = submission.get("allocated_questions", [])
848
+ answers = submission.get("answers", {})
849
+ for i, question in enumerate(questions):
850
+ st.markdown(f"**Q{i+1}:** {question['question']}")
851
+ for opt in question["options"]:
852
+ if opt == question["correct_option"]:
853
+ st.markdown(f"✅ {opt}")
854
+ elif opt == answers.get(str(i)):
855
+ st.markdown(f"❌ {opt}")
856
+ else:
857
+ st.markdown(f"- {opt}")
858
 
859
  else:
860
+ # # Check time remaining
861
+ # start_time = quiz.get('start_time')
862
+ # if not start_time:
863
+ # if st.button("Start Quiz", key=f"start_{quiz['_id']}"):
864
+ # quizzes_collection.update_one(
865
+ # {"_id": quiz["_id"]},
866
+ # {"$set": {"start_time": datetime.now()}}
867
+ # )
868
+ # st.rerun()
869
+ # Start quiz flow
870
+ quiz_state = quizzes_collection.find_one({
871
+ "_id": quiz["_id"],
872
+ "student_states.student_id": student_id
873
+ })
874
+ if not quiz_state or "student_states" not in quiz_state:
875
+ # Not started yet
876
  if st.button("Start Quiz", key=f"start_{quiz['_id']}"):
877
+ # Get random questions
878
+ questions = get_randomized_questions(quiz["_id"])
879
+ if questions:
880
+ # Save allocated questions and start time
881
+ result = quizzes_collection.update_one(
882
+ {"_id": quiz["_id"]},
883
+ {
884
+ "$push": {
885
+ "student_states": {
886
+ "student_id": student_id,
887
+ "allocated_questions": questions,
888
+ "start_time": datetime.now(),
889
+ "completed": False
890
+ }
891
+ }
892
+ }
893
+ )
894
+ if result.modified_count > 0:
895
+ st.rerun()
896
+ else:
897
+ st.error("Error getting quiz questions")
898
  else:
899
+ # Quiz already started
900
+ student_state = next(
901
+ (state for state in quiz_state["student_states"]
902
+ if state["student_id"] == student_id),
903
+ None
904
+ )
905
+ if student_state:
906
+ start_time = student_state["start_time"]
907
+ time_remaining = (start_time + timedelta(minutes=quiz['duration_minutes'])) - datetime.now()
908
 
909
+ if time_remaining.total_seconds() > 0:
910
+ st.info(f"Time remaining: {int(time_remaining.total_seconds() // 60)}:{int(time_remaining.total_seconds() % 60):02d}")
911
+
912
+ # Display questions
913
+ questions = student_state["allocated_questions"]
914
+ with st.form(f"pre_class_quiz_{quiz['_id']}"):
915
+ student_answers = {}
916
+
917
+ for i, question in enumerate(questions):
918
+ st.markdown(f"**Q{i+1}:** {question['question']}")
919
+ options = question["options"]
920
+ answer = st.radio(
921
+ "Select answer:",
922
+ options=options,
923
+ key=f"q_{quiz['_id']}_{i}"
924
+ )
925
+ if answer:
926
+ student_answers[str(i)] = answer
927
 
928
+ if st.form_submit_button("Submit Quiz"):
929
+ if len(student_answers) != len(questions):
930
+ st.error("Please answer all questions before submitting.")
931
+ else:
932
+ # Calculate score
933
+ correct_answers = 0
934
+ for i, question in enumerate(questions):
935
+ if student_answers.get(str(i)) == question["correct_option"]:
936
+ correct_answers += 1
937
+
938
+ score = (correct_answers / len(questions)) * 100
939
+
940
+ # Save submission
941
+ result = quizzes_collection.update_one(
942
+ {"_id": quiz["_id"]},
943
+ {
944
+ "$push": {
945
+ "submissions": {
946
+ "student_id": student_id,
947
+ "allocated_questions": questions,
948
+ "answers": student_answers,
949
+ "score": score,
950
+ "submitted_at": datetime.now()
951
+ }
952
+ },
953
+ "$set": {
954
+ "student_states.$[state].completed": True
955
+ }
956
+ },
957
+ array_filters=[
958
+ {"state.student_id": student_id}
959
+ ]
960
+ )
961
+ if result.modified_count > 0:
962
+ st.success(f"Quiz submitted! Score: {score:.1f}%")
963
+ st.rerun()
964
+ else:
965
+ st.error("Error submitting quiz")
966
+ else:
967
+ st.error("Quiz time expired")
968
+ # start_time = quiz.get("start_time")
969
+ # if not start_time:
970
+ # if st.button("Start Quiz", key=f"start_{quiz['_id']}"):
971
+ # # Get random questions when starting
972
+ # questions = get_randomized_questions(quiz["_id"])
973
+ # if questions:
974
+ # # Save selected questions and start time
975
+ # result = quizzes_collection.update_one(
976
+ # {"_id": quiz["_id"]},
977
+ # {
978
+ # "$set": {
979
+ # "start_time": datetime.now(),
980
+ # f"student_questions.{student_id}": questions
981
+ # }
982
+ # }
983
+ # )
984
+ # if result.modified_count > 0:
985
+ # st.rerun()
986
+ # else:
987
+ # st.error("Error getting quiz questions")
988
+ # else:
989
+ # time_remaining = (start_time + timedelta(minutes=quiz['duration_minutes'])) - datetime.now()
990
+
991
+ # # if time_remaining.total_seconds() > 0:
992
+ # # st.info(f"Time remaining: {int(time_remaining.total_seconds() // 60)}:{int(time_remaining.total_seconds() % 60):02d}")
993
+
994
+ # # # Display quiz form
995
+ # # with st.form(f"pre_class_quiz_{quiz['_id']}"):
996
+ # # student_answers = {}
997
+ # # for i, question in enumerate(quiz["questions"]):
998
+ # # st.markdown(f"**Q{i+1}:** {question['question']}")
999
+ # # options = [opt for opt in question["options"]]
1000
+ # # student_answers[str(i)] = st.radio(
1001
+ # # f"Select answer:",
1002
+ # # options=options,
1003
+ # # key=f"q_{quiz['_id']}_{i}"
1004
+ # # )
1005
+
1006
+ # # if st.form_submit_button("Submit Quiz"):
1007
+ # # score = submit_quiz_answers(
1008
+ # # quiz["_id"],
1009
+ # # student_id,
1010
+ # # student_answers
1011
+ # # )
1012
+ # # if score is not None:
1013
+ # # st.success(f"Quiz submitted! Score: {score:.1f}%")
1014
+ # # st.rerun()
1015
+ # # else:
1016
+ # # st.error("Error submitting quiz")
1017
+ # # else:
1018
+ # # st.error("Quiz time expired")
1019
+ # if time_remaining.total_seconds() > 0:
1020
+ # st.info(f"Time remaining: {int(time_remaining.total_seconds() // 60)}:{int(time_remaining.total_seconds() % 60):02d}")
1021
+
1022
+ # # Get student's randomized questions
1023
+ # student_questions = quiz.get("student_questions", {}).get(student_id)
1024
+
1025
+ # if student_questions:
1026
+ # with st.form(f"pre_class_quiz_{quiz['_id']}"):
1027
+ # student_answers = {}
1028
+
1029
+ # for i, question in enumerate(student_questions):
1030
+ # st.markdown(f"**Q{i+1}:** {question['question']}")
1031
+ # options = question["options"]
1032
+ # student_answers[str(i)] = st.radio(
1033
+ # "Select answer:",
1034
+ # options=options,
1035
+ # key=f"q_{quiz['_id']}_{i}"
1036
+ # )
1037
+
1038
+ # if st.form_submit_button("Submit Quiz"):
1039
+ # score = submit_quiz_answers(
1040
+ # quiz["_id"],
1041
+ # student_id,
1042
+ # student_answers,
1043
+ # student_questions
1044
+ # )
1045
+
1046
+ # if score is not None:
1047
+ # st.success(f"Quiz submitted! Score: {score:.1f}%")
1048
+ # st.rerun()
1049
+ # else:
1050
+ # st.error("Error submitting quiz")
1051
+ # else:
1052
+ # st.error("Quiz time expired")
1053
 
1054
 
1055
  def get_chat_context(session_id):
 
1558
  with pre_class_quiz:
1559
  if st.session_state.user_type == "faculty":
1560
  st.subheader("Create Pre-class Quiz")
1561
+ # with st.form("create_pre_class_quiz_form"):
1562
+ # quiz_title = st.text_input("Quiz Title")
1563
+ # num_questions = st.number_input(
1564
+ # "Number of Questions",
1565
+ # min_value=1,
1566
+ # max_value=20,
1567
+ # value=5
1568
+ # )
1569
+ # duration = st.number_input(
1570
+ # "Quiz Duration (minutes)",
1571
+ # min_value=5,
1572
+ # max_value=60,
1573
+ # value=15
1574
+ # )
1575
+
1576
+ # # Generate quiz button
1577
+ # if st.form_submit_button("Generate Pre-class Quiz"):
1578
+ # if not quiz_title:
1579
+ # st.error("Please enter a quiz title")
1580
+ # return
1581
+
1582
+ # # Get pre-class materials
1583
+ # materials = resources_collection.find({"session_id": session_id})
1584
+ # context = ""
1585
+ # for material in materials:
1586
+ # if 'text_content' in material:
1587
+ # context += material['text_content'] + "\n"
1588
+
1589
+ # if not context:
1590
+ # st.error("No pre-class materials found")
1591
+ # return
1592
+
1593
+ # # Generate questions
1594
+ # questions = generate_mcqs(
1595
+ # context=context,
1596
+ # num_questions=num_questions,
1597
+ # session_title=session['title'],
1598
+ # session_description=session.get('description', '')
1599
+ # )
1600
+
1601
+ # if questions:
1602
+ # # Preview questions
1603
+ # st.subheader("Preview Questions")
1604
+ # for i, q in enumerate(questions, 1):
1605
+ # st.markdown(f"**Q{i}:** {q['question']}")
1606
+ # for opt in q['options']:
1607
+ # st.markdown(f"- {opt}")
1608
+ # st.markdown(f"*Correct: {q['correct_option']}*")
1609
+
1610
+ # # Save quiz
1611
+ # quiz_id = save_pre_class_quiz(
1612
+ # course_id=course_id,
1613
+ # session_id=session_id,
1614
+ # title=quiz_title,
1615
+ # questions=questions,
1616
+ # user_id=st.session_state.user_id,
1617
+ # duration=duration
1618
+ # )
1619
+
1620
+ # if quiz_id:
1621
+ # st.success("Pre-class quiz created successfully!")
1622
+ # else:
1623
+ # st.error("Error saving quiz")
1624
  with st.form("create_pre_class_quiz_form"):
1625
  quiz_title = st.text_input("Quiz Title")
1626
  num_questions = st.number_input(
1627
+ "Number of Questions per Student",
1628
+ min_value=5,
1629
+ max_value=30,
1630
+ value=10
1631
  )
1632
  duration = st.number_input(
1633
  "Quiz Duration (minutes)",
 
1636
  value=15
1637
  )
1638
 
1639
+ if st.form_submit_button("Generate Question Bank"):
1640
+ with st.spinner("Generating question bank..."):
1641
+ try:
1642
+ if not quiz_title:
1643
+ st.error("Please enter a quiz title")
1644
+ return
 
 
 
 
 
 
 
 
 
 
1645
 
1646
+ # Get pre-class materials
1647
+ materials = resources_collection.find({"session_id": session_id})
1648
+ context = ""
1649
+ for material in materials:
1650
+ if 'text_content' in material:
1651
+ context += material['text_content'] + "\n"
 
1652
 
1653
+ if not context:
1654
+ st.error("No pre-class materials found")
1655
+ return
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1656
 
1657
+ # Generate question bank
1658
+ question_bank = generate_pre_class_question_bank(
1659
+ context=context,
1660
+ session_title=session['title'],
1661
+ session_description=session.get('description', '')
1662
+ )
1663
+ if question_bank:
1664
+ print(question_bank)
1665
+ # Preview question bank
1666
+ st.subheader("Question Bank Preview")
1667
+
1668
+ # Show statistics
1669
+ difficulties = [q['difficulty'] for q in question_bank]
1670
+ st.write("Question Distribution:")
1671
+ st.write(f"- Easy: {difficulties.count('easy')}")
1672
+ st.write(f"- Medium: {difficulties.count('medium')}")
1673
+ st.write(f"- Hard: {difficulties.count('hard')}")
1674
+
1675
+ # Show questions
1676
+ for i, q in enumerate(question_bank, 1):
1677
+ with st.expander(f"Q{i}: {q['topic']} ({q['difficulty']})"):
1678
+ st.markdown(f"**Question:** {q['question']}")
1679
+ st.markdown("**Options:**")
1680
+ for opt in q['options']:
1681
+ if opt == q['correct_option']:
1682
+ st.markdown(f"✅ {opt}")
1683
+ else:
1684
+ st.markdown(f"- {opt}")
1685
+ # Save quiz with question bank
1686
+ quiz_id = save_pre_class_quiz_with_bank(
1687
+ course_id=course_id,
1688
+ session_id=session_id,
1689
+ title=quiz_title,
1690
+ question_bank=question_bank,
1691
+ num_questions=num_questions,
1692
+ duration=duration,
1693
+ user_id=st.session_state.user_id
1694
+ )
1695
+ if quiz_id:
1696
+ st.success("Pre-class quiz created successfully!")
1697
+ else:
1698
+ st.error("Error generating question bank")
1699
+ except Exception as e:
1700
+ st.error("Error saving quiz", e)
1701
+ # else:
1702
+ # st.error("Error generating question bank")
1703
+ # question_banks = quizzes_collection.find({
1704
+ # "course_id": course_id,
1705
+ # "session_id": session_id,
1706
+ # "quiz_type": "pre_class"
1707
+ # })
1708
+ question_banks = list(quizzes_collection.find({
1709
+ "course_id": course_id,
1710
+ "session_id": session_id,
1711
+ "quiz_type": "pre_class"
1712
+ }))
1713
+ if question_banks and len(question_banks) > 0:
1714
+ st.markdown("#### Existing Question Banks")
1715
+ for bank in question_banks:
1716
+ try:
1717
+ faculty_member = faculty_collection.find_one({"_id": ObjectId(bank['user_id'])})
1718
+ faculty_name = faculty_member['full_name'] if faculty_member else "Unknown Faculty"
1719
+
1720
+ with st.expander(f"📚 {bank.get('title', 'Untitled Quiz')}"):
1721
+ # Check if question bank exists
1722
+ if 'question_bank' in bank and bank['question_bank']:
1723
+ st.markdown(f"**Number of Questions:** {len(bank['question_bank'])}")
1724
+ st.markdown(f"**Created By:** {faculty_name}")
1725
+ st.markdown(f"**Created At:** {bank['created_at'].strftime('%Y-%m-%d %H:%M:%S')}")
1726
+
1727
+ # Display questions
1728
+ for i, question in enumerate(bank['question_bank'], 1):
1729
+ st.markdown(f"**Question {i}:** {question['question']}")
1730
+ st.markdown("**Options:**")
1731
+ for opt in question['options']:
1732
+ if opt == question['correct_option']:
1733
+ st.markdown(f"✅ {opt}")
1734
+ else:
1735
+ st.markdown(f"- {opt}")
1736
+ st.markdown(f"**Difficulty:** {question['difficulty']}")
1737
+ st.markdown(f"**Topic:** {question['topic']}")
1738
+ else:
1739
+ st.warning("This question bank appears to be empty")
1740
+ except Exception as e:
1741
+ st.error(f"Error displaying question bank: {str(e)}")
1742
+ else:
1743
+ st.info("No question banks yet for this session")
1744
 
1745
  def extract_external_content(url, content_type):
1746
  """Extract content from external resources based on their type"""
 
3729
  def display_quiz_tab(student_id, course_id, session_id):
3730
  """Display quizzes for students"""
3731
  st.header("Course Quizzes")
3732
+ # Get available quizzes for this session, excluding pre-class quizzes
 
3733
  quizzes = quizzes_collection.find({
3734
  "course_id": course_id,
3735
  "session_id": session_id,
3736
+ "status": "active",
3737
+ "quiz_type": {"$ne": "pre_class"}
3738
  })
3739
+ # Get available quizzes for this session
3740
+ # quizzes = quizzes_collection.find({
3741
+ # "course_id": course_id,
3742
+ # "session_id": session_id,
3743
+ # "status": "active"
3744
+ # })
3745
 
3746
  quizzes = list(quizzes)
3747
  if not quizzes:
 
3865
  with tabs[2]:
3866
  display_post_class_content(session, student_id, course_id)
3867
  with tabs[3]:
3868
+ if st.button("Generate Pre-class Analytics") and not st.session_state.analytics_data:
3869
+ display_preclass_analytics2(session, course_id)
3870
  with tabs[4]:
3871
  display_inclass_analytics(session, course_id)
3872
  with tabs[5]: