Harshal Vhatkar commited on
Commit
32a5cd0
Β·
1 Parent(s): fb298f6

add session outline feature

Browse files
Files changed (5) hide show
  1. .gitignore +2 -1
  2. live_chat_feature.py +1 -1
  3. live_polls.py +1 -1
  4. rubrics.py +68 -20
  5. session_page.py +359 -2
.gitignore CHANGED
@@ -19,4 +19,5 @@ topics.json
19
  new_analytics.json
20
  new_analytics2.json
21
  pre_class_analytics.py
22
- sample_files/
 
 
19
  new_analytics.json
20
  new_analytics2.json
21
  pre_class_analytics.py
22
+ sample_files/
23
+ sample_script.py
live_chat_feature.py CHANGED
@@ -20,7 +20,7 @@ model = genai.GenerativeModel("gemini-1.5-flash")
20
  def display_live_chat_interface(session, user_id, course_id):
21
  """Main interface for live chat sessions - handles both faculty and student views"""
22
  st.markdown("<div style='margin-top: 20px;'></div>", unsafe_allow_html=True)
23
- st.subheader("Live Class Chat Session")
24
 
25
  # Initialize session states
26
  if 'chat_active' not in st.session_state:
 
20
  def display_live_chat_interface(session, user_id, course_id):
21
  """Main interface for live chat sessions - handles both faculty and student views"""
22
  st.markdown("<div style='margin-top: 20px;'></div>", unsafe_allow_html=True)
23
+ st.markdown("#### Live Class Chat Session")
24
 
25
  # Initialize session states
26
  if 'chat_active' not in st.session_state:
live_polls.py CHANGED
@@ -11,7 +11,7 @@ class LivePollFeature:
11
 
12
  def display_faculty_interface(self, session_id):
13
  """Display the faculty interface for managing polls"""
14
- st.subheader("Live Polls Management")
15
 
16
  # Create new poll
17
  with st.expander("Create New Poll", expanded=False):
 
11
 
12
  def display_faculty_interface(self, session_id):
13
  """Display the faculty interface for managing polls"""
14
+ st.markdown("#### Live Polls Management")
15
 
16
  # Create new poll
17
  with st.expander("Create New Poll", expanded=False):
rubrics.py CHANGED
@@ -1,3 +1,4 @@
 
1
  import streamlit as st
2
  from pymongo import MongoClient
3
  from openai import OpenAI
@@ -5,10 +6,14 @@ from bson import ObjectId
5
  import json
6
  from dotenv import load_dotenv
7
  import os
 
8
 
9
  load_dotenv()
10
  MONGO_URI = os.getenv('MONGO_URI')
11
  OPENAI_API_KEY = os.getenv('OPENAI_KEY')
 
 
 
12
 
13
  client = MongoClient(MONGO_URI)
14
  db = client['novascholar_db']
@@ -17,12 +22,18 @@ rubrics_collection = db['rubrics']
17
  resources_collection = db['resources']
18
  courses_collection = db['courses']
19
 
