Restore distractor-specific follow-up questions
This commit is contained in:
@@ -29,7 +29,6 @@ var simulation_total_blocks := 12
|
||||
var simulation_deadline_unix := 0.0
|
||||
var review_first_submission_recorded := false
|
||||
var core_block_size := DEFAULT_CORE_BLOCK_SIZE
|
||||
var show_review_followups := true
|
||||
|
||||
const CORE_MIN_TARGET_SECONDS := 45.0
|
||||
const CORE_MAX_TARGET_SECONDS := 150.0
|
||||
@@ -40,12 +39,10 @@ const CORE_BLOCK_SIZE_MAX := 40
|
||||
const SETTINGS_PATH := "user://settings.cfg"
|
||||
const SETTINGS_SECTION := "session"
|
||||
const SETTINGS_KEY_CORE_BLOCK_SIZE := "core_block_size"
|
||||
const SETTINGS_KEY_SHOW_REVIEW_FOLLOWUPS := "show_review_followups"
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_load_core_block_size()
|
||||
_load_show_review_followups()
|
||||
|
||||
|
||||
func set_core_block_size(value: int) -> void:
|
||||
@@ -60,17 +57,6 @@ func set_core_block_size(value: int) -> void:
|
||||
push_warning("Unable to save core question block size preference.")
|
||||
|
||||
|
||||
func set_show_review_followups(value: bool) -> void:
|
||||
if show_review_followups == value:
|
||||
return
|
||||
show_review_followups = value
|
||||
var config := ConfigFile.new()
|
||||
config.load(SETTINGS_PATH)
|
||||
config.set_value(SETTINGS_SECTION, SETTINGS_KEY_SHOW_REVIEW_FOLLOWUPS, show_review_followups)
|
||||
if config.save(SETTINGS_PATH) != OK:
|
||||
push_warning("Unable to save follow-up question preference.")
|
||||
|
||||
|
||||
func _load_core_block_size() -> void:
|
||||
var config := ConfigFile.new()
|
||||
if config.load(SETTINGS_PATH) == OK:
|
||||
@@ -79,12 +65,6 @@ func _load_core_block_size() -> void:
|
||||
CORE_BLOCK_SIZE_MIN, CORE_BLOCK_SIZE_MAX)
|
||||
|
||||
|
||||
func _load_show_review_followups() -> void:
|
||||
var config := ConfigFile.new()
|
||||
if config.load(SETTINGS_PATH) == OK:
|
||||
show_review_followups = bool(config.get_value(SETTINGS_SECTION, SETTINGS_KEY_SHOW_REVIEW_FOLLOWUPS, true))
|
||||
|
||||
|
||||
func start_dynamic_question(question: Dictionary) -> bool:
|
||||
if question.is_empty():
|
||||
return false
|
||||
@@ -284,6 +264,7 @@ func answer_current(choice_id: String, eliminated: Array, flagged: bool, is_subm
|
||||
"question": question.duplicate(true),
|
||||
"selected_choice_id": choice_id,
|
||||
"is_correct": choice_id == str(question.get("correct_choice_id", "")),
|
||||
"first_attempt_is_correct": choice_id == str(question.get("correct_choice_id", "")) and (session_kind != "core" or not core_current_had_wrong_attempt),
|
||||
"eliminated_choice_ids": eliminated.duplicate(),
|
||||
"flagged": flagged,
|
||||
"elapsed_seconds": get_current_elapsed_seconds(),
|
||||
@@ -311,6 +292,7 @@ func submit_core_attempt(choice_id: String, eliminated: Array, flagged: bool) ->
|
||||
"question": question.duplicate(true),
|
||||
"selected_choice_id": choice_id,
|
||||
"is_correct": choice_id == str(question.get("correct_choice_id", "")),
|
||||
"first_attempt_is_correct": choice_id == str(question.get("correct_choice_id", "")) and not core_current_had_wrong_attempt,
|
||||
"eliminated_choice_ids": eliminated.duplicate(),
|
||||
"flagged": flagged,
|
||||
"elapsed_seconds": get_current_elapsed_seconds(),
|
||||
@@ -343,26 +325,50 @@ func submit_core_attempt(choice_id: String, eliminated: Array, flagged: bool) ->
|
||||
}
|
||||
|
||||
|
||||
func submit_bookmark_attempt(choice_id: String, eliminated: Array, flagged: bool) -> Dictionary:
|
||||
func submit_tutor_attempt(choice_id: String, eliminated: Array, flagged: bool, had_wrong_attempt: bool) -> Dictionary:
|
||||
var question := get_current_question()
|
||||
if question.is_empty() or mode != "Tutor" or session_kind not in ["block", "dynamic"]:
|
||||
return {}
|
||||
var current_correct := choice_id == str(question.get("correct_choice_id", ""))
|
||||
var answer := {
|
||||
"question": question.duplicate(true),
|
||||
"selected_choice_id": choice_id,
|
||||
"is_correct": current_correct and not had_wrong_attempt,
|
||||
"first_attempt_is_correct": current_correct and not had_wrong_attempt,
|
||||
"resolved_correct": current_correct,
|
||||
"eliminated_choice_ids": eliminated.duplicate(),
|
||||
"flagged": flagged,
|
||||
"elapsed_seconds": get_current_elapsed_seconds(),
|
||||
"target_seconds": 0.0
|
||||
}
|
||||
if current_correct:
|
||||
answers[current_index] = answer
|
||||
session_changed.emit()
|
||||
return {"answer": answer, "is_correct": current_correct, "final": current_correct}
|
||||
|
||||
|
||||
func submit_bookmark_attempt(choice_id: String, eliminated: Array, flagged: bool, had_wrong_attempt := false) -> Dictionary:
|
||||
var question := get_current_question()
|
||||
if session_kind != "bookmark" or question.is_empty():
|
||||
return {}
|
||||
var answer := {
|
||||
"question": question.duplicate(true),
|
||||
"selected_choice_id": choice_id,
|
||||
"is_correct": choice_id == str(question.get("correct_choice_id", "")),
|
||||
"is_correct": choice_id == str(question.get("correct_choice_id", "")) and not had_wrong_attempt,
|
||||
"first_attempt_is_correct": choice_id == str(question.get("correct_choice_id", "")) and not had_wrong_attempt,
|
||||
"eliminated_choice_ids": eliminated.duplicate(),
|
||||
"flagged": flagged,
|
||||
"elapsed_seconds": get_current_elapsed_seconds(),
|
||||
"target_seconds": 0.0
|
||||
}
|
||||
if bool(answer.is_correct):
|
||||
var current_correct := choice_id == str(question.get("correct_choice_id", ""))
|
||||
if current_correct:
|
||||
answers[current_index] = answer
|
||||
session_changed.emit()
|
||||
return {"answer": answer, "is_correct": bool(answer.is_correct), "final": bool(answer.is_correct)}
|
||||
return {"answer": answer, "is_correct": current_correct, "final": current_correct}
|
||||
|
||||
|
||||
func submit_review_attempt(choice_id: String, eliminated: Array, flagged: bool) -> Dictionary:
|
||||
func submit_review_attempt(choice_id: String, eliminated: Array, flagged: bool, had_wrong_attempt := false) -> Dictionary:
|
||||
var question := get_current_question()
|
||||
if session_kind != "review" or question.is_empty():
|
||||
return {}
|
||||
@@ -370,20 +376,22 @@ func submit_review_attempt(choice_id: String, eliminated: Array, flagged: bool)
|
||||
var answer := {
|
||||
"question": question.duplicate(true),
|
||||
"selected_choice_id": choice_id,
|
||||
"is_correct": choice_id == str(question.get("correct_choice_id", "")),
|
||||
"is_correct": choice_id == str(question.get("correct_choice_id", "")) and not had_wrong_attempt,
|
||||
"first_attempt_is_correct": choice_id == str(question.get("correct_choice_id", "")) and not had_wrong_attempt,
|
||||
"eliminated_choice_ids": eliminated.duplicate(),
|
||||
"flagged": flagged,
|
||||
"elapsed_seconds": get_current_elapsed_seconds(),
|
||||
"target_seconds": 0.0
|
||||
}
|
||||
review_first_submission_recorded = true
|
||||
if bool(answer.is_correct):
|
||||
var current_correct := choice_id == str(question.get("correct_choice_id", ""))
|
||||
if current_correct:
|
||||
answers[current_index] = answer
|
||||
session_changed.emit()
|
||||
return {
|
||||
"answer": answer,
|
||||
"is_correct": bool(answer.is_correct),
|
||||
"final": bool(answer.is_correct),
|
||||
"is_correct": current_correct,
|
||||
"final": current_correct,
|
||||
"first_submission": first_submission
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ func calculate_block_rewards(answers: Array, mode: String, system_name: String)
|
||||
var ending_streak := running_streak
|
||||
|
||||
for answer in answers:
|
||||
if bool(answer.get("is_correct", false)):
|
||||
if bool(answer.get("first_attempt_is_correct", answer.get("is_correct", false))):
|
||||
correct += 1
|
||||
ending_streak += 1
|
||||
longest_streak = max(longest_streak, ending_streak)
|
||||
|
||||
@@ -1613,31 +1613,32 @@ func _submit_or_next() -> void:
|
||||
if selected_choice == "":
|
||||
return
|
||||
var question_id_for_attempt := str(BlockSessionService.get_current_question().get("id", ""))
|
||||
if BlockSessionService.session_kind == "dynamic":
|
||||
var elapsed := int(floor(BlockSessionService.get_current_elapsed_seconds()))
|
||||
DynamicQuestionService.submit_attempt(selected_choice, elapsed)
|
||||
current_answer = BlockSessionService.answer_current(selected_choice, eliminated, false)
|
||||
_show_answer_review()
|
||||
return
|
||||
if BlockSessionService.session_kind in ["core", "bookmark", "review"]:
|
||||
var immediate_feedback := BlockSessionService.session_kind in ["core", "bookmark", "review", "dynamic"] or (BlockSessionService.session_kind == "block" and BlockSessionService.mode == "Tutor")
|
||||
if immediate_feedback:
|
||||
var attempted_choice := selected_choice
|
||||
var had_wrong_attempt := not locked_wrong_choice_ids.is_empty()
|
||||
var met_time_limit := true
|
||||
if BlockSessionService.session_kind == "core":
|
||||
met_time_limit = BlockSessionService.get_current_elapsed_seconds() <= BlockSessionService.core_current_target_seconds
|
||||
if BlockSessionService.session_kind in ["core", "block"] and not had_wrong_attempt:
|
||||
if BlockSessionService.session_kind == "core":
|
||||
met_time_limit = BlockSessionService.get_current_elapsed_seconds() <= BlockSessionService.core_current_target_seconds
|
||||
QuestionBankService.record_first_attempt(
|
||||
question_id_for_attempt,
|
||||
attempted_choice,
|
||||
_presented_choice_ids(),
|
||||
int(floor(BlockSessionService.get_core_question_total_elapsed_seconds())),
|
||||
int(floor(BlockSessionService.get_core_question_total_elapsed_seconds())) if BlockSessionService.session_kind == "core" else int(floor(BlockSessionService.get_current_elapsed_seconds())),
|
||||
met_time_limit
|
||||
)
|
||||
elif BlockSessionService.session_kind == "dynamic" and not had_wrong_attempt:
|
||||
DynamicQuestionService.submit_attempt(attempted_choice, int(floor(BlockSessionService.get_current_elapsed_seconds())))
|
||||
var result: Dictionary
|
||||
if BlockSessionService.session_kind == "core":
|
||||
result = BlockSessionService.submit_core_attempt(selected_choice, eliminated, flagged)
|
||||
elif BlockSessionService.session_kind == "bookmark":
|
||||
result = BlockSessionService.submit_bookmark_attempt(selected_choice, eliminated, flagged)
|
||||
result = BlockSessionService.submit_bookmark_attempt(selected_choice, eliminated, flagged, had_wrong_attempt)
|
||||
elif BlockSessionService.session_kind == "review":
|
||||
result = BlockSessionService.submit_review_attempt(selected_choice, eliminated, flagged, had_wrong_attempt)
|
||||
else:
|
||||
result = BlockSessionService.submit_review_attempt(selected_choice, eliminated, flagged)
|
||||
result = BlockSessionService.submit_tutor_attempt(selected_choice, eliminated, flagged, had_wrong_attempt)
|
||||
if result.is_empty():
|
||||
return
|
||||
var answer: Dictionary = result.get("answer", {})
|
||||
@@ -1817,7 +1818,6 @@ func _dock_correct_review_panel(correct_id: String) -> void:
|
||||
|
||||
func _render_answer_review_sections() -> void:
|
||||
_render_teaching_cards()
|
||||
_render_review_followups()
|
||||
_render_unselected_distractor_explanations()
|
||||
|
||||
|
||||
@@ -1893,12 +1893,9 @@ func _render_review_followups() -> void:
|
||||
if review_followups_content == null:
|
||||
return
|
||||
_clear_container_children(review_followups_content)
|
||||
if BlockSessionService.session_kind == "simulation":
|
||||
review_followups_section.visible = false
|
||||
return
|
||||
if not BlockSessionService.show_review_followups:
|
||||
review_followups_section.visible = false
|
||||
return
|
||||
review_followup_states.clear()
|
||||
review_followups_section.visible = false
|
||||
return
|
||||
var question := BlockSessionService.get_current_question()
|
||||
var authored: Array = question.get("review_followups", [])
|
||||
if review_followup_states.size() != authored.size():
|
||||
@@ -3774,14 +3771,14 @@ func _followup_is_dark() -> bool:
|
||||
|
||||
|
||||
func _choice_review_explanation(choice_id: String, state: Dictionary) -> String:
|
||||
var teaching_point := str(state.get("teaching_point", "")).strip_edges()
|
||||
if teaching_point != "":
|
||||
return teaching_point
|
||||
var question := BlockSessionService.get_current_question()
|
||||
var explanations: Dictionary = question.get("choice_explanations", {})
|
||||
var explanation := str(explanations.get(choice_id, "")).strip_edges()
|
||||
if explanation != "":
|
||||
return explanation
|
||||
var teaching_point := str(state.get("teaching_point", "")).strip_edges()
|
||||
if teaching_point != "":
|
||||
return teaching_point
|
||||
if bool(state.get("is_main_correct", false)):
|
||||
return str(question.get("explanation", "Review the correct answer explanation."))
|
||||
return "Review the stem finding that makes this option less appropriate."
|
||||
|
||||
@@ -9,7 +9,6 @@ const CORE_BLOCK_SIZE_STEP := 5
|
||||
var main: Control
|
||||
var theme_toggle: CheckButton
|
||||
var sound_toggle: CheckButton
|
||||
var followups_toggle: CheckButton
|
||||
var question_scale_value_label: Label
|
||||
var ccs_scale_value_label: Label
|
||||
var core_block_size_value_label: Label
|
||||
@@ -73,13 +72,6 @@ func _ready() -> void:
|
||||
sound_toggle.toggled.connect(UISoundService.set_sounds_enabled)
|
||||
content.add_child(sound_toggle)
|
||||
|
||||
followups_toggle = CheckButton.new()
|
||||
followups_toggle.text = "Follow-up questions"
|
||||
followups_toggle.tooltip_text = "Optional reinforcement questions shown after you answer"
|
||||
followups_toggle.custom_minimum_size = Vector2(0, 52)
|
||||
followups_toggle.toggled.connect(BlockSessionService.set_show_review_followups)
|
||||
content.add_child(followups_toggle)
|
||||
|
||||
content.add_child(_build_text_scale_row("Question bank text size", "question"))
|
||||
content.add_child(_build_text_scale_row("CCS case text size", "ccs"))
|
||||
content.add_child(_build_core_block_size_row())
|
||||
@@ -117,7 +109,6 @@ func on_show(payload: Variant = null) -> void:
|
||||
back_to_session_button.visible = not return_screen.is_empty()
|
||||
theme_toggle.set_pressed_no_signal(UIThemeService.is_dark_mode())
|
||||
sound_toggle.set_pressed_no_signal(UISoundService.are_sounds_enabled())
|
||||
followups_toggle.set_pressed_no_signal(BlockSessionService.show_review_followups)
|
||||
_refresh_text_scale_labels()
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user