Harshal Vhatkar
commited on
Commit
Β·
32a5cd0
1
Parent(s):
fb298f6
add session outline feature
Browse files- .gitignore +2 -1
- live_chat_feature.py +1 -1
- live_polls.py +1 -1
- rubrics.py +68 -20
- 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.
|
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.
|
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(
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
23 |
|
24 |
-
Session
|
25 |
-
{
|
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 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
|
|
56 |
)
|
57 |
-
return response.
|
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 |
-
|
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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
-
|
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("
|
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.
|
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)
|