NSamson1 commited on
Commit
9630dec
Β·
verified Β·
1 Parent(s): 2f92028

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +139 -313
src/streamlit_app.py CHANGED
@@ -9,339 +9,165 @@ import time
9
  import tempfile
10
 
11
  # Page config
12
- st.set_page_config(page_title="πŸŽ“ Smart Math Teacher", layout="wide")
13
 
14
- # Custom CSS with beautiful colors and stable layout
15
  st.markdown("""
16
  <style>
17
- .fun-title {
18
- font-size: 40px;
19
- color: #FF6B6B;
20
- text-align: center;
21
- font-family: 'Comic Sans MS', cursive;
22
- text-shadow: 2px 2px 4px rgba(0,0,0,0.1);
23
- margin-bottom: 20px;
24
- }
25
- .question-box {
26
- border: 4px solid #4ECDC4;
27
- padding: 20px;
28
- border-radius: 15px;
29
- background: linear-gradient(135deg, #FFF9C4, #E3F2FD);
30
- font-size: 20px;
31
- box-shadow: 0 4px 8px rgba(0,0,0,0.1);
32
- margin: 15px 0;
33
- }
34
- .stButton > button {
35
- font-size: 18px;
36
- background: linear-gradient(45deg, #FF6B6B, #FF8E53);
37
- color: white;
38
- border-radius: 10px;
39
- padding: 10px;
40
- border: none;
41
- font-weight: bold;
42
- margin: 5px;
43
- }
44
- .stTextInput > div > input {
45
- font-size: 18px;
46
- border: 2px solid #4ECDC4;
47
- border-radius: 10px;
48
- padding: 10px;
49
- }
50
-
51
- /* Main container background */
52
- .stApp {
53
- background: linear-gradient(135deg, #E3F2FD, #F3E5F5);
54
- }
55
-
56
- /* Progress bar styling */
57
- .stProgress > div > div > div {
58
- background: linear-gradient(45deg, #4ECDC4, #00C9FF);
59
- }
60
-
61
- /* Success message */
62
- .stSuccess {
63
- background: linear-gradient(135deg, #4ECDC4, #00C9FF);
64
- color: white;
65
- border-radius: 10px;
66
- }
67
-
68
- /* Info message */
69
- .stInfo {
70
- background: linear-gradient(135deg, #FFD93D, #FF9A3D);
71
- color: white;
72
- border-radius: 10px;
73
- }
74
 
75
- /* Error message */
76
- .stError {
77
- background: linear-gradient(135deg, #FF6B6B, #FF8E8E);
78
- color: white;
79
- border-radius: 10px;
80
- }
81
-
82
- /* Warning message */
83
- .stWarning {
84
- background: linear-gradient(135deg, #FFD93D, #FF9A3D);
85
- color: white;
86
- border-radius: 10px;
87
- }
88
-
89
- /* Guide box */
90
  .guide-box {
91
- background: linear-gradient(135deg, #A5D6A7, #C8E6C9);
92
  padding: 15px;
93
  border-radius: 10px;
94
  border: 2px solid #4CAF50;
95
  margin: 10px 0;
96
  }
97
-
98
- /* DISABLE ALL ANIMATIONS */
99
- * {
100
- animation: none !important;
101
- transition: none !important;
102
- transform: none !important;
103
- }
104
-
105
- /* Keep content in view */
106
- .main-content {
107
- min-height: 100vh;
108
- }
109
-
110
- /* Sidebar styling */
111
- .sidebar-content {
112
- position: sticky;
113
- top: 20px;
114
- }
115
  </style>
116
  """, unsafe_allow_html=True)
117
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
  # Initialize session state for temp directory
119
  if 'temp_dir' not in st.session_state:
120
  st.session_state.temp_dir = tempfile.mkdtemp()
121
 
