NSamson1 commited on
Commit
521ed9e
ยท
verified ยท
1 Parent(s): ab8d97e

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +501 -35
src/streamlit_app.py CHANGED
@@ -7,35 +7,300 @@ from PIL import Image
7
  import sympy as sp
8
  import time
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
  </style>
22
  """, unsafe_allow_html=True)
23
 
24
- # Welcome title
25
- st.markdown("<div class='fun-title'>๐Ÿง โœจ Welcome to the Smart Math Teacher! โœจ๐Ÿง </div>", unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
  # Initialize session state for temp directory
28
  if 'temp_dir' not in st.session_state:
29
  st.session_state.temp_dir = tempfile.mkdtemp()
30
 
31
- # Age group setup
32
  age_groups = {
33
- "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"},
34
- "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"},
35
- "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"},
36
  }
37
 
38
- selected_age_group = st.selectbox("๐Ÿง’ Select your Age Group:", list(age_groups.keys()))
39
 
40
  # Initialize session
41
  if "session_initialized" not in st.session_state or st.session_state.age_group != selected_age_group:
@@ -62,22 +327,23 @@ try:
62
  with zipfile.ZipFile(zip_path, "r") as zip_ref:
63
  zip_ref.extractall(temp_image_folder)
64
  except Exception as e:
65
- st.warning(f"Error extracting images: {e}")
66
 
67
  if not os.path.exists(dataset_path):
68
- st.error(f"Dataset not found: {dataset_path}")
69
  st.stop()
70
 
71
  try:
72
  df = pd.read_excel(dataset_path)
73
  df['category'] = df['category'].astype(str).str.strip()
74
  except Exception as e:
75
- st.error(f"Error loading dataset: {e}")
76
  st.stop()
77
 
78
- # Category selection
79
  categories = sorted(df['category'].dropna().unique())
80
- selected_category = st.selectbox("๐Ÿ“š Choose a Math Category:", options=categories)
 
81
 
82
  # Update session if category changes
83
  if st.session_state.category != selected_category:
@@ -90,12 +356,135 @@ if st.session_state.category != selected_category:
90
  # Filter questions by selected category only
91
  subset_df = df[df['category'] == selected_category].reset_index(drop=True)
92
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  if not subset_df.empty and st.session_state.question_index < len(subset_df):
94
  question = subset_df.iloc[st.session_state.question_index]
95
  progress = int((st.session_state.question_index / len(subset_df)) * 100)
96
- st.progress(progress)
 
 
 
 
 
 
 
 
 
 
 
97
 
98
- 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)
 
 
 
 
 
 
 
 
 
 
99
 
100
  # Display image with error handling
101
  if pd.notna(question.get('image')):
@@ -111,41 +500,118 @@ if not subset_df.empty and st.session_state.question_index < len(subset_df):
111
  except:
112
  pass
113
  if not image_found:
114
- st.warning("โŒ Image not found.")
 
 
 
115
 
116
- user_ans = st.text_input("๐Ÿ“ Your Answer:", key=f"ans_{st.session_state.question_index}")
117
-
118
- if st.button("โœ… Submit Answer"):
119
  if str(user_ans).strip().lower() == str(question['answer']).strip().lower():
120
- st.success("๐ŸŽ‰ Correct! Well done!")
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  st.balloons()
122
- time.sleep(2)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
  st.session_state.question_index += 1
124
  st.session_state.show_answer = False
125
  st.session_state.show_steps = False
126
  st.rerun()
127
  else:
128
- st.error("โŒ Try again or view the correct answer below.")
 
 
 
129
  st.session_state.show_answer = True
130
  st.session_state.show_steps = False
131
 
 
132
  if st.session_state.show_answer:
133
- st.info(f"โœ… Correct Answer: **{question['answer']}**")
134
- if selected_age_group in ["7-9 Age Group", "13-15 Age Group"]:
135
- if st.button("๐Ÿ” Show Steps"):
 
 
 
 
 
 
136
  st.session_state.show_steps = True
137
  if st.session_state.show_steps and pd.notna(question.get("steps", None)):
138
- st.success(f"### ๐Ÿช„ Steps:\n{question['steps']}")
 
 
 
139
 
140
- if st.button("โญ๏ธ Skip"):
 
141
  st.session_state.question_index += 1
142
  st.session_state.show_answer = False
143
  st.session_state.show_steps = False
 
 
144
  st.rerun()
 
145
  elif subset_df.empty:
146
- st.warning("โš ๏ธ No questions available in this category. Try another one.")
 
 
 
147
  else:
148
- st.success("๐Ÿ You've completed all questions in this category!")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
 
150
  # Cleanup function
151
  def cleanup():
@@ -154,4 +620,4 @@ def cleanup():
154
  shutil.rmtree(st.session_state.temp_dir)
155
 
156
  import atexit
157
- atexit.register(cleanup)
 
7
  import sympy as sp
8
  import time
9
  import tempfile
10
+ import random
11
 
12
  # Page config
13
+ st.set_page_config(page_title="๐ŸŽช Math Adventure Land", layout="centered")
14
 
15
+ # Custom CSS with LOTS of fun animations and styles
16
  st.markdown("""
