Add CCS study tools and case reporting

This commit is contained in:
hz
2026-07-15 10:43:03 -05:00
parent 7256f93002
commit 9f379cda5c
13 changed files with 542 additions and 56 deletions
+21 -17
View File
@@ -2,43 +2,47 @@ extends VBoxContainer
const Style := preload("res://scripts/ui/ui_style.gd")
var main: Control
var list: VBoxContainer
var status: Label
var start_button: Button
func _ready() -> void:
set_anchors_preset(Control.PRESET_FULL_RECT)
add_theme_constant_override("separation", 14)
var back := Button.new(); back.text = "< All exams"; back.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN
Style.style_chip(back, Style.CYAN); back.pressed.connect(func(): main.show_screen("selection", "exam")); add_child(back)
var title := Label.new(); title.text = "CCS Case Practice"; Style.set_label(title, 34, Style.TEXT); add_child(title)
var back := Button.new(); back.text = "< Step 3 modes"; back.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN
Style.style_chip(back, Style.CYAN); back.pressed.connect(func(): main.show_screen("selection", "step3")); add_child(back)
var title := Label.new(); title.text = "CCS Cases"; Style.set_label(title, 34, Style.TEXT); add_child(title)
var note := Label.new(); note.text = "Manage a simulated patient through examination, orders, treatment, location, and time."; Style.set_label(note, 16, Style.MUTED); add_child(note)
status = Label.new(); Style.set_label(status, 15, Style.CYAN); add_child(status)
var scroll := ScrollContainer.new(); scroll.size_flags_vertical = Control.SIZE_EXPAND_FILL; add_child(scroll)
list = VBoxContainer.new(); list.size_flags_horizontal = Control.SIZE_EXPAND_FILL; list.add_theme_constant_override("separation", 10); scroll.add_child(list)
start_button = Button.new()
start_button.text = "Start Timed Case"
start_button.custom_minimum_size = Vector2(280, 64)
start_button.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN
Style.style_primary_button(start_button)
start_button.pressed.connect(_start)
add_child(start_button)
var spacer := Control.new(); spacer.size_flags_vertical = Control.SIZE_EXPAND_FILL; add_child(spacer)
var history := Button.new(); history.text = "Case History"; history.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN
Style.style_chip(history, Style.CYAN); history.pressed.connect(func(): main.show_screen("ccs_history")); add_child(history)
CCSService.cases_changed.connect(_render)
CCSService.attempt_changed.connect(_attempt_ready)
CCSService.request_failed.connect(func(message: String): status.text = message)
CCSService.request_failed.connect(_on_request_failed)
func on_show(_payload: Variant = null) -> void:
status.text = "Loading cases..."
CCSService.load_cases()
func _render() -> void:
for child in list.get_children(): child.queue_free()
status.text = "No published cases are available yet." if CCSService.cases.is_empty() else "%d cases available" % CCSService.cases.size()
for case in CCSService.cases:
var panel := PanelContainer.new(); panel.add_theme_stylebox_override("panel", Style.panel_box(Style.SURFACE_DARK, Color("405475"))); list.add_child(panel)
var row := HBoxContainer.new(); row.add_theme_constant_override("separation", 12); panel.add_child(row)
var details := Label.new(); details.text = "%s\n%s | %d-minute case" % [case.get("title", "Untitled case"), case.get("system", ""), case.get("realTimeMinutes", 20)]
details.size_flags_horizontal = Control.SIZE_EXPAND_FILL; Style.set_label(details, 18, Style.TEXT); row.add_child(details)
var practice := Button.new(); practice.text = "Practice"; Style.style_chip(practice, Style.CYAN); practice.pressed.connect(_start.bind(str(case.get("externalId", "")), "practice")); row.add_child(practice)
var timed := Button.new(); timed.text = "Timed"; Style.style_primary_button(timed); timed.pressed.connect(_start.bind(str(case.get("externalId", "")), "timed")); row.add_child(timed)
start_button.disabled = CCSService.cases.is_empty()
func _start(case_id: String, mode: String) -> void:
func _start() -> void:
status.text = "Starting case..."
CCSService.create_attempt(case_id, mode)
start_button.disabled = true
CCSService.create_attempt("", "timed")
func _attempt_ready() -> void:
if visible and not CCSService.attempt.is_empty(): main.show_screen("ccs_player")
func _on_request_failed(message: String) -> void:
status.text = message
start_button.disabled = CCSService.cases.is_empty()