diff --git a/scripts/ui/question_player.gd b/scripts/ui/question_player.gd index e631b5b..fe7d9d8 100644 --- a/scripts/ui/question_player.gd +++ b/scripts/ui/question_player.gd @@ -1452,15 +1452,12 @@ func _skip_current_question() -> void: return if BlockSessionService.session_kind != "core": if BlockSessionService.session_kind == "simulation": + selected_choice = "" + current_answer = {} _save_simulation_current_response() - var target_index := _next_revisitable_index() + var target_index := _next_pending_simulation_index() if BlockSessionService.session_kind == "simulation" else _next_revisitable_index() if target_index >= 0 and BlockSessionService.move_to(target_index): _load_question() - elif BlockSessionService.session_kind == "simulation" and not simulation_submit_pending: - simulation_submit_pending = true - next_button.disabled = true - next_button.text = "Submitting..." - ExamSimulationService.submit_block() else: _finish() return @@ -1492,6 +1489,18 @@ func _next_revisitable_index() -> int: return (BlockSessionService.current_index + 1) % question_count +func _next_pending_simulation_index() -> int: + var question_count := BlockSessionService.active_questions.size() + if question_count == 0: + return -1 + for offset in range(1, question_count + 1): + var candidate := (BlockSessionService.current_index + offset) % question_count + var answer = BlockSessionService.get_answer_for_index(candidate) + if answer == null or str(answer.get("selected_choice_id", "")) == "": + return candidate + return -1 + + func _choice_gui_input(event: InputEvent, index: int) -> void: if pending_correct_advance or followup_required or _is_correct_answer_locked(): return @@ -1539,12 +1548,15 @@ func _toggle_eliminate_selected() -> void: func _submit_or_next() -> void: if BlockSessionService.session_kind == "simulation": + if selected_choice == "": + return _save_simulation_current_response() - if BlockSessionService.current_index + 1 < BlockSessionService.active_questions.size(): - BlockSessionService.move_next() + var pending_index := _next_pending_simulation_index() + if pending_index >= 0: + BlockSessionService.move_to(pending_index) _load_question() return - elif not simulation_submit_pending: + if not simulation_submit_pending: simulation_submit_pending = true next_button.disabled = true next_button.text = "Submitting..." @@ -1706,6 +1718,9 @@ func _on_random_question_failed(message: String) -> void: func _show_answer_review() -> void: + if BlockSessionService.session_kind == "simulation": + _clear_answer_review() + return _show_explanation() _show_references(BlockSessionService.get_current_question().get("references", [])) _ensure_answer_review_followups() @@ -1844,6 +1859,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 @@ -3327,7 +3345,8 @@ func _refresh_submit_state() -> void: if next_button == null: return if BlockSessionService.session_kind == "simulation": - next_button.disabled = false + next_button.disabled = selected_choice == "" + next_button.text = "Submit Block" if selected_choice != "" and _next_pending_simulation_index() < 0 else "Next" return if pending_correct_advance or followup_required: next_button.disabled = true diff --git a/tests/post_answer_review_test.gd b/tests/post_answer_review_test.gd index 3516fdc..bb51347 100644 --- a/tests/post_answer_review_test.gd +++ b/tests/post_answer_review_test.gd @@ -341,6 +341,14 @@ func _test_revisitable_navigation_prefers_unanswered_questions() -> void: session.answers[1] = {"selected_choice_id": "B"} session.current_index = 2 _assert(player._next_revisitable_index() == 0, "skip should wrap rather than reload the same unanswered question") + session.answers = [{"selected_choice_id": "A"}, null, {"selected_choice_id": "C"}] + session.current_index = 2 + _assert(player._next_pending_simulation_index() == 1, "simulation should cycle an earlier skipped question back") + session.answers[1] = {"selected_choice_id": "B"} + _assert(player._next_pending_simulation_index() == -1, "simulation should submit only after every question has an answer") + session.answers[2] = {"selected_choice_id": ""} + session.current_index = 2 + _assert(player._next_pending_simulation_index() == 2, "the only skipped simulation question should remain pending") player.free() session.active_questions = prior_questions session.answers = prior_answers