122
- # Use columns for sidebar-like layout
123
- col_guide, col_main = st.columns([1, 2])
124
-
125
- # LEFT SIDEBAR - GUIDE
126
- with col_guide:
127
- st.markdown("### πŸ“– How to Use This App")
128
- with st.expander("**Click to Expand Guide**", expanded=True):
129
- st.markdown("""
130
- <div class="guide-box">
131
- <h4>🎯 Quick Start Guide:</h4>
132
-
133
- **Step 1: Choose Your Level** πŸ‘‡
134
- - Select your age group
135
- - 4-6: Basic counting
136
- - 7-9: Addition, subtraction
137
- - 13-15: Advanced math
138
-
139
- **Step 2: Pick a Category** πŸ“š
140
- - Choose math type to practice
141
- - Each category has different questions
142
-
143
- **Step 3: Solve Problems** ✏️
144
- - Read each question
145
- - Type your answer
146
- - Click "Submit Answer"
147
-
148
- **Step 4: Get Help** πŸ’‘
149
- - Use "Show Hint" if stuck
150
- - "Show Steps" for explanation
151
- - "Skip" for next question
152
-
153
- **Tips:** 🌟
154
- - Take your time
155
- - Mistakes help you learn!
156
- - Practice regularly
157
- </div>
158
- """, unsafe_allow_html=True)
159
-
160
- # Age group setup
161
- age_groups = {
162
- "4-6 Age Group": {"dataset": "src/Datase_of_4-6_Age_Group.xlsx", "zip_file": "src/Image_for_group_4-6.zip", "image_folder": "Image_for_group_4-6"},
163
- "7-9 Age Group": {"dataset": "src/Datase_of_7-9_Age_Group.xlsx", "zip_file": "src/Image_for_group_7-9.zip", "image_folder": "Image_for_group_7-9"},
164
- "13-15 Age Group": {"dataset": "src/Datase_of_13-15_Age_Group.xlsx", "zip_file": "src/Image_for_group_13-15.zip", "image_folder": "Image_for_group_13-15"},
165
- }
166
-
167
- # Age group selection in sidebar
168
- st.markdown("---")
169
- st.markdown("### πŸ§’ Choose Your Level")
170
- selected_age_group = st.selectbox(
171
- "Select age group:",
172
- list(age_groups.keys()),
173
- key="age_group_selector"
174
- )
175
-
176
- # Age group descriptions
177
- age_descriptions = {
178
- "4-6 Age Group": "🎨 **Fun with Numbers**: Counting, shapes, basic addition",
179
- "7-9 Age Group": "πŸš€ **Math Adventures**: Addition, subtraction, multiplication",
180
- "13-15 Age Group": "🌟 **Math Master**: Algebra, geometry, problem solving"
181
- }
182
-
183
- st.info(age_descriptions[selected_age_group])
184
-
185
- # MAIN CONTENT AREA - RIGHT SIDE
186
- with col_main:
187
- # Welcome title
188
- st.markdown("<div class='fun-title'>🧠✨ Welcome to the Smart Math Teacher! ✨🧠</div>", unsafe_allow_html=True)
189
-
190
- # Initialize session
191
- if "session_initialized" not in st.session_state or st.session_state.age_group != selected_age_group:
192
- st.session_state.age_group = selected_age_group
193
- st.session_state.category = None
194
- st.session_state.question_index = 0
195
- st.session_state.show_answer = False
196
- st.session_state.show_steps = False
197
- st.session_state.session_initialized = True
198
-
199
- # Load dataset
200
- group_info = age_groups[selected_age_group]
201
- dataset_path = group_info["dataset"]
202
- zip_path = group_info["zip_file"]
203
- image_folder = group_info["image_folder"]
204
-
205
- # Create image folder in temp directory
206
- temp_image_folder = os.path.join(st.session_state.temp_dir, image_folder)
207
- os.makedirs(temp_image_folder, exist_ok=True)
208
-
209
- # Extract images if zip exists
210
- try:
211
- if os.path.exists(zip_path):
212
- with zipfile.ZipFile(zip_path, "r") as zip_ref:
213
- zip_ref.extractall(temp_image_folder)
214
- except Exception as e:
215
- st.warning(f"Error extracting images: {e}")
216
-
217
- if not os.path.exists(dataset_path):
218
- st.error(f"Dataset not found: {dataset_path}")
219
- st.stop()
220
-
221
- try:
222
- df = pd.read_excel(dataset_path)
223
- df['category'] = df['category'].astype(str).str.strip()
224
- except Exception as e:
225
- st.error(f"Error loading dataset: {e}")
226
- st.stop()
227
-
228
- # Category selection in main area
229
- st.markdown("### πŸ“š Choose Your Math Category")
230
- categories = sorted(df['category'].dropna().unique())
231
- selected_category = st.selectbox(
232
- "Select a category to practice:",
233
- options=categories,
234
- key="category_selector"
235
- )
236
-
237
- # Update session if category changes
238
- if st.session_state.category != selected_category:
239
- st.session_state.category = selected_category
240
- st.session_state.question_index = 0
241
  st.session_state.show_answer = False
