mah-diaa commited on
Commit
6e60f8d
Β·
1 Parent(s): 6d3815b

Fix quiz submission: prevent double-counting, ensure feedback visibility, prevent infinite loops

Browse files
Files changed (4) hide show
  1. .gitignore +2 -0
  2. app.py +45 -7
  3. data/preloaded_concepts.json +2 -0
  4. mcp_server.py +2 -0
.gitignore CHANGED
@@ -35,3 +35,5 @@ secrets/
35
 
36
 
37
 
 
 
 
35
 
36
 
37
 
38
+
39
+
app.py CHANGED
@@ -1404,6 +1404,7 @@ with gr.Blocks(title="Gnosis Tutor") as app:
1404
  """Handle answer submission."""
1405
  print(f"πŸ” [SUBMIT] Answer submitted - selected: {selected}, type: {type(selected)}, idx: {idx}")
1406
  print(f"πŸ” [SUBMIT] quiz_data type: {type(quiz_data)}, length: {len(quiz_data) if quiz_data else 'None'}")
 
1407
 
1408
  # If quiz_data is empty or None, try to get it from user_state
1409
  if not quiz_data or (isinstance(quiz_data, list) and len(quiz_data) == 0):
@@ -1423,7 +1424,7 @@ with gr.Blocks(title="Gnosis Tutor") as app:
1423
  gr.update(visible=False),
1424
  gr.update(value=0),
1425
  gr.update(value={"correct": 0, "total": 0}),
1426
- gr.update(value=quiz_data)
1427
  )
1428
 
1429
  # Check if answer was selected
@@ -1440,7 +1441,7 @@ with gr.Blocks(title="Gnosis Tutor") as app:
1440
  gr.update(visible=False), # quiz_next_btn
1441
  gr.update(value=idx), # current_question_idx
1442
  gr.update(value=score), # quiz_score_state (don't update)
1443
- gr.update(value=quiz_data) # quiz_data_state
1444
  )
1445
 
1446
  # Ensure idx is valid - fix the index bug
@@ -1450,12 +1451,18 @@ with gr.Blocks(title="Gnosis Tutor") as app:
1450
 
1451
  print(f"πŸ” [SUBMIT] Processing question {idx + 1} of {len(quiz_data)}")
1452
  q = quiz_data[idx]
 
 
 
 
 
1453
  question_type = q.get('type', '').lower()
1454
  correct_answer = q.get('correct_answer', '')
1455
  is_correct = False
1456
  user_selected_idx = None
1457
 
1458
  print(f"πŸ” [SUBMIT] Question type: {question_type}, correct_answer: {correct_answer}, options: {q.get('options', [])}")
 
1459
 
1460
  if question_type == 'mcq':
1461
  options = q.get('options', [])
@@ -1503,6 +1510,16 @@ with gr.Blocks(title="Gnosis Tutor") as app:
1503
  # Store user's selected answer in the question data for reference
1504
  q['user_selected_answer'] = user_selected_idx if user_selected_idx is not None else selected
1505
  q['is_correct'] = is_correct
 
 
 
 
 
 
 
 
 
 
1506
 
1507
  new_score = {
1508
  "correct": score["correct"] + (1 if is_correct else 0),
@@ -1562,15 +1579,19 @@ with gr.Blocks(title="Gnosis Tutor") as app:
1562
  # Store explanation in user_state to be picked up by chat
1563
  user_state["last_quiz_explanation"] = chat_message
1564
 
 
 
 
1565
  # Return exactly 7 values matching the outputs
 
1566
  return (
1567
  gr.update(visible=True, value=feedback), # quiz_feedback - MAKE SURE IT'S VISIBLE
1568
  gr.update(visible=True, value=explanation), # quiz_explanation - MAKE SURE IT'S VISIBLE
1569
- gr.update(visible=False), # quiz_submit_btn (hide after submission)
1570
  gr.update(visible=idx < len(quiz_data) - 1), # quiz_next_btn
1571
  gr.update(value=idx), # current_question_idx
1572
  gr.update(value=new_score), # quiz_score_state
1573
- gr.update(value=quiz_data) # quiz_data_state
1574
  )
1575
 
1576
  def next_question(quiz_data, idx, score):
@@ -1665,7 +1686,7 @@ with gr.Blocks(title="Gnosis Tutor") as app:
1665
  gr.update(visible=False),
1666
  gr.update(value=0),
1667
  gr.update(value={"correct": 0, "total": 0}),
1668
- gr.update(value=[])
1669
  )
