diff --git a/crates/rrt-cli/src/main.rs b/crates/rrt-cli/src/main.rs index 6e41874..c02d71b 100644 --- a/crates/rrt-cli/src/main.rs +++ b/crates/rrt-cli/src/main.rs @@ -5784,6 +5784,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: None, notes: vec!["exported for test".to_string()], diff --git a/crates/rrt-runtime/src/import.rs b/crates/rrt-runtime/src/import.rs index 981710e..2e72180 100644 --- a/crates/rrt-runtime/src/import.rs +++ b/crates/rrt-runtime/src/import.rs @@ -1471,6 +1471,35 @@ fn project_save_slice_components( .to_string(), ); } + if let Some(summary) = &save_slice.placed_structure_dynamic_side_buffer_summary { + metadata.insert( + "save_slice.placed_structure_dynamic_side_buffer_source_kind".to_string(), + summary.source_kind.clone(), + ); + metadata.insert( + "save_slice.placed_structure_dynamic_side_buffer_semantic_family".to_string(), + summary.semantic_family.clone(), + ); + metadata.insert( + "save_slice.placed_structure_dynamic_side_buffer_entry_count".to_string(), + summary.observed_entry_count.to_string(), + ); + metadata.insert( + "save_slice.placed_structure_dynamic_side_buffer_name_pair_count".to_string(), + summary.unique_embedded_name_pair_count.to_string(), + ); + metadata.insert( + "save_slice.placed_structure_dynamic_side_buffer_triplet_overlap_count".to_string(), + summary.triplet_alignment_overlap_count.to_string(), + ); + metadata.insert( + "save_slice.placed_structure_dynamic_side_buffer_side_buffer_only_name_pair_count" + .to_string(), + summary + .triplet_alignment_side_buffer_only_name_pair_count + .to_string(), + ); + } let named_locomotive_cost = BTreeMap::new(); let all_cargo_price_override = None; @@ -5540,6 +5569,26 @@ mod tests { } } + fn save_placed_structure_dynamic_side_buffer_summary() + -> crate::SmpLoadedPlacedStructureDynamicSideBufferSummary { + crate::SmpLoadedPlacedStructureDynamicSideBufferSummary { + source_kind: "save-placed-structure-dynamic-side-buffer-records".to_string(), + semantic_family: "scenario-save-placed-structure-dynamic-side-buffer-summary" + .to_string(), + observed_entry_count: 118, + owner_shared_dword_hex: "0xff0000ff".to_string(), + unique_embedded_name_pair_count: 9, + decoded_embedded_name_row_count: 118, + first_prefix_leading_dword_hex: "0xff0000ff".to_string(), + first_prefix_trailing_word_hex: "0x0001".to_string(), + first_prefix_separator_byte_hex: "0xff".to_string(), + triplet_alignment_overlap_count: 2, + triplet_alignment_side_buffer_only_name_pair_count: 7, + compact_prefix_pattern_summaries: vec![], + name_pair_summaries: vec![], + } + } + fn save_chairman_profile_table() -> crate::SmpLoadedChairmanProfileTable { crate::SmpLoadedChairmanProfileTable { source_kind: "tracked-save-slice-chairman-profile-table".to_string(), @@ -6040,6 +6089,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: None, notes: vec![], @@ -6088,6 +6138,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: None, notes: vec![], @@ -6318,6 +6369,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: Some(crate::SmpLoadedSpecialConditionsTable { source_kind: "save-fixed-special-conditions-range".to_string(), table_offset: 0x0d64, @@ -6866,6 +6918,7 @@ mod tests { company_roster: Some(save_company_roster()), chairman_profile_table: Some(save_chairman_profile_table()), placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: None, notes: vec![], @@ -6917,6 +6970,9 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: Some(save_placed_structure_collection()), + placed_structure_dynamic_side_buffer_summary: Some( + save_placed_structure_dynamic_side_buffer_summary(), + ), special_conditions_table: None, event_runtime_collection: None, notes: vec![], @@ -6961,6 +7017,30 @@ mod tests { .map(String::as_str), Some("2") ); + assert_eq!( + import + .state + .metadata + .get("save_slice.placed_structure_dynamic_side_buffer_source_kind") + .map(String::as_str), + Some("save-placed-structure-dynamic-side-buffer-records") + ); + assert_eq!( + import + .state + .metadata + .get("save_slice.placed_structure_dynamic_side_buffer_name_pair_count") + .map(String::as_str), + Some("9") + ); + assert_eq!( + import + .state + .metadata + .get("save_slice.placed_structure_dynamic_side_buffer_triplet_overlap_count") + .map(String::as_str), + Some("2") + ); } #[test] @@ -7022,6 +7102,7 @@ mod tests { company_roster: Some(save_company_roster()), chairman_profile_table: Some(save_chairman_profile_table()), placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: None, notes: vec![], @@ -7194,6 +7275,7 @@ mod tests { entries: Vec::new(), }), placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: None, notes: vec![], @@ -7244,6 +7326,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -7377,6 +7460,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -7488,6 +7572,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -7625,6 +7710,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -7723,6 +7809,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -7889,6 +7976,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -8145,6 +8233,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -8236,6 +8325,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -8351,6 +8441,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -8439,6 +8530,7 @@ mod tests { company_roster: Some(save_company_roster()), chairman_profile_table: Some(save_chairman_profile_table()), placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -8530,6 +8622,7 @@ mod tests { company_roster: Some(save_company_roster()), chairman_profile_table: Some(save_chairman_profile_table()), placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -8634,6 +8727,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -8754,6 +8848,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -8845,6 +8940,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -9013,6 +9109,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -9126,6 +9223,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -9216,6 +9314,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -9306,6 +9405,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -9470,6 +9570,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -9579,6 +9680,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -9667,6 +9769,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -9765,6 +9868,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -9872,6 +9976,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -9987,6 +10092,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -10091,6 +10197,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -10181,6 +10288,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -10341,6 +10449,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -10511,6 +10620,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -10629,6 +10739,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -10728,6 +10839,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -10854,6 +10966,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -10974,6 +11087,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -11084,6 +11198,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -11190,6 +11305,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -11310,6 +11426,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -11415,6 +11532,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -11502,6 +11620,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -11594,6 +11713,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -11691,6 +11811,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -11788,6 +11909,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -11901,6 +12023,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -12005,6 +12128,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -12156,6 +12280,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -12306,6 +12431,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -12847,6 +12973,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -13042,6 +13169,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -13182,6 +13310,7 @@ mod tests { company_roster: Some(save_company_roster()), chairman_profile_table: Some(save_chairman_profile_table()), placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -13321,6 +13450,7 @@ mod tests { company_roster: Some(save_company_roster()), chairman_profile_table: Some(save_chairman_profile_table()), placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -13461,6 +13591,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -13585,6 +13716,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -13784,6 +13916,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -13891,6 +14024,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -14000,6 +14134,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -14180,6 +14315,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -14343,6 +14479,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -14447,6 +14584,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -14584,6 +14722,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -14709,6 +14848,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -14908,6 +15048,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), @@ -15117,6 +15258,7 @@ mod tests { company_roster: None, chairman_profile_table: None, placed_structure_collection: None, + placed_structure_dynamic_side_buffer_summary: None, special_conditions_table: None, event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary { source_kind: "packed-event-runtime-collection".to_string(), diff --git a/crates/rrt-runtime/src/lib.rs b/crates/rrt-runtime/src/lib.rs index 7d0ee2d..47f9084 100644 --- a/crates/rrt-runtime/src/lib.rs +++ b/crates/rrt-runtime/src/lib.rs @@ -110,20 +110,21 @@ pub use smp::{ SmpLoadedPackedEventConditionRowSummary, SmpLoadedPackedEventGroupedEffectRowSummary, SmpLoadedPackedEventNegativeSentinelScopeSummary, SmpLoadedPackedEventRecordSummary, SmpLoadedPackedEventTextBandSummary, SmpLoadedPlacedStructureCollection, - SmpLoadedPlacedStructureEntry, SmpLoadedProfile, SmpLoadedSaveSlice, - SmpLoadedSpecialConditionsTable, SmpLoadedWorldEconomicTuningState, - SmpLoadedWorldFinanceNeighborhoodState, SmpLoadedWorldIssue37State, - SmpLocomotivePolicyFieldObservation, SmpLocomotivePolicyFloatAlignmentCandidate, - SmpLocomotivePolicyNeighborhoodProbe, SmpPackedProfileWordLane, - SmpPeriodicCompanyServiceTraceReport, SmpPostSpecialConditionsScalarLane, - SmpPostSpecialConditionsScalarProbe, SmpPostTextFieldNeighborhoodProbe, - SmpPostTextFloatAlignmentCandidate, SmpPostTextGroundedFieldObservation, - SmpPreRecipeScalarPlateauLane, SmpPreRecipeScalarPlateauProbe, SmpPreamble, SmpPreambleWord, - SmpRecipeBookLineSummary, SmpRecipeBookSummaryBook, SmpRecipeBookSummaryProbe, - SmpRegionServiceTraceReport, SmpRt3105PackedProfileBlock, SmpRt3105PackedProfileProbe, - SmpRt3105PostSpanBridgeProbe, SmpRt3105SaveBridgePayloadProbe, SmpRt3105SaveNameTableEntry, - SmpRt3105SaveNameTableProbe, SmpRuntimeAnchorCycleBlock, SmpRuntimePostSpanHeaderCandidate, - SmpRuntimePostSpanProbe, SmpRuntimeTrailerBlock, SmpSaveAnchorRunBlock, SmpSaveBootstrapBlock, + SmpLoadedPlacedStructureDynamicSideBufferSummary, SmpLoadedPlacedStructureEntry, + SmpLoadedProfile, SmpLoadedSaveSlice, SmpLoadedSpecialConditionsTable, + SmpLoadedWorldEconomicTuningState, SmpLoadedWorldFinanceNeighborhoodState, + SmpLoadedWorldIssue37State, SmpLocomotivePolicyFieldObservation, + SmpLocomotivePolicyFloatAlignmentCandidate, SmpLocomotivePolicyNeighborhoodProbe, + SmpPackedProfileWordLane, SmpPeriodicCompanyServiceTraceReport, + SmpPostSpecialConditionsScalarLane, SmpPostSpecialConditionsScalarProbe, + SmpPostTextFieldNeighborhoodProbe, SmpPostTextFloatAlignmentCandidate, + SmpPostTextGroundedFieldObservation, SmpPreRecipeScalarPlateauLane, + SmpPreRecipeScalarPlateauProbe, SmpPreamble, SmpPreambleWord, SmpRecipeBookLineSummary, + SmpRecipeBookSummaryBook, SmpRecipeBookSummaryProbe, SmpRegionServiceTraceReport, + SmpRt3105PackedProfileBlock, SmpRt3105PackedProfileProbe, SmpRt3105PostSpanBridgeProbe, + SmpRt3105SaveBridgePayloadProbe, SmpRt3105SaveNameTableEntry, SmpRt3105SaveNameTableProbe, + SmpRuntimeAnchorCycleBlock, SmpRuntimePostSpanHeaderCandidate, SmpRuntimePostSpanProbe, + SmpRuntimeTrailerBlock, SmpSaveAnchorRunBlock, SmpSaveBootstrapBlock, SmpSaveChairmanRecordAnalysisEntry, SmpSaveCompanyChairmanAnalysisReport, SmpSaveCompanyRecordAnalysisEntry, SmpSaveDwordCandidate, SmpSaveLoadCandidateTableSummary, SmpSaveLoadSummary, SmpSavePlacedStructureDynamicSideBufferAlignmentProbe, diff --git a/crates/rrt-runtime/src/smp.rs b/crates/rrt-runtime/src/smp.rs index d86e156..4592106 100644 --- a/crates/rrt-runtime/src/smp.rs +++ b/crates/rrt-runtime/src/smp.rs @@ -2019,6 +2019,26 @@ pub struct SmpSavePlacedStructureDynamicSideBufferProbe { pub evidence: Vec, } +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct SmpLoadedPlacedStructureDynamicSideBufferSummary { + pub source_kind: String, + pub semantic_family: String, + pub observed_entry_count: u32, + pub owner_shared_dword_hex: String, + pub unique_embedded_name_pair_count: usize, + pub decoded_embedded_name_row_count: usize, + pub first_prefix_leading_dword_hex: String, + pub first_prefix_trailing_word_hex: String, + pub first_prefix_separator_byte_hex: String, + pub triplet_alignment_overlap_count: usize, + pub triplet_alignment_side_buffer_only_name_pair_count: usize, + #[serde(default)] + pub compact_prefix_pattern_summaries: + Vec, + #[serde(default)] + pub name_pair_summaries: Vec, +} + #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct SmpSavePlacedStructureDynamicSideBufferSampleEntry { pub sample_index: usize, @@ -4067,6 +4087,9 @@ pub struct SmpLoadedSaveSlice { pub chairman_profile_table: Option, #[serde(default)] pub placed_structure_collection: Option, + #[serde(default)] + pub placed_structure_dynamic_side_buffer_summary: + Option, pub special_conditions_table: Option, pub event_runtime_collection: Option, pub notes: Vec, @@ -6886,6 +6909,35 @@ fn derive_loaded_placed_structure_collection_from_probe( } } +fn derive_loaded_placed_structure_dynamic_side_buffer_summary( + probe: &SmpSavePlacedStructureDynamicSideBufferProbe, + alignment: Option<&SmpSavePlacedStructureDynamicSideBufferAlignmentProbe>, +) -> SmpLoadedPlacedStructureDynamicSideBufferSummary { + SmpLoadedPlacedStructureDynamicSideBufferSummary { + source_kind: probe.source_kind.clone(), + semantic_family: "scenario-save-placed-structure-dynamic-side-buffer-summary".to_string(), + observed_entry_count: probe.live_record_count, + owner_shared_dword_hex: probe.owner_shared_dword_hex.clone(), + unique_embedded_name_pair_count: probe.unique_embedded_name_pair_count, + decoded_embedded_name_row_count: probe.decoded_embedded_name_row_count, + first_prefix_leading_dword_hex: probe.prefix_leading_dword_hex.clone(), + first_prefix_trailing_word_hex: probe.prefix_trailing_word_hex.clone(), + first_prefix_separator_byte_hex: probe.prefix_separator_byte_hex.clone(), + triplet_alignment_overlap_count: alignment + .map(|alignment| alignment.overlapping_name_pair_count) + .unwrap_or_default(), + triplet_alignment_side_buffer_only_name_pair_count: alignment + .map(|alignment| { + alignment + .unique_side_buffer_name_pair_count + .saturating_sub(alignment.overlapping_name_pair_count) + }) + .unwrap_or_default(), + compact_prefix_pattern_summaries: probe.compact_prefix_pattern_summaries.clone(), + name_pair_summaries: probe.name_pair_summaries.clone(), + } +} + pub fn load_save_slice_file(path: &Path) -> Result> { let inspection = inspect_smp_file(path)?; load_save_slice_from_report(&inspection) @@ -7049,6 +7101,22 @@ pub fn load_save_slice_from_report( let placed_structure_dynamic_side_buffer_probe = report .save_placed_structure_dynamic_side_buffer_probe .clone(); + let placed_structure_dynamic_side_buffer_alignment = report + .save_placed_structure_dynamic_side_buffer_probe + .as_ref() + .zip(report.save_placed_structure_record_triplet_probe.as_ref()) + .map(|(side_buffer, triplets)| { + summarize_placed_structure_dynamic_side_buffer_alignment(side_buffer, triplets) + }); + let placed_structure_dynamic_side_buffer_summary = report + .save_placed_structure_dynamic_side_buffer_probe + .as_ref() + .map(|probe| { + derive_loaded_placed_structure_dynamic_side_buffer_summary( + probe, + placed_structure_dynamic_side_buffer_alignment.as_ref(), + ) + }); let mut notes = summary.notes.clone(); if let Some(probe) = &report.save_world_selection_context_probe { notes.push(format!( @@ -7285,6 +7353,14 @@ pub fn load_save_slice_from_report( ); } } + if let Some(summary) = &placed_structure_dynamic_side_buffer_summary { + notes.push(format!( + "Save-slice projection now also carries the placed-structure dynamic side-buffer summary with {} decoded name rows, {} unique name pairs, and {} overlapping triplet name pairs.", + summary.decoded_embedded_name_row_count, + summary.unique_embedded_name_pair_count, + summary.triplet_alignment_overlap_count + )); + } if let Some(roster) = &report.save_company_roster_probe { notes.push(format!( "Raw save inspection reconstructed {} company direct records from the tagged company collection.", @@ -7317,6 +7393,7 @@ pub fn load_save_slice_from_report( company_roster, chairman_profile_table, placed_structure_collection, + placed_structure_dynamic_side_buffer_summary, special_conditions_table, event_runtime_collection: report.event_runtime_collection_summary.clone(), notes, @@ -25446,7 +25523,86 @@ mod tests { ], evidence: vec![], }); - + report.save_placed_structure_dynamic_side_buffer_probe = + Some(SmpSavePlacedStructureDynamicSideBufferProbe { + profile_family: "rt3-classic-save-container-v1".to_string(), + source_kind: "save-placed-structure-dynamic-side-buffer-records".to_string(), + semantic_family: "scenario-save-placed-structure-dynamic-side-buffer-records" + .to_string(), + metadata_tag_offset: 0x3800, + records_tag_offset: 0x3900, + close_tag_offset: 0x3d00, + records_span_len: 0x400, + direct_record_stride: 6, + direct_record_stride_hex: "0x6".to_string(), + live_id_bound: 0x80, + live_id_bound_hex: "0x00000080".to_string(), + live_record_count: 118, + live_record_count_hex: "0x00000076".to_string(), + owner_shared_dword: 0xff0000ff, + owner_shared_dword_hex: "0xff0000ff".to_string(), + owner_shared_dword_relative_offset: 0, + owner_shared_dword_matches_first_compact_prefix_leading_dword: true, + first_record_child_count_after_owner_shared: Some(1), + first_record_child_count_after_owner_shared_hex: Some("0x0001".to_string()), + first_record_saved_primary_child_byte_after_owner_shared: Some(0xff), + first_record_saved_primary_child_byte_after_owner_shared_hex: Some( + "0xff".to_string(), + ), + first_record_first_name_tag_relative_offset_after_owner_shared: Some(3), + prefix_leading_dword: 0xff0000ff, + prefix_leading_dword_hex: "0xff0000ff".to_string(), + prefix_trailing_word: 1, + prefix_trailing_word_hex: "0x0001".to_string(), + prefix_separator_byte: 0xff, + prefix_separator_byte_hex: "0xff".to_string(), + first_embedded_name_tag_relative_offset: 3, + embedded_name_tag_count: 118, + decoded_embedded_name_row_count: 118, + decoded_embedded_name_row_with_tertiary_name_count: 0, + unique_compact_prefix_pattern_count: 4, + prefix_leading_dword_matching_embedded_profile_tag_count: 0, + unique_embedded_name_pair_count: 9, + first_embedded_primary_name: Some("StationA".to_string()), + first_embedded_secondary_name: Some("StationSetA".to_string()), + first_embedded_tertiary_name: None, + embedded_name_row_samples: vec![], + compact_prefix_pattern_summaries: vec![ + SmpSavePlacedStructureDynamicSideBufferPrefixPatternSummary { + prefix_leading_dword: 0xff0000ff, + prefix_leading_dword_hex: "0xff0000ff".to_string(), + prefix_trailing_word: 1, + prefix_trailing_word_hex: "0x0001".to_string(), + prefix_separator_byte: 0xff, + prefix_separator_byte_hex: "0xff".to_string(), + count: 62, + first_name_tag_relative_offset: 3, + prefix_leading_dword_matches_embedded_profile_tag: false, + section_like_primary_name_count: 12, + cap_like_primary_name_count: 21, + other_primary_name_count: 29, + first_primary_name: Some("StationA".to_string()), + first_secondary_name: Some("StationSetA".to_string()), + }, + ], + name_pair_summaries: vec![SmpSavePlacedStructureDynamicSideBufferNamePairSummary { + primary_name: "StationA".to_string(), + secondary_name: "StationSetA".to_string(), + count: 14, + first_name_tag_relative_offset: 3, + unique_compact_prefix_pattern_count: 1, + dominant_prefix_leading_dword: 0xff0000ff, + dominant_prefix_leading_dword_hex: "0xff0000ff".to_string(), + dominant_prefix_trailing_word: 1, + dominant_prefix_trailing_word_hex: "0x0001".to_string(), + dominant_prefix_separator_byte: 0xff, + dominant_prefix_separator_byte_hex: "0xff".to_string(), + dominant_prefix_count: 14, + }], + payload_envelope_summary: None, + live_entry_prelude_summary: None, + evidence: vec![], + }); let slice = load_save_slice_from_report(&report).expect("classic save slice"); let collection = slice .placed_structure_collection @@ -25459,10 +25615,28 @@ mod tests { assert_eq!(collection.entries[0].primary_name, "FarmCorn"); assert_eq!(collection.entries[0].farm_growth_stage_index, Some(4)); assert_eq!(collection.entries[1].profile_companion_byte_u8, Some(7)); + let side_buffer_summary = slice + .placed_structure_dynamic_side_buffer_summary + .expect("side-buffer summary should project"); + assert_eq!( + side_buffer_summary.source_kind, + "save-placed-structure-dynamic-side-buffer-records" + ); + assert_eq!(side_buffer_summary.observed_entry_count, 118); + assert_eq!(side_buffer_summary.unique_embedded_name_pair_count, 9); + assert_eq!(side_buffer_summary.triplet_alignment_overlap_count, 1); + assert_eq!( + side_buffer_summary.triplet_alignment_side_buffer_only_name_pair_count, + 0 + ); assert!(slice.notes.iter().any(|line| { line.contains("placed-structure triplet rows as first-class context") && line.contains("2") })); + assert!(slice.notes.iter().any(|line| { + line.contains("placed-structure dynamic side-buffer summary") + && line.contains("118 decoded name rows") + })); } #[test] diff --git a/docs/rehost-queue.md b/docs/rehost-queue.md index 7a12c89..832104b 100644 --- a/docs/rehost-queue.md +++ b/docs/rehost-queue.md @@ -80,6 +80,10 @@ Working rule: - the save-side `0x36b1/0x36b2/0x36b3` triplet seam is now also loaded into the checked-in save-slice model as first-class `placed_structure_collection` context, carrying stem pairs plus grounded footer/policy status lanes instead of remaining inspection-only evidence + - the separate `0x38a5/0x38a6/0x38a7` side-buffer seam is now also loaded into the save-slice + model as first-class `placed_structure_dynamic_side_buffer_summary` context, carrying the + grounded owner-shared dword, compact-prefix summaries, name-pair summaries, and overlap counts + against the triplet corpus instead of remaining trace-only evidence - Direct disassembly now narrows that acquisition strip further: - `0x004014b0` scans the live placed-structure collection at `0x0062b26c` - `0x0041f6e0 -> 0x0042b2d0` is the center-cell token gate over the current region