242
  st.session_state.show_steps = False
243
  st.rerun()
244
-
245
- # Filter questions by selected category only
246
- subset_df = df[df['category'] == selected_category].reset_index(drop=True)
247
-
248
- # MAIN CONTENT AREA - QUESTIONS
249
- st.markdown("---")
250
-
251
- if not subset_df.empty and st.session_state.question_index < len(subset_df):
252
- question = subset_df.iloc[st.session_state.question_index]
253
- progress = int((st.session_state.question_index / len(subset_df)) * 100)
254
-
255
- # Progress information
256
- col_progress1, col_progress2 = st.columns([3, 1])
257
- with col_progress1:
258
- st.progress(progress)
259
- with col_progress2:
260
- st.write(f"**{st.session_state.question_index + 1} of {len(subset_df)}**")
261
-
262
- st.markdown(f"<div class='question-box'>πŸ“˜ <b>Question {st.session_state.question_index + 1}:</b><br><br>{question['problem']}</div>", unsafe_allow_html=True)
263
-
264
- # Display image with error handling
265
- if pd.notna(question.get('image')):
266
- image_name = str(question['image']).strip()
267
- image_found = False
268
- for root, _, files in os.walk(temp_image_folder):
269
- for file in files:
270
- if file.lower().startswith(image_name.lower()) or os.path.splitext(file)[0].lower() == image_name.lower():
271
- try:
272
- st.image(Image.open(os.path.join(root, file)), use_column_width=True)
273
- image_found = True
274
- break
275
- except:
276
- pass
277
- if not image_found:
278
- st.warning("❌ Image not found for this question.")
279
-
280
- # Answer section
281
- st.markdown("### ✏️ Your Turn to Solve!")
282
- user_ans = st.text_input("Type your answer below:", key=f"ans_{st.session_state.question_index}")
283
-
284
- # Action buttons in columns
285
- col1, col2, col3 = st.columns(3)
286
-
287
- with col1:
288
- if st.button("βœ… Submit Answer", use_container_width=True):
289
- if str(user_ans).strip().lower() == str(question['answer']).strip().lower():
290
- st.success("πŸŽ‰ Correct! Well done!")
291
- st.balloons()
292
- time.sleep(2)
293
- st.session_state.question_index += 1
294
- st.session_state.show_answer = False
295
- st.session_state.show_steps = False
296
- st.rerun()
297
- else:
298
- st.error("❌ Not quite right. Try again or use the hint below!")
299
- st.session_state.show_answer = True
300
- st.session_state.show_steps = False
301
-
302
- with col2:
303
- if st.button("πŸ’‘ Show Hint", use_container_width=True):
304
- st.session_state.show_answer = True
305
- st.session_state.show_steps = False
306
- st.info("πŸ’‘ Need help? Check the answer below!")
307
-
308
- with col3:
309
- if st.button("⏭️ Skip Question", use_container_width=True):
310
- st.session_state.question_index += 1
311
- st.session_state.show_answer = False
312
- st.session_state.show_steps = False
313
- st.rerun()
314
-
315
- # Help sections
316
- if st.session_state.show_answer:
317
- st.markdown("---")
318
- st.markdown("### πŸ’‘ Need Help?")
319
- st.info(f"**βœ… Correct Answer:** **{question['answer']}**")
320
-
321
- if selected_age_group in ["7-9 Age Group", "13-15 Age Group"]:
322
- if st.button("πŸ” Show Step-by-Step Solution"):
323
- st.session_state.show_steps = True
324
-
325
- if st.session_state.show_steps and pd.notna(question.get("steps", None)):
326
- st.success(f"### πŸͺ„ How to Solve:\n{question['steps']}")
327
-
328
- elif subset_df.empty:
329
- st.warning("⚠️ No questions available in this category. Please try another category!")
330
- else:
331
- st.markdown("---")
332
- st.success("""
333
- # πŸ† Congratulations!
334
-
335
- ### You've completed all questions in this category!
336
-
337
- πŸŽ‰ **Great job!** You're becoming a math superstar!
338
-
339
- **What to do next:**
340
- - Try another category in the same age group
341
- - Move to a more challenging age group
342
- - Practice regularly to keep improving!
343
- """)
344
- st.balloons()
345
 
