Record original-alignment implementation and traceability checkpoint
Capture current source, content data, tests, asset licenses, and original-specification traceability. Original implementation remains incomplete. The accepted matching UI generation passed 154 suites and 12,253 checks, with eight rendered staff-contract screens reviewed. Latest native Windows and full-original acceptance remain outstanding.
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
extends SceneTree
|
||||
## Runs the real UI command handlers, a normal clock and disk save. Invoke again
|
||||
## with -- --read and the same THE_TREE_UPKEEP_UI_SAVE for fresh-process restore.
|
||||
var checks := 0
|
||||
var failures := 0
|
||||
var main: Control
|
||||
var runtime: Variant
|
||||
var clock: Variant
|
||||
func _initialize() -> void:
|
||||
call_deferred("_run")
|
||||
func expect(ok: bool, message: String) -> void:
|
||||
checks += 1
|
||||
if not ok:
|
||||
failures += 1
|
||||
push_error(message)
|
||||
func _run() -> void:
|
||||
runtime = root.get_node("SimulationRuntime")
|
||||
clock = root.get_node("GameClock")
|
||||
var state: Variant = root.get_node("GameState")
|
||||
clock.reset(1, 6, 0)
|
||||
state.reset()
|
||||
runtime.initialize(clock, state, 424242)
|
||||
clock.set_paused(true)
|
||||
root.size = Vector2i(1440, 900)
|
||||
main = load("res://scenes/main/main.tscn").instantiate()
|
||||
var path := OS.get_environment("THE_TREE_UPKEEP_UI_SAVE")
|
||||
if path.is_empty():
|
||||
path = "user://tests/upkeep_closed_%d/manual" % OS.get_process_id()
|
||||
main.set("manual_save_path", path)
|
||||
root.add_child(main)
|
||||
await process_frame
|
||||
runtime.configure_save_policy({&"enabled": false, &"daily_checkpoint_enabled": false})
|
||||
if "--read" in OS.get_cmdline_user_args():
|
||||
_press_text("読込")
|
||||
expect(clock.absolute_minute == 1440, "fresh-process UI load restores midnight")
|
||||
else:
|
||||
(main.get("build_buttons")[&"reception"] as Button).button_pressed = true
|
||||
main.call("_on_map_cell_clicked", Vector3i(-6, 0, 0))
|
||||
expect(runtime.construction_service.get_jobs().size() == 1, "palette and map handler create one construction job")
|
||||
clock.advance_minutes(120)
|
||||
var rooms: Array = runtime.facility_service.get_instances()
|
||||
expect(rooms.size() == 1, "normal clock finishes selected room")
|
||||
if rooms.is_empty():
|
||||
_finish()
|
||||
return
|
||||
var panel: BusinessManagementPanel = main.get("business_management_panel")
|
||||
panel.selected_facility_id = rooms[0].instance_id
|
||||
panel.refresh()
|
||||
panel.business_open_button.button_pressed = false
|
||||
panel.apply_button.pressed.emit()
|
||||
expect(not rooms[0].operator_open, "real business controls close room while paused")
|
||||
expect("維持費" in panel.explanation_label.text, "business controls explain continued upkeep")
|
||||
clock.advance_minutes(959)
|
||||
expect(runtime.economy_service.get_balance(FacilityUpkeepSettlement.EXPENSE) == 0, "23:59 is not settled early")
|
||||
_press_text("保存")
|
||||
var before: Dictionary = runtime.create_snapshot()
|
||||
_press_text("読込")
|
||||
# Save/load deliberately emit distinct audit events and measured durations.
|
||||
# Compare authoritative clock, ownership and money rather than those events.
|
||||
var after: Dictionary = runtime.create_snapshot()
|
||||
expect(after[&"clock"] == before[&"clock"], "UI disk load restores exact pre-midnight clock")
|
||||
for field: StringName in [&"economy", &"facilities", &"facility_upkeep", &"upkeep_settlement"]:
|
||||
expect(after[&"systems"][&"runtime"][field] == before[&"systems"][&"runtime"][field], "UI disk load preserves " + String(field))
|
||||
clock.advance_minutes(1)
|
||||
_verify_closed()
|
||||
await _test_ledger_skin()
|
||||
if "--read" not in OS.get_cmdline_user_args():
|
||||
_press_text("保存")
|
||||
await _capture()
|
||||
_finish()
|
||||
func _test_ledger_skin() -> void:
|
||||
main.call("_set_layer", 0)
|
||||
main.call("_set_ledger_panel_open", true)
|
||||
var ledger: OperatingLedgerPanel = main.get("operating_ledger_panel")
|
||||
var report := ledger.get_report()
|
||||
var cash_label: Label = ledger.get("_cash_label")
|
||||
var closed_label: Label = ledger.get("_closed_label")
|
||||
var before_text := closed_label.text
|
||||
var before_color := cash_label.get_theme_color("font_color")
|
||||
var economy: Dictionary = runtime.economy_service.create_snapshot()
|
||||
main.call("_set_layer", 1)
|
||||
ledger.refresh()
|
||||
expect(cash_label.get_theme_color("font_color") == Color("d8eeea") and closed_label.get_theme_color("font_color") == Color("d8eeea"), "BACK ledger cash and close remain readable after refresh")
|
||||
expect(ledger.get_report() == report and closed_label.text == before_text, "skin preserves selected close and every displayed amount")
|
||||
expect(runtime.economy_service.create_snapshot() == economy, "ledger skin does not post transactions")
|
||||
if DisplayServer.get_name() != "headless":
|
||||
await process_frame;await RenderingServer.frame_post_draw
|
||||
var phase := "read" if "--read" in OS.get_cmdline_user_args() else "write"
|
||||
expect(root.get_texture().get_image().save_png(ProjectSettings.globalize_path("res://artifacts/facility-dimensions-2026-09-29/ledger-skin-back-%s.png" % phase)) == OK, "capture ledger BACK skin")
|
||||
main.call("_set_layer", 0)
|
||||
expect(cash_label.get_theme_color("font_color") == before_color and ledger.get_report() == report, "FRONT restoration retains ledger data")
|
||||
|
||||
func _verify_closed() -> void:
|
||||
var rooms: Array = runtime.facility_service.get_instances()
|
||||
expect(rooms.size() == 1, "saved room remains present")
|
||||
if rooms.is_empty():
|
||||
return
|
||||
var room: FacilityInstance = rooms[0]
|
||||
expect(not room.operator_open, "closed policy survives midnight and restore")
|
||||
# 08:00 completion to 00:00 = 960 minutes at the production 3G/day.
|
||||
expect(runtime.economy_service.get_balance(FacilityUpkeepSettlement.EXPENSE) == 2, "closed room incurs 3 * 960 / 1440 = 2G")
|
||||
expect(runtime.upkeep_settlement.get_facility_balance(room.instance_id)[&"fraction_units"] == 0, "whole-gold settlement leaves no fractional remainder")
|
||||
expect(runtime.upkeep_settlement.get_arrears_total() == 0, "upkeep is paid with no arrears")
|
||||
main.get("world_preview").facility_selected.emit(room.instance_id)
|
||||
expect("3G / 日" in (main.get("selected_detail_label") as Label).text, "inspector uses production daily rate")
|
||||
var midnight: Dictionary = runtime.create_snapshot()
|
||||
var count: int = runtime.upkeep_settlement.get_settled_period_count()
|
||||
clock.advance_minutes(1)
|
||||
expect(runtime.upkeep_settlement.get_settled_period_count() == count, "next minute never repeats midnight settlement")
|
||||
# Restore exact midnight for the independent read phase.
|
||||
expect(runtime.restore_snapshot(midnight), "restore verified midnight for disk handoff")
|
||||
func _press_text(text: String) -> void:
|
||||
if text == "読込":
|
||||
var menu := main.find_child("SaveLoadMenu", true, false) as MenuButton
|
||||
expect(menu != null and not menu.disabled, "normal load menu is available")
|
||||
if menu != null and not menu.disabled:
|
||||
menu.get_popup().id_pressed.emit(0)
|
||||
return
|
||||
for button: Node in main.find_children("*", "Button", true, false):
|
||||
if button.text == text:
|
||||
button.pressed.emit()
|
||||
return
|
||||
expect(false, "UI button found: " + text)
|
||||
func _capture() -> void:
|
||||
if DisplayServer.get_name() == "headless":
|
||||
return
|
||||
for frame in 6:
|
||||
await process_frame
|
||||
await RenderingServer.frame_post_draw
|
||||
var suffix := "read" if "--read" in OS.get_cmdline_user_args() else "write"
|
||||
expect(root.get_texture().get_image().save_png("res://artifacts/upkeep-2026-09-29/closed-ui-%s.png" % suffix) == OK, "native rendered evidence saved")
|
||||
func _finish() -> void:
|
||||
main.queue_free()
|
||||
print("%s: %d checks (phase %s)" % ["PASS" if failures == 0 else "FAIL", checks, "read" if "--read" in OS.get_cmdline_user_args() else "write"])
|
||||
quit(failures)
|
||||
Reference in New Issue
Block a user