extends RefCounted ## Emergency aftermath: responder outcomes reach the review, evacuation clears the ## entrance and locks the door, and an unjustified call opens an investigation. const Rules := preload("res://src/core/rules.gd") const RadioSystem := preload("res://src/core/radio_system.gd") const Coordinator := preload("res://src/core/shift_coordinator.gd") const Factory := preload("res://src/content/scenario_factory.gd") const Strings := preload("res://src/core/strings.gd") func _coordinator() -> Object: var c := Coordinator.new() c.setup(Factory.hollywood_building(), 60.0, 4242) return c func test_responder_outcomes_reach_the_review() -> bool: var c := _coordinator() c.responder_outcomes.append("arrest") c.responder_outcomes.append("command") var review: Dictionary = c.build_review() var outcomes: Array = review.get("responder_outcomes", []) var a := TestUtils.check_eq(outcomes, ["arrest", "command"], "responder outcomes are in the review") var b := TestUtils.check(review.has("investigations"), "review carries an investigations list") c = null return a and b func test_outcomes_reset_with_a_new_shift() -> bool: var c := _coordinator() c.responder_outcomes.append("evacuation") c.investigations.append("note") c.setup(Factory.hollywood_building(), 60.0, 1) var a := TestUtils.check_eq(c.responder_outcomes.size(), 0, "outcomes reset on setup") var b := TestUtils.check_eq(c.investigations.size(), 0, "investigations reset on setup") c = null return a and b func test_evacuation_is_the_emergency_default() -> bool: var call := {"type": "emergency", "report": {"danger_level": 2, "weapons_seen": false}} var a := TestUtils.check_eq(RadioSystem.responder_outcome(call), "restraint", "danger 2 restrains") var call2 := {"type": "emergency", "report": {"danger_level": 1, "weapons_seen": false}} var b := TestUtils.check_eq(RadioSystem.responder_outcome(call2), "evacuation", "low-danger emergency evacuates") var call3 := {"type": "assist", "report": {"danger_level": 1, "weapons_seen": false}} var c := TestUtils.check_eq(RadioSystem.responder_outcome(call3), "command", "assistance just commands") var call4 := {"type": "emergency", "report": {"danger_level": 3, "weapons_seen": true}} var d := TestUtils.check_eq(RadioSystem.responder_outcome(call4), "arrest", "weapons arrest") return a and b and c and d func test_evacuation_wiring_locks_the_door_and_clears_npcs() -> bool: var src := FileAccess.get_file_as_string("res://src/game/game_manager.gd") var a := TestUtils.check(src.contains("func _evacuate_entrance"), "evacuation has a handler") var b := TestUtils.check(src.contains('if outcome == "evacuation":'), "arrival routes evacuation") var c := TestUtils.check(src.contains("door.set_locked(true)"), "evacuation locks the door") var d := TestUtils.check(src.contains("npc.start_flee(door_pos)"), "evacuation sends NPCs away") var e := TestUtils.check(src.contains("controller.leave_requested = true"), "evacuated NPCs are marked as leaving") return a and b and c and d and e func test_unjustified_emergency_is_detected() -> bool: var src := FileAccess.get_file_as_string("res://src/game/game_manager.gd") var a := TestUtils.check(src.contains("func _is_unjustified_emergency"), "unjustified check exists") var b := TestUtils.check(src.contains("return not weapons and danger <= 1"), "no weapon and low danger is unjustified") var c := TestUtils.check(src.contains("coordinator.investigations.append"), "an investigation note is recorded") var d := TestUtils.check(src.contains('"type": "investigation_opened"'), "the incident log records the investigation") var e := TestUtils.check(src.contains('coordinator.reputation.apply("false_report"'), "the false-report hit applies") return a and b and c and d and e func test_radio_arrival_reconnects_after_setup() -> bool: ## coordinator.setup() builds a new RadioSystem, so the arrival handler must be ## re-connected each shift or dispatched responders never resolve anything. var src := FileAccess.get_file_as_string("res://src/game/game_manager.gd") var a := TestUtils.check(src.contains("func _connect_radio"), "radio wiring has a helper") var b := TestUtils.check(src.contains("coordinator.radio.responder_arrived.connect(_on_responder_arrived)"), "the helper connects the arrival handler") var c := TestUtils.check(src.contains("_connect_radio()"), "shifts call the helper") return a and b and c func test_review_strings_exist() -> bool: var a := TestUtils.check(Strings.lookup("review.responder") != "review.responder", "responder line exists") var b := TestUtils.check(Strings.lookup("review.investigations") != "review.investigations", "investigation line exists") var c := TestUtils.check(Strings.lookup("review.none") != "review.none", "empty placeholder exists") var d := TestUtils.check(Strings.lookup("responder.evacuated") != "responder.evacuated", "evacuation log line exists") var e := TestUtils.check(Strings.lookup("investigation.started") != "investigation.started", "investigation log line exists") return a and b and c and d and e func test_review_renders_outcomes_and_investigations() -> bool: var Review := load("res://src/game/ui/shift_review.gd") var panel: Node = Review.new() var review := { "scenario_id": "hollywood_building", "reputation": {"rating": 61.0, "grade": "C", "modifiers": []}, "incidents": {"incidents": []}, "crowd": {"mood": 0.4, "panic": false}, "radio": {"battery": 70.0, "emergency_cooldown_s": 0.0}, "spawned_count": 3, "responder_outcomes": ["evacuation"], "investigations": ["Emergency call reviewed"], } panel.show_review(review, Factory.hollywood_building(), []) var text: String = panel.report_label.text var a := TestUtils.check(text.contains("evacuation"), "review names the responder outcome") var b := TestUtils.check(text.contains("Emergency call reviewed"), "review shows the investigation note") var c := TestUtils.check(text.contains("Investigations:"), "investigations line is labelled") panel.free() return a and b and c