Make locomotive context save-native
This commit is contained in:
parent
13c7268b0d
commit
b060c42fa2
18 changed files with 1240 additions and 83 deletions
|
|
@ -7,7 +7,7 @@ use crate::persistence::{load_runtime_snapshot_document, validate_runtime_snapsh
|
|||
use crate::{
|
||||
CalendarPoint, RuntimeCompanyConditionTestScope, RuntimeCompanyControllerKind,
|
||||
RuntimeCompanyTarget, RuntimeCondition, RuntimeEffect, RuntimeEventRecord,
|
||||
RuntimeEventRecordTemplate, RuntimePackedEventCollectionSummary,
|
||||
RuntimeEventRecordTemplate, RuntimeLocomotiveCatalogEntry, RuntimePackedEventCollectionSummary,
|
||||
RuntimePackedEventCompactControlSummary, RuntimePackedEventConditionRowSummary,
|
||||
RuntimePackedEventGroupedEffectRowSummary, RuntimePackedEventNegativeSentinelScopeSummary,
|
||||
RuntimePackedEventRecordSummary, RuntimePackedEventTextBandSummary,
|
||||
|
|
@ -95,6 +95,7 @@ struct SaveSliceProjection {
|
|||
event_runtime_records: Vec<RuntimeEventRecord>,
|
||||
candidate_availability: BTreeMap<String, u32>,
|
||||
named_locomotive_availability: BTreeMap<String, u32>,
|
||||
locomotive_catalog: Option<Vec<RuntimeLocomotiveCatalogEntry>>,
|
||||
named_locomotive_cost: BTreeMap<String, u32>,
|
||||
cargo_production_overrides: BTreeMap<u32, u32>,
|
||||
special_conditions: BTreeMap<String, u32>,
|
||||
|
|
@ -243,7 +244,7 @@ pub fn project_save_slice_to_runtime_state_import(
|
|||
players: Vec::new(),
|
||||
selected_player_id: None,
|
||||
trains: Vec::new(),
|
||||
locomotive_catalog: Vec::new(),
|
||||
locomotive_catalog: projection.locomotive_catalog.unwrap_or_default(),
|
||||
territories: Vec::new(),
|
||||
company_territory_track_piece_counts: Vec::new(),
|
||||
company_territory_access: Vec::new(),
|
||||
|
|
@ -305,7 +306,9 @@ pub fn project_save_slice_overlay_to_runtime_state_import(
|
|||
players: base_state.players.clone(),
|
||||
selected_player_id: base_state.selected_player_id,
|
||||
trains: base_state.trains.clone(),
|
||||
locomotive_catalog: base_state.locomotive_catalog.clone(),
|
||||
locomotive_catalog: projection
|
||||
.locomotive_catalog
|
||||
.unwrap_or_else(|| base_state.locomotive_catalog.clone()),
|
||||
territories: base_state.territories.clone(),
|
||||
company_territory_track_piece_counts: base_state
|
||||
.company_territory_track_piece_counts
|
||||
|
|
@ -351,6 +354,11 @@ fn project_save_slice_components(
|
|||
"save_slice.named_locomotive_availability_present".to_string(),
|
||||
save_slice.named_locomotive_availability_table.is_some(),
|
||||
);
|
||||
world_flags.insert(
|
||||
"save_slice.locomotive_catalog_present".to_string(),
|
||||
save_slice.locomotive_catalog.is_some()
|
||||
|| save_slice.named_locomotive_availability_table.is_some(),
|
||||
);
|
||||
world_flags.insert(
|
||||
"save_slice.event_runtime_collection_present".to_string(),
|
||||
save_slice.event_runtime_collection.is_some(),
|
||||
|
|
@ -441,31 +449,6 @@ fn project_save_slice_components(
|
|||
metadata.insert("save_slice.bridge_family".to_string(), family.clone());
|
||||
}
|
||||
|
||||
let (packed_event_collection, event_runtime_records) =
|
||||
project_packed_event_collection(save_slice, company_context)?;
|
||||
if let Some(summary) = &save_slice.event_runtime_collection {
|
||||
metadata.insert(
|
||||
"save_slice.event_runtime_collection_source_kind".to_string(),
|
||||
summary.source_kind.clone(),
|
||||
);
|
||||
metadata.insert(
|
||||
"save_slice.event_runtime_collection_version_hex".to_string(),
|
||||
summary.packed_state_version_hex.clone(),
|
||||
);
|
||||
metadata.insert(
|
||||
"save_slice.event_runtime_collection_record_count".to_string(),
|
||||
summary.live_record_count.to_string(),
|
||||
);
|
||||
metadata.insert(
|
||||
"save_slice.event_runtime_collection_decoded_record_count".to_string(),
|
||||
summary.decoded_record_count.to_string(),
|
||||
);
|
||||
metadata.insert(
|
||||
"save_slice.event_runtime_collection_imported_runtime_record_count".to_string(),
|
||||
event_runtime_records.len().to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
let save_profile = if let Some(profile) = &save_slice.profile {
|
||||
metadata.insert(
|
||||
"save_slice.profile_kind".to_string(),
|
||||
|
|
@ -645,10 +628,105 @@ fn project_save_slice_components(
|
|||
named_locomotive_availability.insert(entry.text.clone(), entry.availability_dword);
|
||||
}
|
||||
}
|
||||
let locomotive_catalog = if let Some(catalog) = &save_slice.locomotive_catalog {
|
||||
metadata.insert(
|
||||
"save_slice.locomotive_catalog_source_kind".to_string(),
|
||||
catalog.source_kind.clone(),
|
||||
);
|
||||
metadata.insert(
|
||||
"save_slice.locomotive_catalog_semantic_family".to_string(),
|
||||
catalog.semantic_family.clone(),
|
||||
);
|
||||
metadata.insert(
|
||||
"save_slice.locomotive_catalog_entry_count".to_string(),
|
||||
catalog.observed_entry_count.to_string(),
|
||||
);
|
||||
if let Some(entries_offset) = catalog.entries_offset {
|
||||
metadata.insert(
|
||||
"save_slice.locomotive_catalog_entries_offset".to_string(),
|
||||
entries_offset.to_string(),
|
||||
);
|
||||
}
|
||||
Some(
|
||||
catalog
|
||||
.entries
|
||||
.iter()
|
||||
.map(|entry| RuntimeLocomotiveCatalogEntry {
|
||||
locomotive_id: entry.locomotive_id,
|
||||
name: entry.name.clone(),
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
} else if let Some(table) = &save_slice.named_locomotive_availability_table {
|
||||
metadata.insert(
|
||||
"save_slice.locomotive_catalog_source_kind".to_string(),
|
||||
"derived-from-named-locomotive-availability-table".to_string(),
|
||||
);
|
||||
metadata.insert(
|
||||
"save_slice.locomotive_catalog_semantic_family".to_string(),
|
||||
"scenario-save-derived-locomotive-catalog".to_string(),
|
||||
);
|
||||
metadata.insert(
|
||||
"save_slice.locomotive_catalog_entry_count".to_string(),
|
||||
table.observed_entry_count.to_string(),
|
||||
);
|
||||
if let Some(entries_offset) = table.entries_offset {
|
||||
metadata.insert(
|
||||
"save_slice.locomotive_catalog_entries_offset".to_string(),
|
||||
entries_offset.to_string(),
|
||||
);
|
||||
}
|
||||
Some(
|
||||
table
|
||||
.entries
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, entry)| RuntimeLocomotiveCatalogEntry {
|
||||
locomotive_id: (index + 1) as u32,
|
||||
name: entry.text.clone(),
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let named_locomotive_cost = BTreeMap::new();
|
||||
let cargo_production_overrides = BTreeMap::new();
|
||||
|
||||
let mut packed_event_context = company_context.clone();
|
||||
if let Some(catalog) = &locomotive_catalog {
|
||||
packed_event_context.locomotive_catalog_names_by_id = catalog
|
||||
.iter()
|
||||
.map(|entry| (entry.locomotive_id, entry.name.clone()))
|
||||
.collect();
|
||||
}
|
||||
|
||||
let (packed_event_collection, event_runtime_records) =
|
||||
project_packed_event_collection(save_slice, &packed_event_context)?;
|
||||
if let Some(summary) = &save_slice.event_runtime_collection {
|
||||
metadata.insert(
|
||||
"save_slice.event_runtime_collection_source_kind".to_string(),
|
||||
summary.source_kind.clone(),
|
||||
);
|
||||
metadata.insert(
|
||||
"save_slice.event_runtime_collection_version_hex".to_string(),
|
||||
summary.packed_state_version_hex.clone(),
|
||||
);
|
||||
metadata.insert(
|
||||
"save_slice.event_runtime_collection_record_count".to_string(),
|
||||
summary.live_record_count.to_string(),
|
||||
);
|
||||
metadata.insert(
|
||||
"save_slice.event_runtime_collection_decoded_record_count".to_string(),
|
||||
summary.decoded_record_count.to_string(),
|
||||
);
|
||||
metadata.insert(
|
||||
"save_slice.event_runtime_collection_imported_runtime_record_count".to_string(),
|
||||
event_runtime_records.len().to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
for (index, note) in save_slice.notes.iter().enumerate() {
|
||||
metadata.insert(format!("save_slice.note.{index}"), note.clone());
|
||||
}
|
||||
|
|
@ -662,6 +740,7 @@ fn project_save_slice_components(
|
|||
event_runtime_records,
|
||||
candidate_availability,
|
||||
named_locomotive_availability,
|
||||
locomotive_catalog,
|
||||
named_locomotive_cost,
|
||||
cargo_production_overrides,
|
||||
special_conditions,
|
||||
|
|
@ -3242,6 +3321,32 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
fn save_named_locomotive_table(
|
||||
count: usize,
|
||||
) -> crate::SmpLoadedNamedLocomotiveAvailabilityTable {
|
||||
crate::SmpLoadedNamedLocomotiveAvailabilityTable {
|
||||
source_kind: "runtime-save-direct-serializer".to_string(),
|
||||
semantic_family: "scenario-named-locomotive-availability-table".to_string(),
|
||||
header_offset: None,
|
||||
entries_offset: Some(0x7c78),
|
||||
entries_end_offset: Some(0x7c78 + count * 0x41),
|
||||
observed_entry_count: count,
|
||||
zero_availability_count: 0,
|
||||
zero_availability_names: vec![],
|
||||
entries: (0..count)
|
||||
.map(|index| crate::SmpRt3105SaveNameTableEntry {
|
||||
index,
|
||||
offset: 0x7c78 + index * 0x41,
|
||||
text: format!("Locomotive {}", index + 1),
|
||||
availability_dword: 1,
|
||||
availability_dword_hex: "0x00000001".to_string(),
|
||||
trailer_word: 1,
|
||||
trailer_word_hex: "0x00000001".to_string(),
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
fn real_cargo_production_row(
|
||||
descriptor_id: u32,
|
||||
value: i32,
|
||||
|
|
@ -3498,6 +3603,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: None,
|
||||
notes: vec![],
|
||||
|
|
@ -3537,6 +3643,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: None,
|
||||
notes: vec![],
|
||||
|
|
@ -3650,6 +3757,7 @@ mod tests {
|
|||
],
|
||||
},
|
||||
),
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: Some(crate::SmpLoadedSpecialConditionsTable {
|
||||
source_kind: "save-fixed-special-conditions-range".to_string(),
|
||||
table_offset: 0x0d64,
|
||||
|
|
@ -3903,6 +4011,11 @@ mod tests {
|
|||
import.state.named_locomotive_availability.get("GP7"),
|
||||
Some(&1)
|
||||
);
|
||||
assert_eq!(import.state.locomotive_catalog.len(), 2);
|
||||
assert_eq!(import.state.locomotive_catalog[0].locomotive_id, 1);
|
||||
assert_eq!(import.state.locomotive_catalog[0].name, "Big Boy");
|
||||
assert_eq!(import.state.locomotive_catalog[1].locomotive_id, 2);
|
||||
assert_eq!(import.state.locomotive_catalog[1].name, "GP7");
|
||||
assert_eq!(
|
||||
import.state.special_conditions.get("Disable Cargo Economy"),
|
||||
Some(&0)
|
||||
|
|
@ -3923,6 +4036,14 @@ mod tests {
|
|||
.map(String::as_str),
|
||||
Some("2")
|
||||
);
|
||||
assert_eq!(
|
||||
import
|
||||
.state
|
||||
.metadata
|
||||
.get("save_slice.locomotive_catalog_source_kind")
|
||||
.map(String::as_str),
|
||||
Some("derived-from-named-locomotive-availability-table")
|
||||
);
|
||||
assert_eq!(
|
||||
import
|
||||
.state
|
||||
|
|
@ -3961,6 +4082,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -4075,6 +4197,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -4167,6 +4290,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -4277,6 +4401,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -4360,6 +4485,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -4493,6 +4619,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -4734,6 +4861,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -4810,6 +4938,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -4908,6 +5037,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -4981,6 +5111,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -5079,6 +5210,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -5143,6 +5275,108 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn imports_scalar_locomotive_availability_rows_with_save_derived_catalog_context() {
|
||||
let save_slice = SmpLoadedSaveSlice {
|
||||
file_extension_hint: Some("gms".to_string()),
|
||||
container_profile_family: Some("rt3-classic-save-container-v1".to_string()),
|
||||
mechanism_family: "classic-save-rehydrate-v1".to_string(),
|
||||
mechanism_confidence: "grounded".to_string(),
|
||||
trailer_family: None,
|
||||
bridge_family: None,
|
||||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: Some(save_named_locomotive_table(112)),
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
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()),
|
||||
metadata_tag_offset: 0x7100,
|
||||
records_tag_offset: 0x7200,
|
||||
close_tag_offset: 0x7600,
|
||||
packed_state_version: 0x3e9,
|
||||
packed_state_version_hex: "0x000003e9".to_string(),
|
||||
live_id_bound: 33,
|
||||
live_record_count: 1,
|
||||
live_entry_ids: vec![33],
|
||||
decoded_record_count: 1,
|
||||
imported_runtime_record_count: 0,
|
||||
records: vec![crate::SmpLoadedPackedEventRecordSummary {
|
||||
record_index: 0,
|
||||
live_entry_id: 33,
|
||||
payload_offset: Some(0x7202),
|
||||
payload_len: Some(120),
|
||||
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: Some(false),
|
||||
compact_control: Some(real_compact_control()),
|
||||
text_bands: vec![],
|
||||
standalone_condition_row_count: 0,
|
||||
standalone_condition_rows: vec![],
|
||||
negative_sentinel_scope: None,
|
||||
grouped_effect_row_counts: vec![2, 0, 0, 0],
|
||||
grouped_effect_rows: vec![
|
||||
real_locomotive_availability_row(250, 42),
|
||||
real_locomotive_availability_row(457, 7),
|
||||
],
|
||||
decoded_conditions: Vec::new(),
|
||||
decoded_actions: vec![],
|
||||
executable_import_ready: false,
|
||||
notes: vec![
|
||||
"scalar locomotive availability rows use save-derived catalog context"
|
||||
.to_string(),
|
||||
],
|
||||
}],
|
||||
}),
|
||||
notes: vec![],
|
||||
};
|
||||
|
||||
let mut import = project_save_slice_to_runtime_state_import(
|
||||
&save_slice,
|
||||
"save-derived-locomotive-availability",
|
||||
None,
|
||||
)
|
||||
.expect("save slice should project");
|
||||
|
||||
assert_eq!(import.state.locomotive_catalog.len(), 112);
|
||||
assert_eq!(import.state.event_runtime_records.len(), 1);
|
||||
assert_eq!(
|
||||
import
|
||||
.state
|
||||
.packed_event_collection
|
||||
.as_ref()
|
||||
.and_then(|summary| summary.records[0].import_outcome.as_deref()),
|
||||
Some("imported")
|
||||
);
|
||||
|
||||
execute_step_command(
|
||||
&mut import.state,
|
||||
&StepCommand::ServiceTriggerKind { trigger_kind: 7 },
|
||||
)
|
||||
.expect("save-derived locomotive availability record should run");
|
||||
|
||||
assert_eq!(
|
||||
import
|
||||
.state
|
||||
.named_locomotive_availability
|
||||
.get("Locomotive 10"),
|
||||
Some(&42)
|
||||
);
|
||||
assert_eq!(
|
||||
import
|
||||
.state
|
||||
.named_locomotive_availability
|
||||
.get("Locomotive 112"),
|
||||
Some(&7)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn overlays_scalar_locomotive_availability_rows_into_named_availability_effects() {
|
||||
let base_state = RuntimeState {
|
||||
|
|
@ -5196,6 +5430,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -5297,6 +5532,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -5372,6 +5608,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -5435,6 +5672,101 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn imports_scalar_locomotive_cost_rows_with_save_derived_catalog_context() {
|
||||
let save_slice = SmpLoadedSaveSlice {
|
||||
file_extension_hint: Some("gms".to_string()),
|
||||
container_profile_family: Some("rt3-classic-save-container-v1".to_string()),
|
||||
mechanism_family: "classic-save-rehydrate-v1".to_string(),
|
||||
mechanism_confidence: "grounded".to_string(),
|
||||
trailer_family: None,
|
||||
bridge_family: None,
|
||||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: Some(save_named_locomotive_table(112)),
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
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()),
|
||||
metadata_tag_offset: 0x7100,
|
||||
records_tag_offset: 0x7200,
|
||||
close_tag_offset: 0x7600,
|
||||
packed_state_version: 0x3e9,
|
||||
packed_state_version_hex: "0x000003e9".to_string(),
|
||||
live_id_bound: 41,
|
||||
live_record_count: 1,
|
||||
live_entry_ids: vec![41],
|
||||
decoded_record_count: 1,
|
||||
imported_runtime_record_count: 0,
|
||||
records: vec![crate::SmpLoadedPackedEventRecordSummary {
|
||||
record_index: 0,
|
||||
live_entry_id: 41,
|
||||
payload_offset: Some(0x7202),
|
||||
payload_len: Some(120),
|
||||
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: Some(false),
|
||||
compact_control: Some(real_compact_control()),
|
||||
text_bands: vec![],
|
||||
standalone_condition_row_count: 0,
|
||||
standalone_condition_rows: vec![],
|
||||
negative_sentinel_scope: None,
|
||||
grouped_effect_row_counts: vec![2, 0, 0, 0],
|
||||
grouped_effect_rows: vec![
|
||||
real_locomotive_cost_row(352, 250000),
|
||||
real_locomotive_cost_row(475, 325000),
|
||||
],
|
||||
decoded_conditions: Vec::new(),
|
||||
decoded_actions: vec![],
|
||||
executable_import_ready: false,
|
||||
notes: vec![
|
||||
"scalar locomotive cost rows use save-derived catalog context".to_string(),
|
||||
],
|
||||
}],
|
||||
}),
|
||||
notes: vec![],
|
||||
};
|
||||
|
||||
let mut import = project_save_slice_to_runtime_state_import(
|
||||
&save_slice,
|
||||
"save-derived-locomotive-cost",
|
||||
None,
|
||||
)
|
||||
.expect("save slice should project");
|
||||
|
||||
assert_eq!(import.state.locomotive_catalog.len(), 112);
|
||||
assert_eq!(import.state.event_runtime_records.len(), 1);
|
||||
assert_eq!(
|
||||
import
|
||||
.state
|
||||
.packed_event_collection
|
||||
.as_ref()
|
||||
.and_then(|summary| summary.records[0].import_outcome.as_deref()),
|
||||
Some("imported")
|
||||
);
|
||||
|
||||
execute_step_command(
|
||||
&mut import.state,
|
||||
&StepCommand::ServiceTriggerKind { trigger_kind: 7 },
|
||||
)
|
||||
.expect("save-derived locomotive cost record should run");
|
||||
|
||||
assert_eq!(
|
||||
import.state.named_locomotive_cost.get("Locomotive 1"),
|
||||
Some(&250000)
|
||||
);
|
||||
assert_eq!(
|
||||
import.state.named_locomotive_cost.get("Locomotive 101"),
|
||||
Some(&325000)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn overlays_scalar_locomotive_cost_rows_into_named_cost_effects() {
|
||||
let base_state = RuntimeState {
|
||||
|
|
@ -5488,6 +5820,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -5582,6 +5915,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -5655,6 +5989,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -5738,6 +6073,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -5863,6 +6199,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -6007,6 +6344,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -6110,6 +6448,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -6194,6 +6533,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -6299,6 +6639,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -6404,6 +6745,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -6499,6 +6841,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -6590,6 +6933,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -6689,6 +7033,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -6779,6 +7124,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -6851,6 +7197,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -6928,6 +7275,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -7010,6 +7358,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -7092,6 +7441,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -7190,6 +7540,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -7279,6 +7630,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -7394,6 +7746,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -7519,6 +7872,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -7628,6 +7982,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -7800,6 +8155,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -7892,6 +8248,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -7980,6 +8337,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -8133,6 +8491,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -8275,6 +8634,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -8364,6 +8724,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -8480,6 +8841,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -8584,6 +8946,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -8729,6 +9092,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
@ -8903,6 +9267,7 @@ mod tests {
|
|||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue