Add interactive CCS case practice

This commit is contained in:
hz
2026-07-15 10:17:53 -05:00
parent d73fd5f2cf
commit 7256f93002
23 changed files with 1429 additions and 4 deletions
+44
View File
@@ -0,0 +1,44 @@
extends VBoxContainer
const Style := preload("res://scripts/ui/ui_style.gd")
var main: Control
var list: VBoxContainer
var status: Label
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 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)
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)
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)
func _start(case_id: String, mode: String) -> void:
status.text = "Starting case..."
CCSService.create_attempt(case_id, mode)
func _attempt_ready() -> void:
if visible and not CCSService.attempt.is_empty(): main.show_screen("ccs_player")