20
- def generate_rubrics(api_key, session_title, outcome_description, taxonomy, pre_class_material):
 
 
 
 
 
 
21
  prompt = f"""
22
- You are an expert educational AI assistant specializing in instructional design. Generate a detailed rubric for the session titled "{session_title}". The rubric should be aligned with Bloom's Taxonomy level "{taxonomy}" and use numerical scoring levels (4,3,2,1) instead of descriptive levels. Use the following context:
23
 
24
- Session Outcome Description:
25
- {outcome_description}
26
 
27
  Pre-class Material:
28
  {pre_class_material}
@@ -49,12 +60,13 @@ def generate_rubrics(api_key, session_title, outcome_description, taxonomy, pre_
49
  ]
50
 
51
  try:
52
- client = OpenAI(api_key=api_key)
53
- response = client.chat.completions.create(
54
- model="gpt-4-0125-preview",
55
- messages=messages
 
56
  )
57
- return response.choices[0].message.content
58
  except Exception as e:
59
  st.error(f"Failed to generate rubrics: {e}")
60
  return None
@@ -73,15 +85,24 @@ def display_rubrics_tab(session, course_id):
73
 
74
  # Extract session learning outcomes
75
  if 'session_learning_outcomes' in session_data and len(session_data['session_learning_outcomes']) > 0:
76
- outcome = session_data['session_learning_outcomes'][0]
77
- outcome_description = outcome.get('outcome_description', '')
78
- taxonomy_level = outcome.get('bloom_taxonomy_level', '')
79
 
80
  # Display fetched information
81
  st.markdown("### Session Information")
82
  st.markdown(f"**Session Title:** {session['title']}")
83
- st.markdown(f"**Learning Outcome:** {outcome_description}")
84
- st.markdown(f"**Taxonomy Level:** {taxonomy_level}")
 
 
 
 
 
 
 
 
 
85
 
86
  # Fetch pre-class material
87
  pre_class_material_docs = resources_collection.find({"session_id": session['session_id']})
@@ -89,10 +110,8 @@ def display_rubrics_tab(session, course_id):
89
 
90
  if st.button("Generate Rubric"):
91
  rubric = generate_rubrics(
92
- OPENAI_API_KEY,
93
  session['title'],
94
- outcome_description,
95
- taxonomy_level,
96
  pre_class_material
97
  )
98
 
@@ -102,10 +121,39 @@ def display_rubrics_tab(session, course_id):
102
  rubric_data = {
103
  "course_id": course_id,
104
  "session_id": session['session_id'],
105
- "rubric": json.loads(rubric)
 
 
106
  }
107
- rubrics_collection.insert_one(rubric_data)
108
- st.success("Rubric saved successfully!")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  else:
110
  st.error("No learning outcomes found for this session")
111
  else:
 
1
+ from datetime import datetime
2
  import streamlit as st
3
  from pymongo import MongoClient
4
  from openai import OpenAI
 
6
  import json
7
  from dotenv import load_dotenv
8
  import os
9
+ import google.generativeai as genai
10
 
11
  load_dotenv()
12
  MONGO_URI = os.getenv('MONGO_URI')
13
  OPENAI_API_KEY = os.getenv('OPENAI_KEY')
14
+ GEMINI_API_KEY = os.getenv('GEMINI_KEY')
15
+ genai.configure(api_key=GEMINI_API_KEY)
16
+ model = genai.GenerativeModel("gemini-1.5-flash")
17
 
18
  client = MongoClient(MONGO_URI)
19
  db = client['novascholar_db']
 
22
  resources_collection = db['resources']
23
  courses_collection = db['courses']
24
 
25
+ def generate_rubrics(session_title, outcomes, pre_class_material):
26
+ # Format outcomes for prompt
27
+ outcomes_text = "\n".join([
28
+ f"Outcome {i+1}:\n- Description: {outcome.get('outcome_description')}\n- Taxonomy Level: {outcome.get('bloom_taxanomy_level')}"
29
+ for i, outcome in enumerate(outcomes)
30
+ ])
31
+
32
  prompt = f"""
33
+ You are an expert educational AI assistant specializing in instructional design. Generate a detailed rubric for the session titled "{session_title}". The rubric should cover multiple learning outcomes and use numerical scoring levels (4,3,2,1). Use the following context:
34
 
35
+ Session Outcomes Description:
36
+ {outcomes_text}
37
 
38
  Pre-class Material:
39
  {pre_class_material}
 
60
  ]
61
 
62
  try:
63
+ response = model.generate_content(
64
+ prompt,
65
+ generation_config=genai.GenerationConfig(
66
+ response_mime_type="application/json"
67
+ )
68
  )
69
+ return response.text
70
  except Exception as e:
71
  st.error(f"Failed to generate rubrics: {e}")
72
  return None
 
85
 
86
  # Extract session learning outcomes
87
  if 'session_learning_outcomes' in session_data and len(session_data['session_learning_outcomes']) > 0:
88
+ outcomes = session_data['session_learning_outcomes']
89
+ # outcome_description = outcome.get('outcome_description', None)
90
+ # taxonomy_level = outcome.get('bloom_taxonomy_level', None)
91
 
92
  # Display fetched information
93
  st.markdown("### Session Information")
