Implement whole-game packed event conditions

This commit is contained in:
Jan Petykiewicz 2026-04-15 21:41:40 -07:00
commit cc54a00e25
16 changed files with 1184 additions and 42 deletions

View file

@ -56,8 +56,10 @@ pub struct RuntimeSummary {
pub packed_event_blocked_missing_territory_context_count: usize,
pub packed_event_blocked_named_territory_binding_count: usize,
pub packed_event_blocked_unmapped_ordinary_condition_count: usize,
pub packed_event_blocked_unmapped_world_condition_count: usize,
pub packed_event_blocked_missing_compact_control_count: usize,
pub packed_event_blocked_unmapped_real_descriptor_count: usize,
pub packed_event_blocked_unmapped_world_descriptor_count: usize,
pub packed_event_blocked_territory_access_variant_count: usize,
pub packed_event_blocked_territory_access_scope_count: usize,
pub packed_event_blocked_missing_train_context_count: usize,
@ -393,6 +395,20 @@ impl RuntimeSummary {
.count()
})
.unwrap_or(0),
packed_event_blocked_unmapped_world_condition_count: state
.packed_event_collection
.as_ref()
.map(|summary| {
summary
.records
.iter()
.filter(|record| {
record.import_outcome.as_deref()
== Some("blocked_unmapped_world_condition")
})
.count()
})
.unwrap_or(0),
packed_event_blocked_missing_compact_control_count: state
.packed_event_collection
.as_ref()
@ -421,6 +437,20 @@ impl RuntimeSummary {
.count()
})
.unwrap_or(0),
packed_event_blocked_unmapped_world_descriptor_count: state
.packed_event_collection
.as_ref()
.map(|summary| {
summary
.records
.iter()
.filter(|record| {
record.import_outcome.as_deref()
== Some("blocked_unmapped_world_descriptor")
})
.count()
})
.unwrap_or(0),
packed_event_blocked_territory_access_variant_count: state
.packed_event_collection
.as_ref()
@ -843,4 +873,107 @@ mod tests {
assert_eq!(summary.company_count, 2);
assert_eq!(summary.active_company_count, 1);
}
#[test]
fn counts_world_frontier_buckets_separately() {
let state = RuntimeState {
calendar: CalendarPoint {
year: 1830,
month_slot: 0,
phase_slot: 0,
tick_slot: 0,
},
world_flags: BTreeMap::new(),
save_profile: RuntimeSaveProfileState::default(),
world_restore: RuntimeWorldRestoreState::default(),
metadata: BTreeMap::new(),
companies: Vec::new(),
selected_company_id: None,
players: Vec::new(),
selected_player_id: None,
trains: Vec::new(),
territories: Vec::new(),
company_territory_track_piece_counts: Vec::new(),
company_territory_access: Vec::new(),
packed_event_collection: Some(RuntimePackedEventCollectionSummary {
source_kind: "packed-event-runtime-collection".to_string(),
mechanism_family: "classic-save-rehydrate-v1".to_string(),
mechanism_confidence: "grounded".to_string(),
container_profile_family: Some("rt3-classic-save-container-v1".to_string()),
packed_state_version: 0x3e9,
packed_state_version_hex: "0x000003e9".to_string(),
live_id_bound: 2,
live_record_count: 2,
live_entry_ids: vec![21, 22],
decoded_record_count: 2,
imported_runtime_record_count: 0,
records: vec![
RuntimePackedEventRecordSummary {
record_index: 0,
live_entry_id: 21,
payload_offset: Some(0x7202),
payload_len: Some(96),
decode_status: "parity_only".to_string(),
payload_family: "real_packed_v1".to_string(),
trigger_kind: Some(7),
active: None,
marks_collection_dirty: None,
one_shot: None,
compact_control: None,
text_bands: Vec::new(),
standalone_condition_row_count: 0,
standalone_condition_rows: Vec::new(),
negative_sentinel_scope: None,
grouped_effect_row_counts: vec![1, 0, 0, 0],
grouped_effect_rows: Vec::new(),
grouped_company_targets: Vec::new(),
decoded_conditions: Vec::new(),
decoded_actions: Vec::new(),
executable_import_ready: false,
import_outcome: Some("blocked_unmapped_world_descriptor".to_string()),
notes: Vec::new(),
},
RuntimePackedEventRecordSummary {
record_index: 1,
live_entry_id: 22,
payload_offset: Some(0x7242),
payload_len: Some(96),
decode_status: "parity_only".to_string(),
payload_family: "real_packed_v1".to_string(),
trigger_kind: Some(7),
active: None,
marks_collection_dirty: None,
one_shot: None,
compact_control: None,
text_bands: Vec::new(),
standalone_condition_row_count: 1,
standalone_condition_rows: Vec::new(),
negative_sentinel_scope: None,
grouped_effect_row_counts: vec![0, 0, 0, 0],
grouped_effect_rows: Vec::new(),
grouped_company_targets: Vec::new(),
decoded_conditions: Vec::new(),
decoded_actions: Vec::new(),
executable_import_ready: false,
import_outcome: Some("blocked_unmapped_world_condition".to_string()),
notes: Vec::new(),
},
],
}),
event_runtime_records: Vec::new(),
candidate_availability: BTreeMap::new(),
special_conditions: BTreeMap::new(),
service_state: RuntimeServiceState::default(),
};
let summary = RuntimeSummary::from_state(&state);
assert_eq!(
summary.packed_event_blocked_unmapped_world_descriptor_count,
1
);
assert_eq!(
summary.packed_event_blocked_unmapped_world_condition_count,
1
);
}
}