Files
TheTree_mock/scripts/environment/weather_timeline.gd
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

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