94
  st.markdown(f"**Session Title:** {session['title']}")
95
+ # st.markdown(f"**Learning Outcome:** {outcome_description}")
96
+ # if taxonomy_level:
97
+ # st.markdown(f"**Taxonomy Level:** {taxonomy_level}")
98
+ # Display all learning outcomes
99
+ st.markdown("### Learning Outcomes:")
100
+ for i, outcome in enumerate(outcomes, 1):
101
+ st.markdown(f"""
102
+ **Outcome {i}:**
103
+ - Description: {outcome.get('outcome_description')}
104
+ - Taxonomy Level: {outcome.get('bloom_taxanomy_level')}
105
+ """)
106
 
107
  # Fetch pre-class material
108
  pre_class_material_docs = resources_collection.find({"session_id": session['session_id']})
 
110
 
111
  if st.button("Generate Rubric"):
112
  rubric = generate_rubrics(
 
113
  session['title'],
114
+ outcomes,
 
115
  pre_class_material
116
  )
117
 
 
121
  rubric_data = {
122
  "course_id": course_id,
123
  "session_id": session['session_id'],
124
+ "rubric": json.loads(rubric),
125
+ "outcomes": outcomes,
126
+ "created_at": datetime.now()
127
  }
128
+ # rubrics_collection.insert_one(rubric_data)
129
+ # st.success("Rubric saved successfully!")
130
+ # Check for existing rubric and update or insert
131
+ existing_rubric = rubrics_collection.find_one({
132
+ "session_id": session['session_id']
133
+ })
134
+
135
+ if existing_rubric:
136
+ rubrics_collection.update_one(
137
+ {"_id": existing_rubric["_id"]},
138
+ {"$set": rubric_data}
139
+ )
140
+ st.success("Rubric updated successfully!")
141
+ else:
142
+ rubrics_collection.insert_one(rubric_data)
143
+ st.success("Rubric saved successfully!")
144
+
145
+ # Display existing rubric if available
146
+ existing_rubric = rubrics_collection.find_one({
147
+ "session_id": session['session_id']
148
+ })
149
+
150
+ if existing_rubric:
151
+ with st.expander("View Existing Rubric"):
152
+ st.json(existing_rubric['rubric'])
153
+ st.caption(f"Last updated: {existing_rubric['created_at'].strftime('%Y-%m-%d %H:%M:%S')}")
154
+
155
+ if st.button("Generate New Rubric", key="new_rubric"):
156
+ st.rerun()
157
  else:
158
  st.error("No learning outcomes found for this session")
159
  else:
session_page.py CHANGED
@@ -1126,7 +1126,7 @@ def extract_youtube_id(url):
1126
  return None
1127
 
1128
  def display_live_presentation(session, user_type, course_id):
1129
- st.markdown("### Live Presentation")
1130
 
1131
  # Get active presentation
