feministmystique commited on
Commit
de430ac
Β·
verified Β·
1 Parent(s): 87832d9

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +320 -90
src/streamlit_app.py CHANGED
@@ -84,7 +84,7 @@ class GoogleSheetsLogger:
84
  def _init_google_sheets(_self):
85
  """Initialize Google Sheets connection with caching"""
86
  try:
87
- creds_dict = json.loads(_self.config.google_creds_json)
88
  scope = [
89
  "https://www.googleapis.com/auth/spreadsheets",
90
  "https://www.googleapis.com/auth/drive"
@@ -188,7 +188,7 @@ Please follow these guidelines:
188
  repetition_penalty=1.1,
189
  )
190
 
191
- # `response` is a string; clean it
192
  cleaned_response = re.sub(r"<think>.*?</think>", "", response, flags=re.DOTALL)
193
  return cleaned_response.strip()
194
 
@@ -245,10 +245,12 @@ class HelpInterface:
245
 
246
  def render_question(self, question: str, question_id: str, is_demo: bool = False):
247
  """Render a single question interface"""
 
248
  logger.info(f"Rendering question {question_id}, is_demo: {is_demo}")
249
 
250
- # Question container styling
251
  if is_demo:
 
252
  st.markdown(f"""
253
  <div style='
254
  background: linear-gradient(135deg, #fdcb6e 0%, #e17055 100%);
@@ -281,6 +283,7 @@ class HelpInterface:
281
  </div>
282
  """, unsafe_allow_html=True)
283
  else:
 
284
  st.markdown(f"""
285
  <div style='
286
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
@@ -313,8 +316,10 @@ class HelpInterface:
313
  </div>
314
  """, unsafe_allow_html=True)
315
 
 
316
  is_submitted = self.session_manager.get_question_state(question_id, "submitted", False)
317
 
 
318
  if not is_submitted:
319
  st.markdown("<div style='margin: 20px 0;'>", unsafe_allow_html=True)
320
  st.text_area(
@@ -326,6 +331,7 @@ class HelpInterface:
326
  )
327
  st.markdown("</div>", unsafe_allow_html=True)
328
 
 
329
  st.markdown("""
330
  <div style='
331
  margin: 30px 0 20px 0;
@@ -334,6 +340,7 @@ class HelpInterface:
334
  '>
335
  """, unsafe_allow_html=True)
336
 
 
337
  col1, col2, col3 = st.columns([1, 0.2, 1])
338
 
339
  with col1:
@@ -366,9 +373,11 @@ class HelpInterface:
366
  if st.button("πŸ” Need Help?", key=f"help_{question_id}", type="primary", use_container_width=True):
367
  self._toggle_help(question, question_id, is_demo)
368
  else:
 
369
  st.markdown("<div style='height: 55px;'></div>", unsafe_allow_html=True)
370
 
371
  with col2:
 
372
  st.markdown("<div style='height: 55px;'></div>", unsafe_allow_html=True)
373
 
374
  with col3:
@@ -401,6 +410,7 @@ class HelpInterface:
401
  if st.button("πŸ“ Submit Answer", key=f"submit_{question_id}", use_container_width=True):
402
  self._handle_submit(question, question_id, is_demo)
403
  else:
 
404
  st.markdown("""
405
  <div style='
406
  background: linear-gradient(135deg, #48bb78 0%, #38a169 100%);
@@ -421,22 +431,29 @@ class HelpInterface:
421
  </div>
422
  """, unsafe_allow_html=True)
423
 
 
424
  st.markdown("</div>", unsafe_allow_html=True)
425
 
 
426
  if (self.session_manager.get_question_state(question_id, "show_sections", False) and
427
  not is_submitted):
428
  self._render_help_section(question, question_id, is_demo)
429
 
 
430
  st.markdown("<div style='margin-bottom: 40px;'></div>", unsafe_allow_html=True)
431
 
432
  def _handle_submit(self, question: str, question_id: str, is_demo: bool = False):
 
433
  logger.info(f"Handle submit called for question {question_id}, is_demo: {is_demo}")
