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)