1670
  try:
1671
  result = submit_answer(selected, quiz_data, idx, score)
@@ -1682,7 +1703,7 @@ with gr.Blocks(title="Gnosis Tutor") as app:
1682
  gr.update(visible=False),
1683
  gr.update(value=idx),
1684
  gr.update(value=score),
1685
- gr.update(value=quiz_data)
1686
  )
1687
 
1688
  quiz_submit_btn.click(
@@ -2090,13 +2111,30 @@ if __name__ == "__main__":
2090
  /* Quiz Block - Uses EXACT same styling as left sidebar (glass-tabs-container) */
2091
  /* All quiz elements inherit from glass-tabs-container styling automatically */
2092
 
2093
- /* Quiz feedback and explanation visibility */
2094
  .quiz-feedback,
2095
  .quiz-explanation {
2096
  display: block !important;
2097
  visibility: visible !important;
2098
  opacity: 1 !important;
2099
  margin: 1rem 0 !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2100
  }
2101
 
2102
  /* Chat Interface Glass - Enhanced & Fully Rounded */
 
1404
  """Handle answer submission."""
1405
  print(f"πŸ” [SUBMIT] Answer submitted - selected: {selected}, type: {type(selected)}, idx: {idx}")
1406
  print(f"πŸ” [SUBMIT] quiz_data type: {type(quiz_data)}, length: {len(quiz_data) if quiz_data else 'None'}")
1407
+ print(f"πŸ” [SUBMIT] Current score: {score}")
1408
 
1409
  # If quiz_data is empty or None, try to get it from user_state
1410
  if not quiz_data or (isinstance(quiz_data, list) and len(quiz_data) == 0):
 
1424
  gr.update(visible=False),
1425
  gr.update(value=0),
1426
  gr.update(value={"correct": 0, "total": 0}),
1427
+ gr.update() # Don't update quiz_data_state to avoid loops
1428
  )
1429
 
1430
  # Check if answer was selected
 
1441
  gr.update(visible=False), # quiz_next_btn
1442
  gr.update(value=idx), # current_question_idx
1443
  gr.update(value=score), # quiz_score_state (don't update)
1444
+ gr.update() # Don't update quiz_data_state to avoid loops
1445
  )
1446
 
1447
  # Ensure idx is valid - fix the index bug
 
1451
 
1452
  print(f"πŸ” [SUBMIT] Processing question {idx + 1} of {len(quiz_data)}")
1453
  q = quiz_data[idx]
1454
+
1455
+ # Check if this question was already answered to prevent double-counting
1456
+ was_answered = q.get('is_answered', False)
1457
+ previous_correct = q.get('is_correct', False)
1458
+
1459
  question_type = q.get('type', '').lower()
1460
  correct_answer = q.get('correct_answer', '')
1461
  is_correct = False
1462
  user_selected_idx = None
1463
 
1464
  print(f"πŸ” [SUBMIT] Question type: {question_type}, correct_answer: {correct_answer}, options: {q.get('options', [])}")
1465
+ print(f"πŸ” [SUBMIT] Question already answered: {was_answered}, previous correct: {previous_correct}")
1466
 
1467
  if question_type == 'mcq':
1468
  options = q.get('options', [])
 
1510
  # Store user's selected answer in the question data for reference
1511
  q['user_selected_answer'] = user_selected_idx if user_selected_idx is not None else selected
1512
  q['is_correct'] = is_correct
