Files
TheTree_mock/tests/environment/test_facility_cleanliness.gd
T
Takeshi 5dde0c5ec2 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.
2026-09-30 23:52:24 +09:00

90 lines
7.0 KiB
GDScript

extends SceneTree
const Cleanliness = preload("res://scripts/environment/facility_cleanliness_service.gd")
var checks := 0
var failures := 0
func expect(ok: bool, label: String) -> void:
checks += 1
if not ok: failures += 1; push_error(label)
func _initialize() -> void: call_deferred("run")
func run() -> void:
var room: FacilityDefinition = load("res://data/facilities/expansion/cleaning_room.tres")
expect(room.is_valid() and room.footprint == Vector2i(2,1) and room.layer == FacilityDefinition.ViewLayer.BACK, "original cleaning room dimensions and layer")
expect(room.construction_cost == {&"gold":350,&"materials":4} and room.build_minutes == 60 and room.maintenance_gold == 2, "approved trial construction and upkeep")
expect(room.staff_min == 1 and room.staff_max == 2 and room.required_roles == [&"cleaner"], "approved cleaner staffing")
expect(room.customer_capacity == 0 and room.base_price == 0, "cleaning room has no customer use or fee")
var policy: Dictionary = JSON.parse_string(FileAccess.get_file_as_string("res://data/environment/cleaning_policy.json"))
expect(policy["initial_cleanliness"] == 100 and policy["maximum_cleanliness"] == 100 and policy["clean_at_or_below"] == 75 and policy["work_minutes"] == 8 and policy["recovery_per_completed_task"] == 25, "approved trial cleaning policy")
var rules = preload("res://scripts/environment/facility_cleaning_policy.gd").new()
expect(rules.load_file(), "approved JSON policy loads through strict validator")
var approved: Dictionary = rules.create_snapshot()
var corrupt_policies: Array = []
for change: Dictionary in [{"schema_version":2}, {"initial_cleanliness":101}, {"maximum_cleanliness":0}, {"clean_at_or_below":100}, {"work_minutes":0}, {"work_minutes":8.5}, {"recovery_per_completed_task":0}, {"work_minutes":true}, {"work_minutes":INF}]:
var invalid_policy: Dictionary = approved.duplicate(true)
invalid_policy.merge(change, true)
corrupt_policies.append(invalid_policy)
var missing_policy: Dictionary = approved.duplicate(true)
missing_policy.erase("work_minutes")
corrupt_policies.append(missing_policy)
for invalid_policy: Dictionary in corrupt_policies:
expect(not rules.configure(invalid_policy) and rules.create_snapshot() == approved, "invalid policy rejects without replacing approved values")
var detached_policy: Dictionary = rules.create_snapshot()
detached_policy["work_minutes"] = 99
expect(rules.create_snapshot()["work_minutes"] == 8, "policy read cannot change work duration")
var ordered = Cleanliness.new()
var names: Array[String] = []
for index in range(31, -1, -1):
var name := "clean_order_%03d" % ((index * 17) % 32)
names.append(name)
ordered.register_facility(StringName(name), 75, 100)
names.sort()
var dirty := ordered.get_dirty_facility_ids(75)
var rows: Array = ordered.create_snapshot()["facilities"]
var text_order_matches := true
for index in names.size():
text_order_matches = text_order_matches and String(dirty[index]) == names[index] and rows[index]["id"] == names[index]
expect(text_order_matches, "generated IDs use lexical order for saves and cleaning dispatch")
var reordered: Dictionary = ordered.create_snapshot()
reordered["facilities"].reverse()
expect(ordered.restore_snapshot(reordered) and ordered.create_snapshot()["facilities"] == rows, "legacy row order restores to canonical lexical order")
var service = Cleanliness.new()
expect(service.register_facility(&"b", 100, 100) and service.register_facility(&"a", 50, 100), "explicit initial and maximum values")
expect(not service.register_facility(&"b", 100,100), "duplicate facility rejected")
expect(not service.register_facility(&"bad", -1,100), "invalid initial value rejected")
expect(service.record_use(&"b", &"visit",25), "completed visit soils facility")
expect(service.get_facility(&"b")["current"]==75, "soil amount applied")
expect(service.get_dirty_facility_ids(75)==[&"a",&"b"], "threshold inclusive with stable ordering")
expect(service.get_dirty_facility_ids(74)==[&"a"], "threshold excludes cleaner facility")
var saved: Dictionary=service.create_snapshot()
expect(service.record_use(&"b", &"visit",25) and service.create_snapshot()==saved, "replayed completion does not double soil")
expect(not service.record_use(&"b", &"visit",26) and service.create_snapshot()==saved, "conflicting completion is atomic")
expect(not service.record_use(&"missing", &"unknown",1), "unknown facility cannot receive effect")
expect(not service.record_cleaning(&"b",&"negative",-1), "negative recovery rejected")
expect(service.record_cleaning(&"b",&"work",9223372036854775807) and service.get_facility(&"b")["current"]==100, "recovery clamps without overflow")
expect(service.record_use(&"b",&"dirty",9223372036854775807) and service.get_facility(&"b")["current"]==0, "soil clamps without overflow")
expect(service.record_cleaning(&"b",&"work",9223372036854775807) and service.get_facility(&"b")["current"]==0, "old cleaning completion does not clean later dirt again")
var restored=Cleanliness.new()
expect(restored.restore_snapshot(service.create_snapshot()), "history and state restore")
expect(restored.create_snapshot()==service.create_snapshot(), "exact roundtrip")
expect(restored.record_cleaning(&"b",&"next",25) and service.record_cleaning(&"b",&"next",25) and restored.create_snapshot()==service.create_snapshot(), "restored continuation matches")
var detached: Dictionary=restored.get_facility(&"b");detached["current"]=99
expect(restored.get_facility(&"b")["current"]==25, "read result detached")
var intact: Dictionary=restored.create_snapshot()
var bad_cases: Array=[]
var bad: Dictionary=intact.duplicate(true);bad["schema_version"]=2;bad_cases.append(bad)
bad=intact.duplicate(true);bad["facilities"][0]["current"]=33;bad_cases.append(bad)
bad=intact.duplicate(true);bad["facilities"].append(bad["facilities"][0].duplicate(true));bad_cases.append(bad)
bad=intact.duplicate(true);bad["receipts"].append(bad["receipts"][0].duplicate(true));bad_cases.append(bad)
bad=intact.duplicate(true);bad["receipts"][0]["facility_id"]="missing";bad_cases.append(bad)
bad=intact.duplicate(true);bad["receipts"][0]["amount"]=1.5;bad_cases.append(bad)
bad=intact.duplicate(true);bad["receipts"][0]["kind"]="unknown";bad_cases.append(bad)
bad=intact.duplicate(true);bad["facilities"]=false;bad_cases.append(bad)
bad=intact.duplicate(true);bad["unexpected"]=1;bad_cases.append(bad)
for candidate: Dictionary in bad_cases:
expect(not restored.restore_snapshot(candidate) and restored.create_snapshot()==intact, "malformed or inconsistent save preserves live state")
var mutated: Dictionary=restored.create_snapshot();mutated["receipts"].clear();mutated["facilities"].clear()
expect(restored.create_snapshot()==intact, "saved arrays do not alias live state")
expect(restored.unregister_facility(&"b") and restored.get_facility(&"b").is_empty(), "demolition removes facility state")
var after_remove=Cleanliness.new()
expect(after_remove.restore_snapshot(restored.create_snapshot()), "demolition retains no dangling completion receipts")
print("Facility cleanliness: %d checks, %d failures" % [checks,failures]);quit(failures)