346
  # Cleanup function
347
  def cleanup():
 
9
  import tempfile
10
 
11
  # Page config
12
+ st.set_page_config(page_title="πŸŽ“ Smart Math Teacher", layout="centered")
13
 
14
+ # Custom CSS
15
  st.markdown("""
16
  <style>
17
+ .fun-title { font-size: 40px; color: #ff3399; text-align: center; font-family: 'Comic Sans MS', cursive; }
18
+ .question-box { border: 4px dotted #ffcc00; padding: 20px; border-radius: 20px; background-color: #fff7e6; font-size: 20px; }
19
+ .stButton > button { font-size: 18px; background-color: #00cc99; color: white; border-radius: 10px; padding: 10px; }
20
+ .stTextInput > div > input { font-size: 18px; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
+ /* Guide styling */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  .guide-box {
24
+ background-color: #e8f5e8;
25
  padding: 15px;
26
  border-radius: 10px;
27
  border: 2px solid #4CAF50;
28
  margin: 10px 0;
29
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  </style>
31
  """, unsafe_allow_html=True)
32
 
33
+ # Welcome title
34
+ st.markdown("<div class='fun-title'>🧠✨ Welcome to the Smart Math Teacher! ✨🧠</div>", unsafe_allow_html=True)
35
+
36
+ # USER GUIDE - Always visible at the top
37
+ st.markdown("""
38
+ <div class="guide-box">
39
+ <h3>πŸ“– How to Use This App:</h3>
40
+
41
+ **1. Select Your Age Group** - Choose your learning level (4-6, 7-9, or 13-15 years)<br>
42
+ **2. Choose Math Category** - Pick what type of math to practice<br>
43
+ **3. Solve Questions** - Read each question and type your answer<br>
44
+ **4. Get Help** - Use hints or skip if needed<br>
45
+ **5. Learn** - See correct answers and step-by-step solutions
46
+ </div>
47
+ """, unsafe_allow_html=True)
48
+
49
  # Initialize session state for temp directory
50
  if 'temp_dir' not in st.session_state:
51
  st.session_state.temp_dir = tempfile.mkdtemp()
52
 