1132
  session_data = courses_collection.find_one(
@@ -1193,11 +1193,349 @@ def display_live_presentation(session, user_type, course_id):
1193
  else:
1194
  st.info("πŸ“ No active presentations at this time.")
1195
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1196
  def display_in_class_content(session, user_type, course_id, user_id):
1197
  # """Display in-class activities and interactions"""
1198
  """Display in-class activities and interactions"""
1199
- st.header("In-class Activities")
1200
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1201
  # Initialize Live Polls feature
1202
  live_polls = LivePollFeature()
1203
 
@@ -1212,6 +1550,25 @@ def display_in_class_content(session, user_type, course_id, user_id):
1212
  # Live Presentation Feature
1213
  display_live_presentation(session, user_type, course_id)
1214
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1215
  def generate_random_assignment_id():
1216
  """Generate a random integer ID for assignments"""
1217
  return random.randint(100000, 999999)
 
1126
  return None
1127
 
1128
  def display_live_presentation(session, user_type, course_id):
1129
+ st.markdown("#### Live Presentation")
1130
 
1131
  # Get active presentation
1132
  session_data = courses_collection.find_one(
 
1193
  else:
1194
  st.info("πŸ“ No active presentations at this time.")
1195
 
1196
+
1197
+ def generate_session_outline(session_id, course_id):
1198
+ """
1199
+ Generate a comprehensive session outline based on pre-class materials, learning outcomes, and analytics.
1200
+ """
1201
+ try:
1202
+ # Fetch session details
1203
+ session_data = courses_collection.find_one(
1204
+ {"course_id": course_id, "sessions.session_id": session_id},
1205
+ {"sessions.$": 1}
1206
+ )
1207
+
1208
+ if not session_data or 'sessions' not in session_data:
1209
+ st.error("Session data not found")
1210
+ return None
1211
+
1212
+ session = session_data['sessions'][0]
1213
+
1214
+ # Fetch pre-class materials
1215
+ materials = resources_collection.find({"session_id": session_id})
1216
+ materials_context = ""
1217
+ for material in materials:
1218
+ if 'text_content' in material:
1219
+ materials_context += f"\nMaterial: {material['file_name']}\n{material['text_content']}\n"
1220
+
1221
+ # Get learning outcomes
1222
+ learning_outcomes = session.get('session_learning_outcomes', [])
1223
+ outcomes_text = "\n".join([
1224
+ f"Outcome {i+1}: {outcome.get('outcome_description', '')}"
1225
+ for i, outcome in enumerate(learning_outcomes)
1226
+ ])
1227
+
1228
+ # Get analytics
1229
+ analytics = session.get('pre_class', {}).get('analytics', {})
1230
+
1231
+ # Craft the prompt for Gemini
1232
+ prompt = f"""
1233
+ As an expert educational planner, create a detailed session outline based on the following context:
1234
+
1235
+ SESSION INFORMATION:
1236
+ Title: {session.get('title', '')}
1237
+ Duration: 70 minutes
1238
+
1239
+ LEARNING OUTCOMES:
1240
+ {outcomes_text}
1241
+
1242
+ PRE-CLASS MATERIALS SUMMARY:
1243
+ {materials_context}
1244
+
1245
+ ANALYTICS INSIGHTS:
1246
+ Struggling Topics: {[topic['topic'] for topic in analytics.get('topic_wise_insights', [])]}
1247
+ Key Issues: {[topic.get('key_issues', []) for topic in analytics.get('topic_wise_insights', [])]}
1248
+ Student Understanding: {analytics.get('course_health', {}).get('overall_engagement', 'N/A')}
1249
+
1250
+ Based on this context, create a detailed session outline that includes:
1251
+
1252
+ 1. Opening (8-10 minutes):
1253
+ - How to start the session
1254
+ - Initial engagement activities
1255
+ - Connection to pre-class materials
1256
+
1257
+ 2. Main Activities (50 minutes):
1258
+ - Sequence of learning activities
1259
+ - Teaching strategies for struggling topics
1260
+ - Interactive elements and discussions
1261
+ - Time allocation for each activity
1262
+
1263
+ 3. Closing (10-12 minutes):
1264
+ - Assessment strategies
1265
+ - Summary activities
1266
+ - Preview of next session
1267
+
1268
+ 4. Additional Considerations:
1269
+ - Student engagement strategies
1270
+ - Addressing identified misconceptions
1271
+ - Integration of technology/tools
1272
+ - Backup activities if needed
1273
+
1274
+ Format the response as a JSON object with these exact keys:
1275
+ {{
1276
+ "opening_activities": [{{
1277
+ "activity": "string",
1278
+ "duration": "string",
1279
+ "purpose": "string",
1280
+ "materials_needed": ["string"]
1281
+ }}],
1282
+ "main_activities": [{{
1283
+ "activity": "string",
1284
+ "duration": "string",
1285
+ "learning_outcome_addressed": "string",
1286
+ "teaching_strategy": "string",
1287
+ "materials_needed": ["string"]
1288
+ }}],
1289
+ "closing_activities": [{{
1290
+ "activity": "string",
1291
+ "duration": "string",
1292
+ "purpose": "string"
1293
+ }}],
1294
+ "contingency_plans": [{{
1295
+ "scenario": "string",
1296
+ "alternative_activity": "string"
1297
+ }}]
1298
+ }}
1299
+ """
1300
+ GEMINI_API_KEY = os.getenv("GEMINI_KEY")
1301
+ genai.configure(api_key=GEMINI_API_KEY)
1302
+ model = genai.GenerativeModel("gemini-1.5-flash")
1303
+
1304
+ # Generate response using Gemini
1305
+ response = model.generate_content(
1306
+ prompt,
1307
+ generation_config=genai.GenerationConfig(
1308
+ temperature=0.3,
1309
+ response_mime_type="application/json"
1310
+ )
1311
+ )
1312
+
1313
+ if not response or not response.text:
1314
+ st.error("No response received from Gemini")
1315
+ return None
1316
+
1317
+ # Parse and validate the response
1318
+ try:
1319
+ outline = json.loads(response.text)
1320
+ return outline
1321
+ except json.JSONDecodeError as e:
1322
+ st.error(f"Error parsing response: {str(e)}")
1323
+ return None
1324
+
1325
+ except Exception as e:
1326
+ st.error(f"Error generating session outline: {str(e)}")
1327
+ return None
1328
+
1329
+ def display_session_outline(session, outline, course_id):
1330
+ """Display the generated session outline in a structured format"""
1331
+ if not outline:
1332
+ return
1333
+
1334
+ # Initialize session state for storing outline if not exists
1335
+ if 'session_outline' not in st.session_state:
1336
+ st.session_state.session_outline = None
1337
+
1338
+ # Store the outline in session state
1339
+ st.session_state.session_outline = outline
1340
+
1341
+ # Main Display
1342
+ st.markdown("""
1343
+ <style>
1344
+ .session-section {
1345
+ border-radius: 8px;
1346
+ background-color: #f8f9fa;
1347
+ margin: 15px 0;
1348
+ }
1349
+ .activity-item {
1350
+ padding: 15px;
1351
+ border-left: 4px solid #3b82f6;
1352
+ margin: 10px 0;
1353
+ background-color: white;
1354
+ border-radius: 4px;
1355
+ }
1356
+ .section-title {
1357
+ color: #1e3a8a;
1358
+ font-size: 1.2rem;
1359
+ font-weight: 600;
1360
+ margin-bottom: 15px;
1361
+ }
1362
+ </style>
1363
+ """, unsafe_allow_html=True)
1364
+
1365
+ # st.markdown("### πŸ“‹ Session Outline")
1366
+
1367
+ # # Opening Activities
1368
+ # st.markdown("#### 🎯 Opening Activities")
1369
+ # for activity in outline["opening_activities"]:
1370
+ # with st.expander(f"{activity['activity']} ({activity['duration']})"):
1371
+ # st.markdown(f"**Purpose:** {activity['purpose']}")
1372
+ # st.markdown("**Materials Needed:**")
1373
+ # for material in activity["materials_needed"]:
1374
+ # st.markdown(f"- {material}")
1375
+ st.markdown("#### πŸ“‹ Session Outline")
1376
+ with st.expander("View Session Outline"):
1377
+ # Opening Activities Section
1378
+ # st.markdown('<div class="session-section">', unsafe_allow_html=True)
1379
+ st.markdown("<div style='margin-top: 10px;'></div>", unsafe_allow_html=True)
1380
+ st.markdown("###### 🎯 Opening Activities (8-10 minutes)")
1381
+ for activity in outline["opening_activities"]:
1382
+ st.markdown(f"""
1383
+ <div class="activity-item">
1384
+ <h6>{activity['activity']} ({activity['duration']})</h6>
1385
+ <p><strong>Purpose:</strong> {activity['purpose']}</p>
1386
+ </div>
1387
+ """, unsafe_allow_html=True)
1388
+ # st.markdown('</div>', unsafe_allow_html=True)
1389
+
1390
+ # Main Activities
1391
+ # st.markdown("#### πŸ“š Main Activities")
1392
+ # for activity in outline["main_activities"]:
1393
+ # with st.expander(f"{activity['activity']} ({activity['duration']})"):
1394
+ # st.markdown(f"**Learning Outcome:** {activity['learning_outcome_addressed']}")
1395
+ # st.markdown(f"**Teaching Strategy:** {activity['teaching_strategy']}")
1396
+ # st.markdown("**Materials Needed:**")
1397
+ # for material in activity["materials_needed"]:
1398
+ # st.markdown(f"- {material}")
1399
+ # Main Activities Section
1400
+ # st.markdown('<div class="session-section">', unsafe_allow_html=True)
1401
+ st.markdown("<div style='margin-top: 10px;'></div>", unsafe_allow_html=True)
1402
+ st.markdown("###### πŸ“š Main Activities (50 minutes)")
1403
+ for activity in outline["main_activities"]:
1404
+ st.markdown(f"""
1405
+ <div class="activity-item">
1406
+ <h6>{activity['activity']} ({activity['duration']})</h6>
1407
+ <p><strong>Learning Outcome:</strong> {activity['learning_outcome_addressed']}</p>
1408
+ <p><strong>Teaching Strategy:</strong> {activity['teaching_strategy']}</p>
1409
+ </div>
1410
+ """, unsafe_allow_html=True)
1411
+ # st.markdown('</div>', unsafe_allow_html=True)
1412
+
1413
+ # Closing Activities
1414
+ # st.markdown("#### 🎬 Closing Activities")
1415
+ # for activity in outline["closing_activities"]:
1416
+ # with st.expander(f"{activity['activity']} ({activity['duration']})"):
1417
+ # st.markdown(f"**Purpose:** {activity['purpose']}")
1418
+ # st.markdown('<div class="session-section">', unsafe_allow_html=True)
1419
+ st.markdown("<div style='margin-top: 10px;'></div>", unsafe_allow_html=True)
1420
+ st.markdown("###### 🎬 Closing Activities (10-12 minutes)")
1421
+ for activity in outline["closing_activities"]:
1422
+ st.markdown(f"""
1423
+ <div class="activity-item">
1424
+ <h6>{activity['activity']} ({activity['duration']})</h6>
1425
+ <p><strong>Purpose:</strong> {activity['purpose']}</p>
1426
+ </div>
1427
+ """, unsafe_allow_html=True)
1428
+ # st.markdown('</div>', unsafe_allow_html=True)
1429
+
1430
+ # Contingency Plans
1431
+ # st.markdown("#### πŸ”„ Contingency Plans")
1432
+ # for plan in outline["contingency_plans"]:
1433
+ # with st.expander(f"If: {plan['scenario']}"):
1434
+ # st.markdown(f"**Alternative Activity:** {plan['alternative_activity']}")
1435
+ # st.markdown('<div class="session-section">', unsafe_allow_html=True)
1436
+ st.markdown("<div style='margin-top: 10px;'></div>", unsafe_allow_html=True)
1437
+ st.markdown("###### πŸ”„ Contingency Plans")
1438
+ for plan in outline["contingency_plans"]:
1439
+ st.markdown(f"""
1440
+ <div class="activity-item">
1441
+ <p><strong>If:</strong> {plan['scenario']}</p>
1442
+ <p><strong>Alternative Activity:</strong> {plan['alternative_activity']}</p>
1443
+ </div>
1444
+ """, unsafe_allow_html=True)
1445
+ # st.markdown('</div>', unsafe_allow_html=True)
1446
+
1447
+ # Add save/download options
1448
+ if st.button("πŸ’Ύ Save Outline"):
1449
+ try:
1450
+ courses_collection.update_one(
1451
+ {"course_id": course_id, "sessions.session_id": session['session_id']},
1452
+ {"$set": {"sessions.$.session_outline": st.session_state.session_outline}}
1453
+ )
1454
+ st.success("Outline saved successfully!")
1455
+ except Exception as e:
1456
+ st.error(f"Error saving outline: {str(e)}")
1457
+
1458
+ # Download option
1459
+ if st.download_button(
1460
+ "πŸ“₯ Download Outline",
1461
+ data=json.dumps(st.session_state.session_outline, indent=2),
1462
+ file_name="session_outline.json",
1463
+ mime="application/json"
1464
+ ):
1465
+ st.success("Outline downloaded successfully!")
1466
+
1467
+
1468
  def display_in_class_content(session, user_type, course_id, user_id):
1469
  # """Display in-class activities and interactions"""
1470
  """Display in-class activities and interactions"""
1471
+ st.markdown("### In-class Activities")
1472
 
1473
+ # Check if session outline exists in the database
1474
+ # session_data = courses_collection.find_one(
1475
+ # {"course_id": course_id, "sessions.session_id": session['session_id']},
1476
+ # {"sessions.$": 1}
1477
+ # )
1478
+ # # Initialize session state for storing outline if not exists
1479
+ # if 'session_outline' not in st.session_state:
1480
+ # if session_data and session_data.get('sessions'):
1481
+ # session_outline = session_data['sessions'][0].get('session_outline')
1482
+ # if session_outline:
1483
+ # st.session_state.session_outline = session_outline
1484
+ # display_session_outline(session, session_outline, course_id)
1485
+ # else:
1486
+ # st.session_state.session_outline = None
1487
+
1488
+ # Initialize session state for outline
1489
+ if 'session_outline' not in st.session_state:
1490
+ st.session_state.session_outline = None
1491
+
1492
+ # Check if session outline exists in the database
1493
+ try:
1494
+ # Debug log
1495
+ # st.write("Fetching session outline from database...")
1496
+
1497
+ session_data = courses_collection.find_one(
1498
+ {
1499
+ "course_id": course_id,
1500
+ "sessions.session_id": session['session_id']
1501
+ },
1502
+ {"sessions.$": 1}
1503
+ )
1504
+
1505
+ if session_data and session_data.get('sessions'):
1506
+ current_session = session_data['sessions'][0]
1507
+ stored_outline = current_session.get('session_outline')
1508
+
1509
+ if stored_outline:
1510
+ # st.write("Found existing session outline")
1511
+ st.session_state.session_outline = stored_outline
1512
+ else:
1513
+ st.write("No existing session outline found")
1514
+ st.session_state.session_outline = None
1515
+
1516
+ except Exception as e:
1517
+ st.error(f"Error fetching session outline: {e}")
1518
+ st.session_state.session_outline = None
1519
+
1520
+ if user_type == 'faculty':
1521
+ # st.markdown("<div style='margin-top: 10px;'></div>", unsafe_allow_html=True)
1522
+ if not st.session_state.session_outline:
1523
+ st.markdown("#### Session Outline")
1524
+ if st.button("Generate a Session Outline"):
1525
+ with st.spinner("Generating session outline..."):
1526
+ outline = generate_session_outline(session['session_id'], course_id)
1527
+ if outline:
1528
+ display_session_outline(session, outline, course_id)
1529
+ st.rerun()
1530
+ print("Session outline is: ", outline)
1531
+ # Save outline to database
1532
+ # courses_collection.update_one(
1533
+ # {"course_id": course_id, "sessions.session_id": session['session_id']},
1534
+ # {"$set": {"sessions.$.session_outline": outline}}
1535
+ # )
1536
+ else:
1537
+ display_session_outline(session, st.session_state.session_outline, course_id)
1538
+
1539
  # Initialize Live Polls feature
1540
  live_polls = LivePollFeature()
1541
 
 
1550
  # Live Presentation Feature
1551
  display_live_presentation(session, user_type, course_id)
1552
 
1553
+ def get_current_context(session):
1554
+ """Get current context from session outline and materials"""
1555
+ context = ""
1556
+
1557
+ # Get context from session outline
1558
+ if st.session_state.session_outline:
1559
+ outline = st.session_state.session_outline
1560
+ current_activities = outline.get("main_activities", [])
1561
+ for activity in current_activities:
1562
+ context += f"{activity['activity']} - {activity['learning_outcome_addressed']}\n"
1563
+
1564
+ # Get context from materials
1565
+ materials = resources_collection.find({"session_id": session['session_id']})
1566
+ for material in materials:
1567
+ if 'text_content' in material:
1568
+ context += material['text_content'] + "\n"
1569
+
1570
+ return context
1571
+
1572
  def generate_random_assignment_id():
1573
  """Generate a random integer ID for assignments"""
1574
  return random.randint(100000, 999999)