17
  <style>
18
+ @import url('https://fonts.googleapis.com/css2?family=Comic+Neue:wght@700&display=swap');
19
+
20
+ .main-container {
21
+ background: linear-gradient(45deg, #FF6B6B, #4ECDC4, #45B7D1, #96CEB4, #FFEAA7);
22
+ background-size: 400% 400%;
23
+ animation: gradientBG 15s ease infinite;
24
+ padding: 20px;
25
+ border-radius: 25px;
26
+ border: 8px dashed #FFD93D;
27
+ }
28
+
29
+ @keyframes gradientBG {
30
+ 0% { background-position: 0% 50% }
31
+ 50% { background-position: 100% 50% }
32
+ 100% { background-position: 0% 50% }
33
+ }
34
+
35
+ .fun-title {
36
+ font-size: 50px;
37
+ color: #FF6B6B;
38
+ text-align: center;
39
+ font-family: 'Comic Neue', cursive;
40
+ text-shadow: 3px 3px 0 #FFD93D, 6px 6px 0 #4ECDC4;
41
+ animation: bounce 2s infinite;
42
+ margin-bottom: 30px;
43
+ }
44
+
45
+ @keyframes bounce {
46
+ 0%, 100% { transform: translateY(0); }
47
+ 50% { transform: translateY(-20px); }
48
+ }
49
+
50
+ .question-box {
51
+ border: 6px dotted #FF6B6B;
52
+ padding: 25px;
53
+ border-radius: 25px;
54
+ background-color: rgba(255, 255, 255, 0.9);
55
+ font-size: 22px;
56
+ font-family: 'Comic Neue', cursive;
57
+ box-shadow: 0 10px 25px rgba(0,0,0,0.2);
58
+ animation: wiggle 3s ease-in-out infinite;
59
+ margin: 20px 0;
60
+ }
61
+
62
+ @keyframes wiggle {
63
+ 0%, 100% { transform: rotate(-1deg); }
64
+ 50% { transform: rotate(1deg); }
65
+ }
66
+
67
+ .stButton > button {
68
+ font-size: 20px;
69
+ background: linear-gradient(45deg, #FF6B6B, #FFD93D);
70
+ color: white;
71
+ border-radius: 15px;
72
+ padding: 12px 25px;
73
+ border: none;
74
+ font-family: 'Comic Neue', cursive;
75
+ font-weight: bold;
76
+ transition: all 0.3s ease;
77
+ box-shadow: 0 5px 15px rgba(255, 107, 107, 0.4);
78
+ }
79
+
80
+ .stButton > button:hover {
81
+ transform: scale(1.1);
82
+ box-shadow: 0 8px 25px rgba(255, 107, 107, 0.6);
83
+ }
84
+
85
+ .stTextInput > div > input {
86
+ font-size: 20px;
87
+ border-radius: 15px;
88
+ border: 3px solid #4ECDC4;
89
+ padding: 15px;
90
+ font-family: 'Comic Neue', cursive;
91
+ }
92
+
93
+ /* Calculator Styles */
94
+ .calculator-container {
95
+ background: rgba(255, 255, 255, 0.95);
96
+ padding: 25px 30px;
97
+ border-radius: 20px;
98
+ box-shadow: 0 15px 35px rgba(0, 0, 0, 0.2);
99
+ text-align: center;
100
+ width: 320px;
101
+ margin: 20px auto;
102
+ border: 5px solid #FFD93D;
103
+ animation: float 4s ease-in-out infinite;
104
+ }
105
+
106
+ @keyframes float {
107
+ 0%, 100% { transform: translateY(0px); }
108
+ 50% { transform: translateY(-10px); }
109
+ }
110
+
111
+ .calculator-title {
112
+ margin-bottom: 15px;
113
+ color: #FF6B6B;
114
+ font-family: 'Comic Neue', cursive;
115
+ font-size: 28px;
116
+ text-shadow: 2px 2px 0 #FFD93D;
117
+ }
118
+
119
+ .calculator-input {
120
+ width: 80%;
121
+ padding: 12px;
122
+ margin: 10px 0;
123
+ border-radius: 12px;
124
+ border: 3px solid #4ECDC4;
125
+ text-align: center;
126
+ font-size: 18px;
127
+ font-family: 'Comic Neue', cursive;
128
+ background: #FFF9C4;
129
+ }
130
+
131
+ .calculator-buttons {
132
+ margin-top: 15px;
133
+ }
134
+
135
+ .calculator-button {
136
+ margin: 6px;
137
+ padding: 12px 18px;
138
+ border: none;
139
+ border-radius: 12px;
140
+ cursor: pointer;
141
+ font-size: 18px;
142
+ color: white;
143
+ background: linear-gradient(45deg, #4ECDC4, #45B7D1);
144
+ transition: all 0.3s ease;
145
+ font-family: 'Comic Neue', cursive;
146
+ font-weight: bold;
147
+ }
148
+
149
+ .calculator-button:hover {
150
+ transform: scale(1.1);
151
+ background: linear-gradient(45deg, #45B7D1, #4ECDC4);
152
+ }
153
+
154
+ .calculator-clear {
155
+ background: linear-gradient(45deg, #FF6B6B, #FF8E8E);
156
+ }
157
+
158
+ .calculator-clear:hover {
159
+ background: linear-gradient(45deg, #FF8E8E, #FF6B6B);
160
+ }
161
+
162
+ .calculator-result {
163
+ margin-top: 15px;
164
+ font-size: 20px;
165
+ font-weight: bold;
166
+ color: #FF6B6B;
167
+ min-height: 30px;
168
+ font-family: 'Comic Neue', cursive;
169
+ padding: 10px;
170
+ background: #FFF9C4;
171
+ border-radius: 10px;
172
+ border: 2px dashed #FFD93D;
173
+ }
174
+
175
+ /* Fun elements */
176
+ .emoji-rain {
177
+ position: fixed;
178
+ top: 0;
179
+ left: 0;
180
+ pointer-events: none;
181
+ z-index: 9999;
182
+ }
183
+
184
+ .emoji {
185
+ position: absolute;
186
+ font-size: 24px;
187
+ animation: fall linear forwards;
188
+ }
189
+
190
+ @keyframes fall {
191
+ to { transform: translateY(100vh) rotate(360deg); }
192
+ }
193
+
194
+ .confetti {
195
+ position: fixed;
196
+ width: 15px;
197
+ height: 15px;
198
+ background: #FF6B6B;
199
+ animation: confetti-fall 3s linear forwards;
200
+ z-index: 9998;
201
+ }
202
+
203
+ @keyframes confetti-fall {
204
+ 0% { transform: translateY(-100px) rotate(0deg); }
205
+ 100% { transform: translateY(100vh) rotate(360deg); }
206
+ }
207
+
208
+ .progress-bar {
209
+ background: linear-gradient(45deg, #FF6B6B, #FFD93D, #4ECDC4);
210
+ border-radius: 10px;
211
+ height: 25px;
212
+ margin: 20px 0;
213
+ }
214
+
215
+ .animal-characters {
216
+ display: flex;
217
+ justify-content: space-around;
218
+ margin: 20px 0;
219
+ font-size: 40px;
220
+ animation: bounce 2s infinite;
221
+ }
222
  </style>
223
  """, unsafe_allow_html=True)
224
 
225
+ # JavaScript for animations and effects
226
+ st.markdown("""
227
+ <script>
228
+ function createEmojiRain() {
229
+ const emojis = ['๐ŸŽ‰', '๐ŸŽˆ', 'โญ', '๐ŸŽŠ', '๐ŸŒˆ', '๐Ÿš€', '๐ŸŽจ', '๐Ÿฑ', '๐Ÿถ', '๐Ÿฆ„'];
230
+ const container = document.createElement('div');
231
+ container.className = 'emoji-rain';
232
+ document.body.appendChild(container);
233
+
234
+ for (let i = 0; i < 50; i++) {
235
+ setTimeout(() => {
236
+ const emoji = document.createElement('div');
237
+ emoji.className = 'emoji';
238
+ emoji.textContent = emojis[Math.floor(Math.random() * emojis.length)];
239
+ emoji.style.left = Math.random() * 100 + 'vw';
240
+ emoji.style.animationDuration = (Math.random() * 3 + 2) + 's';
241
+ container.appendChild(emoji);
242
+
243
+ setTimeout(() => emoji.remove(), 5000);
244
+ }, i * 100);
245
+ }
246
+
247
+ setTimeout(() => container.remove(), 6000);
248
+ }
249
+
250
+ function createConfetti() {
251
+ const colors = ['#FF6B6B', '#4ECDC4', '#FFD93D', '#45B7D1', '#96CEB4'];
252
+ for (let i = 0; i < 150; i++) {
253
+ setTimeout(() => {
254
+ const confetti = document.createElement('div');
255
+ confetti.className = 'confetti';
256
+ confetti.style.background = colors[Math.floor(Math.random() * colors.length)];
257
+ confetti.style.left = Math.random() * 100 + 'vw';
258
+ confetti.style.animationDuration = (Math.random() * 2 + 1) + 's';
259
+ document.body.appendChild(confetti);
260
+
261
+ setTimeout(() => confetti.remove(), 3000);
262
+ }, i * 10);
263
+ }
264
+ }
265
+
266
+ function celebrate() {
267
+ createEmojiRain();
268
+ createConfetti();
269
+ // Play celebration sound (you can add actual sound files)
270
+ console.log("๐ŸŽ‰ Celebration time!");
271
+ }
272
+ </script>
273
+ """, unsafe_allow_html=True)
274
+
275
+ # Welcome title with fun characters
276
+ st.markdown("""
277
+ <div class="main-container">
278
+ <div class="animal-characters">
279
+ <span>๐Ÿฑ</span>
280
+ <span>๐Ÿถ</span>
281
+ <span>๐Ÿฆ„</span>
282
+ <span>๐Ÿผ</span>
283
+ <span>๐Ÿฏ</span>
284
+ </div>
285
+ <div class="fun-title">๐ŸŽช Welcome to Math Adventure Land! ๐ŸŽช</div>
286
+ <div style="text-align: center; font-size: 24px; color: #FF6B6B; font-family: 'Comic Neue', cursive;">
287
+ Where Numbers Become Friends! ๐Ÿค—
288
+ </div>
289
+ </div>
290
+ """, unsafe_allow_html=True)
291
 
292
  # Initialize session state for temp directory
293
  if 'temp_dir' not in st.session_state:
294
  st.session_state.temp_dir = tempfile.mkdtemp()
295
 
296
+ # Age group setup with fun descriptions
297
  age_groups = {
298
+ "๐Ÿ‘ถ Little Explorers (4-6)": {"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", "emoji": "๐Ÿ‘ถ"},
299
+ "๐Ÿš€ Math Adventurers (7-9)": {"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", "emoji": "๐Ÿš€"},
300
+ "๐ŸŒŸ Math Wizards (13-15)": {"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", "emoji": "๐ŸŒŸ"}
301
  }
302
 
303
+ selected_age_group = st.selectbox("๐ŸŽฏ Choose Your Adventure Level:", list(age_groups.keys()))
304
 
305
  # Initialize session
306
  if "session_initialized" not in st.session_state or st.session_state.age_group != selected_age_group:
 
327
  with zipfile.ZipFile(zip_path, "r") as zip_ref:
328
  zip_ref.extractall(temp_image_folder)
329
  except Exception as e:
330
+ st.warning(f"โš ๏ธ Oops! Our image treasure chest is hiding! {e}")
331
 
332
  if not os.path.exists(dataset_path):
333
+ st.error(f"โŒ Adventure map not found: {dataset_path}")
334
  st.stop()
335
 
336
  try:
337
  df = pd.read_excel(dataset_path)
338
  df['category'] = df['category'].astype(str).str.strip()
339
  except Exception as e:
340
+ st.error(f"โŒ Oh no! The math treasure got mixed up! {e}")
341
  st.stop()
342
 
343
+ # Category selection with fun names
344
  categories = sorted(df['category'].dropna().unique())
345
+ category_emojis = {"Addition": "โž•", "Subtraction": "โž–", "Multiplication": "โœ–๏ธ", "Division": "โž—", "Geometry": "๐Ÿ“", "Algebra": "๐Ÿ“Š"}
346
+ selected_category = st.selectbox("๐Ÿ“š Choose Your Math Quest:", options=categories)
347
 
348
  # Update session if category changes
349
  if st.session_state.category != selected_category:
 
356
  # Filter questions by selected category only
357
  subset_df = df[df['category'] == selected_category].reset_index(drop=True)
358
 
359
+ # ๐Ÿงฎ SUPER FUN CALCULATOR SECTION
360
+ st.markdown("---")
361
+ st.markdown("<h2 style='text-align: center; color: #FF6B6B; font-family: Comic Neue, cursive;'>๐Ÿงฎ Magical Math Calculator ๐Ÿงฎ</h2>", unsafe_allow_html=True)
362
+ st.markdown("<p style='text-align: center; font-size: 18px; color: #4ECDC4;'>Use this magical calculator to help with your math adventures! โœจ</p>", unsafe_allow_html=True)
363
+
364
+ # Create calculator in columns
365
+ col1, col2, col3 = st.columns([1, 2, 1])
366
+
367
+ with col2:
368
+ st.markdown(f"""
369
+ <div class="calculator-container">
370
+ <h3 class="calculator-title">โœจ Magic Calculator โœจ</h3>
371
+ <input type="number" id="num1" class="calculator-input" placeholder="๐Ÿ”ข First number">
372
+ <input type="number" id="num2" class="calculator-input" placeholder="๐Ÿ”ข Second number">
373
+
374
+ <div class="calculator-buttons">
375
+ <button class="calculator-button" onclick="calculate('+')">โž• Add</button>
376
+ <button class="calculator-button" onclick="calculate('-')">โž– Subtract</button>
377
+ <button class="calculator-button" onclick="calculate('*')">โœ–๏ธ Multiply</button>
378
+ <button class="calculator-button" onclick="calculate('/')">โž— Divide</button>
379
+ <button class="calculator-button calculator-clear" onclick="clearCalculator()">๐Ÿงน Clear</button>
380
+ </div>
381
+
382
+ <div id="result" class="calculator-result">๐ŸŽฏ Your answer will appear here!</div>
383
+ </div>
384
+ """, unsafe_allow_html=True)
385
+
386
+ # JavaScript for calculator with fun messages
387
+ st.markdown("""
388
+ <script>
389
+ function calculate(operator) {
390
+ const num1 = parseFloat(document.getElementById('num1').value);
391
+ const num2 = parseFloat(document.getElementById('num2').value);
392
+ const resultDisplay = document.getElementById('result');
393
+
394
+ // Error handling for invalid input
395
+ if (isNaN(num1) || isNaN(num2)) {
396
+ resultDisplay.innerHTML = "โš ๏ธ Oops! Please enter magical numbers! โœจ";
397
+ resultDisplay.style.color = "#FF6B6B";
398
+ return;
399
+ }
400
+
401
+ let result;
402
+ let emoji = "๐ŸŽ‰";
403
+ switch (operator) {
404
+ case '+':
405
+ result = num1 + num2;
406
+ emoji = "๐ŸŽŠ";
407
+ break;
408
+ case '-':
409
+ result = num1 - num2;
410
+ emoji = "๐Ÿš€";
411
+ break;
412
+ case '*':
413
+ result = num1 * num2;
414
+ emoji = "๐ŸŒˆ";
415
+ break;
416
+ case '/':
417
+ if (num2 === 0) {
418
+ resultDisplay.innerHTML = "โŒ Whoa! You can't divide by zero! ๐Ÿšซ";
419
+ resultDisplay.style.color = "#FF6B6B";
420
+ return;
421
+ }
422
+ result = num1 / num2;
423
+ emoji = "โญ";
424
+ break;
425
+ default:
426
+ resultDisplay.innerHTML = "๐Ÿค” Unknown magic operation!";
427
+ return;
428
+ }
429
+
430
+ resultDisplay.innerHTML = `${emoji} Magical Result: <strong>${result}</strong> ${emoji}`;
431
+ resultDisplay.style.color = "#4ECDC4";
432
+
433
+ // Mini celebration for calculator
434
+ if(Math.abs(result) > 100) {
435
+ setTimeout(() => {
436
+ const miniEmoji = document.createElement('div');
437
+ miniEmoji.textContent = '๐ŸŽ‰';
438
+ miniEmoji.style.position = 'fixed';
439
+ miniEmoji.style.fontSize = '30px';
440
+ miniEmoji.style.left = Math.random() * 100 + 'vw';
441
+ miniEmoji.style.animation = 'fall 2s linear forwards';
442
+ document.body.appendChild(miniEmoji);
443
+ setTimeout(() => miniEmoji.remove(), 2000);
444
+ }, 100);
445
+ }
446
+ }
447
+
448
+ // Clear function
449
+ function clearCalculator() {
450
+ document.getElementById('num1').value = '';
451
+ document.getElementById('num2').value = '';
452
+ document.getElementById('result').innerHTML = "๐ŸŽฏ Your answer will appear here!";
453
+ document.getElementById('result').style.color = "#FF6B6B";
454
+ }
455
+ </script>
456
+ """, unsafe_allow_html=True)
457
+
458
+ st.markdown("---")
459
+
460
+ # ๐ŸŽฎ MATH QUESTIONS SECTION
461
  if not subset_df.empty and st.session_state.question_index < len(subset_df):
462
  question = subset_df.iloc[st.session_state.question_index]
463
  progress = int((st.session_state.question_index / len(subset_df)) * 100)
464
+
465
+ # Fun progress bar
466
+ st.markdown(f"""
467
+ <div style="text-align: center; margin: 20px 0;">
468
+ <div style="font-family: 'Comic Neue', cursive; color: #FF6B6B; font-size: 18px;">
469
+ ๐ŸŽฏ Adventure Progress: {st.session_state.question_index + 1} of {len(subset_df)}
470
+ </div>
471
+ <div class="progress-bar" style="width: 100%; background: #f0f0f0; border-radius: 10px; height: 25px;">
472
+ <div style="width: {progress}%; background: linear-gradient(45deg, #FF6B6B, #FFD93D); height: 100%; border-radius: 10px; transition: width 0.5s;"></div>
473
+ </div>
474
+ </div>
475
+ """, unsafe_allow_html=True)
476
 
477
+ # Display question with fun styling
478
+ category_emoji = category_emojis.get(selected_category, "โ“")
479
+ st.markdown(f"""
480
+ <div class="question-box">
481
+ <div style="text-align: center; font-size: 30px; margin-bottom: 15px;">
482
+ {category_emoji} Challenge {st.session_state.question_index + 1} {category_emoji}
483
+ </div>
484
+ ๐Ÿ“˜ <b>Math Quest:</b><br><br>
485
+ {question['problem']}
486
+ </div>
487
+ """, unsafe_allow_html=True)
488
 
489
  # Display image with error handling
490
  if pd.notna(question.get('image')):
 
500
  except:
501
  pass
502
  if not image_found:
503
+ st.warning("๐Ÿ–ผ๏ธ Oh no! The picture is playing hide and seek!")
504
+
505
+ # Fun answer input
506
+ user_ans = st.text_input("โœ๏ธ Your Magical Answer:", key=f"ans_{st.session_state.question_index}")
507
 
508
+ # Submit button with celebration
509
+ if st.button("๐ŸŽฏ Submit Answer", key=f"submit_{st.session_state.question_index}"):
 
510
  if str(user_ans).strip().lower() == str(question['answer']).strip().lower():
511
+ # MEGA CELEBRATION FOR CORRECT ANSWER!
512
+ st.markdown("""
513
+ <script>
514
+ celebrate();
515
+ </script>
516
+ """, unsafe_allow_html=True)
517
+
518
+ st.success("""
519
+ ๐ŸŽ‰โœจ AMAZING! YOU'RE A MATH SUPERSTAR! โœจ๐ŸŽ‰
520
+ """)
521
+
522
+ # Multiple balloons and effects
523
+ st.balloons()
524
+ st.balloons()
525
  st.balloons()
526
+
527
+ # Fun success message with random emojis
528
+ success_messages = [
529
+ "๐ŸŒŸ You're shining brighter than a supernova!",
530
+ "๐Ÿš€ To infinity and beyond! Math genius detected!",
531
+ "๐ŸŒˆ You just painted the town with math brilliance!",
532
+ "๐ŸŽŠ Party time! You nailed it!",
533
+ "๐Ÿฆ„ Unicorn-level math skills activated!"
534
+ ]
535
+
536
+ st.markdown(f"""
537
+ <div style="text-align: center; font-size: 24px; color: #FF6B6B; font-family: 'Comic Neue', cursive; padding: 20px;">
538
+ {random.choice(success_messages)}
539
+ </div>
540
+ """, unsafe_allow_html=True)
541
+
542
+ time.sleep(3)
543
  st.session_state.question_index += 1
544
  st.session_state.show_answer = False
545
  st.session_state.show_steps = False
546
  st.rerun()
547
  else:
548
+ st.error("""
549
+ โŒ Oops! That's not quite right, but don't give up!
550
+ Every great math wizard makes mistakes sometimes! ๐Ÿ’ซ
551
+ """)
552
  st.session_state.show_answer = True
553
  st.session_state.show_steps = False
554
 
555
+ # Show answer with encouragement
556
  if st.session_state.show_answer:
557
+ st.info(f"""
558
+ ๐Ÿ’ก **Hint from Your Math Friend:**
559
+ The magical answer is **{question['answer']}**
560
+
561
+ Remember: Even math superheroes need help sometimes! ๐Ÿฆธ
562
+ """)
563
+
564
+ if selected_age_group in ["๐Ÿš€ Math Adventurers (7-9)", "๐ŸŒŸ Math Wizards (13-15)"]:
565
+ if st.button("๐Ÿ” Show Magic Steps", key=f"steps_{st.session_state.question_index}"):
566
  st.session_state.show_steps = True
567
  if st.session_state.show_steps and pd.notna(question.get("steps", None)):
568
+ st.success(f"""
569
+ ### ๐Ÿช„ Secret Math Magic:
570
+ {question['steps']}
571
+ """)
572
 
573
+ # Skip button with fun message
574
+ if st.button("โญ๏ธ Skip to Next Adventure", key=f"skip_{st.session_state.question_index}"):
575
  st.session_state.question_index += 1
576
  st.session_state.show_answer = False
577
  st.session_state.show_steps = False
578
+ st.info("๐Ÿ’จ Zooming to the next challenge! Get ready! ๐Ÿš€")
579
+ time.sleep(1)
580
  st.rerun()
581
+
582
  elif subset_df.empty:
583
+ st.warning("""
584
+ โš ๏ธ Oh dear! No math adventures here yet!
585
+ Try another magical category! ๐Ÿง™
586
+ """)
587
  else:
588
+ # GRAND FINALE CELEBRATION!
589
+ st.markdown("""
590
+ <div style="text-align: center; padding: 40px;">
591
+ <div style="font-size: 60px; margin-bottom: 20px;">
592
+ ๐Ÿ†๐ŸŽ‰โœจ
593
+ </div>
594
+ <h1 style="color: #FF6B6B; font-family: 'Comic Neue', cursive;">
595
+ YOU DID IT! MATH CHAMPION! ๐Ÿ…
596
+ </h1>
597
+ <p style="font-size: 24px; color: #4ECDC4;">
598
+ You've completed all the challenges in this category!<br>
599
+ </p>
600
+ <div style="font-size: 40px; margin: 20px 0;">
601
+ ๐ŸŒŸ๐ŸŽŠ๐Ÿ‘‘๐ŸŽˆ๐Ÿš€
602
+ </div>
603
+ </div>
604
+ """, unsafe_allow_html=True)
605
+
606
+ st.balloons()
607
+ st.balloons()
608
+ st.balloons()
609
+
610
+ if st.button("๐Ÿ”„ Start New Adventure"):
611
+ st.session_state.question_index = 0
612
+ st.session_state.show_answer = False
613
+ st.session_state.show_steps = False
614
+ st.rerun()
615
 
616
  # Cleanup function
617
  def cleanup():
 
620
  shutil.rmtree(st.session_state.temp_dir)
621
 
622
  import atexit
623
+ atexit.register(cleanup)