class_name ScenarioValidator extends RefCounted ## Validates authored venue data before a shift. Keeps content-matrix failures ## out of runtime: every event must reference a known profile and a valid phase, ## event ids must be unique, and the matrix must cover enough kinds/phases. const Rules := preload("res://src/core/rules.gd") static func validate(scenario: Resource) -> Array[String]: var problems: Array[String] = [] if scenario == null: return ["scenario is null"] var profile_types := {} for profile in scenario.npc_profiles: if profile != null: profile_types[int(profile.npc_type)] = true var ids := {} var routine := 0 var scripted := 0 var recovery := 0 var phases := {} for event in scenario.event_pool: if not (event is Dictionary): problems.append("event is not a dictionary") continue var event_id := str(event.get("id", "")) if event_id == "": problems.append("event has no id") elif ids.has(event_id): problems.append("duplicate event id: %s" % event_id) ids[event_id] = true var phase := int(event.get("phase", -1)) if phase < Rules.Phase.EARLY or phase > Rules.Phase.LATE: problems.append("%s has invalid phase %d" % [event_id, phase]) var npc_type := int(event.get("npc_type", -1)) if not profile_types.has(npc_type): problems.append("%s references missing profile type %d" % [event_id, npc_type]) if str(event.get("intent", "")) == "": problems.append("%s has no intent" % event_id) var kind := str(event.get("kind", "routine")) if kind == "routine": routine += 1 elif kind == "scripted": scripted += 1 elif kind == "recovery": recovery += 1 elif kind != "routine": problems.append("%s has unknown kind %s" % [event_id, kind]) phases[phase] = true if scenario.event_pool.size() < 12: problems.append("event matrix has %d events; need at least 12" % scenario.event_pool.size()) if routine < 6: problems.append("event matrix needs at least 6 routine events") if scripted < 2: problems.append("event matrix needs at least 2 scripted events") if recovery < 1: problems.append("event matrix needs at least 1 recovery event") if phases.size() < 2: problems.append("event matrix must cover at least 2 shift phases") return problems