53
+ # Age group setup
54
+ age_groups = {
55
+ "4-6 Age Group": {"dataset": "src/Datase_of_4-6_Age_Group.xlsx", "zip_file": "src/Image_for_group_4-6.zip", "image_folder": "Image_for_group_4-6"},
56
+ "7-9 Age Group": {"dataset": "src/Datase_of_7-9_Age_Group.xlsx", "zip_file": "src/Image_for_group_7-9.zip", "image_folder": "Image_for_group_7-9"},
57
+ "13-15 Age Group": {"dataset": "src/Datase_of_13-15_Age_Group.xlsx", "zip_file": "src/Image_for_group_13-15.zip", "image_folder": "Image_for_group_13-15"},
58
+ }
59
+
60
+ selected_age_group = st.selectbox("πŸ§’ Select your Age Group:", list(age_groups.keys()))
61
+
62
+ # Initialize session
63
+ if "session_initialized" not in st.session_state or st.session_state.age_group != selected_age_group:
64
+ st.session_state.age_group = selected_age_group
65
+ st.session_state.category = None
66
+ st.session_state.question_index = 0
67
+ st.session_state.show_answer = False
68
+ st.session_state.show_steps = False
69
+ st.session_state.session_initialized = True
70
+
71
+ # Load dataset
72
+ group_info = age_groups[selected_age_group]
73
+ dataset_path = group_info["dataset"]
74
+ zip_path = group_info["zip_file"]
75
+ image_folder = group_info["image_folder"]
76
+
77
+ # Create image folder in temp directory
78
+ temp_image_folder = os.path.join(st.session_state.temp_dir, image_folder)
79
+ os.makedirs(temp_image_folder, exist_ok=True)
80
+
81
+ # Extract images if zip exists
82
+ try:
83
+ if os.path.exists(zip_path):
84
+ with zipfile.ZipFile(zip_path, "r") as zip_ref:
85
+ zip_ref.extractall(temp_image_folder)
86
+ except Exception as e:
87
+ st.warning(f"Error extracting images: {e}")
88
+
89
+ if not os.path.exists(dataset_path):
90
+ st.error(f"Dataset not found: {dataset_path}")
91
+ st.stop()
92
+
93
+ try:
94
+ df = pd.read_excel(dataset_path)
95
+ df['category'] = df['category'].astype(str).str.strip()
96
+ except Exception as e:
97
+ st.error(f"Error loading dataset: {e}")
98
+ st.stop()
99
+
100
+ # Category selection
101
+ categories = sorted(df['category'].dropna().unique())
102
+ selected_category = st.selectbox("πŸ“š Choose a Math Category:", options=categories)
103
+
104
+ # Update session if category changes
105
+ if st.session_state.category != selected_category:
106
+ st.session_state.category = selected_category
107
+ st.session_state.question_index = 0
108
+ st.session_state.show_answer = False
109
+ st.session_state.show_steps = False
110
+ st.rerun()
111
+
112
+ # Filter questions by selected category only
113
+ subset_df = df[df['category'] == selected_category].reset_index(drop=True)
114
+
115
+ if not subset_df.empty and st.session_state.question_index < len(subset_df):
116
+ question = subset_df.iloc[st.session_state.question_index]
117
+ progress = int((st.session_state.question_index / len(subset_df)) * 100)
118
+ st.progress(progress)
119
+
120
+ st.markdown(f"<div class='question-box'>πŸ“˜ <b>Question {st.session_state.question_index + 1}:</b><br><br>{question['problem']}</div>", unsafe_allow_html=True)
121
+
122
+ # Display image with error handling
123
+ if pd.notna(question.get('image')):
124
+ image_name = str(question['image']).strip()
125
+ image_found = False
126
+ for root, _, files in os.walk(temp_image_folder):
127
+ for file in files:
128
+ if file.lower().startswith(image_name.lower()) or os.path.splitext(file)[0].lower() == image_name.lower():
129
+ try:
130
+ st.image(Image.open(os.path.join(root, file)), use_column_width=True)
131
+ image_found = True
132
+ break
133
+ except:
134
+ pass
135
+ if not image_found:
136
+ st.warning("❌ Image not found.")
137
+
138
+ user_ans = st.text_input("πŸ“ Your Answer:", key=f"ans_{st.session_state.question_index}")
139
+
140
+ if st.button("βœ… Submit Answer"):
141
+ if str(user_ans).strip().lower() == str(question['answer']).strip().lower():
142
+ st.success("πŸŽ‰ Correct! Well done!")
143
+ st.balloons()
144
+ time.sleep(2)
145
+ st.session_state.question_index += 1
146
+ st.session_state.show_answer = False
147
+ st.session_state.show_steps = False
148
+ st.rerun()
149
+ else:
150
+ st.error("❌ Try again or view the correct answer below.")
151
+ st.session_state.show_answer = True
152
+ st.session_state.show_steps = False
153
+
154
+ if st.session_state.show_answer:
155
+ st.info(f"βœ… Correct Answer: **{question['answer']}**")
156
+ if selected_age_group in ["7-9 Age Group", "13-15 Age Group"]:
157
+ if st.button("πŸ” Show Steps"):
158
+ st.session_state.show_steps = True
159
+ if st.session_state.show_steps and pd.notna(question.get("steps", None)):
160
+ st.success(f"### πŸͺ„ Steps:\n{question['steps']}")
161
+
162
+ if st.button("⏭️ Skip"):
163
+ st.session_state.question_index += 1
 
 
 
 
 
 
 
 
164
  st.session_state.show_answer = False
165
  st.session_state.show_steps = False
166
  st.rerun()
167
+ elif subset_df.empty:
168
+ st.warning("⚠️ No questions available in this category. Try another one.")
169
+ else:
170
+ st.success("🏁 You've completed all questions in this category!")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
 
172
  # Cleanup function
173
  def cleanup():