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.
95 lines
3.7 KiB
GDScript
95 lines
3.7 KiB
GDScript
extends RefCounted
|
|
|
|
## Weather state and scheduled transitions. The caller owns generation policy;
|
|
## this model invents neither probabilities nor rain/fog balance multipliers.
|
|
const VERSION := 1
|
|
const KINDS := [&"clear", &"rain", &"storm", &"mana_fog"]
|
|
const MAX_MINUTE := 2147483647
|
|
const MAX_PENDING := 4096
|
|
var _minute := -1
|
|
var _kind: StringName = &""
|
|
var _since := -1
|
|
var _pending: Array[Dictionary] = []
|
|
|
|
func initialize(kind: Variant, minute: Variant) -> bool:
|
|
if _minute >= 0 or not _valid_kind(kind) or not _valid_minute(minute):
|
|
return false
|
|
_minute = minute
|
|
_since = minute
|
|
_kind = StringName(kind)
|
|
return true
|
|
|
|
func get_kind() -> StringName:
|
|
return _kind
|
|
|
|
func get_minute() -> int:
|
|
return _minute
|
|
|
|
func permits_new_arrivals() -> bool:
|
|
return _minute >= 0 and _kind != &"storm"
|
|
|
|
func schedule(kind: Variant, minute: Variant) -> Dictionary:
|
|
if _minute < 0 or not _valid_kind(kind) or not _valid_minute(minute) or minute <= _minute:
|
|
return {&"ok": false, &"code": &"INVALID_TRANSITION"}
|
|
for row: Dictionary in _pending:
|
|
if row[&"minute"] == minute:
|
|
return {&"ok": row[&"kind"] == StringName(kind), &"replayed": row[&"kind"] == StringName(kind)}
|
|
if _pending.size() >= MAX_PENDING:
|
|
return {&"ok": false, &"code": &"SCHEDULE_FULL"}
|
|
_pending.append({&"kind": StringName(kind), &"minute": minute})
|
|
_pending.sort_custom(func(a: Dictionary, b: Dictionary) -> bool: return a[&"minute"] < b[&"minute"])
|
|
return {&"ok": true, &"replayed": false}
|
|
|
|
func advance_to(minute: Variant) -> Dictionary:
|
|
if _minute < 0 or not _valid_minute(minute) or minute < _minute:
|
|
return {&"ok": false, &"code": &"INVALID_TIME"}
|
|
var changes: Array[Dictionary] = []
|
|
var replayed: bool = minute == _minute
|
|
while not _pending.is_empty() and int(_pending[0][&"minute"]) <= minute:
|
|
var transition: Dictionary = _pending.pop_front()
|
|
if transition[&"kind"] == _kind:
|
|
continue
|
|
changes.append({&"from": _kind, &"to": transition[&"kind"], &"minute": transition[&"minute"]})
|
|
_kind = transition[&"kind"]
|
|
_since = transition[&"minute"]
|
|
_minute = minute
|
|
return {&"ok": true, &"replayed": replayed, &"changes": changes}
|
|
|
|
func create_snapshot() -> Dictionary:
|
|
return {&"version": VERSION, &"minute": _minute, &"kind": _kind,
|
|
&"since": _since, &"pending": _pending.duplicate(true)}
|
|
|
|
func restore_snapshot(source: Dictionary) -> bool:
|
|
if not _keys(source, ["version", "minute", "kind", "since", "pending"]) \
|
|
or typeof(source["version"]) != TYPE_INT or source["version"] != VERSION \
|
|
or not _valid_minute(source["minute"]) or not _valid_minute(source["since"]) \
|
|
or source["since"] > source["minute"] or not _valid_kind(source["kind"]) \
|
|
or not source["pending"] is Array or source["pending"].size() > MAX_PENDING:
|
|
return false
|
|
var previous: int = source["minute"]
|
|
var pending: Array[Dictionary] = []
|
|
for value: Variant in source["pending"]:
|
|
if not value is Dictionary or not _keys(value, ["kind", "minute"]) \
|
|
or not _valid_kind(value["kind"]) or not _valid_minute(value["minute"]) \
|
|
or value["minute"] <= previous:
|
|
return false
|
|
previous = value["minute"]
|
|
pending.append({&"kind": StringName(value["kind"]), &"minute": value["minute"]})
|
|
_minute = source["minute"]
|
|
_kind = StringName(source["kind"])
|
|
_since = source["since"]
|
|
_pending = pending
|
|
return true
|
|
|
|
static func _valid_kind(value: Variant) -> bool:
|
|
return typeof(value) in [TYPE_STRING, TYPE_STRING_NAME] and StringName(value) in KINDS
|
|
|
|
static func _valid_minute(value: Variant) -> bool:
|
|
return typeof(value) == TYPE_INT and value >= 0 and value <= MAX_MINUTE
|
|
|
|
static func _keys(source: Dictionary, expected: Array) -> bool:
|
|
if source.size() != expected.size(): return false
|
|
for key: Variant in source:
|
|
if typeof(key) not in [TYPE_STRING, TYPE_STRING_NAME] or String(key) not in expected: return false
|
|
return true
|