Move distractor explanations inline instead of a repeated bottom section
The "WHY OTHER OPTIONS ARE INCORRECT" aggregate section duplicated explanations that selected wrong choices already showed inside their own resolved follow-up quiz. Removed that section entirely; choices the user never picked now get their "why incorrect" explanation docked directly inside their own card (reusing the same followup panel/attached-card styling), so every distractor's explanation lives with its choice instead of in a separate list at the bottom.
This commit is contained in:
@@ -73,10 +73,7 @@ var correct_review_panel: PanelContainer
|
||||
var teaching_cards: HFlowContainer
|
||||
var review_followups_section: VBoxContainer
|
||||
var review_followups_content: VBoxContainer
|
||||
var wrong_options_section: VBoxContainer
|
||||
var wrong_options_content: VBoxContainer
|
||||
var review_followup_states: Array = []
|
||||
var wrong_option_expanded := {}
|
||||
var question_scroll: ScrollContainer
|
||||
var question_elo_label: Label
|
||||
var next_button: Button
|
||||
@@ -635,19 +632,6 @@ func _build_answer_review_ui() -> void:
|
||||
review_followups_content.add_theme_constant_override("separation", 8)
|
||||
review_followups_section.add_child(review_followups_content)
|
||||
|
||||
wrong_options_section = VBoxContainer.new()
|
||||
wrong_options_section.visible = false
|
||||
wrong_options_section.add_theme_constant_override("separation", 8)
|
||||
question_content.add_child(wrong_options_section)
|
||||
var wrong_options_heading := Label.new()
|
||||
wrong_options_heading.text = "WHY OTHER OPTIONS ARE INCORRECT"
|
||||
wrong_options_heading.name = "WrongOptionsHeading"
|
||||
_set_scaled_label(wrong_options_heading, 15, Brand.text_color(true))
|
||||
wrong_options_section.add_child(wrong_options_heading)
|
||||
wrong_options_content = VBoxContainer.new()
|
||||
wrong_options_content.add_theme_constant_override("separation", 6)
|
||||
wrong_options_section.add_child(wrong_options_content)
|
||||
|
||||
|
||||
func _fit_modal_panels() -> void:
|
||||
var available := get_viewport_rect().size - Vector2(32, 32)
|
||||
@@ -875,19 +859,6 @@ func _review_followup_box(_dark: bool, accent: Color, answered: bool) -> StyleBo
|
||||
return box
|
||||
|
||||
|
||||
func _wrong_option_box(dark: bool) -> StyleBoxFlat:
|
||||
var box := StyleBoxFlat.new()
|
||||
box.bg_color = Color("0b172b") if dark else Color("ffffff")
|
||||
box.border_color = Color("2b3958") if dark else Brand.LIGHT_BORDER
|
||||
box.set_border_width_all(1)
|
||||
box.set_corner_radius_all(6)
|
||||
box.content_margin_left = 10
|
||||
box.content_margin_right = 10
|
||||
box.content_margin_top = 6
|
||||
box.content_margin_bottom = 6
|
||||
return box
|
||||
|
||||
|
||||
func _style_review_followup_option(button: Button, dark: bool, option_id: String, selected_id: String, correct_id: String, answered: bool) -> void:
|
||||
var state := "default"
|
||||
if answered and option_id == correct_id:
|
||||
@@ -929,9 +900,6 @@ func _apply_question_theme() -> void:
|
||||
var review_followup_subtitle := find_child("ReviewFollowupSubtitle", true, false) as Label
|
||||
if review_followup_subtitle != null:
|
||||
review_followup_subtitle.add_theme_color_override("font_color", Brand.muted_color(dark))
|
||||
var wrong_options_heading := find_child("WrongOptionsHeading", true, false) as Label
|
||||
if wrong_options_heading != null:
|
||||
wrong_options_heading.add_theme_color_override("font_color", Brand.text_color(dark))
|
||||
if correct_review_panel != null:
|
||||
correct_review_panel.add_theme_stylebox_override("panel", _correct_review_panel_box(dark))
|
||||
question_elo_label.add_theme_color_override("font_color", Brand.AMBER)
|
||||
@@ -975,7 +943,7 @@ func _apply_question_theme() -> void:
|
||||
if correct_review_panel != null and correct_review_panel.visible:
|
||||
_render_teaching_cards()
|
||||
_render_review_followups()
|
||||
_render_wrong_option_reviews()
|
||||
_render_unselected_distractor_explanations()
|
||||
|
||||
|
||||
func on_show(_payload: Variant = null) -> void:
|
||||
@@ -1542,7 +1510,7 @@ func _dock_correct_review_panel(correct_id: String) -> void:
|
||||
func _render_answer_review_sections() -> void:
|
||||
_render_teaching_cards()
|
||||
_render_review_followups()
|
||||
_render_wrong_option_reviews()
|
||||
_render_unselected_distractor_explanations()
|
||||
|
||||
|
||||
func _clear_answer_review() -> void:
|
||||
@@ -1552,13 +1520,9 @@ func _clear_answer_review() -> void:
|
||||
correct_review_panel.visible = false
|
||||
_clear_container_children(teaching_cards)
|
||||
_clear_container_children(review_followups_content)
|
||||
_clear_container_children(wrong_options_content)
|
||||
review_followup_states.clear()
|
||||
wrong_option_expanded.clear()
|
||||
if review_followups_section != null:
|
||||
review_followups_section.visible = false
|
||||
if wrong_options_section != null:
|
||||
wrong_options_section.visible = false
|
||||
_update_content_vertical_alignment()
|
||||
|
||||
|
||||
@@ -1699,58 +1663,53 @@ func _answer_review_followup(index: int, choice_id: String) -> void:
|
||||
_render_review_followups()
|
||||
|
||||
|
||||
func _render_wrong_option_reviews() -> void:
|
||||
if wrong_options_content == null:
|
||||
return
|
||||
_clear_container_children(wrong_options_content)
|
||||
func _render_unselected_distractor_explanations() -> void:
|
||||
# Choices the user never picked (so never triggered the wrong-answer
|
||||
# follow-up quiz) still need their "why incorrect" explanation shown -
|
||||
# nest it directly in that choice's own card instead of a repeated
|
||||
# aggregate list at the bottom. Choices that DID trigger a follow-up
|
||||
# already show this same explanation inside the resolved quiz view.
|
||||
var question := BlockSessionService.get_current_question()
|
||||
var correct_id := str(question.get("correct_choice_id", ""))
|
||||
var explanations: Dictionary = question.get("choice_explanations", {})
|
||||
var incorrect_count := 0
|
||||
for choice in _get_presented_choices():
|
||||
var choices := _get_presented_choices()
|
||||
for index in range(choices.size()):
|
||||
if index >= choice_followup_panels.size():
|
||||
continue
|
||||
var choice: Dictionary = choices[index]
|
||||
if typeof(choice) != TYPE_DICTIONARY:
|
||||
continue
|
||||
var choice_id := str(choice.get("id", ""))
|
||||
if choice_id == correct_id:
|
||||
if choice_id == "" or choice_id == correct_id or followup_states.has(choice_id):
|
||||
continue
|
||||
incorrect_count += 1
|
||||
_add_wrong_option_review(choice, str(explanations.get(choice_id, "")))
|
||||
wrong_options_section.visible = incorrect_count > 0
|
||||
_clear_followup_content(index)
|
||||
var content := choice_followup_contents[index]
|
||||
var body_content := _add_followup_body(content, false)
|
||||
var heading := Label.new()
|
||||
heading.text = "Why this is incorrect:"
|
||||
_set_scaled_label(heading, 14, Color("fb5f6d"))
|
||||
body_content.add_child(heading)
|
||||
var explanation := Label.new()
|
||||
explanation.text = _distractor_explanation_text(choice_id)
|
||||
explanation.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
_set_scaled_label(explanation, 14, Brand.text_color(_followup_is_dark()))
|
||||
body_content.add_child(explanation)
|
||||
choice_followup_panels[index].add_theme_stylebox_override(
|
||||
"panel",
|
||||
_attached_panel_box(_followup_is_dark(), Color("fb7185"))
|
||||
)
|
||||
choice_followup_panels[index].visible = true
|
||||
_style_choice_button_for_state(index, choice_id)
|
||||
|
||||
|
||||
func _add_wrong_option_review(choice: Dictionary, explanation: String) -> void:
|
||||
var dark := _followup_is_dark()
|
||||
var choice_id := str(choice.get("id", ""))
|
||||
var expanded := bool(wrong_option_expanded.get(choice_id, false))
|
||||
var card := PanelContainer.new()
|
||||
card.add_theme_stylebox_override("panel", _wrong_option_box(dark))
|
||||
wrong_options_content.add_child(card)
|
||||
var content := VBoxContainer.new()
|
||||
content.add_theme_constant_override("separation", 6)
|
||||
card.add_child(content)
|
||||
var header := Button.new()
|
||||
header.flat = true
|
||||
header.alignment = HORIZONTAL_ALIGNMENT_LEFT
|
||||
header.text = "%s. %s" % [_display_label_for_choice_id(choice_id), str(choice.get("text", ""))]
|
||||
header.icon = preload("res://assets/icons/lucide/chevron-down.svg") if expanded else preload("res://assets/icons/lucide/chevron-right.svg")
|
||||
header.icon_alignment = HORIZONTAL_ALIGNMENT_RIGHT
|
||||
header.expand_icon = false
|
||||
header.add_theme_color_override("font_color", Brand.text_color(dark))
|
||||
header.add_theme_color_override("icon_normal_color", Brand.muted_color(dark))
|
||||
_set_scaled_button_font(header, 14)
|
||||
header.pressed.connect(_toggle_wrong_option_review.bind(choice_id))
|
||||
content.add_child(header)
|
||||
if expanded:
|
||||
var detail := Label.new()
|
||||
detail.text = explanation
|
||||
detail.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
_set_scaled_label(detail, 14, Brand.muted_color(dark))
|
||||
content.add_child(detail)
|
||||
|
||||
|
||||
func _toggle_wrong_option_review(choice_id: String) -> void:
|
||||
wrong_option_expanded[choice_id] = not bool(wrong_option_expanded.get(choice_id, false))
|
||||
_render_wrong_option_reviews()
|
||||
func _distractor_explanation_text(choice_id: String) -> String:
|
||||
var question := BlockSessionService.get_current_question()
|
||||
var explanations: Dictionary = question.get("choice_explanations", {})
|
||||
var explanation := str(explanations.get(choice_id, "")).strip_edges()
|
||||
if explanation.begins_with("Correct. "):
|
||||
explanation = explanation.substr(9)
|
||||
if explanation != "":
|
||||
return explanation
|
||||
return "Review the stem finding that makes this option less appropriate."
|
||||
|
||||
|
||||
func _strip_correct_prefix(value: String) -> String:
|
||||
|
||||
Reference in New Issue
Block a user