NSamson1 commited on
Commit
b6e28f4
·
verified ·
1 Parent(s): 74b5d8e

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +416 -330
src/streamlit_app.py CHANGED
@@ -10,7 +10,7 @@ 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("""
@@ -24,6 +24,7 @@ st.markdown("""
24
  padding: 20px;
25
  border-radius: 25px;
26
  border: 8px dashed #FFD93D;
 
27
  }
28
 
29
  @keyframes gradientBG {
@@ -90,86 +91,84 @@ st.markdown("""
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 */
@@ -219,12 +218,23 @@ st.markdown("""
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');
@@ -266,9 +276,107 @@ function createConfetti() {
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
 
@@ -300,318 +408,296 @@ age_groups = {
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:
307
- st.session_state.age_group = selected_age_group
308
- st.session_state.category = None
309
- st.session_state.question_index = 0
310
- st.session_state.show_answer = False
311
- st.session_state.show_steps = False
312
- st.session_state.session_initialized = True
313
-
314
- # Load dataset
315
- group_info = age_groups[selected_age_group]
316
- dataset_path = group_info["dataset"]
317
- zip_path = group_info["zip_file"]
318
- image_folder = group_info["image_folder"]
319
-
320
- # Create image folder in temp directory
321
- temp_image_folder = os.path.join(st.session_state.temp_dir, image_folder)
322
- os.makedirs(temp_image_folder, exist_ok=True)
323
-
324
- # Extract images if zip exists
325
- try:
326
- if os.path.exists(zip_path):
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:
350
- st.session_state.category = selected_category
351
- st.session_state.question_index = 0
352
- st.session_state.show_answer = False
353
- st.session_state.show_steps = False
354
- st.rerun()
355
-
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')):
491
- image_name = str(question['image']).strip()
492
- image_found = False
493
- for root, _, files in os.walk(temp_image_folder):
494
- for file in files:
495
- if file.lower().startswith(image_name.lower()) or os.path.splitext(file)[0].lower() == image_name.lower():
496
- try:
497
- st.image(Image.open(os.path.join(root, file)), use_column_width=True)
498
- image_found = True
499
- break
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():
 
10
  import random
11
 
12
  # Page config
13
+ st.set_page_config(page_title="🎪 Math Adventure Land", layout="wide")
14
 
15
  # Custom CSS with LOTS of fun animations and styles
16
  st.markdown("""
 
24
  padding: 20px;
25
  border-radius: 25px;
26
  border: 8px dashed #FFD93D;
27
+ margin-bottom: 20px;
28
  }
29
 
30
  @keyframes gradientBG {
 
91
  font-family: 'Comic Neue', cursive;
92
  }
93
 
94
+ /* Compact Calculator Styles */
95
  .calculator-container {
96
  background: rgba(255, 255, 255, 0.95);
97
+ padding: 15px;
98
+ border-radius: 15px;
99
+ box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
100
  text-align: center;
101
+ border: 4px solid #FFD93D;
 
 
102
  animation: float 4s ease-in-out infinite;
103
+ margin-bottom: 20px;
104
  }
105
 
106
  @keyframes float {
107
  0%, 100% { transform: translateY(0px); }
108
+ 50% { transform: translateY(-5px); }
109
  }
110
 
111
  .calculator-title {
112
+ margin-bottom: 10px;
113
  color: #FF6B6B;
114
  font-family: 'Comic Neue', cursive;
115
+ font-size: 20px;
116
+ text-shadow: 1px 1px 0 #FFD93D;
117
  }
118
 
119
+ .calculator-display {
120
+ width: 100%;
121
  padding: 12px;
122
+ margin: 8px 0;
123
+ border-radius: 10px;
124
  border: 3px solid #4ECDC4;
125
+ text-align: right;
126
  font-size: 18px;
127
  font-family: 'Comic Neue', cursive;
128
  background: #FFF9C4;
129
+ font-weight: bold;
130
  }
131
 
132
+ .calculator-buttons-compact {
133
+ display: grid;
134
+ grid-template-columns: repeat(4, 1fr);
135
+ gap: 5px;
136
+ margin-top: 10px;
137
  }
138
 
139
+ .calc-btn {
140
+ padding: 10px 5px;
 
141
  border: none;
142
+ border-radius: 8px;
143
  cursor: pointer;
144
+ font-size: 16px;
145
  color: white;
146
  background: linear-gradient(45deg, #4ECDC4, #45B7D1);
147
+ transition: all 0.2s ease;
148
  font-family: 'Comic Neue', cursive;
149
  font-weight: bold;
150
  }
151
 
152
+ .calc-btn:hover {
153
+ transform: scale(1.05);
154
  background: linear-gradient(45deg, #45B7D1, #4ECDC4);
155
  }
156
 
157
+ .calc-btn-clear {
158
  background: linear-gradient(45deg, #FF6B6B, #FF8E8E);
159
  }
160
 
161
+ .calc-btn-clear:hover {
162
  background: linear-gradient(45deg, #FF8E8E, #FF6B6B);
163
  }
164
 
165
+ .calc-btn-equals {
166
+ background: linear-gradient(45deg, #96CEB4, #4ECDC4);
167
+ grid-column: span 2;
168
+ }
169
+
170
+ .calc-btn-zero {
171
+ grid-column: span 2;
 
 
 
 
172
  }
173
 
174
  /* Fun elements */
 
218
  font-size: 40px;
219
  animation: bounce 2s infinite;
220
  }
221
+
222
+ /* Sidebar styling */
223
+ .sidebar-content {
224
+ padding: 10px;
225
+ }
226
+
227
+ /* Main content area */
228
+ .main-content {
229
+ padding: 20px;
230
+ }
231
  </style>
232
  """, unsafe_allow_html=True)
233
 
234
+ # JavaScript for animations and calculator
235
  st.markdown("""
236
  <script>
237
+ // Celebration functions
238
  function createEmojiRain() {
239
  const emojis = ['🎉', '🎈', '⭐', '🎊', '🌈', '🚀', '🎨', '🐱', '🐶', '🦄'];
240
  const container = document.createElement('div');
 
276
  function celebrate() {
277
  createEmojiRain();
278
  createConfetti();
 
 
279
  }
280
+
281
+ // Calculator functionality
282
+ let currentInput = '0';
283
+ let previousInput = '';
284
+ let operation = null;
285
+ let resetScreen = false;
286
+
287
+ function updateDisplay() {
288
+ const display = document.getElementById('calc-display');
289
+ if (display) {
290
+ display.value = currentInput;
291
+ }
292
+ }
293
+
294
+ function appendNumber(number) {
295
+ if (currentInput === '0' || resetScreen) {
296
+ currentInput = number;
297
+ resetScreen = false;
298
+ } else {
299
+ currentInput += number;
300
+ }
301
+ updateDisplay();
302
+ }
303
+
304
+ function chooseOperation(op) {
305
+ if (currentInput === '') return;
306
+
307
+ if (previousInput !== '') {
308
+ compute();
309
+ }
310
+ operation = op;
311
+ previousInput = currentInput;
312
+ resetScreen = true;
313
+ }
314
+
315
+ function compute() {
316
+ let computation;
317
+ const prev = parseFloat(previousInput);
318
+ const current = parseFloat(currentInput);
319
+
320
+ if (isNaN(prev) || isNaN(current)) return;
321
+
322
+ switch (operation) {
323
+ case '+':
324
+ computation = prev + current;
325
+ break;
326
+ case '-':
327
+ computation = prev - current;
328
+ break;
329
+ case '*':
330
+ computation = prev * current;
331
+ break;
332
+ case '/':
333
+ computation = prev / current;
334
+ break;
335
+ default:
336
+ return;
337
+ }
338
+
339
+ currentInput = computation.toString();
340
+ operation = undefined;
341
+ previousInput = '';
342
+ resetScreen = true;
343
+ updateDisplay();
344
+
345
+ // Mini celebration for big results
346
+ if (Math.abs(computation) > 1000) {
347
+ const miniEmoji = document.createElement('div');
348
+ miniEmoji.textContent = '🎉';
349
+ miniEmoji.style.position = 'fixed';
350
+ miniEmoji.style.fontSize = '20px';
351
+ miniEmoji.style.left = Math.random() * 100 + 'vw';
352
+ miniEmoji.style.animation = 'fall 2s linear forwards';
353
+ document.body.appendChild(miniEmoji);
354
+ setTimeout(() => miniEmoji.remove(), 2000);
355
+ }
356
+ }
357
+
358
+ function clearCalculator() {
359
+ currentInput = '0';
360
+ previousInput = '';
361
+ operation = null;
362
+ updateDisplay();
363
+ }
364
+
365
+ function appendDecimal() {
366
+ if (resetScreen) {
367
+ currentInput = '0';
368
+ resetScreen = false;
369
+ }
370
+ if (!currentInput.includes('.')) {
371
+ currentInput += '.';
372
+ }
373
+ updateDisplay();
374
+ }
375
+
376
+ // Initialize calculator
377
+ document.addEventListener('DOMContentLoaded', function() {
378
+ updateDisplay();
379
+ });
380
  </script>
381
  """, unsafe_allow_html=True)
382
 
 
408
  "🌟 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": "🌟"}
409
  }
410
 
411
+ # SIDEBAR - Calculator and Controls
412
+ with st.sidebar:
413
+ st.markdown("### 🧮 Math Helper Calculator")
414
+ st.markdown("Use this calculator to help with your math problems! ✨")
415
+
416
+ # Compact Calculator
417
+ st.markdown("""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
418
  <div class="calculator-container">
419
+ <div class="calculator-title">✨ Magic Calculator ✨</div>
420
+ <input type="text" id="calc-display" class="calculator-display" readonly value="0">
 
421
 
422
+ <div class="calculator-buttons-compact">
423
+ <button class="calc-btn calc-btn-clear" onclick="clearCalculator()">C</button>
424
+ <button class="calc-btn calc-btn-clear" onclick="currentInput = currentInput.slice(0, -1) || '0'; updateDisplay();">⌫</button>
425
+ <button class="calc-btn" onclick="chooseOperation('/')">/</button>
426
+ <button class="calc-btn" onclick="chooseOperation('*')">×</button>
427
+
428
+ <button class="calc-btn" onclick="appendNumber('7')">7</button>
429
+ <button class="calc-btn" onclick="appendNumber('8')">8</button>
430
+ <button class="calc-btn" onclick="appendNumber('9')">9</button>
431
+ <button class="calc-btn" onclick="chooseOperation('-')">-</button>
432
+
433
+ <button class="calc-btn" onclick="appendNumber('4')">4</button>
434
+ <button class="calc-btn" onclick="appendNumber('5')">5</button>
435
+ <button class="calc-btn" onclick="appendNumber('6')">6</button>
436
+ <button class="calc-btn" onclick="chooseOperation('+')">+</button>
437
+
438
+ <button class="calc-btn" onclick="appendNumber('1')">1</button>
439
+ <button class="calc-btn" onclick="appendNumber('2')">2</button>
440
+ <button class="calc-btn" onclick="appendNumber('3')">3</button>
441
+ <button class="calc-btn calc-btn-equals" onclick="compute()" rowspan="2">=</button>
442
+
443
+ <button class="calc-btn calc-btn-zero" onclick="appendNumber('0')">0</button>
444
+ <button class="calc-btn" onclick="appendDecimal()">.</button>
445
  </div>
 
 
446
  </div>
447
  """, unsafe_allow_html=True)
448
 
449
+ st.markdown("---")
450
+ st.markdown("### 🎯 Quick Tips")
451
+ st.info("""
452
+ 💡 **Calculator Help:**
453
+ - Click numbers and operators
454
+ - Press = to calculate
455
+ - Press C to clear
456
+ - Use backspace (⌫) to erase
457
+ """)
458
+
459
+ st.markdown("---")
460
+ st.markdown("### 📚 Need Help?")
461
+ st.write("Stuck on a problem? Use the calculator above or ask for hints! 🦸")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
462
 
463
+ # MAIN CONTENT AREA
464
+ col1, col2 = st.columns([3, 1])
465
 
466
+ with col1:
467
+ # Age group selection
468
+ selected_age_group = st.selectbox("🎯 Choose Your Adventure Level:", list(age_groups.keys()))
 
 
 
 
 
 
 
 
 
 
 
 
 
469
 
470
+ # Initialize session
471
+ if "session_initialized" not in st.session_state or st.session_state.age_group != selected_age_group:
472
+ st.session_state.age_group = selected_age_group
473
+ st.session_state.category = None
474
+ st.session_state.question_index = 0
475
+ st.session_state.show_answer = False
476
+ st.session_state.show_steps = False
477
+ st.session_state.session_initialized = True
478
+
479
+ # Load dataset
480
+ group_info = age_groups[selected_age_group]
481
+ dataset_path = group_info["dataset"]
482
+ zip_path = group_info["zip_file"]
483
+ image_folder = group_info["image_folder"]
484
+
485
+ # Create image folder in temp directory
486
+ temp_image_folder = os.path.join(st.session_state.temp_dir, image_folder)
487
+ os.makedirs(temp_image_folder, exist_ok=True)
488
+
489
+ # Extract images if zip exists
490
+ try:
491
+ if os.path.exists(zip_path):
492
+ with zipfile.ZipFile(zip_path, "r") as zip_ref:
493
+ zip_ref.extractall(temp_image_folder)
494
+ except Exception as e:
495
+ st.warning(f"⚠️ Oops! Our image treasure chest is hiding! {e}")
496
+
497
+ if not os.path.exists(dataset_path):
498
+ st.error(f"❌ Adventure map not found: {dataset_path}")
499
+ st.stop()
500
+
501
+ try:
502
+ df = pd.read_excel(dataset_path)
503
+ df['category'] = df['category'].astype(str).str.strip()
504
+ except Exception as e:
505
+ st.error(f"❌ Oh no! The math treasure got mixed up! {e}")
506
+ st.stop()
507
+
508
+ # Category selection with fun names
509
+ categories = sorted(df['category'].dropna().unique())
510
+ category_emojis = {"Addition": "➕", "Subtraction": "➖", "Multiplication": "✖️", "Division": "➗", "Geometry": "📐", "Algebra": "📊"}
511
+ selected_category = st.selectbox("📚 Choose Your Math Quest:", options=categories)
512
+
513
+ # Update session if category changes
514
+ if st.session_state.category != selected_category:
515
+ st.session_state.category = selected_category
516
+ st.session_state.question_index = 0
517
+ st.session_state.show_answer = False
518
+ st.session_state.show_steps = False
519
+ st.rerun()
520
+
521
+ # Filter questions by selected category only
522
+ subset_df = df[df['category'] == selected_category].reset_index(drop=True)
523
+
524
+ # 🎮 MATH QUESTIONS SECTION
525
+ if not subset_df.empty and st.session_state.question_index < len(subset_df):
526
+ question = subset_df.iloc[st.session_state.question_index]
527
+ progress = int((st.session_state.question_index / len(subset_df)) * 100)
528
+
529
+ # Fun progress bar
530
+ st.markdown(f"""
531
+ <div style="text-align: center; margin: 20px 0;">
532
+ <div style="font-family: 'Comic Neue', cursive; color: #FF6B6B; font-size: 18px;">
533
+ 🎯 Adventure Progress: {st.session_state.question_index + 1} of {len(subset_df)}
534
+ </div>
535
+ <div class="progress-bar" style="width: 100%; background: #f0f0f0; border-radius: 10px; height: 25px;">
536
+ <div style="width: {progress}%; background: linear-gradient(45deg, #FF6B6B, #FFD93D); height: 100%; border-radius: 10px; transition: width 0.5s;"></div>
537
+ </div>
538
  </div>
539
+ """, unsafe_allow_html=True)
540
+
541
+ # Display question with fun styling
542
+ category_emoji = category_emojis.get(selected_category, "")
543
+ st.markdown(f"""
544
+ <div class="question-box">
545
+ <div style="text-align: center; font-size: 30px; margin-bottom: 15px;">
546
+ {category_emoji} Challenge {st.session_state.question_index + 1} {category_emoji}
547
+ </div>
548
+ 📘 <b>Math Quest:</b><br><br>
549
+ {question['problem']}
550
+ </div>
551
+ """, unsafe_allow_html=True)
552
+
553
+ # Display image with error handling
554
+ if pd.notna(question.get('image')):
555
+ image_name = str(question['image']).strip()
556
+ image_found = False
557
+ for root, _, files in os.walk(temp_image_folder):
558
+ for file in files:
559
+ if file.lower().startswith(image_name.lower()) or os.path.splitext(file)[0].lower() == image_name.lower():
560
+ try:
561
+ st.image(Image.open(os.path.join(root, file)), use_column_width=True)
562
+ image_found = True
563
+ break
564
+ except:
565
+ pass
566
+ if not image_found:
567
+ st.warning("🖼️ Oh no! The picture is playing hide and seek!")
568
+
569
+ # Fun answer input
570
+ user_ans = st.text_input("✏️ Your Magical Answer:", key=f"ans_{st.session_state.question_index}")
571
 
572
+ # Submit button with celebration
573
+ col_btn1, col_btn2, col_btn3 = st.columns([1, 1, 1])
574
+
575
+ with col_btn1:
576
+ if st.button("🎯 Submit Answer", key=f"submit_{st.session_state.question_index}", use_container_width=True):
577
+ if str(user_ans).strip().lower() == str(question['answer']).strip().lower():
578
+ # MEGA CELEBRATION FOR CORRECT ANSWER!
579
+ st.markdown("""
580
+ <script>
581
+ celebrate();
582
+ </script>
583
+ """, unsafe_allow_html=True)
584
+
585
+ st.success("""
586
+ 🎉✨ AMAZING! YOU'RE A MATH SUPERSTAR! ✨🎉
587
+ """)
588
+
589
+ # Multiple balloons and effects
590
+ st.balloons()
591
+ st.balloons()
592
+ st.balloons()
593
+
594
+ # Fun success message with random emojis
595
+ success_messages = [
596
+ "🌟 You're shining brighter than a supernova!",
597
+ "🚀 To infinity and beyond! Math genius detected!",
598
+ "🌈 You just painted the town with math brilliance!",
599
+ "🎊 Party time! You nailed it!",
600
+ "🦄 Unicorn-level math skills activated!"
601
+ ]
602
+
603
+ st.markdown(f"""
604
+ <div style="text-align: center; font-size: 24px; color: #FF6B6B; font-family: 'Comic Neue', cursive; padding: 20px;">
605
+ {random.choice(success_messages)}
606
+ </div>
607
+ """, unsafe_allow_html=True)
608
+
609
+ time.sleep(3)
610
+ st.session_state.question_index += 1
611
+ st.session_state.show_answer = False
612
+ st.session_state.show_steps = False
613
+ st.rerun()
614
+ else:
615
+ st.error("""
616
+ ❌ Oops! That's not quite right, but don't give up!
617
+ Every great math wizard makes mistakes sometimes! 💫
618
+ """)
619
+ st.session_state.show_answer = True
620
+ st.session_state.show_steps = False
621
+
622
+ with col_btn2:
623
+ if st.button("⏭️ Skip Challenge", key=f"skip_{st.session_state.question_index}", use_container_width=True):
624
+ st.session_state.question_index += 1
625
+ st.session_state.show_answer = False
626
+ st.session_state.show_steps = False
627
+ st.info("💨 Zooming to the next challenge! Get ready! 🚀")
628
+ time.sleep(1)
629
+ st.rerun()
630
+
631
+ # Show answer with encouragement
632
+ if st.session_state.show_answer:
633
+ st.info(f"""
634
+ 💡 **Hint from Your Math Friend:**
635
+ The magical answer is **{question['answer']}**
636
 
637
+ Remember: Even math superheroes need help sometimes! 🦸
 
638
  """)
639
 
640
+ if selected_age_group in ["🚀 Math Adventurers (7-9)", "🌟 Math Wizards (13-15)"]:
641
+ if st.button("🔍 Show Magic Steps", key=f"steps_{st.session_state.question_index}"):
642
+ st.session_state.show_steps = True
643
+ if st.session_state.show_steps and pd.notna(question.get("steps", None)):
644
+ st.success(f"""
645
+ ### 🪄 Secret Math Magic:
646
+ {question['steps']}
647
+ """)
648
 
649
+ elif subset_df.empty:
650
+ st.warning("""
651
+ ⚠️ Oh dear! No math adventures here yet!
652
+ Try another magical category! 🧙
653
+ """)
654
+ else:
655
+ # GRAND FINALE CELEBRATION!
656
+ st.markdown("""
657
+ <div style="text-align: center; padding: 40px;">
658
+ <div style="font-size: 60px; margin-bottom: 20px;">
659
+ 🏆🎉✨
 
660
  </div>
661
+ <h1 style="color: #FF6B6B; font-family: 'Comic Neue', cursive;">
662
+ YOU DID IT! MATH CHAMPION! 🏅
663
+ </h1>
664
+ <p style="font-size: 24px; color: #4ECDC4;">
665
+ You've completed all the challenges in this category!<br>
666
+ </p>
667
+ <div style="font-size: 40px; margin: 20px 0;">
668
+ 🌟🎊👑🎈🚀
669
+ </div>
670
+ </div>
671
+ """, unsafe_allow_html=True)
672
+
673
+ st.balloons()
674
+ st.balloons()
675
+ st.balloons()
676
+
677
+ if st.button("🔄 Start New Adventure"):
678
+ st.session_state.question_index = 0
679
  st.session_state.show_answer = False
680
  st.session_state.show_steps = False
681
  st.rerun()
 
 
 
 
 
 
 
682
 
683
+ with col2:
684
+ st.markdown("### 🎨 Fun Zone")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
685
  st.markdown("""
686
+ <div style="text-align: center; font-size: 40px; margin: 20px 0;">
687
+ 🎪<br>✨<br>🌟
 
 
 
 
 
 
 
 
 
 
 
688
  </div>
689
  """, unsafe_allow_html=True)
690
 
691
+ st.markdown("### 🏆 Your Achievements")
692
+ if not subset_df.empty:
693
+ completed = min(st.session_state.question_index, len(subset_df))
694
+ st.metric("Challenges Completed", f"{completed}/{len(subset_df)}")
695
 
696
+ st.markdown("### 💫 Pro Tip")
697
+ st.info("""
698
+ Use the calculator in the sidebar to help solve tricky problems!
699
+ It's your math superhero sidekick! 🦸‍♂️
700
+ """)
701
 
702
  # Cleanup function
703
  def cleanup():