434
 
 
435
  self.session_manager.set_question_state(question_id, "submitted", True)
436
 
 
437
  if not is_demo:
438
  help_clicks = self.session_manager.get_question_state(question_id, "help_clicks", 0)
439
  retry_count = self.session_manager.get_question_state(question_id, "retry_counts", 0)
 
440
  logger.info(f"Logging submit for question {question_id}")
441
  self.logger.log_button_click(
442
  "Submit", question, SUBJECT, help_clicks, retry_count
@@ -447,108 +464,321 @@ class HelpInterface:
447
  st.rerun()
448
 
449
  def _toggle_help(self, question: str, question_id: str, is_demo: bool = False):
 
450
  logger.info(f"Toggle help called for question {question_id}, is_demo: {is_demo}")
 
451
  current_help_clicks = self.session_manager.get_question_state(question_id, "help_clicks", 0)
452
  self.session_manager.set_question_state(question_id, "help_clicks", current_help_clicks + 1)
453
- self.session_manager.set_question_state(question_id, "show_sections", True)
 
 
 
 
 
454
  self.session_manager.set_question_state(question_id, "help_dismissed", False)
 
 
455
  if not is_demo:
456
  retry_count = self.session_manager.get_question_state(question_id, "retry_counts", 0)
 
457
  self.logger.log_button_click(
458
- "Need Help", question, SUBJECT, current_help_clicks + 1, retry_count
 
459
  )
460
- st.rerun()
461
-
 
462
  def _render_help_section(self, question: str, question_id: str, is_demo: bool = False):
463
- st.markdown("<hr style='margin: 30px 0'>", unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
464
  col1, col2, col3 = st.columns(3)
465
- for col, btn_name in zip([col1, col2, col3],
466
- ["Explain the question", "Give an example", "Who cares?"]):
467
- with col:
468
- btn_key = f"{btn_name}_{question_id}"
469
- if st.button(btn_name, key=btn_key, use_container_width=True):
470
- self._handle_ai_button_click(question, question_id, btn_name, is_demo)
471
-
472
- responses = self.session_manager.get_question_state(question_id, "responses", {})
473
- last_clicked = self.session_manager.get_question_state(question_id, "button_clicked", None)
474
- loading_states = self.session_manager.get_question_state(question_id, "loading_states", {})
475
-
476
- if last_clicked and last_clicked in responses:
477
- if loading_states.get(last_clicked, False):
478
- with st.spinner(f"Generating {last_clicked}..."):
479
- time.sleep(0.5)
480
- st.markdown(f"### {last_clicked} Response:")
481
- st.write(responses[last_clicked])
482
-
483
- retry_key = f"retry_{last_clicked}_{question_id}"
484
- if st.button("πŸ”„ Try a different explanation", key=retry_key):
485
- self._retry_ai_response(question, question_id, last_clicked, is_demo)
486
-
487
- def _handle_ai_button_click(self, question: str, question_id: str, button_name: str, is_demo: bool = False):
488
- logger.info(f"AI button clicked: {button_name} for question {question_id}")
489
- retry_counts = self.session_manager.get_question_state(question_id, "retry_counts", {})
490
- retry_counts[button_name] = 0
491
- self.session_manager.set_question_state(question_id, "retry_counts", retry_counts)
492
- loading_states = self.session_manager.get_question_state(question_id, "loading_states", {})
493
- loading_states[button_name] = True
494
- self.session_manager.set_question_state(question_id, "loading_states", loading_states)
495
- st.rerun()
496
-
497
- def _retry_ai_response(self, question: str, question_id: str, button_name: str, is_demo: bool = False):
498
- logger.info(f"Retry AI response for button {button_name} on question {question_id}")
499
- retry_counts = self.session_manager.get_question_state(question_id, "retry_counts", {})
500
- retry_counts[button_name] = retry_counts.get(button_name, 0) + 1
501
- self.session_manager.set_question_state(question_id, "retry_counts", retry_counts)
502
- loading_states = self.session_manager.get_question_state(question_id, "loading_states", {})
503
- loading_states[button_name] = True
504
- self.session_manager.set_question_state(question_id, "loading_states", loading_states)
 
 
 
 
 
 
 
 
 
505
  st.rerun()
506
-
507
- def _generate_and_store_response(self, question: str, question_id: str, button_name: str):
508
- retry_counts = self.session_manager.get_question_state(question_id, "retry_counts", {})
509
- retry_count = retry_counts.get(button_name, 0)
510
- response = self.ai_assistant.generate_response(button_name, question, retry_count)
511
- responses = self.session_manager.get_question_state(question_id, "responses", {})
512
- responses[button_name] = response
513
- self.session_manager.set_question_state(question_id, "responses", responses)
514
- self.session_manager.set_question_state(question_id, "button_clicked", button_name)
515
- loading_states = self.session_manager.get_question_state(question_id, "loading_states", {})
516
- loading_states[button_name] = False
517
- self.session_manager.set_question_state(question_id, "loading_states", loading_states)
518
-
519
- if not question_id.startswith("demo"):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
520
  help_clicks = self.session_manager.get_question_state(question_id, "help_clicks", 0)
521
- self.logger.log_button_click(button_name, question, SUBJECT, help_clicks, retry_count)
522
-
523
- def run(self):
524
- st.title("πŸ“š Interactive Help Interface for Precalculus")
525
- demo_question = DEFAULT_QUESTIONS[0]
526
- self.render_question(demo_question, "demo_1", is_demo=True)
527
-
528
- for i, question in enumerate(DEFAULT_QUESTIONS[1:], start=1):
529
- self.render_question(question, f"q{i+1}", is_demo=False)
530
-
531
- for question_id in st.session_state.get("button_clicked", {}):
532
- button_name = st.session_state["button_clicked"].get(question_id)
533
- loading_states = st.session_state.get("loading_states", {})
534
- if button_name and loading_states.get(button_name, False):
535
- question = None
536
- if question_id.startswith("demo"):
537
- question = demo_question
538
- else:
539
- idx = int(question_id[1:]) - 2
540
- if 0 <= idx < len(DEFAULT_QUESTIONS[1:]):
541
- question = DEFAULT_QUESTIONS[idx + 1]
542
- if question:
543
- self._generate_and_store_response(question, question_id, button_name)
544
- st.rerun()
545
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
546
 
547
- # Main entry point for Streamlit app
548
  def main():
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
549
  config = ConfigManager()
550
- app = HelpInterface(config)
551
- app.run()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
552
 
553
  if __name__ == "__main__":
554
  main()
 
 
 
84
  def _init_google_sheets(_self):
85
  """Initialize Google Sheets connection with caching"""
86
  try:
87
+ creds_dict = json.loads(_self.config.google_sheets_credentials)
88
  scope = [
89
  "https://www.googleapis.com/auth/spreadsheets",
90
  "https://www.googleapis.com/auth/drive"
 
188
  repetition_penalty=1.1,
189
  )
190
 
191
+ # `response` will be a string, so just clean it
192
  cleaned_response = re.sub(r"<think>.*?</think>", "", response, flags=re.DOTALL)
193
  return cleaned_response.strip()
194
 
 
245
 
246
  def render_question(self, question: str, question_id: str, is_demo: bool = False):
247
  """Render a single question interface"""
248
+ # Debug logging
249
  logger.info(f"Rendering question {question_id}, is_demo: {is_demo}")
250
 
251
+ # Question container with enhanced styling
252
  if is_demo:
253
+ # Demo question styling
254
  st.markdown(f"""
255
  <div style='
256
  background: linear-gradient(135deg, #fdcb6e 0%, #e17055 100%);
 
283
  </div>
284
  """, unsafe_allow_html=True)
285
  else:
286
+ # Regular question styling
287
  st.markdown(f"""
288
  <div style='
289
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
 
316
  </div>
317
  """, unsafe_allow_html=True)
318
 
319
+ # Check if question is submitted
320
  is_submitted = self.session_manager.get_question_state(question_id, "submitted", False)
321
 
322
+ # Student response area with improved spacing - only show if not submitted
323
  if not is_submitted:
324
  st.markdown("<div style='margin: 20px 0;'>", unsafe_allow_html=True)
325
  st.text_area(
 
331
  )
332
  st.markdown("</div>", unsafe_allow_html=True)
333
 
334
+ # Enhanced button section with better spacing and styling
335
  st.markdown("""
336
  <div style='
337
  margin: 30px 0 20px 0;
 
340
  '>
341
  """, unsafe_allow_html=True)
342
 
343
+ # Button layout with improved spacing
344
  col1, col2, col3 = st.columns([1, 0.2, 1])
345
 
346
  with col1:
 
373
  if st.button("πŸ” Need Help?", key=f"help_{question_id}", type="primary", use_container_width=True):
374
  self._toggle_help(question, question_id, is_demo)
375
  else:
376
+ # Empty space to maintain layout when submitted
377
  st.markdown("<div style='height: 55px;'></div>", unsafe_allow_html=True)
378
 
379
  with col2:
380
+ # Empty column for spacing
381
  st.markdown("<div style='height: 55px;'></div>", unsafe_allow_html=True)
382
 
383
  with col3:
 
410
  if st.button("πŸ“ Submit Answer", key=f"submit_{question_id}", use_container_width=True):
411
  self._handle_submit(question, question_id, is_demo)
412
  else:
413
+ # Submitted state with enhanced styling
414
  st.markdown("""
415
  <div style='
416
  background: linear-gradient(135deg, #48bb78 0%, #38a169 100%);
 
431
  </div>
432
  """, unsafe_allow_html=True)
433
 
434
+ # Close button container
435
  st.markdown("</div>", unsafe_allow_html=True)
436
 
437
+ # Render help section if active and not submitted
438
  if (self.session_manager.get_question_state(question_id, "show_sections", False) and
439
  not is_submitted):
440
  self._render_help_section(question, question_id, is_demo)
441
 
442
+ # Add spacing between questions
443
  st.markdown("<div style='margin-bottom: 40px;'></div>", unsafe_allow_html=True)
444
 
445
  def _handle_submit(self, question: str, question_id: str, is_demo: bool = False):
446
+ """Handle submit button click"""
447
  logger.info(f"Handle submit called for question {question_id}, is_demo: {is_demo}")
448
 
449
+ # Set submission state
450
  self.session_manager.set_question_state(question_id, "submitted", True)
451
 
452
+ # Log submit only if not demo
453
  if not is_demo:
454
  help_clicks = self.session_manager.get_question_state(question_id, "help_clicks", 0)
455
  retry_count = self.session_manager.get_question_state(question_id, "retry_counts", 0)
456
+
457
  logger.info(f"Logging submit for question {question_id}")
458
  self.logger.log_button_click(
459
  "Submit", question, SUBJECT, help_clicks, retry_count
 
464
  st.rerun()
465
 
466
  def _toggle_help(self, question: str, question_id: str, is_demo: bool = False):
467
+ """Toggle help section visibility"""
468
  logger.info(f"Toggle help called for question {question_id}, is_demo: {is_demo}")
469
+
470
  current_help_clicks = self.session_manager.get_question_state(question_id, "help_clicks", 0)
471
  self.session_manager.set_question_state(question_id, "help_clicks", current_help_clicks + 1)
472
+
473
+ current_show = self.session_manager.get_question_state(question_id, "show_sections", False)
474
+ self.session_manager.set_question_state(question_id, "show_sections", not current_show)
475
+
476
+ # Reset other states
477
+ self.session_manager.set_question_state(question_id, "button_clicked", None)
478
  self.session_manager.set_question_state(question_id, "help_dismissed", False)
479
+
480
+ # Log the help button click only if not demo
481
  if not is_demo:
482
  retry_count = self.session_manager.get_question_state(question_id, "retry_counts", 0)
483
+ logger.info(f"Logging help click for question {question_id}")
484
  self.logger.log_button_click(
485
+ "Help", question, SUBJECT,
486
+ current_help_clicks + 1, retry_count
487
  )
488
+ else:
489
+ logger.info(f"Skipping logging for demo question {question_id}")
490
+
491
  def _render_help_section(self, question: str, question_id: str, is_demo: bool = False):
492
+ """Render the help section with options"""
493
+ st.markdown("""
494
+ <div style='
495
+ background: linear-gradient(135deg, #ffeaa7 0%, #fab1a0 100%);
496
+ padding: 15px;
497
+ border-radius: 10px;
498
+ margin: 15px 0;
499
+ border: 1px solid #e17055;
500
+ box-shadow: 0 4px 15px rgba(0,0,0,0.1);
501
+ '>
502
+ <h4 style='
503
+ margin: 0 0 10px 0;
504
+ color: #2d3436;
505
+ font-size: 1.1em;
506
+ '>🎯 Choose Your Learning Style</h4>
507
+ <p style='
508
+ margin: 0;
509
+ font-size: 14px;
510
+ color: #636e72;
511
+ '>Select the type of help that works best for you:</p>
512
+ </div>
513
+ """, unsafe_allow_html=True)
514
+
515
+ # Help option buttons in a more compact layout
516
  col1, col2, col3 = st.columns(3)
517
+
518
+ with col1:
519
+ if st.button("πŸ“ Explain", key=f"explain_{question_id}", use_container_width=True):
520
+ self._handle_help_button("Explain the question", question, question_id, is_demo)
521
+
522
+ with col2:
523
+ if st.button("πŸ’‘ Example", key=f"example_{question_id}", use_container_width=True):
524
+ self._handle_help_button("Give an example", question, question_id, is_demo)
525
+
526
+ with col3:
527
+ if st.button("πŸ€” Who cares?", key=f"application_{question_id}", use_container_width=True):
528
+ self._handle_help_button("Who cares?", question, question_id, is_demo)
529
+
530
+ # Show response if available - NO GREEN BAR
531
+ current_response = self.session_manager.get_question_state(question_id, "responses", "")
532
+ current_button = self.session_manager.get_question_state(question_id, "button_clicked", None)
533
+
534
+ if current_response and current_button:
535
+ # Simply display the response without any container styling
536
+ st.write(current_response)
537
+
538
+ self._render_action_buttons(question, question_id, is_demo)
539
+
540
+ def _handle_help_button(self, button_name: str, question: str, question_id: str, is_demo: bool = False):
541
+ """Handle help button click and generate response"""
542
+ logger.info(f"Handle help button called: {button_name} for question {question_id}, is_demo: {is_demo}")
543
+
544
+ # Log button click only if not demo
545
+ if not is_demo:
546
+ help_clicks = self.session_manager.get_question_state(question_id, "help_clicks", 0)
547
+ retry_count = self.session_manager.get_question_state(question_id, "retry_counts", 0)
548
+
549
+ logger.info(f"Logging {button_name} click for question {question_id}")
550
+ self.logger.log_button_click(
551
+ button_name, question, SUBJECT, help_clicks, retry_count
552
+ )
553
+ else:
554
+ logger.info(f"Skipping logging for demo question {question_id}")
555
+
556
+ # Generate response
557
+ with st.spinner("Generating response..."):
558
+ retry_count = self.session_manager.get_question_state(question_id, "retry_counts", 0)
559
+ response = self.ai_assistant.generate_response(button_name, question, retry_count)
560
+
561
+ # Store response and button clicked
562
+ self.session_manager.set_question_state(question_id, "responses", response)
563
+ self.session_manager.set_question_state(question_id, "button_clicked", button_name)
564
+ self.session_manager.set_question_state(question_id, "retry_counts", 0)
565
+
566
  st.rerun()
567
+
568
+ def _render_action_buttons(self, question: str, question_id: str, is_demo: bool = False):
569
+ """Render action buttons after showing response"""
570
+ st.markdown("<div style='margin-top: 15px;'>", unsafe_allow_html=True)
571
+ col1, col2, col3 = st.columns(3)
572
+
573
+ with col1:
574
+ if st.button("πŸ”„ Retry", key=f"retry_{question_id}", use_container_width=True):
575
+ self._handle_retry(question, question_id, is_demo)
576
+
577
+ with col2:
578
+ if st.button("πŸ’¬ ChatGPT", key=f"chatgpt_{question_id}", use_container_width=True):
579
+ self._handle_chatgpt_redirect(question, question_id, is_demo)
580
+
581
+ with col3:
582
+ if st.button("βœ… Helped!", key=f"thanks_{question_id}", use_container_width=True):
583
+ self._handle_thank_you(question, question_id, is_demo)
584
+
585
+ st.markdown("</div>", unsafe_allow_html=True)
586
+
587
+ def _handle_retry(self, question: str, question_id: str, is_demo: bool = False):
588
+ """Handle retry button click"""
589
+ logger.info(f"Handle retry called for question {question_id}, is_demo: {is_demo}")
590
+
591
+ current_retry = self.session_manager.get_question_state(question_id, "retry_counts", 0)
592
+ new_retry_count = current_retry + 1
593
+
594
+ self.session_manager.set_question_state(question_id, "retry_counts", new_retry_count)
595
+
596
+ # Log retry only if not demo
597
+ if not is_demo:
598
  help_clicks = self.session_manager.get_question_state(question_id, "help_clicks", 0)
599
+ logger.info(f"Logging retry for question {question_id}")
600
+ self.logger.log_button_click(
601
+ "More help", question, SUBJECT, help_clicks, new_retry_count
602
+ )
603
+ else:
604
+ logger.info(f"Skipping retry logging for demo question {question_id}")
605
+
606
+ # Generate new response
607
+ current_button = self.session_manager.get_question_state(question_id, "button_clicked", None)
608
+ if current_button:
609
+ with st.spinner("Generating alternative response..."):
610
+ response = self.ai_assistant.generate_response(current_button, question, new_retry_count)
611
+ self.session_manager.set_question_state(question_id, "responses", response)
612
+ st.rerun()
613
+
614
+ def _handle_chatgpt_redirect(self, question: str, question_id: str, is_demo: bool = False):
615
+ """Handle ChatGPT redirect"""
616
+ logger.info(f"Handle ChatGPT redirect called for question {question_id}, is_demo: {is_demo}")
617
+
618
+ # Log only if not demo
619
+ if not is_demo:
620
+ help_clicks = self.session_manager.get_question_state(question_id, "help_clicks", 0)
621
+ retry_count = self.session_manager.get_question_state(question_id, "retry_counts", 0)
622
+
623
+ logger.info(f"Logging ChatGPT redirect for question {question_id}")
624
+ self.logger.log_button_click(
625
+ "Take me to ChatGPT", question, SUBJECT, help_clicks, retry_count
626
+ )
627
+ else:
628
+ logger.info(f"Skipping ChatGPT redirect logging for demo question {question_id}")
629
+
630
+ st.markdown(f"""
631
+ <div style='text-align: center; margin: 15px 0;'>
632
+ <a href="https://chat.openai.com" target="_blank" style="
633
+ display: inline-block;
634
+ background: linear-gradient(135deg, #10A37F 0%, #0e8c6b 100%);
635
+ color: white;
636
+ padding: 12px 24px;
637
+ text-decoration: none;
638
+ border-radius: 8px;
639
+ font-weight: 500;
640
+ box-shadow: 0 4px 15px rgba(16, 163, 127, 0.3);
641
+ transition: all 0.3s ease;
642
+ ">🌐 Open ChatGPT</a>
643
+ </div>
644
+ """, unsafe_allow_html=True)
645
+
646
+ def _handle_thank_you(self, question: str, question_id: str, is_demo: bool = False):
647
+ """Handle thank you button click"""
648
+ logger.info(f"Handle thank you called for question {question_id}, is_demo: {is_demo}")
649
+
650
+ # Log only if not demo
651
+ if not is_demo:
652
+ help_clicks = self.session_manager.get_question_state(question_id, "help_clicks", 0)
653
+ retry_count = self.session_manager.get_question_state(question_id, "retry_counts", 0)
654
+
655
+ logger.info(f"Logging thank you for question {question_id}")
656
+ self.logger.log_button_click(
657
+ "Thank you", question, SUBJECT, help_clicks, retry_count
658
+ )
659
+ else:
660
+ logger.info(f"Skipping thank you logging for demo question {question_id}")
661
+
662
+ # Hide help section
663
+ self.session_manager.set_question_state(question_id, "show_sections", False)
664
+ self.session_manager.set_question_state(question_id, "help_dismissed", True)
665
+
666
+ st.success("πŸŽ‰ Glad I could help! Feel free to ask for help anytime.")
667
+ st.rerun()
668
 
 
669
  def main():
670
+ """Main application entry point"""
671
+ st.markdown("""
672
+ <div style='
673
+ text-align: center;
674
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
675
+ padding: 30px;
676
+ border-radius: 20px;
677
+ margin-bottom: 30px;
678
+ box-shadow: 0 10px 40px rgba(0,0,0,0.15);
679
+ '>
680
+ <h1 style='
681
+ color: white;
682
+ margin: 0 0 10px 0;
683
+ font-size: 2.5em;
684
+ text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
685
+ '>πŸŽ“ Interactive Learning Quiz</h1>
686
+ <p style='
687
+ color: #e8eaed;
688
+ margin: 0;
689
+ font-size: 1.2em;
690
+ font-weight: 300;
691
+ '>Subject: {SUBJECT}</p>
692
+ </div>
693
+ """.format(SUBJECT=SUBJECT), unsafe_allow_html=True)
694
+
695
+ # Initialize configuration and interface
696
  config = ConfigManager()
697
+ interface = HelpInterface(config)
698
+
699
+ # Render questions with proper numbering
700
+ question_number = 1
701
+ for i, question in enumerate(DEFAULT_QUESTIONS):
702
+ if i == 0:
703
+ # First question is demo - no logging, special styling
704
+ interface.render_question(question, "demo", is_demo=True)
705
+ else:
706
+ # Regular questions with logging and proper numbering (1, 2, 3, 4, 5)
707
+ interface.render_question(question, str(question_number), is_demo=False)
708
+ question_number += 1
709
+
710
+ # Add custom CSS for enhanced styling
711
+ st.markdown("""
712
+ <style>
713
+ /* Enhanced button styling */
714
+ .stButton > button {
715
+ height: 2.5em;
716
+ font-size: 0.9rem;
717
+ border-radius: 8px;
718
+ transition: all 0.3s ease;
719
+ border: none;
720
+ font-weight: 500;
721
+ }
722
+
723
+ .stButton > button:hover {
724
+ transform: translateY(-2px);
725
+ box-shadow: 0 6px 20px rgba(0,0,0,0.15);
726
+ }
727
+
728
+ /* Primary button styling */
729
+ .stButton > button[kind="primary"] {
730
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
731
+ color: white;
732
+ }
733
+
734
+ /* Text area styling */
735
+ .stTextArea > div > div > textarea {
736
+ border-radius: 10px;
737
+ border: 2px solid #e0e4e7;
738
+ font-size: 16px;
739
+ padding: 12px;
740
+ transition: all 0.3s ease;
741
+ }
742
+
743
+ .stTextArea > label {
744
+ font-size: 14px;
745
+ font-weight: 500;
746
+ color: #666;
747
+ }
748
+
749
+ .stTextArea > div > div > textarea:focus {
750
+ border-color: #667eea;
751
+ box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
752
+ }
753
+
754
+ /* Remove default spacing */
755
+ .block-container {
756
+ padding-top: 2rem;
757
+ padding-bottom: 2rem;
758
+ }
759
+
760
+ /* Custom spacing */
761
+ .stMarkdown {
762
+ margin-bottom: 0;
763
+ }
764
+
765
+ /* Success message styling */
766
+ .stSuccess {
767
+ background: linear-gradient(135deg, #00b894 0%, #00a085 100%);
768
+ border: none;
769
+ border-radius: 10px;
770
+ padding: 15px;
771
+ color: white;
772
+ }
773
+
774
+ /* Spinner styling */
775
+ .stSpinner {
776
+ color: #667eea;
777
+ }
778
+ </style>
779
+ """, unsafe_allow_html=True)
780
 
781
  if __name__ == "__main__":
782
  main()
783
+
784
+