class_name MobileGroupStateRecord extends RefCounted const SCHEMA_VERSION := 1 var data: Dictionary func _init(record_data: Dictionary = {}) -> void: data = record_data.duplicate(true) static func create_at_location( group_id: StringName, group_type: StringName, display_name: String, polity_id: StringName, address: SpatialAddress, detailed_member_ids: Array = [], cohort_counts: Dictionary = {}, cargo_ledger: Dictionary = {}, cargo_capacity: float = 0.0, last_cargo_event_id: int = -1, history_event_ids: Array = [] ) -> MobileGroupStateRecord: return _create( group_id, group_type, display_name, polity_id, address, &"", &"", &"", -1, -1, detailed_member_ids, cohort_counts, cargo_ledger, cargo_capacity, last_cargo_event_id, history_event_ids ) static func create_on_route( group_id: StringName, group_type: StringName, display_name: String, polity_id: StringName, route_id: StringName, departure_location_id: StringName, arrival_location_id: StringName, departure_tick: int, arrival_tick: int, detailed_member_ids: Array = [], cohort_counts: Dictionary = {}, cargo_ledger: Dictionary = {}, cargo_capacity: float = 0.0, last_cargo_event_id: int = -1, history_event_ids: Array = [] ) -> MobileGroupStateRecord: return _create( group_id, group_type, display_name, polity_id, null, route_id, departure_location_id, arrival_location_id, departure_tick, arrival_tick, detailed_member_ids, cohort_counts, cargo_ledger, cargo_capacity, last_cargo_event_id, history_event_ids ) static func _create( group_id: StringName, group_type: StringName, display_name: String, polity_id: StringName, address: Variant, route_id: StringName, departure_location_id: StringName, arrival_location_id: StringName, departure_tick: int, arrival_tick: int, detailed_member_ids: Array, cohort_counts: Dictionary, cargo_ledger: Dictionary, cargo_capacity: float, last_cargo_event_id: int, history_event_ids: Array ) -> MobileGroupStateRecord: var normalized_members: Variant = RegionalStateSupport.normalize_id_array(detailed_member_ids) var normalized_cohorts: Variant = RegionalStateSupport.normalize_count_ledger(cohort_counts) var normalized_cargo: Variant = RegionalStateSupport.normalize_amount_ledger(cargo_ledger) var normalized_history: Variant = RegionalStateSupport.normalize_history_event_ids( history_event_ids ) var normalized_address: Variant = null if address != null: normalized_address = RegionalStateSupport.normalize_address(address) if ( normalized_members == null or normalized_cohorts == null or normalized_cargo == null or normalized_history == null or (address != null and normalized_address == null) ): return null var record := ( MobileGroupStateRecord . new( { "schema_version": SCHEMA_VERSION, "group_id": String(group_id), "group_type": String(group_type), "display_name": display_name, "polity_id": String(polity_id), "location_address": normalized_address, "route_id": String(route_id), "departure_location_id": String(departure_location_id), "arrival_location_id": String(arrival_location_id), "departure_tick": departure_tick, "arrival_tick": arrival_tick, "detailed_member_ids": normalized_members, "cohort_counts": normalized_cohorts, "cargo_ledger": normalized_cargo, "cargo_capacity": cargo_capacity, "last_cargo_event_id": last_cargo_event_id, "history_event_ids": normalized_history, } ) ) return record if record.is_valid() else null static func from_dictionary(record_data: Dictionary) -> MobileGroupStateRecord: if int(record_data.get("schema_version", -1)) != SCHEMA_VERSION: return null if not ( record_data . has_all( [ "group_id", "group_type", "display_name", "polity_id", "location_address", "route_id", "departure_location_id", "arrival_location_id", "departure_tick", "arrival_tick", "detailed_member_ids", "cohort_counts", "cargo_ledger", "cargo_capacity", "last_cargo_event_id", "history_event_ids", ] ) ): return null if ( ( record_data["location_address"] != null and not record_data["location_address"] is Dictionary ) or not record_data["detailed_member_ids"] is Array or not record_data["cohort_counts"] is Dictionary or not record_data["cargo_ledger"] is Dictionary or not record_data["history_event_ids"] is Array ): return null return _create( StringName(record_data["group_id"]), StringName(record_data["group_type"]), String(record_data["display_name"]), StringName(record_data["polity_id"]), record_data["location_address"], StringName(record_data["route_id"]), StringName(record_data["departure_location_id"]), StringName(record_data["arrival_location_id"]), int(record_data["departure_tick"]), int(record_data["arrival_tick"]), record_data["detailed_member_ids"], record_data["cohort_counts"], record_data["cargo_ledger"], float(record_data["cargo_capacity"]), int(record_data["last_cargo_event_id"]), record_data["history_event_ids"] ) func is_valid() -> bool: if ( get_group_id().is_empty() or get_group_type().is_empty() or get_display_name().is_empty() or get_polity_id().is_empty() or not is_finite(get_cargo_capacity()) or get_cargo_capacity() < 0.0 or RegionalStateSupport.amount_ledger_total(data["cargo_ledger"]) > get_cargo_capacity() or get_last_cargo_event_id() < -1 or ( get_last_cargo_event_id() >= 0 and get_last_cargo_event_id() not in get_history_event_ids() ) ): return false if is_at_location(): return ( get_route_id().is_empty() and get_departure_location_id().is_empty() and get_arrival_location_id().is_empty() and get_departure_tick() == -1 and get_arrival_tick() == -1 ) return ( is_on_route() and not get_departure_location_id().is_empty() and not get_arrival_location_id().is_empty() and get_departure_location_id() != get_arrival_location_id() and get_departure_tick() >= 0 and get_arrival_tick() > get_departure_tick() ) func is_at_location() -> bool: return data["location_address"] is Dictionary func is_on_route() -> bool: return data["location_address"] == null and not get_route_id().is_empty() func get_group_id() -> StringName: return StringName(data["group_id"]) func get_group_type() -> StringName: return StringName(data["group_type"]) func get_display_name() -> String: return String(data["display_name"]) func get_polity_id() -> StringName: return StringName(data["polity_id"]) func get_location_address() -> SpatialAddress: return RegionalStateSupport.address_from_data(data["location_address"]) func get_current_location_id() -> StringName: var address := get_location_address() return address.get_location_id() if address != null else &"" func get_route_id() -> StringName: return StringName(data["route_id"]) func get_departure_location_id() -> StringName: return StringName(data["departure_location_id"]) func get_arrival_location_id() -> StringName: return StringName(data["arrival_location_id"]) func get_departure_tick() -> int: return int(data["departure_tick"]) func get_arrival_tick() -> int: return int(data["arrival_tick"]) func get_detailed_member_ids() -> Array[StringName]: return RegionalStateSupport.copy_string_array(data["detailed_member_ids"]) func get_cohort_counts() -> Dictionary: return data["cohort_counts"].duplicate(true) func get_cargo_ledger() -> Dictionary: return data["cargo_ledger"].duplicate(true) func get_cargo_amount(item_id: StringName) -> float: return float(data["cargo_ledger"].get(String(item_id), 0.0)) func get_total_cargo_amount() -> float: return RegionalStateSupport.amount_ledger_total(data["cargo_ledger"]) func get_cargo_capacity() -> float: return float(data["cargo_capacity"]) func get_last_cargo_event_id() -> int: return int(data["last_cargo_event_id"]) func get_history_event_ids() -> Array[int]: return RegionalStateSupport.copy_int_array(data["history_event_ids"]) func get_headcount() -> int: var headcount := get_detailed_member_ids().size() for count: Variant in data["cohort_counts"].values(): headcount += int(count) return headcount func with_location(address: SpatialAddress, cause_event_id: int = -1) -> MobileGroupStateRecord: var history_event_ids := _history_with_event(cause_event_id) return create_at_location( get_group_id(), get_group_type(), get_display_name(), get_polity_id(), address, data["detailed_member_ids"], data["cohort_counts"], data["cargo_ledger"], get_cargo_capacity(), get_last_cargo_event_id(), history_event_ids ) func with_route_journey( route_id: StringName, departure_location_id: StringName, arrival_location_id: StringName, departure_tick: int, arrival_tick: int, cause_event_id: int = -1 ) -> MobileGroupStateRecord: var history_event_ids := _history_with_event(cause_event_id) return create_on_route( get_group_id(), get_group_type(), get_display_name(), get_polity_id(), route_id, departure_location_id, arrival_location_id, departure_tick, arrival_tick, data["detailed_member_ids"], data["cohort_counts"], data["cargo_ledger"], get_cargo_capacity(), get_last_cargo_event_id(), history_event_ids ) func with_cargo_ledger(cargo_ledger: Dictionary, cargo_event_id: int) -> MobileGroupStateRecord: var history_event_ids := _history_with_event(cargo_event_id) return _create( get_group_id(), get_group_type(), get_display_name(), get_polity_id(), data["location_address"], get_route_id(), get_departure_location_id(), get_arrival_location_id(), get_departure_tick(), get_arrival_tick(), data["detailed_member_ids"], data["cohort_counts"], cargo_ledger, get_cargo_capacity(), cargo_event_id, history_event_ids ) func _history_with_event(event_id: int) -> Array: var history_event_ids: Array = data["history_event_ids"].duplicate() if event_id >= 0 and event_id not in history_event_ids: history_event_ids.append(event_id) return history_event_ids func to_dictionary() -> Dictionary: return data.duplicate(true)