1513
+ q['is_answered'] = True # Mark as answered
1514
+
1515
+ # Calculate new score - only increment if question wasn't already answered
1516
+ if was_answered:
1517
+ # Question was already answered, adjust score based on new answer
1518
+ # Remove previous answer's contribution
1519
+ if previous_correct:
1520
+ score["correct"] = max(0, score["correct"] - 1)
1521
+ score["total"] = max(0, score["total"] - 1)
1522
+ print(f"πŸ” [SUBMIT] Question was already answered, adjusting score: {score}")
1523
 
1524
  new_score = {
1525
  "correct": score["correct"] + (1 if is_correct else 0),
 
1579
  # Store explanation in user_state to be picked up by chat
1580
  user_state["last_quiz_explanation"] = chat_message
1581
 
1582
+ # Update user_state with the modified quiz_data
1583
+ user_state["current_quiz"] = quiz_data
1584
+
1585
  # Return exactly 7 values matching the outputs
1586
+ # Use gr.update() without value for quiz_data_state to avoid triggering change events
1587
  return (
1588
  gr.update(visible=True, value=feedback), # quiz_feedback - MAKE SURE IT'S VISIBLE
1589
  gr.update(visible=True, value=explanation), # quiz_explanation - MAKE SURE IT'S VISIBLE
1590
+ gr.update(visible=False, interactive=False), # quiz_submit_btn (hide after submission)
1591
  gr.update(visible=idx < len(quiz_data) - 1), # quiz_next_btn
1592
  gr.update(value=idx), # current_question_idx
1593
  gr.update(value=new_score), # quiz_score_state
1594
+ gr.update() # quiz_data_state - don't update to avoid infinite loops
1595
  )
1596
 
1597
  def next_question(quiz_data, idx, score):
 
1686
  gr.update(visible=False),
1687
  gr.update(value=0),
1688
  gr.update(value={"correct": 0, "total": 0}),
1689
+ gr.update() # Don't update quiz_data_state to avoid loops
1690
  )
1691
  try:
1692
  result = submit_answer(selected, quiz_data, idx, score)
 
1703
  gr.update(visible=False),
1704
  gr.update(value=idx),
1705
  gr.update(value=score),
1706
+ gr.update() # Don't update quiz_data_state to avoid loops
1707
  )
1708
 
1709
  quiz_submit_btn.click(
 
2111
  /* Quiz Block - Uses EXACT same styling as left sidebar (glass-tabs-container) */
2112
  /* All quiz elements inherit from glass-tabs-container styling automatically */
2113
 
2114
+ /* Quiz feedback and explanation visibility - Force visibility when content exists */
2115
  .quiz-feedback,
2116
  .quiz-explanation {
2117
  display: block !important;
2118
  visibility: visible !important;
2119
  opacity: 1 !important;
2120
  margin: 1rem 0 !important;
2121
+ z-index: 100 !important;
2122
+ position: relative !important;
2123
+ }
2124
+
2125
+ /* Ensure feedback is visible even when Gradio tries to hide it */
2126
+ .quiz-feedback[style*="display: none"],
2127
+ .quiz-explanation[style*="display: none"] {
2128
+ display: block !important;
2129
+ visibility: visible !important;
2130
+ }
2131
+
2132
+ /* Make sure HTML content inside feedback is visible */
2133
+ .quiz-feedback > div,
2134
+ .quiz-explanation > div {
2135
+ display: block !important;
2136
+ visibility: visible !important;
2137
+ opacity: 1 !important;
2138
  }
2139
 
2140
  /* Chat Interface Glass - Enhanced & Fully Rounded */
data/preloaded_concepts.json CHANGED
@@ -50,3 +50,5 @@
50
 
51
 
52
 
 
 
 
50
 
51
 
52
 
53
+
54
+
mcp_server.py CHANGED
@@ -354,3 +354,5 @@ if __name__ == "__main__":
354
  mcp.run()
355
 
356
 
 
 
 
354
  mcp.run()
355
 
356
 
357
+
358
+