Integrate examinations into CCS interview
This commit is contained in:
@@ -241,6 +241,21 @@ icon_max_width = 25
|
||||
expand_icon = true
|
||||
text = "Computer"
|
||||
|
||||
[node name="ExaminationLauncher" type="Button" parent="."]
|
||||
visible = false
|
||||
z_index = 40
|
||||
layout_mode = 0
|
||||
offset_left = 202.0
|
||||
offset_top = 24.0
|
||||
offset_right = 394.0
|
||||
offset_bottom = 78.0
|
||||
mouse_default_cursor_shape = 2
|
||||
tooltip_text = "Perform physical examination"
|
||||
icon = ExtResource("10_vitals")
|
||||
icon_max_width = 25
|
||||
expand_icon = true
|
||||
text = "Examination"
|
||||
|
||||
[node name="ComputerOverlay" type="Control" parent="."]
|
||||
visible = false
|
||||
z_index = 100
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
extends Control
|
||||
|
||||
signal choice_selected(choice_id: String)
|
||||
signal interview_continue_requested
|
||||
signal physical_exam_selected(exam_code: String)
|
||||
signal physical_exam_finish_requested
|
||||
signal debrief_return_requested
|
||||
@@ -32,6 +31,7 @@ const DIALOGUE_BUBBLE_VERTICAL_CHROME := 95.0
|
||||
@onready var page_label: Label = $DialogueChoiceArea/ChoicePager/Page
|
||||
@onready var next_page_button: Button = $DialogueChoiceArea/ChoicePager/Next
|
||||
@onready var computer_launcher: Button = $ComputerLauncher
|
||||
@onready var examination_launcher: Button = $ExaminationLauncher
|
||||
@onready var computer_overlay: Control = $ComputerOverlay
|
||||
@onready var computer_close_button: Button = $ComputerOverlay/Close
|
||||
@onready var vitals_launcher: Button = $ComputerOverlay/VitalsLauncher
|
||||
@@ -57,6 +57,15 @@ var physical_exam_finding_text: Label
|
||||
var physical_exam_status: Label
|
||||
var physical_exam_finish_button: Button
|
||||
var physical_exam_buttons := {}
|
||||
var physical_exam_close_button: Button
|
||||
var physical_exam_result_button: Button
|
||||
var physical_exam_terminal := false
|
||||
var available_exams: Array = []
|
||||
var attempt_chart: Array = []
|
||||
var medical_history_section_title: Label
|
||||
var medical_history_exam_text: RichTextLabel
|
||||
var medical_history_tab_button: Button
|
||||
var physical_exam_tab_button: Button
|
||||
var experience_mode := "management"
|
||||
var pending_choices: Array = []
|
||||
var available_choices: Array = []
|
||||
@@ -77,6 +86,7 @@ func _ready() -> void:
|
||||
previous_page_button.pressed.connect(_change_choice_page.bind(-1))
|
||||
next_page_button.pressed.connect(_change_choice_page.bind(1))
|
||||
computer_launcher.pressed.connect(open_computer)
|
||||
examination_launcher.pressed.connect(show_exam_selector)
|
||||
computer_close_button.pressed.connect(close_computer)
|
||||
vitals_launcher.pressed.connect(open_vitals)
|
||||
vitals_close_button.pressed.connect(close_vitals)
|
||||
@@ -92,6 +102,7 @@ func _ready() -> void:
|
||||
_style_computer_window(medical_history_window)
|
||||
_style_desktop_shortcut(vitals_launcher)
|
||||
_style_desktop_shortcut(medical_history_launcher)
|
||||
_build_medical_history_tabs()
|
||||
_resize_computer_windows()
|
||||
_update_clock()
|
||||
_schedule_patient_blink()
|
||||
@@ -117,7 +128,7 @@ func _update_clock() -> void:
|
||||
|
||||
func configure_presentation(
|
||||
presentation: Dictionary, simulated_start: String, simulated_minute: int,
|
||||
vitals: Dictionary = {}, medical_history: String = "") -> void:
|
||||
vitals: Dictionary = {}, medical_history: String = "", chart: Array = []) -> void:
|
||||
if str(presentation.get("patientAssetKey", "")) != "patient_44_white_male":
|
||||
push_warning("Unsupported CCS patient asset key; using the office default.")
|
||||
var date_time := Time.get_datetime_dict_from_datetime_string(simulated_start, false)
|
||||
@@ -129,6 +140,8 @@ func configure_presentation(
|
||||
medical_history_text.text = medical_history.strip_edges() \
|
||||
if not medical_history.strip_edges().is_empty() \
|
||||
else "No past medical history is available."
|
||||
attempt_chart = chart.duplicate(true)
|
||||
_render_physical_exam_history()
|
||||
|
||||
|
||||
func configure_experience_mode(value: String) -> void:
|
||||
@@ -217,7 +230,7 @@ func configure_interview(node: Dictionary) -> void:
|
||||
if bool(node.get("isTerminal", false)):
|
||||
next_choices = [{
|
||||
"id": "__continue",
|
||||
"text": "Begin Physical Examination" if experience_mode == "graphical_interview" else "Continue to Patient Management"
|
||||
"text": "Review Examinations" if experience_mode == "graphical_interview" else "Continue to Patient Management"
|
||||
}]
|
||||
else:
|
||||
next_choices = node.get("choices", [])
|
||||
@@ -269,6 +282,7 @@ func complete_response_transition() -> void:
|
||||
dialogue_page_index = 0
|
||||
dialogue_reveal_complete = false
|
||||
show_dialogue_choices(choices)
|
||||
_update_examination_launcher()
|
||||
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
@@ -324,6 +338,14 @@ func is_computer_open() -> bool:
|
||||
|
||||
|
||||
func close_transient_overlay() -> bool:
|
||||
if physical_exam_panel != null and physical_exam_panel.visible:
|
||||
if physical_exam_result_button.visible:
|
||||
_close_exam_result()
|
||||
elif not physical_exam_terminal:
|
||||
close_exam_overlay()
|
||||
else:
|
||||
return false
|
||||
return true
|
||||
var top_window := _topmost_computer_window()
|
||||
if top_window == vitals_window:
|
||||
return close_vitals()
|
||||
@@ -374,6 +396,61 @@ func is_medical_history_open() -> bool:
|
||||
return medical_history_window.visible
|
||||
|
||||
|
||||
func _build_medical_history_tabs() -> void:
|
||||
var content := medical_history_text.get_parent() as VBoxContainer
|
||||
medical_history_section_title = content.get_node("SectionTitle") as Label
|
||||
var tabs := HBoxContainer.new()
|
||||
tabs.add_theme_constant_override("separation", 8)
|
||||
content.add_child(tabs)
|
||||
content.move_child(tabs, medical_history_section_title.get_index())
|
||||
medical_history_tab_button = Button.new()
|
||||
medical_history_tab_button.text = "Medical History"
|
||||
medical_history_tab_button.pressed.connect(_show_chart_tab.bind(false))
|
||||
tabs.add_child(medical_history_tab_button)
|
||||
physical_exam_tab_button = Button.new()
|
||||
physical_exam_tab_button.text = "Physical Exam"
|
||||
physical_exam_tab_button.pressed.connect(_show_chart_tab.bind(true))
|
||||
tabs.add_child(physical_exam_tab_button)
|
||||
medical_history_exam_text = RichTextLabel.new()
|
||||
medical_history_exam_text.fit_content = true
|
||||
medical_history_exam_text.custom_minimum_size = Vector2(0.0, 120.0)
|
||||
medical_history_exam_text.add_theme_font_size_override("normal_font_size", 18)
|
||||
content.add_child(medical_history_exam_text)
|
||||
_show_chart_tab(false)
|
||||
|
||||
|
||||
func _show_chart_tab(show_exams: bool) -> void:
|
||||
medical_history_section_title.visible = not show_exams
|
||||
medical_history_text.visible = not show_exams
|
||||
medical_history_exam_text.visible = show_exams
|
||||
medical_history_tab_button.disabled = not show_exams
|
||||
physical_exam_tab_button.disabled = show_exams
|
||||
_resize_computer_windows()
|
||||
|
||||
|
||||
func _render_physical_exam_history() -> void:
|
||||
if medical_history_exam_text == null:
|
||||
return
|
||||
var exam_codes := {}
|
||||
for raw_exam in available_exams:
|
||||
exam_codes[str(raw_exam.get("code", ""))] = true
|
||||
var findings: Array[String] = []
|
||||
for raw_entry in attempt_chart:
|
||||
var entry: Dictionary = raw_entry
|
||||
if exam_codes.has(str(entry.get("code", ""))):
|
||||
findings.append("[b]%s[/b]\n%s" % [str(entry.get("title", "Examination")), str(entry.get("text", ""))])
|
||||
medical_history_exam_text.text = "\n\n".join(findings) if not findings.is_empty() \
|
||||
else "No physical examinations have been completed."
|
||||
|
||||
|
||||
func _update_examination_launcher() -> void:
|
||||
if examination_launcher == null:
|
||||
return
|
||||
examination_launcher.visible = choice_container.visible and not computer_overlay.visible \
|
||||
and (physical_exam_panel == null or not physical_exam_panel.visible)
|
||||
examination_launcher.disabled = available_exams.is_empty()
|
||||
|
||||
|
||||
func _render_vitals(vitals: Dictionary) -> void:
|
||||
for child in vitals_rows.get_children():
|
||||
vitals_rows.remove_child(child)
|
||||
@@ -490,9 +567,11 @@ func _resize_computer_windows() -> void:
|
||||
minf(720.0, maxf(320.0, size.x - 48.0)),
|
||||
minf(vitals_content_height, maxf(300.0, size.y - 48.0)))
|
||||
_set_centered_window_rect(vitals_window, vitals_size, Vector2(-55.0, -25.0))
|
||||
var exam_count := medical_history_exam_text.text.count("[b]") if medical_history_exam_text != null else 0
|
||||
var history_height := 340.0 if not medical_history_exam_text.visible else clampf(250.0 + exam_count * 90.0, 340.0, 650.0)
|
||||
var history_size := Vector2(
|
||||
minf(560.0, maxf(320.0, size.x - 48.0)),
|
||||
minf(300.0, maxf(260.0, size.y - 48.0)))
|
||||
minf(680.0, maxf(320.0, size.x - 48.0)),
|
||||
minf(history_height, maxf(300.0, size.y - 48.0)))
|
||||
_set_centered_window_rect(medical_history_window, history_size, Vector2(55.0, 25.0))
|
||||
|
||||
|
||||
@@ -667,6 +746,7 @@ func _render_choice_page() -> void:
|
||||
next_page_button.disabled = choice_page >= page_count - 1
|
||||
choice_area.visible = true
|
||||
choice_container.visible = true
|
||||
_update_examination_launcher()
|
||||
|
||||
|
||||
func hide_dialogue_choices() -> void:
|
||||
@@ -676,6 +756,7 @@ func hide_dialogue_choices() -> void:
|
||||
choice_container.visible = false
|
||||
choice_pager.visible = false
|
||||
choice_area.visible = false
|
||||
_update_examination_launcher()
|
||||
|
||||
|
||||
func _clear_choice_buttons() -> void:
|
||||
@@ -723,18 +804,19 @@ func _on_choice_pressed_visual(button: TextureButton, pressed: bool) -> void:
|
||||
|
||||
func _on_dialogue_choice_pressed(choice_id: String) -> void:
|
||||
if choice_id == "__continue":
|
||||
interview_continue_requested.emit()
|
||||
show_exam_selector(true)
|
||||
else:
|
||||
choice_selected.emit(choice_id)
|
||||
|
||||
|
||||
func show_physical_exam(exams: Array, chart: Array, pending_code: String = "") -> void:
|
||||
hide_patient_dialogue()
|
||||
hide_dialogue_choices()
|
||||
computer_available = true
|
||||
computer_launcher.visible = not computer_overlay.visible
|
||||
available_exams = exams.duplicate(true)
|
||||
attempt_chart = chart.duplicate(true)
|
||||
_ensure_physical_exam_panel()
|
||||
physical_exam_panel.visible = true
|
||||
physical_exam_finding_title.visible = true
|
||||
physical_exam_finding_text.visible = true
|
||||
physical_exam_result_button.visible = false
|
||||
for child in physical_exam_grid.get_children():
|
||||
physical_exam_grid.remove_child(child)
|
||||
child.queue_free()
|
||||
@@ -777,6 +859,59 @@ func show_physical_exam(exams: Array, chart: Array, pending_code: String = "") -
|
||||
set_physical_exam_pending(pending_code)
|
||||
|
||||
|
||||
func configure_examinations(exams: Array, chart: Array) -> void:
|
||||
available_exams = exams.duplicate(true)
|
||||
attempt_chart = chart.duplicate(true)
|
||||
_render_physical_exam_history()
|
||||
_update_examination_launcher()
|
||||
|
||||
|
||||
func show_exam_selector(terminal: bool = false) -> void:
|
||||
if not choice_container.visible or (physical_exam_panel != null and physical_exam_panel.visible):
|
||||
return
|
||||
physical_exam_terminal = terminal
|
||||
show_physical_exam(available_exams, attempt_chart)
|
||||
physical_exam_finish_button.visible = terminal
|
||||
physical_exam_close_button.visible = not terminal
|
||||
|
||||
|
||||
func show_exam_result(chart: Array, exam_code: String) -> void:
|
||||
attempt_chart = chart.duplicate(true)
|
||||
_render_physical_exam_history()
|
||||
_ensure_physical_exam_panel()
|
||||
physical_exam_panel.visible = true
|
||||
for child in physical_exam_grid.get_children():
|
||||
child.visible = false
|
||||
var finding := _chart_exam_entry(chart, exam_code)
|
||||
physical_exam_finding_title.text = str(finding.get("title", "Examination Finding"))
|
||||
physical_exam_finding_text.text = str(finding.get("text", "No finding was reported."))
|
||||
physical_exam_result_button.visible = true
|
||||
physical_exam_close_button.visible = false
|
||||
physical_exam_finish_button.visible = false
|
||||
|
||||
|
||||
func close_exam_overlay() -> void:
|
||||
if physical_exam_panel != null:
|
||||
physical_exam_panel.visible = false
|
||||
_update_examination_launcher()
|
||||
|
||||
|
||||
func _close_exam_result() -> void:
|
||||
if physical_exam_terminal:
|
||||
physical_exam_panel.visible = false
|
||||
show_exam_selector(true)
|
||||
else:
|
||||
close_exam_overlay()
|
||||
|
||||
|
||||
func _chart_exam_entry(chart: Array, code: String) -> Dictionary:
|
||||
for index in range(chart.size() - 1, -1, -1):
|
||||
var entry: Dictionary = chart[index]
|
||||
if str(entry.get("code", "")) == code:
|
||||
return entry
|
||||
return {}
|
||||
|
||||
|
||||
func set_physical_exam_pending(exam_code: String) -> void:
|
||||
var pending := not exam_code.is_empty()
|
||||
for code in physical_exam_buttons:
|
||||
@@ -801,12 +936,13 @@ func _ensure_physical_exam_panel() -> void:
|
||||
physical_exam_panel = PanelContainer.new()
|
||||
physical_exam_panel.name = "PhysicalExamination"
|
||||
physical_exam_panel.z_index = 50
|
||||
physical_exam_panel.custom_minimum_size = Vector2(980.0, 650.0)
|
||||
add_child(physical_exam_panel)
|
||||
physical_exam_panel.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
physical_exam_panel.offset_left = 44.0
|
||||
physical_exam_panel.offset_top = 28.0
|
||||
physical_exam_panel.offset_right = -44.0
|
||||
physical_exam_panel.offset_bottom = -28.0
|
||||
physical_exam_panel.set_anchors_preset(Control.PRESET_CENTER)
|
||||
physical_exam_panel.offset_left = -490.0
|
||||
physical_exam_panel.offset_top = -325.0
|
||||
physical_exam_panel.offset_right = 490.0
|
||||
physical_exam_panel.offset_bottom = 325.0
|
||||
var panel_style := StyleBoxFlat.new()
|
||||
panel_style.bg_color = Color(0.96, 0.97, 0.98, 0.97)
|
||||
panel_style.border_color = Color(0.12, 0.22, 0.28, 0.9)
|
||||
@@ -869,6 +1005,17 @@ func _ensure_physical_exam_panel() -> void:
|
||||
physical_exam_finish_button.custom_minimum_size = Vector2(170.0, 48.0)
|
||||
physical_exam_finish_button.pressed.connect(func(): physical_exam_finish_requested.emit())
|
||||
actions.add_child(physical_exam_finish_button)
|
||||
physical_exam_close_button = Button.new()
|
||||
physical_exam_close_button.text = "Return to Interview"
|
||||
physical_exam_close_button.custom_minimum_size = Vector2(190.0, 48.0)
|
||||
physical_exam_close_button.pressed.connect(close_exam_overlay)
|
||||
actions.add_child(physical_exam_close_button)
|
||||
physical_exam_result_button = Button.new()
|
||||
physical_exam_result_button.text = "Continue"
|
||||
physical_exam_result_button.custom_minimum_size = Vector2(150.0, 48.0)
|
||||
physical_exam_result_button.visible = false
|
||||
physical_exam_result_button.pressed.connect(_close_exam_result)
|
||||
actions.add_child(physical_exam_result_button)
|
||||
|
||||
|
||||
func _style_physical_exam_button(button: Button, complete: bool) -> void:
|
||||
|
||||
@@ -89,9 +89,13 @@ func _on_cases_changed() -> void:
|
||||
|
||||
func _on_attempt_changed() -> void:
|
||||
active_loaded = true
|
||||
var completed_action := pending_action
|
||||
var completed_exam_code := pending_exam_code
|
||||
pending_action = ""
|
||||
pending_exam_code = ""
|
||||
_render_state()
|
||||
if completed_action == "physical_exam" and active_scene != null:
|
||||
active_scene.show_exam_result(CCSService.attempt.get("chart", []), completed_exam_code)
|
||||
|
||||
|
||||
func _render_state() -> void:
|
||||
@@ -129,9 +133,6 @@ func _render_attempt(attempt: Dictionary) -> void:
|
||||
and bool(attempt.get("openingCompleted", false)) and not bool(node.get("isTerminal", false)):
|
||||
_show_unsupported_attempt("This case has progressed beyond the graphical interview.")
|
||||
return
|
||||
if current_view == "physical_examination" and bool(node.get("isTerminal", false)):
|
||||
_show_physical_examination(attempt)
|
||||
return
|
||||
_show_doctor_office(node, attempt)
|
||||
|
||||
|
||||
@@ -227,7 +228,6 @@ func _show_doctor_office(node: Dictionary, attempt: Dictionary = {}) -> void:
|
||||
if active_scene == null:
|
||||
_set_active_scene(DOCTOR_SCENE.instantiate(), "doctor_office")
|
||||
active_scene.choice_selected.connect(_submit_dialogue_choice)
|
||||
active_scene.interview_continue_requested.connect(_begin_physical_examination)
|
||||
active_scene.physical_exam_selected.connect(_submit_physical_exam)
|
||||
active_scene.physical_exam_finish_requested.connect(_finish_physical_examination)
|
||||
active_scene.debrief_return_requested.connect(_return_to_cases)
|
||||
@@ -240,7 +240,8 @@ func _show_doctor_office(node: Dictionary, attempt: Dictionary = {}) -> void:
|
||||
str(attempt.get("simulatedStartUtc", "")),
|
||||
int(attempt.get("simulatedMinute", 0)),
|
||||
attempt.get("vitals", {}),
|
||||
str(attempt.get("medicalHistory", "")))
|
||||
str(attempt.get("medicalHistory", "")), attempt.get("chart", []))
|
||||
active_scene.configure_examinations(attempt.get("availableExams", []), attempt.get("chart", []))
|
||||
active_scene.configure_interview(node)
|
||||
active_scene.set_choices_pending(not pending_action.is_empty())
|
||||
|
||||
@@ -253,33 +254,6 @@ func _submit_dialogue_choice(choice_id: String) -> void:
|
||||
CCSService.send_dialogue_choice(choice_id)
|
||||
|
||||
|
||||
func _begin_physical_examination() -> void:
|
||||
if not pending_action.is_empty():
|
||||
return
|
||||
_show_physical_examination(CCSService.attempt)
|
||||
|
||||
|
||||
func _show_physical_examination(attempt: Dictionary) -> void:
|
||||
if active_scene == null:
|
||||
_set_active_scene(DOCTOR_SCENE.instantiate(), "physical_examination")
|
||||
active_scene.physical_exam_selected.connect(_submit_physical_exam)
|
||||
active_scene.physical_exam_finish_requested.connect(_finish_physical_examination)
|
||||
active_scene.debrief_return_requested.connect(_return_to_cases)
|
||||
active_scene.debrief_repeat_requested.connect(_repeat_interview)
|
||||
selection_view.visible = false
|
||||
stage_root.visible = true
|
||||
active_scene.configure_experience_mode("graphical_interview")
|
||||
active_scene.configure_presentation(
|
||||
attempt.get("graphicalPresentation", {}),
|
||||
str(attempt.get("simulatedStartUtc", "")),
|
||||
int(attempt.get("simulatedMinute", 0)),
|
||||
attempt.get("vitals", {}),
|
||||
str(attempt.get("medicalHistory", "")))
|
||||
active_scene.show_physical_exam(
|
||||
attempt.get("availableExams", []), attempt.get("chart", []), pending_exam_code)
|
||||
current_view = "physical_examination"
|
||||
|
||||
|
||||
func _submit_physical_exam(exam_code: String) -> void:
|
||||
if not pending_action.is_empty() or exam_code.is_empty():
|
||||
return
|
||||
@@ -309,7 +283,7 @@ func _render_debrief(attempt: Dictionary) -> void:
|
||||
str(attempt.get("simulatedStartUtc", "")),
|
||||
int(attempt.get("simulatedMinute", 0)),
|
||||
attempt.get("vitals", {}),
|
||||
str(attempt.get("medicalHistory", "")))
|
||||
str(attempt.get("medicalHistory", "")), attempt.get("chart", []))
|
||||
active_scene.show_debrief(attempt.get("interviewDebrief", {}), attempt.get("score", {}))
|
||||
current_view = "interview_debrief"
|
||||
|
||||
@@ -369,7 +343,7 @@ func _on_request_failed(message: String) -> void:
|
||||
retry_button.visible = true
|
||||
return
|
||||
if active_scene != null:
|
||||
if current_view == "physical_examination":
|
||||
if failed_action == "physical_exam":
|
||||
pending_exam_code = ""
|
||||
active_scene.show_physical_exam_error(message)
|
||||
else:
|
||||
@@ -398,7 +372,7 @@ func _clear_active_scene() -> void:
|
||||
active_scene.get_parent().remove_child(active_scene)
|
||||
active_scene.queue_free()
|
||||
active_scene = null
|
||||
if current_view in ["doctor_office", "physical_examination"]:
|
||||
if current_view == "doctor_office":
|
||||
current_view = ""
|
||||
|
||||
|
||||
|
||||
@@ -81,6 +81,7 @@ func _run() -> void:
|
||||
_assert(screen.current_view == "doctor_office", "an active interactive attempt should open the doctor office")
|
||||
_assert(not screen.active_scene.is_patient_dialogue_visible(), "the opening should wait for a clinician dialogue selection")
|
||||
_assert(screen.active_scene.choice_container.get_child_count() == 1, "the scene should render server-provided dialogue choices")
|
||||
_assert(screen.active_scene.examination_launcher.visible, "Examination should be available while questions are visible")
|
||||
_assert(screen.active_scene.computer_launcher.visible, "the doctor office should expose the simulated computer launcher")
|
||||
_assert(screen.active_scene.computer_launcher.icon.resource_path.ends_with("monitor.svg"), "the computer launcher should use the monitor icon")
|
||||
screen.active_scene.computer_launcher.pressed.emit()
|
||||
@@ -103,7 +104,9 @@ func _run() -> void:
|
||||
screen.active_scene.medical_history_launcher.pressed.emit()
|
||||
_assert(screen.active_scene.is_vitals_open() and screen.active_scene.is_medical_history_open(), "both chart windows should be able to remain open")
|
||||
_assert(screen.active_scene.medical_history_text.text == "Hyperlipidemia", "Medical History should render the case-authored past medical history")
|
||||
_assert(screen.active_scene.medical_history_window.size.y <= 310.0, "Medical History should size closely to its short content (size %s, minimum %s)" % [screen.active_scene.medical_history_window.size, screen.active_scene.medical_history_window.get_combined_minimum_size()])
|
||||
_assert(screen.active_scene.medical_history_window.size.y <= 350.0, "Medical History should size closely to its tabbed content (size %s, minimum %s)" % [screen.active_scene.medical_history_window.size, screen.active_scene.medical_history_window.get_combined_minimum_size()])
|
||||
_assert(screen.active_scene.physical_exam_tab_button.text == "Physical Exam", "Medical History should include a Physical Exam tab")
|
||||
_assert(screen.active_scene.medical_history_exam_text.text == "No physical examinations have been completed.", "Physical Exam should begin with an empty state")
|
||||
_assert(screen.active_scene.vitals_window.size.y <= 410.0, "Vitals should size to its rendered measurement rows")
|
||||
_assert(screen.active_scene.medical_history_window.z_index > screen.active_scene.vitals_window.z_index, "the most recently opened chart window should come to the front")
|
||||
var original_history_position: Vector2 = screen.active_scene.medical_history_window.position
|
||||
@@ -145,6 +148,7 @@ func _run() -> void:
|
||||
screen._render_state()
|
||||
await process_frame
|
||||
_assert(screen.active_scene.is_patient_dialogue_visible(), "a selected topic should display the patient's response")
|
||||
_assert(not screen.active_scene.examination_launcher.visible, "Examination should be unavailable while the patient is speaking")
|
||||
_assert(not screen.active_scene.choice_container.visible, "the next choices should wait until the patient finishes speaking")
|
||||
_assert(screen.active_scene.dialogue_pages.size() > 1, "long patient responses should split into readable dialogue pages")
|
||||
_assert(_label_content_fits(screen.active_scene.dialogue_text), "the first patient response page should fit inside its speech bubble")
|
||||
@@ -211,16 +215,18 @@ func _run() -> void:
|
||||
_assert(not screen.active_scene.choice_pager.visible, "a single terminal action should not show paging controls")
|
||||
var terminal_choice := screen.active_scene.choice_container.get_child(0) as Control
|
||||
_assert(terminal_choice.size.x <= 360.0, "a single terminal choice should remain a compact centered card")
|
||||
_assert((terminal_choice.get_child(0) as Label).text == "Begin Physical Examination",
|
||||
_assert((terminal_choice.get_child(0) as Label).text == "Review Examinations",
|
||||
"terminal dialogue should lead into the graphical physical examination")
|
||||
screen.active_scene.interview_continue_requested.emit()
|
||||
terminal_choice.pressed.emit()
|
||||
await process_frame
|
||||
_assert(screen.current_view == "physical_examination", "the examination should remain inside CCS Cases 2")
|
||||
_assert(screen.current_view == "doctor_office", "the examination should remain inside the active interview")
|
||||
_assert(screen.active_scene.is_physical_exam_visible(), "the physical examination panel should be visible")
|
||||
_assert(screen.active_scene.physical_exam_grid.columns == 2, "exam components should use two responsive columns")
|
||||
_assert(screen.active_scene.physical_exam_grid.get_child_count() == 12, "all twelve examination components should be available")
|
||||
_assert(not screen.active_scene.physical_exam_finish_button.disabled, "Finish Case should remain available before every exam is complete")
|
||||
screen.active_scene.set_physical_exam_pending("abdomen")
|
||||
screen.pending_action = "physical_exam"
|
||||
screen.pending_exam_code = "abdomen"
|
||||
_assert(screen.active_scene.physical_exam_finish_button.disabled, "case completion should pause while an exam command is pending")
|
||||
_assert(screen.active_scene.physical_exam_buttons.values().all(func(button): return button.disabled),
|
||||
"exam controls should disable while one component is submitted")
|
||||
@@ -229,10 +235,15 @@ func _run() -> void:
|
||||
service.attempt = examined_attempt
|
||||
screen._on_attempt_changed()
|
||||
await process_frame
|
||||
_assert(screen.current_view == "physical_examination", "attempt refreshes should preserve the physical examination phase")
|
||||
_assert(screen.active_scene.physical_exam_buttons.abdomen.text.begins_with("[Done]"), "completed exams should be marked")
|
||||
_assert(screen.active_scene.physical_exam_buttons.abdomen.disabled, "completed exams should not be repeated")
|
||||
_assert(screen.current_view == "doctor_office", "attempt refreshes should preserve the interview phase")
|
||||
_assert(screen.active_scene.physical_exam_finding_text.text == "Mild epigastric tenderness.", "the returned chart finding should be displayed")
|
||||
_assert(screen.active_scene.physical_exam_result_button.visible, "a completed exam should present a focused result card")
|
||||
screen.active_scene.physical_exam_result_button.pressed.emit()
|
||||
_assert(screen.active_scene.is_physical_exam_visible(), "terminal exam results should return to the exam selector")
|
||||
screen.active_scene.open_computer()
|
||||
screen.active_scene.open_medical_history()
|
||||
screen.active_scene.physical_exam_tab_button.pressed.emit()
|
||||
_assert(screen.active_scene.medical_history_exam_text.text.contains("Mild epigastric tenderness."), "completed findings should be stored in the Physical Exam tab")
|
||||
|
||||
service.attempt = {"id": "classic-attempt", "state": "active", "openingCompleted": false, "interview": {}}
|
||||
host.shown_screen = ""
|
||||
|
||||
Reference in New Issue
Block a user