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.
124 lines
5.7 KiB
GDScript
124 lines
5.7 KiB
GDScript
class_name FacilityCleanlinessService
|
|
extends RefCounted
|
|
|
|
## Parameterized cleanliness state. Runtime supplies approved initial/max values
|
|
## and completed-use/task IDs; this model invents no operating balance values.
|
|
var last_error := ""
|
|
var _facilities: Dictionary = {}
|
|
var _receipts: Array[Dictionary] = []
|
|
var _receipt_index: Dictionary = {}
|
|
|
|
func register_facility(id: StringName, initial: int, maximum: int) -> bool:
|
|
if id.is_empty() or _facilities.has(id) or maximum <= 0 or initial < 0 or initial > maximum:
|
|
return _fail("Invalid or duplicate cleanliness facility")
|
|
_facilities[id] = {"id": String(id), "initial": initial, "maximum": maximum, "current": initial}
|
|
last_error = ""
|
|
return true
|
|
|
|
func unregister_facility(id: StringName) -> bool:
|
|
if not _facilities.has(id): return _fail("Unknown cleanliness facility")
|
|
_facilities.erase(id)
|
|
var retained: Array[Dictionary] = []
|
|
_receipt_index.clear()
|
|
for receipt: Dictionary in _receipts:
|
|
if StringName(receipt["facility_id"]) != id:
|
|
retained.append(receipt)
|
|
_receipt_index[_receipt_key(receipt)] = receipt
|
|
_receipts = retained
|
|
last_error = ""
|
|
return true
|
|
|
|
func record_use(id: StringName, service_id: StringName, soil_amount: int) -> bool:
|
|
return _apply(id, service_id, soil_amount, "use")
|
|
|
|
func record_cleaning(id: StringName, task_id: StringName, recovery_amount: int) -> bool:
|
|
return _apply(id, task_id, recovery_amount, "clean")
|
|
|
|
func get_facility(id: StringName) -> Dictionary:
|
|
return (_facilities.get(id, {}) as Dictionary).duplicate(true)
|
|
|
|
func get_dirty_facility_ids(threshold: int) -> Array[StringName]:
|
|
var result: Array[StringName] = []
|
|
for id: StringName in _facilities:
|
|
if int(_facilities[id]["current"]) <= threshold:
|
|
result.append(id)
|
|
result.sort_custom(_id_before)
|
|
return result
|
|
|
|
func create_snapshot() -> Dictionary:
|
|
var rows: Array[Dictionary] = []
|
|
var ids: Array = _facilities.keys()
|
|
ids.sort_custom(_id_before)
|
|
for id: StringName in ids: rows.append(_facilities[id].duplicate(true))
|
|
return {"schema_version": 1, "facilities": rows, "receipts": _receipts.duplicate(true)}
|
|
|
|
func restore_snapshot(snapshot: Dictionary) -> bool:
|
|
if not _keys(snapshot, ["schema_version", "facilities", "receipts"]) or typeof(snapshot.get("schema_version")) != TYPE_INT or snapshot["schema_version"] != 1:
|
|
return _fail("Unsupported cleanliness snapshot")
|
|
if not snapshot["facilities"] is Array or not snapshot["receipts"] is Array:
|
|
return _fail("Invalid cleanliness collections")
|
|
var candidate := FacilityCleanlinessService.new()
|
|
var expected: Dictionary = {}
|
|
for value: Variant in snapshot["facilities"]:
|
|
if not value is Dictionary or not _keys(value, ["id", "initial", "maximum", "current"]):
|
|
return _fail("Invalid cleanliness facility row")
|
|
if typeof(value["id"]) != TYPE_STRING or typeof(value["initial"]) != TYPE_INT or typeof(value["maximum"]) != TYPE_INT or typeof(value["current"]) != TYPE_INT:
|
|
return _fail("Invalid cleanliness facility value types")
|
|
var id := StringName(value["id"])
|
|
if not candidate.register_facility(id, value["initial"], value["maximum"]):
|
|
return _fail(candidate.last_error)
|
|
expected[id] = value["current"]
|
|
for value: Variant in snapshot["receipts"]:
|
|
if not value is Dictionary or not _keys(value, ["facility_id", "source_id", "kind", "amount"]):
|
|
return _fail("Invalid cleanliness receipt")
|
|
if typeof(value["facility_id"]) != TYPE_STRING or typeof(value["source_id"]) != TYPE_STRING or typeof(value["kind"]) != TYPE_STRING or typeof(value["amount"]) != TYPE_INT:
|
|
return _fail("Invalid cleanliness receipt value types")
|
|
if candidate._receipt_index.has(_receipt_key(value)) or not candidate._apply(StringName(value["facility_id"]), StringName(value["source_id"]), value["amount"], value["kind"]):
|
|
return _fail("Invalid, duplicated or dangling cleanliness receipt")
|
|
for id: StringName in expected:
|
|
if candidate._facilities[id]["current"] != expected[id]:
|
|
return _fail("Cleanliness value does not match its completed work")
|
|
_facilities = candidate._facilities
|
|
_receipts = candidate._receipts
|
|
_receipt_index = candidate._receipt_index
|
|
last_error = ""
|
|
return true
|
|
|
|
func _apply(id: StringName, source_id: StringName, amount: int, kind: String) -> bool:
|
|
if not _facilities.has(id) or source_id.is_empty() or amount < 0 or kind not in ["use", "clean"]:
|
|
return _fail("Invalid cleanliness effect")
|
|
var receipt := {"facility_id": String(id), "source_id": String(source_id), "kind": kind, "amount": amount}
|
|
var key := _receipt_key(receipt)
|
|
if _receipt_index.has(key):
|
|
if _receipt_index[key] != receipt: return _fail("Conflicting cleanliness completion replay")
|
|
last_error = ""
|
|
return true
|
|
var row: Dictionary = _facilities[id]
|
|
# Clamp the operand before addition/subtraction to avoid int overflow.
|
|
if kind == "use": row["current"] -= mini(amount, int(row["current"]))
|
|
else: row["current"] += mini(amount, int(row["maximum"]) - int(row["current"]))
|
|
_receipts.append(receipt)
|
|
_receipt_index[key] = receipt
|
|
last_error = ""
|
|
return true
|
|
|
|
static func _receipt_key(receipt: Dictionary) -> String:
|
|
return String(receipt["kind"]) + ":" + String(receipt["source_id"])
|
|
|
|
static func _keys(value: Dictionary, expected: Array) -> bool:
|
|
if value.size() != expected.size(): return false
|
|
for key: Variant in value:
|
|
if typeof(key) not in [TYPE_STRING, TYPE_STRING_NAME] or String(key) not in expected: return false
|
|
for key: String in expected:
|
|
if not value.has(key): return false
|
|
return true
|
|
|
|
func _fail(message: String) -> bool:
|
|
last_error = message
|
|
return false
|
|
|
|
# StringName's built-in ordering is process-local. Persisted row ordering and
|
|
# dispatch priority must instead use the stable textual facility identifier.
|
|
static func _id_before(a: StringName, b: StringName) -> bool:
|
|
return String(a) < String(b)
|