extends SceneTree var _checks := 0 var _failures := 0 var _path: PathService var _elevators: ElevatorService var _config: Dictionary var _minute := 0 func _initialize() -> void: call_deferred("_run") func _run() -> void: var clock := root.get_node_or_null("GameClock") if clock != null: clock.set_paused(true) _test_paired_boarding() _test_grouping() _test_capacity_and_time() _test_access_and_shared_cabin() _test_restore_and_emergency() _test_mutations_and_cancellation() _test_snapshot_rejections() print("Elevator service: %d checks, %d failures" % [_checks, _failures]) quit(0 if _failures == 0 else 1) func _setup(layer := 0, floors := 4) -> void: _path = PathService.new() var cells: Array[Vector3i] = [] for y: int in range(floors + 2): cells.append(Vector3i(0, y, layer)) _path.rebuild_graph(cells) _elevators = ElevatorService.new() _elevators.configure(_path) _config = {&"shaft_id": StringName("transport.shaft.%d.0.0.%d" % [layer, 2 if layer == 0 else 3]), &"module_ids": [&"module.0", &"module.1"], &"stops": [], &"width": 2 if layer == 0 else 3, &"capacity": 4 if layer == 0 else 8, &"travel_minutes_per_floor": 10 if layer == 0 else 5, &"access_id": &"" if layer == 0 else &"staff"} for y: int in range(floors): (_config[&"stops"] as Array).append(Vector3i(0, y, layer)) _expect(_elevators.synchronize([_config], 0)[&"ok"], "shaft initializes") _minute = 0 func _request(actor: StringName, from: int, to: int, layer := 0) -> Dictionary: var access: Array[StringName] = [] if layer == 1: access.append(&"staff") return _elevators.request_trip(actor, Vector3i(0, from, layer), Vector3i(0, to, layer), _minute, access) func _tick(count := 1) -> Array[Dictionary]: var arrivals: Array[Dictionary] = [] for i: int in range(count): _minute += 1 arrivals.append_array(_elevators.advance_one_minute(_minute)) return arrivals func _car() -> Dictionary: return _elevators.get_report()[&"shafts"][0] func _test_grouping() -> void: var registry := DefinitionRegistry.new() registry.rebuild() var records: Array = [] for row: Array in [[&"g2", &"guest_elevator", Vector3i(0, 2, 0)], [&"g0", &"guest_elevator", Vector3i(0, 0, 0)], [&"g6", &"guest_elevator", Vector3i(0, 6, 0)], [&"b0", &"service_elevator", Vector3i(0, 0, 1)], [&"other", &"reception", Vector3i(6, 0, 0)]]: records.append({&"instance_id": row[0], &"definition_id": row[1], &"origin": row[2]}) var configs := ElevatorService.configurations_from_facilities(records, registry) _expect(configs.size() == 3, "adjacent modules form one shaft, gaps and layers form separate shafts") _expect(configs[0][&"stops"] == [Vector3i(0, 0, 0), Vector3i(0, 1, 0), Vector3i(0, 2, 0), Vector3i(0, 3, 0)], "each occupied integer floor gets a landing") _expect(configs[0][&"module_ids"] == [&"g0", &"g2"], "construction ordering does not change module/stop ordering") _expect(configs[2][&"capacity"] == 8 and configs[2][&"travel_minutes_per_floor"] == 5 and configs[2][&"access_id"] == &"staff", "BACK shaft has eight seats, five minutes per floor and staff access") records.reverse() _expect(ElevatorService.configurations_from_facilities(records, registry) == configs, "configuration generation is deterministic") func _test_capacity_and_time() -> void: _setup() _expect(_path.create_snapshot()[&"connectors"].size() == 6, "four stops expose six bidirectional direct links") for i: int in range(5): _expect(_request(StringName("guest/%d" % i), 0, 3)[&"ok"], "guest queues without moving") _expect(_car()[&"passenger_count"] == 0 and _car()[&"waiting_count"] == 5, "requests do not board before simulation advances") _expect(_tick().is_empty() and _car()[&"passenger_count"] == 4 and _car()[&"waiting_count"] == 1, "shared cabin boards at most four FRONT actors") _expect(_car()[&"phase"] == &"BOARDING" and _car()[&"remaining_minutes"] == 6, "doors take two minutes plus one per boarding actor") _expect(_tick(6).is_empty() and _car()[&"phase"] == &"TRAVEL", "boarding duration elapses before cabin travels") _expect(_tick(15).is_empty() and is_equal_approx(_car()[&"visual_floor"], 1.5), "cabin interpolates actual half journey without arriving") _expect(_tick(15).is_empty() and _car()[&"phase"] == &"ALIGHTING", "three FRONT floors take thirty minutes before alighting") _expect(_tick(5).is_empty(), "passengers remain owned while doors are unloading") var arrivals := _tick() _expect(arrivals.size() == 4 and _minute == 43, "first four arrivals happen only after both door intervals and travel") for arrival: Dictionary in arrivals: _expect(arrival[&"cell"] == Vector3i(0, 3, 0) and not arrival[&"emergency"] and _path.get_active_elevator_request(arrival[&"actor_id"]).is_empty(), "arrival transfers actor once and releases Path ownership") _expect(_car()[&"phase"] == &"PICKUP" and _car()[&"waiting_count"] == 1, "remaining guest waits for same cabin to return") arrivals = _tick(66) _expect(arrivals.size() == 1 and arrivals[0][&"actor_id"] == &"guest/4" and _car()[&"phase"] == &"IDLE", "fifth guest waits for real return and completes without starvation") _expect(_tick(10).is_empty(), "completed request never arrives twice") var read := _elevators.get_report() read[&"shafts"][0][&"boarded"].append(&"tamper") _expect(_car()[&"boarded"].is_empty(), "report returns defensive copies") func _test_access_and_shared_cabin() -> void: _setup(1) _expect(not _elevators.request_trip(&"guest/no_access", Vector3i(0, 0, 1), Vector3i(0, 3, 1), 0)[&"ok"], "BACK elevator rejects actor without staff access") for i: int in range(9): _expect(_request(StringName("staff/%d" % i), 0, 3, 1)[&"ok"], "authorized staff queues") _tick() _expect(_car()[&"passenger_count"] == 8 and _car()[&"waiting_count"] == 1, "BACK cabin shares eight seats across requests") _tick(10) _expect(_car()[&"phase"] == &"TRAVEL" and _car()[&"remaining_minutes"] == 15, "BACK shaft uses five minutes per floor") _tick(15) _expect(_car()[&"phase"] == &"ALIGHTING", "BACK travel duration is physical") _expect(_tick(10).size() == 8, "BACK eight passengers alight together after paid time") _setup() _request(&"a", 0, 3) _request(&"b", 1, 2) _tick() _expect(_car()[&"passenger_count"] == 1 and _car()[&"waiting_count"] == 1, "different floor pair cannot create a second cabin") _expect(_elevators.get_actor_trip(&"b")[&"state"] == PathService.ELEVATOR_REQUEST_QUEUED, "other connector actor remains waiting while shared car moves") _expect(_elevators.owns_connector(_elevators.get_actor_trip(&"a")[&"connector_id"]), "transport identifies its owned path step") _expect(not _elevators.owns_connector(&"door.other"), "unrelated door connector is not transport-owned") var all := _tick(100) _expect(all.size() == 2 and all[0][&"actor_id"] == &"a" and all[1][&"actor_id"] == &"b", "FIFO serves different floor pair after first journey") func _test_restore_and_emergency() -> void: _setup() _request(&"rider", 0, 3) _tick(20) _expect(_car()[&"phase"] == &"TRAVEL" and _car()[&"visual_floor"] > 1.0, "midride fixture is physically between floors") var state := _elevators.create_snapshot() var path_state := _path.create_snapshot() var future := _tick(40) var final_state := _elevators.create_snapshot() _expect(_path.restore_snapshot(path_state), "Path queue/boarded state restores") _expect(_elevators.restore_snapshot(state), "midride save restores against matching Path ownership: %s" % _elevators.last_error) _minute = state[&"current_minute"] _expect(_tick(40) == future and _elevators.create_snapshot() == final_state, "restored trip produces identical arrivals and final snapshot") _setup() _request(&"aboard", 0, 3) _request(&"waiting", 2, 3) _tick(20) var released := _elevators.set_powered(_config[&"shaft_id"], false, _minute) _expect(released.size() == 2, "power failure releases both waiting and boarded owners") _expect(released[0][&"actor_id"] == &"aboard" and released[0][&"cell"] == Vector3i(0, 2, 0) and released[0][&"emergency"], "power failure unloads boarded actor at nearest valid floor") _expect(released[1][&"actor_id"] == &"waiting" and released[1][&"cell"] == Vector3i(0, 2, 0) and released[1][&"cancelled"], "waiting cancellation stays on original landing for replan") _expect(_car()[&"operator_open"] and not _car()[&"powered"] and not _car()[&"operational"], "power loss does not alter player operation policy") _expect(_path.get_active_elevator_request(&"aboard").is_empty() and _elevators.get_actor_trip(&"waiting").is_empty(), "emergency leaves no orphan owner") _expect(not _request(&"stopped", 0, 3)[&"ok"], "stopped elevator rejects new boarding") _expect(_elevators.restore_snapshot(_elevators.create_snapshot()), "stopped elevator restores with Path outage state") _elevators.set_operator_open(_config[&"shaft_id"], false, _minute) _elevators.set_powered(_config[&"shaft_id"], true, _minute) _expect(not _car()[&"operator_open"] and _car()[&"powered"] and not _car()[&"operational"], "power restoration preserves player-requested stop") _expect(_elevators.restore_snapshot(_elevators.create_snapshot()), "player-stopped powered elevator state restores") _elevators.set_operator_open(_config[&"shaft_id"], true, _minute) _expect(_car()[&"operational"] and _request(&"resumed", 2, 0)[&"ok"], "player reopens restored elevator") _expect(_tick(27).size() == 1, "reopened cabin resumes from emergency landing with real travel") _setup() _request(&"blocked_destination", 0, 3) _tick(20) _path.configure_cell_traffic(Vector3i(0, 3, 0), 4, 0, true) released = _tick() _expect(released.size() == 1 and released[0][&"emergency"] and released[0][&"cell"] != Vector3i(0, 3, 0), "blocked destination causes emergency at a valid landing") _setup() _request(&"held", 0, 3) _request(&"waiting_held", 2, 3) _tick(15) for cell: Vector3i in _config[&"stops"]: _path.configure_cell_traffic(cell, 4, 0, true) released = _elevators.set_operator_open(_config[&"shaft_id"], false, _minute) _expect(released.size() == 1 and released[0][&"actor_id"] == &"waiting_held" and released[0][&"cancelled"], "all-landings closure still cancels waiting actors at their original position") _expect(_car()[&"passenger_count"] == 1 and not _car()[&"operational"] and not _path.get_active_elevator_request(&"held").is_empty(), "no valid landing holds boarded actor safely with ownership") var held_remaining: int = _car()[&"remaining_minutes"] _tick(20) _expect(_car()[&"remaining_minutes"] == held_remaining and _elevators.restore_snapshot(_elevators.create_snapshot()), "held cabin survives elapsed time and save restore without advancing or losing its rider") for cell: Vector3i in _config[&"stops"]: _path.configure_cell_traffic(cell) _elevators.set_operator_open(_config[&"shaft_id"], true, _minute) _expect(_elevators.restore_snapshot(_elevators.create_snapshot()), "repaired cabin resumes with an adjusted physical phase clock") _expect(_tick(40).size() == 1, "held actor arrives exactly once after landing repair") func _test_mutations_and_cancellation() -> void: _setup() _request(&"waiter", 0, 3) var before := _elevators.create_snapshot() _expect(not _elevators.synchronize([], _minute)[&"ok"] and _elevators.create_snapshot() == before, "queued rider prevents destructive shaft modification atomically") var larger := _config.duplicate(true) larger[&"module_ids"].append(&"module.2") larger[&"stops"].append(Vector3i(0, 4, 0)) larger[&"stops"].append(Vector3i(0, 5, 0)) _expect(not _elevators.synchronize([larger], _minute)[&"ok"], "extension waits until cabin and queues are idle") _expect(_elevators.cancel_actor(&"waiter") and _path.get_active_elevator_request(&"waiter").is_empty(), "waiting actor removal cancels Path queue ownership") _expect(_elevators.synchronize([larger], _minute)[&"ok"] and _car()[&"stops"].size() == 6, "idle upward extension joins existing physical cabin") _expect(_request(&"despawn", 0, 3)[&"ok"], "new request uses fresh request ID after cancellation") _tick(2) _expect(_elevators.cancel_actor(&"despawn") and _path.get_active_elevator_request(&"despawn").is_empty() and _car()[&"passenger_count"] == 0, "boarded actor despawn removes only seat and ownership") _expect(_elevators.restore_snapshot(_elevators.create_snapshot()), "saved doors remain valid after only passenger despawns") _expect(_tick(50).is_empty() and _car()[&"phase"] == &"IDLE", "empty cabin safely finishes its motion without resurrecting despawned actor") _expect(_elevators.synchronize([], _minute)[&"ok"] and _path.create_snapshot()[&"connectors"].is_empty(), "idle demolition removes all owned connectors") _setup() _request(&"duplicate", 0, 3) _expect(_elevators.restore_snapshot(_elevators.create_snapshot()), "queued snapshot restores with matching floor, request, and Path unit") var replay := _request(&"duplicate", 0, 3) _expect(replay[&"ok"] and replay[&"replay"] and _car()[&"waiting_count"] == 1, "same actor route request replays without duplicate queue") _expect(not _request(&"duplicate", 0, 2)[&"ok"], "actor cannot own another simultaneous destination") _expect(_elevators.advance_one_minute(8).is_empty() and _elevators.current_minute == 0, "skipped simulation minutes are rejected") _expect(_tick().is_empty() and _elevators.advance_one_minute(1).is_empty() and _car()[&"remaining_minutes"] == 3, "duplicate minute cannot advance cabin twice") func _test_snapshot_rejections() -> void: _setup() _request(&"saved", 0, 3) _tick(10) var saved := _elevators.create_snapshot() _expect(_elevators.restore_snapshot(saved), "valid active snapshot restores") var bad := saved.duplicate(true) bad[&"shafts"][0][&"config"][&"capacity"] = 5 _reject(bad, saved, "tampered FRONT capacity") bad = saved.duplicate(true) bad[&"shafts"][0][&"config"][&"travel_minutes_per_floor"] = 1 _reject(bad, saved, "tampered floor speed") bad = saved.duplicate(true) bad[&"shafts"][0][&"remaining_minutes"] -= 1 _reject(bad, saved, "tampered cabin countdown") bad = saved.duplicate(true) bad[&"trips"][0][&"to"] = Vector3i(0, 2, 0) _reject(bad, saved, "tampered destination") bad = saved.duplicate(true) bad[&"shafts"][0][&"boarded"] = [] _reject(bad, saved, "missing passenger seat") bad = saved.duplicate(true) bad[&"trips"] = [] _reject(bad, saved, "missing active trip") bad = saved.duplicate(true) bad[&"request_sequence"] = 0 _reject(bad, saved, "active request sequence reuse") bad = saved.duplicate(true) bad[&"shafts"][0][&"powered"] = false _reject(bad, saved, "inconsistent power and operation") bad = saved.duplicate(true) bad[&"unexpected"] = true _reject(bad, saved, "unknown snapshot field") _tick(50) saved = _elevators.create_snapshot() bad = saved.duplicate(true) bad[&"request_sequence"] = 0 _reject(bad, saved, "retired request sequence reuse") _expect(_elevators.restore_snapshot(saved), "completed trip history permits valid restore") func _reject(bad: Dictionary, before: Dictionary, label: String) -> void: _expect(not _elevators.restore_snapshot(bad) and _elevators.create_snapshot() == before, "%s is rejected atomically" % label) func _expect(condition: bool, label: String) -> void: _checks += 1 if condition: print("PASS: %s" % label) else: _failures += 1 push_error("FAIL: %s" % label) func _test_paired_boarding() -> void: _setup(1) for i: int in range(7): _request(StringName("a%d" % i), 0, 3, 1) _expect(_elevators.request_pair(&"medic", &"patient", Vector3i(0,0,1), Vector3i(0,3,1), 0, [&"staff"])[&"ok"], "rescue pair reserves two real seats") var before := _elevators.create_snapshot() _expect(_elevators.request_pair(&"medic", &"patient", Vector3i(0,0,1), Vector3i(0,3,1), 0, [&"staff"])[&"replay"] and _elevators.create_snapshot() == before, "pair retry is idempotent") _tick() _expect(_car()[&"passenger_count"] == 7 and _car()[&"waiting_count"] == 2, "one remaining seat never splits the rescue pair") _expect(_elevators.get_actor_trip(&"medic")[&"state"] == _elevators.get_actor_trip(&"patient")[&"state"], "pair retains the same queued state") var state := _elevators.create_snapshot() var paths := _path.create_snapshot() var arrivals := _tick(150) var paired: Array[Dictionary] = [] for arrival: Dictionary in arrivals: if arrival[&"actor_id"] in [&"medic", &"patient"]: paired.append(arrival) _expect(paired.size() == 2 and paired[0][&"cell"] == paired[1][&"cell"], "both rescue passengers arrive at the same landing") _expect(_path.restore_snapshot(paths) and _elevators.restore_snapshot(state), "queued pair and seat ownership restore") _minute = state[&"current_minute"] _expect(_tick(150) == arrivals, "queued pair replays exact arrivals") _setup(1) _elevators.request_pair(&"medic", &"patient", Vector3i(0,0,1), Vector3i(0,3,1), 0, [&"staff"]) _expect(_elevators.cancel_actor(&"patient") and _elevators.get_report()[&"trips"].is_empty() and _path.get_active_elevator_request(&"medic").is_empty(), "queued cancellation releases both passengers") _elevators.request_pair(&"medic", &"patient", Vector3i(0,0,1), Vector3i(0,3,1), 0, [&"staff"]) _tick(10) state = _elevators.create_snapshot(); paths = _path.create_snapshot() _expect(not _elevators.cancel_actor(&"patient") and _elevators.create_snapshot() == state, "onboard pair cannot teleport out through cancellation") var corrupt := state.duplicate(true) corrupt[&"trips"][0][&"companion_id"] = &"missing" _expect(not _elevators.restore_snapshot(corrupt) and _elevators.create_snapshot() == state, "orphan companion save is rejected atomically") _expect(_elevators.restore_snapshot(state), "boarded pair restores") var released := _elevators.set_powered(_config[&"shaft_id"], false, _minute) _expect(released.size() == 2 and released[0][&"cell"] == released[1][&"cell"] and released[0][&"emergency"] and released[1][&"emergency"], "power loss unloads the pair together") _expect(_elevators.restore_snapshot(_elevators.create_snapshot()), "emergency release leaves a valid snapshot") _setup(1) _request(&"patient", 0, 2, 1) state = _elevators.create_snapshot(); paths = _path.create_snapshot() _expect(not _elevators.request_pair(&"medic", &"patient", Vector3i(0,0,1), Vector3i(0,3,1), 0, [&"staff"])[&"ok"] and _elevators.create_snapshot() == state and _path.create_snapshot() == paths, "conflicting pair reservation leaves all ownership unchanged") _setup(1) for i: int in range(ElevatorService.QUEUE_CAPACITY - 1): _request(StringName("crowd_%d" % i), 0, 3, 1) state = _elevators.create_snapshot(); paths = _path.create_snapshot() _expect(_car()[&"waiting_count"] == ElevatorService.QUEUE_CAPACITY - 1, "queue fixture has exactly one free request slot") _expect(not _elevators.request_pair(&"medic", &"patient", Vector3i(0,0,1), Vector3i(0,3,1), 0, [&"staff"])[&"ok"] and _elevators.create_snapshot() == state and _path.create_snapshot() == paths, "second-member queue rejection rolls back first member and request sequence")