Add named locomotive availability runtime surface
This commit is contained in:
parent
c04c19ac82
commit
8c7ff335cb
16 changed files with 542 additions and 13 deletions
14
README.md
14
README.md
|
|
@ -51,11 +51,15 @@ recovered locomotives-page `real_packed_v1` record that lands in the explicit
|
||||||
`blocked_unmapped_world_descriptor` bucket. The next recovered descriptor band is now partially
|
`blocked_unmapped_world_descriptor` bucket. The next recovered descriptor band is now partially
|
||||||
executable too: descriptors `454..456` (`All Steam/Diesel/Electric Locos Avail.`) now lower
|
executable too: descriptors `454..456` (`All Steam/Diesel/Electric Locos Avail.`) now lower
|
||||||
through checked-in metadata into keyed `world_flags`, while the wider locomotive availability/cost
|
through checked-in metadata into keyed `world_flags`, while the wider locomotive availability/cost
|
||||||
scalar bands remain recovered-but-parity-only until per-locomotive identity is grounded. Explicit
|
scalar bands remain recovered-but-parity-only until per-locomotive identity is grounded. The
|
||||||
unmapped world-condition and world-descriptor frontier buckets still remain where current
|
runtime now carries the save-owned named locomotive availability table directly too: checked-in
|
||||||
checked-in metadata stops. Shell purchase-flow and selected-profile parity remain out of scope.
|
save-slice documents can populate `RuntimeState.named_locomotive_availability`, and imported
|
||||||
Mixed supported/unsupported real rows still stay parity-only. The PE32 hook remains useful as
|
runtime effects can mutate that map through the ordinary event-service path without needing full
|
||||||
capture and integration tooling, but it is no longer the main execution milestone.
|
Trainbuy or live-locomotive parity. Explicit unmapped world-condition and world-descriptor
|
||||||
|
frontier buckets still remain where current checked-in metadata stops. Shell purchase-flow and
|
||||||
|
selected-profile parity remain out of scope. Mixed supported/unsupported real rows still stay
|
||||||
|
parity-only. The PE32 hook remains useful as capture and integration tooling, but it is no longer
|
||||||
|
the main execution milestone.
|
||||||
|
|
||||||
## Project Docs
|
## Project Docs
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4454,6 +4454,9 @@ mod tests {
|
||||||
let mixed_overlay_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(
|
let mixed_overlay_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(
|
||||||
"../../fixtures/runtime/packed-event-mixed-company-descriptor-overlay-fixture.json",
|
"../../fixtures/runtime/packed-event-mixed-company-descriptor-overlay-fixture.json",
|
||||||
);
|
);
|
||||||
|
let named_locomotive_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(
|
||||||
|
"../../fixtures/runtime/packed-event-named-locomotive-availability-save-slice-fixture.json",
|
||||||
|
);
|
||||||
|
|
||||||
run_runtime_summarize_fixture(&parity_fixture)
|
run_runtime_summarize_fixture(&parity_fixture)
|
||||||
.expect("save-slice-backed parity fixture should summarize");
|
.expect("save-slice-backed parity fixture should summarize");
|
||||||
|
|
@ -4471,6 +4474,8 @@ mod tests {
|
||||||
.expect("overlay-backed track-capacity fixture should summarize");
|
.expect("overlay-backed track-capacity fixture should summarize");
|
||||||
run_runtime_summarize_fixture(&mixed_overlay_fixture)
|
run_runtime_summarize_fixture(&mixed_overlay_fixture)
|
||||||
.expect("overlay-backed mixed real-row fixture should summarize");
|
.expect("overlay-backed mixed real-row fixture should summarize");
|
||||||
|
run_runtime_summarize_fixture(&named_locomotive_fixture)
|
||||||
|
.expect("save-slice-backed named locomotive availability fixture should summarize");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -4495,6 +4500,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: None,
|
event_runtime_collection: None,
|
||||||
notes: vec!["exported for test".to_string()],
|
notes: vec!["exported for test".to_string()],
|
||||||
|
|
|
||||||
|
|
@ -183,6 +183,7 @@ mod tests {
|
||||||
packed_event_collection: None,
|
packed_event_collection: None,
|
||||||
event_runtime_records: Vec::new(),
|
event_runtime_records: Vec::new(),
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
},
|
},
|
||||||
|
|
@ -259,6 +260,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: None,
|
event_runtime_collection: None,
|
||||||
notes: vec![],
|
notes: vec![],
|
||||||
|
|
@ -352,6 +354,7 @@ mod tests {
|
||||||
packed_event_collection: None,
|
packed_event_collection: None,
|
||||||
event_runtime_records: Vec::new(),
|
event_runtime_records: Vec::new(),
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
},
|
},
|
||||||
|
|
@ -371,6 +374,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(
|
event_runtime_collection: Some(
|
||||||
rrt_runtime::SmpLoadedEventRuntimeCollectionSummary {
|
rrt_runtime::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
|
|
|
||||||
|
|
@ -150,6 +150,10 @@ pub struct ExpectedRuntimeSummary {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub zero_candidate_availability_count: Option<usize>,
|
pub zero_candidate_availability_count: Option<usize>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
pub named_locomotive_availability_count: Option<usize>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub zero_named_locomotive_availability_count: Option<usize>,
|
||||||
|
#[serde(default)]
|
||||||
pub special_condition_count: Option<usize>,
|
pub special_condition_count: Option<usize>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub enabled_special_condition_count: Option<usize>,
|
pub enabled_special_condition_count: Option<usize>,
|
||||||
|
|
@ -735,6 +739,22 @@ impl ExpectedRuntimeSummary {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let Some(count) = self.named_locomotive_availability_count {
|
||||||
|
if actual.named_locomotive_availability_count != count {
|
||||||
|
mismatches.push(format!(
|
||||||
|
"named_locomotive_availability_count mismatch: expected {count}, got {}",
|
||||||
|
actual.named_locomotive_availability_count
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(count) = self.zero_named_locomotive_availability_count {
|
||||||
|
if actual.zero_named_locomotive_availability_count != count {
|
||||||
|
mismatches.push(format!(
|
||||||
|
"zero_named_locomotive_availability_count mismatch: expected {count}, got {}",
|
||||||
|
actual.zero_named_locomotive_availability_count
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
if let Some(count) = self.special_condition_count {
|
if let Some(count) = self.special_condition_count {
|
||||||
if actual.special_condition_count != count {
|
if actual.special_condition_count != count {
|
||||||
mismatches.push(format!(
|
mismatches.push(format!(
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,7 @@ struct SaveSliceProjection {
|
||||||
packed_event_collection: Option<RuntimePackedEventCollectionSummary>,
|
packed_event_collection: Option<RuntimePackedEventCollectionSummary>,
|
||||||
event_runtime_records: Vec<RuntimeEventRecord>,
|
event_runtime_records: Vec<RuntimeEventRecord>,
|
||||||
candidate_availability: BTreeMap<String, u32>,
|
candidate_availability: BTreeMap<String, u32>,
|
||||||
|
named_locomotive_availability: BTreeMap<String, u32>,
|
||||||
special_conditions: BTreeMap<String, u32>,
|
special_conditions: BTreeMap<String, u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -238,6 +239,7 @@ pub fn project_save_slice_to_runtime_state_import(
|
||||||
packed_event_collection: projection.packed_event_collection,
|
packed_event_collection: projection.packed_event_collection,
|
||||||
event_runtime_records: projection.event_runtime_records,
|
event_runtime_records: projection.event_runtime_records,
|
||||||
candidate_availability: projection.candidate_availability,
|
candidate_availability: projection.candidate_availability,
|
||||||
|
named_locomotive_availability: projection.named_locomotive_availability,
|
||||||
special_conditions: projection.special_conditions,
|
special_conditions: projection.special_conditions,
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -295,6 +297,7 @@ pub fn project_save_slice_overlay_to_runtime_state_import(
|
||||||
packed_event_collection: projection.packed_event_collection,
|
packed_event_collection: projection.packed_event_collection,
|
||||||
event_runtime_records: projection.event_runtime_records,
|
event_runtime_records: projection.event_runtime_records,
|
||||||
candidate_availability: projection.candidate_availability,
|
candidate_availability: projection.candidate_availability,
|
||||||
|
named_locomotive_availability: projection.named_locomotive_availability,
|
||||||
special_conditions: projection.special_conditions,
|
special_conditions: projection.special_conditions,
|
||||||
service_state: base_state.service_state.clone(),
|
service_state: base_state.service_state.clone(),
|
||||||
};
|
};
|
||||||
|
|
@ -325,6 +328,10 @@ fn project_save_slice_components(
|
||||||
"save_slice.special_conditions_present".to_string(),
|
"save_slice.special_conditions_present".to_string(),
|
||||||
save_slice.special_conditions_table.is_some(),
|
save_slice.special_conditions_table.is_some(),
|
||||||
);
|
);
|
||||||
|
world_flags.insert(
|
||||||
|
"save_slice.named_locomotive_availability_present".to_string(),
|
||||||
|
save_slice.named_locomotive_availability_table.is_some(),
|
||||||
|
);
|
||||||
world_flags.insert(
|
world_flags.insert(
|
||||||
"save_slice.event_runtime_collection_present".to_string(),
|
"save_slice.event_runtime_collection_present".to_string(),
|
||||||
save_slice.event_runtime_collection.is_some(),
|
save_slice.event_runtime_collection.is_some(),
|
||||||
|
|
@ -590,6 +597,35 @@ fn project_save_slice_components(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut named_locomotive_availability = BTreeMap::new();
|
||||||
|
if let Some(table) = &save_slice.named_locomotive_availability_table {
|
||||||
|
metadata.insert(
|
||||||
|
"save_slice.named_locomotive_availability_source_kind".to_string(),
|
||||||
|
table.source_kind.clone(),
|
||||||
|
);
|
||||||
|
metadata.insert(
|
||||||
|
"save_slice.named_locomotive_availability_semantic_family".to_string(),
|
||||||
|
table.semantic_family.clone(),
|
||||||
|
);
|
||||||
|
metadata.insert(
|
||||||
|
"save_slice.named_locomotive_availability_entry_count".to_string(),
|
||||||
|
table.observed_entry_count.to_string(),
|
||||||
|
);
|
||||||
|
metadata.insert(
|
||||||
|
"save_slice.named_locomotive_availability_zero_count".to_string(),
|
||||||
|
table.zero_availability_count.to_string(),
|
||||||
|
);
|
||||||
|
if let Some(header_offset) = table.header_offset {
|
||||||
|
metadata.insert(
|
||||||
|
"save_slice.named_locomotive_availability_header_offset".to_string(),
|
||||||
|
header_offset.to_string(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
for entry in &table.entries {
|
||||||
|
named_locomotive_availability.insert(entry.text.clone(), entry.availability_dword);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (index, note) in save_slice.notes.iter().enumerate() {
|
for (index, note) in save_slice.notes.iter().enumerate() {
|
||||||
metadata.insert(format!("save_slice.note.{index}"), note.clone());
|
metadata.insert(format!("save_slice.note.{index}"), note.clone());
|
||||||
}
|
}
|
||||||
|
|
@ -602,6 +638,7 @@ fn project_save_slice_components(
|
||||||
packed_event_collection,
|
packed_event_collection,
|
||||||
event_runtime_records,
|
event_runtime_records,
|
||||||
candidate_availability,
|
candidate_availability,
|
||||||
|
named_locomotive_availability,
|
||||||
special_conditions,
|
special_conditions,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -1133,6 +1170,12 @@ fn lower_condition_targets_in_effect(
|
||||||
value: *value,
|
value: *value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
RuntimeEffect::SetNamedLocomotiveAvailability { name, value } => {
|
||||||
|
RuntimeEffect::SetNamedLocomotiveAvailability {
|
||||||
|
name: name.clone(),
|
||||||
|
value: *value,
|
||||||
|
}
|
||||||
|
}
|
||||||
RuntimeEffect::SetSpecialCondition { label, value } => RuntimeEffect::SetSpecialCondition {
|
RuntimeEffect::SetSpecialCondition { label, value } => RuntimeEffect::SetSpecialCondition {
|
||||||
label: label.clone(),
|
label: label.clone(),
|
||||||
value: *value,
|
value: *value,
|
||||||
|
|
@ -1562,6 +1605,12 @@ fn smp_runtime_effect_to_runtime_effect(
|
||||||
value: *value,
|
value: *value,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
RuntimeEffect::SetNamedLocomotiveAvailability { name, value } => {
|
||||||
|
Ok(RuntimeEffect::SetNamedLocomotiveAvailability {
|
||||||
|
name: name.clone(),
|
||||||
|
value: *value,
|
||||||
|
})
|
||||||
|
}
|
||||||
RuntimeEffect::SetSpecialCondition { label, value } => {
|
RuntimeEffect::SetSpecialCondition { label, value } => {
|
||||||
Ok(RuntimeEffect::SetSpecialCondition {
|
Ok(RuntimeEffect::SetSpecialCondition {
|
||||||
label: label.clone(),
|
label: label.clone(),
|
||||||
|
|
@ -2111,6 +2160,7 @@ fn runtime_effect_uses_condition_true_company(effect: &RuntimeEffect) -> bool {
|
||||||
| RuntimeEffect::SetPlayerCash { .. }
|
| RuntimeEffect::SetPlayerCash { .. }
|
||||||
| RuntimeEffect::DeactivatePlayer { .. }
|
| RuntimeEffect::DeactivatePlayer { .. }
|
||||||
| RuntimeEffect::SetCandidateAvailability { .. }
|
| RuntimeEffect::SetCandidateAvailability { .. }
|
||||||
|
| RuntimeEffect::SetNamedLocomotiveAvailability { .. }
|
||||||
| RuntimeEffect::SetSpecialCondition { .. }
|
| RuntimeEffect::SetSpecialCondition { .. }
|
||||||
| RuntimeEffect::ActivateEventRecord { .. }
|
| RuntimeEffect::ActivateEventRecord { .. }
|
||||||
| RuntimeEffect::DeactivateEventRecord { .. }
|
| RuntimeEffect::DeactivateEventRecord { .. }
|
||||||
|
|
@ -2188,6 +2238,7 @@ fn runtime_effect_company_target_import_blocker(
|
||||||
| RuntimeEffect::SetLimitedTrackBuildingAmount { .. }
|
| RuntimeEffect::SetLimitedTrackBuildingAmount { .. }
|
||||||
| RuntimeEffect::SetEconomicStatusCode { .. }
|
| RuntimeEffect::SetEconomicStatusCode { .. }
|
||||||
| RuntimeEffect::SetCandidateAvailability { .. }
|
| RuntimeEffect::SetCandidateAvailability { .. }
|
||||||
|
| RuntimeEffect::SetNamedLocomotiveAvailability { .. }
|
||||||
| RuntimeEffect::SetSpecialCondition { .. }
|
| RuntimeEffect::SetSpecialCondition { .. }
|
||||||
| RuntimeEffect::ActivateEventRecord { .. }
|
| RuntimeEffect::ActivateEventRecord { .. }
|
||||||
| RuntimeEffect::DeactivateEventRecord { .. }
|
| RuntimeEffect::DeactivateEventRecord { .. }
|
||||||
|
|
@ -2526,6 +2577,7 @@ mod tests {
|
||||||
packed_event_collection: None,
|
packed_event_collection: None,
|
||||||
event_runtime_records: Vec::new(),
|
event_runtime_records: Vec::new(),
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
}
|
}
|
||||||
|
|
@ -3080,6 +3132,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: None,
|
event_runtime_collection: None,
|
||||||
notes: vec![],
|
notes: vec![],
|
||||||
|
|
@ -3118,6 +3171,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: None,
|
event_runtime_collection: None,
|
||||||
notes: vec![],
|
notes: vec![],
|
||||||
|
|
@ -3199,6 +3253,38 @@ mod tests {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
named_locomotive_availability_table: Some(
|
||||||
|
crate::SmpLoadedNamedLocomotiveAvailabilityTable {
|
||||||
|
source_kind: "runtime-save-direct-serializer".to_string(),
|
||||||
|
semantic_family: "scenario-named-locomotive-availability-table".to_string(),
|
||||||
|
header_offset: None,
|
||||||
|
entries_offset: None,
|
||||||
|
entries_end_offset: None,
|
||||||
|
observed_entry_count: 2,
|
||||||
|
zero_availability_count: 1,
|
||||||
|
zero_availability_names: vec!["Big Boy".to_string()],
|
||||||
|
entries: vec![
|
||||||
|
crate::SmpRt3105SaveNameTableEntry {
|
||||||
|
index: 0,
|
||||||
|
offset: 0,
|
||||||
|
text: "Big Boy".to_string(),
|
||||||
|
availability_dword: 0,
|
||||||
|
availability_dword_hex: "0x00000000".to_string(),
|
||||||
|
trailer_word: 0,
|
||||||
|
trailer_word_hex: "0x00000000".to_string(),
|
||||||
|
},
|
||||||
|
crate::SmpRt3105SaveNameTableEntry {
|
||||||
|
index: 1,
|
||||||
|
offset: 0x41,
|
||||||
|
text: "GP7".to_string(),
|
||||||
|
availability_dword: 1,
|
||||||
|
availability_dword_hex: "0x00000001".to_string(),
|
||||||
|
trailer_word: 1,
|
||||||
|
trailer_word_hex: "0x00000001".to_string(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
special_conditions_table: Some(crate::SmpLoadedSpecialConditionsTable {
|
special_conditions_table: Some(crate::SmpLoadedSpecialConditionsTable {
|
||||||
source_kind: "save-fixed-special-conditions-range".to_string(),
|
source_kind: "save-fixed-special-conditions-range".to_string(),
|
||||||
table_offset: 0x0d64,
|
table_offset: 0x0d64,
|
||||||
|
|
@ -3444,10 +3530,34 @@ mod tests {
|
||||||
import.state.candidate_availability.get("Uranium Mine"),
|
import.state.candidate_availability.get("Uranium Mine"),
|
||||||
Some(&0)
|
Some(&0)
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
import.state.named_locomotive_availability.get("Big Boy"),
|
||||||
|
Some(&0)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
import.state.named_locomotive_availability.get("GP7"),
|
||||||
|
Some(&1)
|
||||||
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
import.state.special_conditions.get("Disable Cargo Economy"),
|
import.state.special_conditions.get("Disable Cargo Economy"),
|
||||||
Some(&0)
|
Some(&0)
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
import
|
||||||
|
.state
|
||||||
|
.metadata
|
||||||
|
.get("save_slice.named_locomotive_availability_source_kind")
|
||||||
|
.map(String::as_str),
|
||||||
|
Some("runtime-save-direct-serializer")
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
import
|
||||||
|
.state
|
||||||
|
.metadata
|
||||||
|
.get("save_slice.named_locomotive_availability_entry_count")
|
||||||
|
.map(String::as_str),
|
||||||
|
Some("2")
|
||||||
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
import
|
import
|
||||||
.state
|
.state
|
||||||
|
|
@ -3485,6 +3595,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -3598,6 +3709,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -3689,6 +3801,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -3798,6 +3911,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -3880,6 +3994,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -4012,6 +4127,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -4252,6 +4368,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -4327,6 +4444,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -4424,6 +4542,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -4496,6 +4615,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -4615,6 +4735,7 @@ mod tests {
|
||||||
packed_event_collection: None,
|
packed_event_collection: None,
|
||||||
event_runtime_records: Vec::new(),
|
event_runtime_records: Vec::new(),
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -4627,6 +4748,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -4769,6 +4891,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -4871,6 +4994,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -4954,6 +5078,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -5058,6 +5183,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -5162,6 +5288,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -5256,6 +5383,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -5346,6 +5474,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -5444,6 +5573,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -5533,6 +5663,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -5604,6 +5735,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -5680,6 +5812,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -5761,6 +5894,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -5842,6 +5976,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -5939,6 +6074,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -6027,6 +6163,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -6141,6 +6278,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -6264,6 +6402,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -6372,6 +6511,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -6543,6 +6683,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -6634,6 +6775,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -6721,6 +6863,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -6873,6 +7016,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -7014,6 +7158,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -7102,6 +7247,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -7217,6 +7363,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -7320,6 +7467,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -7443,6 +7591,7 @@ mod tests {
|
||||||
effects: vec![],
|
effects: vec![],
|
||||||
}],
|
}],
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState {
|
service_state: RuntimeServiceState {
|
||||||
periodic_boundary_calls: 9,
|
periodic_boundary_calls: 9,
|
||||||
|
|
@ -7460,6 +7609,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
@ -7609,6 +7759,7 @@ mod tests {
|
||||||
packed_event_collection: None,
|
packed_event_collection: None,
|
||||||
event_runtime_records: Vec::new(),
|
event_runtime_records: Vec::new(),
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
},
|
},
|
||||||
|
|
@ -7629,6 +7780,7 @@ mod tests {
|
||||||
bridge_family: None,
|
bridge_family: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
candidate_availability_table: None,
|
candidate_availability_table: None,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table: None,
|
special_conditions_table: None,
|
||||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||||
source_kind: "packed-event-runtime-collection".to_string(),
|
source_kind: "packed-event-runtime-collection".to_string(),
|
||||||
|
|
|
||||||
|
|
@ -53,10 +53,11 @@ pub use smp::{
|
||||||
SmpClassicRehydrateProfileProbe, SmpContainerProfile, SmpEarlyContentProbe,
|
SmpClassicRehydrateProfileProbe, SmpContainerProfile, SmpEarlyContentProbe,
|
||||||
SmpHeaderVariantProbe, SmpInspectionReport, SmpKnownTagHit,
|
SmpHeaderVariantProbe, SmpInspectionReport, SmpKnownTagHit,
|
||||||
SmpLoadedCandidateAvailabilityTable, SmpLoadedEventRuntimeCollectionSummary,
|
SmpLoadedCandidateAvailabilityTable, SmpLoadedEventRuntimeCollectionSummary,
|
||||||
SmpLoadedPackedEventCompactControlSummary, SmpLoadedPackedEventConditionRowSummary,
|
SmpLoadedNamedLocomotiveAvailabilityTable, SmpLoadedPackedEventCompactControlSummary,
|
||||||
SmpLoadedPackedEventGroupedEffectRowSummary, SmpLoadedPackedEventNegativeSentinelScopeSummary,
|
SmpLoadedPackedEventConditionRowSummary, SmpLoadedPackedEventGroupedEffectRowSummary,
|
||||||
SmpLoadedPackedEventRecordSummary, SmpLoadedPackedEventTextBandSummary, SmpLoadedProfile,
|
SmpLoadedPackedEventNegativeSentinelScopeSummary, SmpLoadedPackedEventRecordSummary,
|
||||||
SmpLoadedSaveSlice, SmpLoadedSpecialConditionsTable, SmpLocomotivePolicyFieldObservation,
|
SmpLoadedPackedEventTextBandSummary, SmpLoadedProfile, SmpLoadedSaveSlice,
|
||||||
|
SmpLoadedSpecialConditionsTable, SmpLocomotivePolicyFieldObservation,
|
||||||
SmpLocomotivePolicyFloatAlignmentCandidate, SmpLocomotivePolicyNeighborhoodProbe,
|
SmpLocomotivePolicyFloatAlignmentCandidate, SmpLocomotivePolicyNeighborhoodProbe,
|
||||||
SmpPackedProfileWordLane, SmpPostSpecialConditionsScalarLane,
|
SmpPackedProfileWordLane, SmpPostSpecialConditionsScalarLane,
|
||||||
SmpPostSpecialConditionsScalarProbe, SmpPostTextFieldNeighborhoodProbe,
|
SmpPostSpecialConditionsScalarProbe, SmpPostTextFieldNeighborhoodProbe,
|
||||||
|
|
|
||||||
|
|
@ -103,6 +103,7 @@ mod tests {
|
||||||
packed_event_collection: None,
|
packed_event_collection: None,
|
||||||
event_runtime_records: Vec::new(),
|
event_runtime_records: Vec::new(),
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -307,6 +307,10 @@ pub enum RuntimeEffect {
|
||||||
name: String,
|
name: String,
|
||||||
value: u32,
|
value: u32,
|
||||||
},
|
},
|
||||||
|
SetNamedLocomotiveAvailability {
|
||||||
|
name: String,
|
||||||
|
value: bool,
|
||||||
|
},
|
||||||
SetSpecialCondition {
|
SetSpecialCondition {
|
||||||
label: String,
|
label: String,
|
||||||
value: u32,
|
value: u32,
|
||||||
|
|
@ -637,6 +641,8 @@ pub struct RuntimeState {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub candidate_availability: BTreeMap<String, u32>,
|
pub candidate_availability: BTreeMap<String, u32>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
pub named_locomotive_availability: BTreeMap<String, u32>,
|
||||||
|
#[serde(default)]
|
||||||
pub special_conditions: BTreeMap<String, u32>,
|
pub special_conditions: BTreeMap<String, u32>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub service_state: RuntimeServiceState,
|
pub service_state: RuntimeServiceState,
|
||||||
|
|
@ -1119,6 +1125,11 @@ impl RuntimeState {
|
||||||
return Err("candidate_availability contains an empty key".to_string());
|
return Err("candidate_availability contains an empty key".to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for key in self.named_locomotive_availability.keys() {
|
||||||
|
if key.trim().is_empty() {
|
||||||
|
return Err("named_locomotive_availability contains an empty key".to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
for key in self.special_conditions.keys() {
|
for key in self.special_conditions.keys() {
|
||||||
if key.trim().is_empty() {
|
if key.trim().is_empty() {
|
||||||
return Err("special_conditions contains an empty key".to_string());
|
return Err("special_conditions contains an empty key".to_string());
|
||||||
|
|
@ -1190,6 +1201,11 @@ fn validate_runtime_effect(
|
||||||
return Err("name must not be empty".to_string());
|
return Err("name must not be empty".to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
RuntimeEffect::SetNamedLocomotiveAvailability { name, .. } => {
|
||||||
|
if name.trim().is_empty() {
|
||||||
|
return Err("name must not be empty".to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
RuntimeEffect::SetSpecialCondition { label, .. } => {
|
RuntimeEffect::SetSpecialCondition { label, .. } => {
|
||||||
if label.trim().is_empty() {
|
if label.trim().is_empty() {
|
||||||
return Err("label must not be empty".to_string());
|
return Err("label must not be empty".to_string());
|
||||||
|
|
@ -1409,6 +1425,7 @@ mod tests {
|
||||||
packed_event_collection: None,
|
packed_event_collection: None,
|
||||||
event_runtime_records: Vec::new(),
|
event_runtime_records: Vec::new(),
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -1464,6 +1481,7 @@ mod tests {
|
||||||
packed_event_collection: None,
|
packed_event_collection: None,
|
||||||
event_runtime_records: Vec::new(),
|
event_runtime_records: Vec::new(),
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -1518,6 +1536,7 @@ mod tests {
|
||||||
}],
|
}],
|
||||||
}],
|
}],
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -1582,6 +1601,7 @@ mod tests {
|
||||||
}],
|
}],
|
||||||
}],
|
}],
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -1677,6 +1697,7 @@ mod tests {
|
||||||
}),
|
}),
|
||||||
event_runtime_records: Vec::new(),
|
event_runtime_records: Vec::new(),
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -1718,6 +1739,7 @@ mod tests {
|
||||||
packed_event_collection: None,
|
packed_event_collection: None,
|
||||||
event_runtime_records: Vec::new(),
|
event_runtime_records: Vec::new(),
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -1759,6 +1781,7 @@ mod tests {
|
||||||
packed_event_collection: None,
|
packed_event_collection: None,
|
||||||
event_runtime_records: Vec::new(),
|
event_runtime_records: Vec::new(),
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -1817,6 +1840,7 @@ mod tests {
|
||||||
packed_event_collection: None,
|
packed_event_collection: None,
|
||||||
event_runtime_records: Vec::new(),
|
event_runtime_records: Vec::new(),
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -1865,6 +1889,7 @@ mod tests {
|
||||||
packed_event_collection: None,
|
packed_event_collection: None,
|
||||||
event_runtime_records: Vec::new(),
|
event_runtime_records: Vec::new(),
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -1917,6 +1942,7 @@ mod tests {
|
||||||
packed_event_collection: None,
|
packed_event_collection: None,
|
||||||
event_runtime_records: Vec::new(),
|
event_runtime_records: Vec::new(),
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -1965,6 +1991,7 @@ mod tests {
|
||||||
packed_event_collection: None,
|
packed_event_collection: None,
|
||||||
event_runtime_records: Vec::new(),
|
event_runtime_records: Vec::new(),
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -2019,6 +2046,7 @@ mod tests {
|
||||||
packed_event_collection: None,
|
packed_event_collection: None,
|
||||||
event_runtime_records: Vec::new(),
|
event_runtime_records: Vec::new(),
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -2067,6 +2095,7 @@ mod tests {
|
||||||
packed_event_collection: None,
|
packed_event_collection: None,
|
||||||
event_runtime_records: Vec::new(),
|
event_runtime_records: Vec::new(),
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -2115,6 +2144,7 @@ mod tests {
|
||||||
packed_event_collection: None,
|
packed_event_collection: None,
|
||||||
event_runtime_records: Vec::new(),
|
event_runtime_records: Vec::new(),
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1503,6 +1503,22 @@ pub struct SmpLoadedCandidateAvailabilityTable {
|
||||||
pub entries: Vec<SmpRt3105SaveNameTableEntry>,
|
pub entries: Vec<SmpRt3105SaveNameTableEntry>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct SmpLoadedNamedLocomotiveAvailabilityTable {
|
||||||
|
pub source_kind: String,
|
||||||
|
pub semantic_family: String,
|
||||||
|
#[serde(default)]
|
||||||
|
pub header_offset: Option<usize>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub entries_offset: Option<usize>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub entries_end_offset: Option<usize>,
|
||||||
|
pub observed_entry_count: usize,
|
||||||
|
pub zero_availability_count: usize,
|
||||||
|
pub zero_availability_names: Vec<String>,
|
||||||
|
pub entries: Vec<SmpRt3105SaveNameTableEntry>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct SmpLoadedSpecialConditionsTable {
|
pub struct SmpLoadedSpecialConditionsTable {
|
||||||
pub source_kind: String,
|
pub source_kind: String,
|
||||||
|
|
@ -1673,6 +1689,7 @@ pub struct SmpLoadedSaveSlice {
|
||||||
pub bridge_family: Option<String>,
|
pub bridge_family: Option<String>,
|
||||||
pub profile: Option<SmpLoadedProfile>,
|
pub profile: Option<SmpLoadedProfile>,
|
||||||
pub candidate_availability_table: Option<SmpLoadedCandidateAvailabilityTable>,
|
pub candidate_availability_table: Option<SmpLoadedCandidateAvailabilityTable>,
|
||||||
|
pub named_locomotive_availability_table: Option<SmpLoadedNamedLocomotiveAvailabilityTable>,
|
||||||
pub special_conditions_table: Option<SmpLoadedSpecialConditionsTable>,
|
pub special_conditions_table: Option<SmpLoadedSpecialConditionsTable>,
|
||||||
pub event_runtime_collection: Option<SmpLoadedEventRuntimeCollectionSummary>,
|
pub event_runtime_collection: Option<SmpLoadedEventRuntimeCollectionSummary>,
|
||||||
pub notes: Vec<String>,
|
pub notes: Vec<String>,
|
||||||
|
|
@ -1840,6 +1857,7 @@ pub fn load_save_slice_from_report(
|
||||||
bridge_family: summary.bridge_family.clone(),
|
bridge_family: summary.bridge_family.clone(),
|
||||||
profile,
|
profile,
|
||||||
candidate_availability_table,
|
candidate_availability_table,
|
||||||
|
named_locomotive_availability_table: None,
|
||||||
special_conditions_table,
|
special_conditions_table,
|
||||||
event_runtime_collection: report.event_runtime_collection_summary.clone(),
|
event_runtime_collection: report.event_runtime_collection_summary.clone(),
|
||||||
notes: summary.notes.clone(),
|
notes: summary.notes.clone(),
|
||||||
|
|
@ -2659,6 +2677,11 @@ fn parse_real_grouped_effect_row_summary(
|
||||||
if descriptor_metadata.is_none() {
|
if descriptor_metadata.is_none() {
|
||||||
notes.push("descriptor id not yet recovered in the checked-in effect table".to_string());
|
notes.push("descriptor id not yet recovered in the checked-in effect table".to_string());
|
||||||
}
|
}
|
||||||
|
if let Some(loco_id) = recovered_locomotive_availability_loco_id(descriptor_id) {
|
||||||
|
notes.push(format!(
|
||||||
|
"locomotive availability descriptor maps to live locomotive id {loco_id}"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
Some(SmpLoadedPackedEventGroupedEffectRowSummary {
|
Some(SmpLoadedPackedEventGroupedEffectRowSummary {
|
||||||
group_index,
|
group_index,
|
||||||
|
|
@ -2836,6 +2859,16 @@ fn recovered_locomotive_availability_descriptor_metadata(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn recovered_locomotive_availability_loco_id(descriptor_id: u32) -> Option<u32> {
|
||||||
|
if (241..=351).contains(&descriptor_id) {
|
||||||
|
return Some(descriptor_id - 240);
|
||||||
|
}
|
||||||
|
if (457..=474).contains(&descriptor_id) {
|
||||||
|
return Some(descriptor_id - 345);
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
fn recovered_locomotive_cost_descriptor_metadata(
|
fn recovered_locomotive_cost_descriptor_metadata(
|
||||||
descriptor_id: u32,
|
descriptor_id: u32,
|
||||||
) -> Option<RealGroupedEffectDescriptorMetadata> {
|
) -> Option<RealGroupedEffectDescriptorMetadata> {
|
||||||
|
|
@ -3409,6 +3442,7 @@ fn runtime_effect_supported_for_save_import(effect: &RuntimeEffect) -> bool {
|
||||||
| RuntimeEffect::SetLimitedTrackBuildingAmount { .. }
|
| RuntimeEffect::SetLimitedTrackBuildingAmount { .. }
|
||||||
| RuntimeEffect::SetEconomicStatusCode { .. }
|
| RuntimeEffect::SetEconomicStatusCode { .. }
|
||||||
| RuntimeEffect::SetCandidateAvailability { .. }
|
| RuntimeEffect::SetCandidateAvailability { .. }
|
||||||
|
| RuntimeEffect::SetNamedLocomotiveAvailability { .. }
|
||||||
| RuntimeEffect::SetSpecialCondition { .. }
|
| RuntimeEffect::SetSpecialCondition { .. }
|
||||||
| RuntimeEffect::ConfiscateCompanyAssets { .. }
|
| RuntimeEffect::ConfiscateCompanyAssets { .. }
|
||||||
| RuntimeEffect::DeactivateCompany { .. }
|
| RuntimeEffect::DeactivateCompany { .. }
|
||||||
|
|
|
||||||
|
|
@ -490,6 +490,11 @@ fn apply_runtime_effects(
|
||||||
RuntimeEffect::SetCandidateAvailability { name, value } => {
|
RuntimeEffect::SetCandidateAvailability { name, value } => {
|
||||||
state.candidate_availability.insert(name.clone(), *value);
|
state.candidate_availability.insert(name.clone(), *value);
|
||||||
}
|
}
|
||||||
|
RuntimeEffect::SetNamedLocomotiveAvailability { name, value } => {
|
||||||
|
state
|
||||||
|
.named_locomotive_availability
|
||||||
|
.insert(name.clone(), u32::from(*value));
|
||||||
|
}
|
||||||
RuntimeEffect::SetSpecialCondition { label, value } => {
|
RuntimeEffect::SetSpecialCondition { label, value } => {
|
||||||
state.special_conditions.insert(label.clone(), *value);
|
state.special_conditions.insert(label.clone(), *value);
|
||||||
}
|
}
|
||||||
|
|
@ -1158,6 +1163,7 @@ mod tests {
|
||||||
packed_event_collection: None,
|
packed_event_collection: None,
|
||||||
event_runtime_records: Vec::new(),
|
event_runtime_records: Vec::new(),
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
}
|
}
|
||||||
|
|
@ -1372,6 +1378,43 @@ mod tests {
|
||||||
assert_eq!(result.service_events[0].mutated_company_ids, vec![2]);
|
assert_eq!(result.service_events[0].mutated_company_ids, vec![2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn applies_named_locomotive_availability_effects() {
|
||||||
|
let mut state = RuntimeState {
|
||||||
|
event_runtime_records: vec![RuntimeEventRecord {
|
||||||
|
record_id: 10,
|
||||||
|
trigger_kind: 7,
|
||||||
|
active: true,
|
||||||
|
service_count: 0,
|
||||||
|
marks_collection_dirty: false,
|
||||||
|
one_shot: false,
|
||||||
|
has_fired: false,
|
||||||
|
conditions: Vec::new(),
|
||||||
|
effects: vec![
|
||||||
|
RuntimeEffect::SetNamedLocomotiveAvailability {
|
||||||
|
name: "Big Boy".to_string(),
|
||||||
|
value: false,
|
||||||
|
},
|
||||||
|
RuntimeEffect::SetNamedLocomotiveAvailability {
|
||||||
|
name: "GP7".to_string(),
|
||||||
|
value: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
..state()
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = execute_step_command(
|
||||||
|
&mut state,
|
||||||
|
&StepCommand::ServiceTriggerKind { trigger_kind: 7 },
|
||||||
|
)
|
||||||
|
.expect("named locomotive availability effects should succeed");
|
||||||
|
|
||||||
|
assert_eq!(state.named_locomotive_availability.get("Big Boy"), Some(&0));
|
||||||
|
assert_eq!(state.named_locomotive_availability.get("GP7"), Some(&1));
|
||||||
|
assert_eq!(result.service_events[0].applied_effect_count, 2);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn resolves_symbolic_company_targets() {
|
fn resolves_symbolic_company_targets() {
|
||||||
let mut state = RuntimeState {
|
let mut state = RuntimeState {
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,8 @@ pub struct RuntimeSummary {
|
||||||
pub event_runtime_record_count: usize,
|
pub event_runtime_record_count: usize,
|
||||||
pub candidate_availability_count: usize,
|
pub candidate_availability_count: usize,
|
||||||
pub zero_candidate_availability_count: usize,
|
pub zero_candidate_availability_count: usize,
|
||||||
|
pub named_locomotive_availability_count: usize,
|
||||||
|
pub zero_named_locomotive_availability_count: usize,
|
||||||
pub special_condition_count: usize,
|
pub special_condition_count: usize,
|
||||||
pub enabled_special_condition_count: usize,
|
pub enabled_special_condition_count: usize,
|
||||||
pub save_profile_kind: Option<String>,
|
pub save_profile_kind: Option<String>,
|
||||||
|
|
@ -570,6 +572,12 @@ impl RuntimeSummary {
|
||||||
.values()
|
.values()
|
||||||
.filter(|value| **value == 0)
|
.filter(|value| **value == 0)
|
||||||
.count(),
|
.count(),
|
||||||
|
named_locomotive_availability_count: state.named_locomotive_availability.len(),
|
||||||
|
zero_named_locomotive_availability_count: state
|
||||||
|
.named_locomotive_availability
|
||||||
|
.values()
|
||||||
|
.filter(|value| **value == 0)
|
||||||
|
.count(),
|
||||||
special_condition_count: state.special_conditions.len(),
|
special_condition_count: state.special_conditions.len(),
|
||||||
enabled_special_condition_count: state
|
enabled_special_condition_count: state
|
||||||
.special_conditions
|
.special_conditions
|
||||||
|
|
@ -781,6 +789,7 @@ mod tests {
|
||||||
}),
|
}),
|
||||||
event_runtime_records: Vec::new(),
|
event_runtime_records: Vec::new(),
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -869,6 +878,7 @@ mod tests {
|
||||||
packed_event_collection: None,
|
packed_event_collection: None,
|
||||||
event_runtime_records: Vec::new(),
|
event_runtime_records: Vec::new(),
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
@ -878,6 +888,44 @@ mod tests {
|
||||||
assert_eq!(summary.active_company_count, 1);
|
assert_eq!(summary.active_company_count, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn counts_named_locomotive_availability_entries_and_zero_values() {
|
||||||
|
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: None,
|
||||||
|
event_runtime_records: Vec::new(),
|
||||||
|
candidate_availability: BTreeMap::new(),
|
||||||
|
named_locomotive_availability: BTreeMap::from([
|
||||||
|
("Big Boy".to_string(), 0),
|
||||||
|
("GP7".to_string(), 1),
|
||||||
|
("Mikado".to_string(), 0),
|
||||||
|
]),
|
||||||
|
special_conditions: BTreeMap::new(),
|
||||||
|
service_state: RuntimeServiceState::default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let summary = RuntimeSummary::from_state(&state);
|
||||||
|
assert_eq!(summary.named_locomotive_availability_count, 3);
|
||||||
|
assert_eq!(summary.zero_named_locomotive_availability_count, 2);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn counts_world_frontier_buckets_separately() {
|
fn counts_world_frontier_buckets_separately() {
|
||||||
let state = RuntimeState {
|
let state = RuntimeState {
|
||||||
|
|
@ -966,6 +1014,7 @@ mod tests {
|
||||||
}),
|
}),
|
||||||
event_runtime_records: Vec::new(),
|
event_runtime_records: Vec::new(),
|
||||||
candidate_availability: BTreeMap::new(),
|
candidate_availability: BTreeMap::new(),
|
||||||
|
named_locomotive_availability: BTreeMap::new(),
|
||||||
special_conditions: BTreeMap::new(),
|
special_conditions: BTreeMap::new(),
|
||||||
service_state: RuntimeServiceState::default(),
|
service_state: RuntimeServiceState::default(),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -127,6 +127,10 @@ The highest-value next passes are now:
|
||||||
descriptors `454..456` (`All Steam/Diesel/Electric Locos Avail.`) now lower through checked-in
|
descriptors `454..456` (`All Steam/Diesel/Electric Locos Avail.`) now lower through checked-in
|
||||||
metadata into keyed `world_flags`, while the wider locomotive availability/cost scalar bands
|
metadata into keyed `world_flags`, while the wider locomotive availability/cost scalar bands
|
||||||
remain recovered-but-parity-only until per-locomotive identity is grounded
|
remain recovered-but-parity-only until per-locomotive identity is grounded
|
||||||
|
- the runtime now also carries the save-owned named locomotive availability table directly:
|
||||||
|
checked-in save-slice documents can populate `RuntimeState.named_locomotive_availability`, and
|
||||||
|
imported runtime effects can mutate that map through the ordinary event-service path without
|
||||||
|
needing full live locomotive-pool parity
|
||||||
- keep in mind that the current local `.gms` corpus still exports with no packed event collection,
|
- keep in mind that the current local `.gms` corpus still exports with no packed event collection,
|
||||||
so real descriptor mapping needs to stay plumbing-first until better captures exist
|
so real descriptor mapping needs to stay plumbing-first until better captures exist
|
||||||
- use `rrt-hook` primarily as optional capture or integration tooling, not as the first execution
|
- use `rrt-hook` primarily as optional capture or integration tooling, not as the first execution
|
||||||
|
|
|
||||||
|
|
@ -82,12 +82,16 @@ Implemented today:
|
||||||
descriptors `230..240`, `241..351`, `352..451`, `453`, and `457..500` now carry recovered
|
descriptors `230..240`, `241..351`, `352..451`, `453`, and `457..500` now carry recovered
|
||||||
world-side scalar metadata, while descriptors `454..456` (`All Steam/Diesel/Electric Locos
|
world-side scalar metadata, while descriptors `454..456` (`All Steam/Diesel/Electric Locos
|
||||||
Avail.`) now execute as keyed `world_flags`
|
Avail.`) now execute as keyed `world_flags`
|
||||||
|
- a first-class named locomotive availability runtime surface now exists too:
|
||||||
|
save-slice documents can carry the persisted `[world+0x66b6]` name table into
|
||||||
|
`RuntimeState.named_locomotive_availability`, and imported runtime effects can mutate that map
|
||||||
|
through the ordinary event-service path without requiring Trainbuy or live locomotive-pool parity
|
||||||
|
|
||||||
That means the next implementation work is breadth, not bootstrap. The recommended next slice is
|
That means the next implementation work is breadth, not bootstrap. The recommended next slice is
|
||||||
broader real grouped-descriptor and ordinary condition-id coverage beyond the current access,
|
broader real grouped-descriptor and ordinary condition-id coverage beyond the current access,
|
||||||
whole-game toggle, train, player, and numeric-threshold batches. Richer runtime ownership should
|
whole-game toggle, train, player, numeric-threshold, and named locomotive availability batches.
|
||||||
still be added only where a later descriptor or condition family needs more than the current
|
Richer runtime ownership should still be added only where a later descriptor or condition family
|
||||||
event-owned roster.
|
needs more than the current event-owned roster.
|
||||||
|
|
||||||
## Why This Boundary
|
## Why This Boundary
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
{
|
||||||
|
"format_version": 1,
|
||||||
|
"fixture_id": "packed-event-named-locomotive-availability-save-slice-fixture",
|
||||||
|
"source": {
|
||||||
|
"kind": "captured-runtime",
|
||||||
|
"description": "Fixture backed by a tracked save-slice document that imports the named locomotive availability table and mutates it through an imported packed-event record."
|
||||||
|
},
|
||||||
|
"state_save_slice_path": "packed-event-named-locomotive-availability-save-slice.json",
|
||||||
|
"commands": [
|
||||||
|
{
|
||||||
|
"kind": "service_trigger_kind",
|
||||||
|
"trigger_kind": 7
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"expected_summary": {
|
||||||
|
"calendar_projection_is_placeholder": true,
|
||||||
|
"packed_event_collection_present": true,
|
||||||
|
"packed_event_record_count": 1,
|
||||||
|
"packed_event_decoded_record_count": 1,
|
||||||
|
"packed_event_imported_runtime_record_count": 1,
|
||||||
|
"event_runtime_record_count": 1,
|
||||||
|
"named_locomotive_availability_count": 3,
|
||||||
|
"zero_named_locomotive_availability_count": 2,
|
||||||
|
"total_event_record_service_count": 1,
|
||||||
|
"total_trigger_dispatch_count": 1,
|
||||||
|
"dirty_rerun_count": 0
|
||||||
|
},
|
||||||
|
"expected_state_fragment": {
|
||||||
|
"world_flags": {
|
||||||
|
"save_slice.named_locomotive_availability_present": true
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"save_slice.named_locomotive_availability_source_kind": "runtime-save-direct-serializer",
|
||||||
|
"save_slice.named_locomotive_availability_entry_count": "2",
|
||||||
|
"save_slice.named_locomotive_availability_zero_count": "1"
|
||||||
|
},
|
||||||
|
"named_locomotive_availability": {
|
||||||
|
"Big Boy": 0,
|
||||||
|
"GP7": 0,
|
||||||
|
"Mikado": 1
|
||||||
|
},
|
||||||
|
"packed_event_collection": {
|
||||||
|
"live_entry_ids": [
|
||||||
|
17
|
||||||
|
],
|
||||||
|
"records": [
|
||||||
|
{
|
||||||
|
"decode_status": "executable",
|
||||||
|
"import_outcome": "imported"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"event_runtime_records": [
|
||||||
|
{
|
||||||
|
"record_id": 17,
|
||||||
|
"service_count": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,117 @@
|
||||||
|
{
|
||||||
|
"format_version": 1,
|
||||||
|
"save_slice_id": "packed-event-named-locomotive-availability-save-slice",
|
||||||
|
"source": {
|
||||||
|
"description": "Tracked save-slice document proving named locomotive availability survives save import and can be mutated by imported packed events.",
|
||||||
|
"original_save_filename": "captured-named-locomotive-availability.gms",
|
||||||
|
"original_save_sha256": "named-locomotive-availability-sample-sha256",
|
||||||
|
"notes": [
|
||||||
|
"tracked as JSON save-slice document rather than raw .smp",
|
||||||
|
"locks the named locomotive availability import surface without guessing per-descriptor locomotive names"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"save_slice": {
|
||||||
|
"file_extension_hint": "gms",
|
||||||
|
"container_profile_family": "rt3-classic-save-container-v1",
|
||||||
|
"mechanism_family": "classic-save-rehydrate-v1",
|
||||||
|
"mechanism_confidence": "grounded",
|
||||||
|
"trailer_family": null,
|
||||||
|
"bridge_family": null,
|
||||||
|
"profile": null,
|
||||||
|
"candidate_availability_table": null,
|
||||||
|
"named_locomotive_availability_table": {
|
||||||
|
"source_kind": "runtime-save-direct-serializer",
|
||||||
|
"semantic_family": "scenario-named-locomotive-availability-table",
|
||||||
|
"header_offset": null,
|
||||||
|
"entries_offset": null,
|
||||||
|
"entries_end_offset": null,
|
||||||
|
"observed_entry_count": 2,
|
||||||
|
"zero_availability_count": 1,
|
||||||
|
"zero_availability_names": [
|
||||||
|
"GP7"
|
||||||
|
],
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"offset": 0,
|
||||||
|
"text": "Big Boy",
|
||||||
|
"availability_dword": 1,
|
||||||
|
"availability_dword_hex": "0x00000001",
|
||||||
|
"trailer_word": 1,
|
||||||
|
"trailer_word_hex": "0x00000001"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"offset": 65,
|
||||||
|
"text": "GP7",
|
||||||
|
"availability_dword": 0,
|
||||||
|
"availability_dword_hex": "0x00000000",
|
||||||
|
"trailer_word": 0,
|
||||||
|
"trailer_word_hex": "0x00000000"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"special_conditions_table": null,
|
||||||
|
"event_runtime_collection": {
|
||||||
|
"source_kind": "packed-event-runtime-collection",
|
||||||
|
"mechanism_family": "classic-save-rehydrate-v1",
|
||||||
|
"mechanism_confidence": "grounded",
|
||||||
|
"container_profile_family": "rt3-classic-save-container-v1",
|
||||||
|
"metadata_tag_offset": 28928,
|
||||||
|
"records_tag_offset": 29184,
|
||||||
|
"close_tag_offset": 29440,
|
||||||
|
"packed_state_version": 1001,
|
||||||
|
"packed_state_version_hex": "0x000003e9",
|
||||||
|
"live_id_bound": 17,
|
||||||
|
"live_record_count": 1,
|
||||||
|
"live_entry_ids": [
|
||||||
|
17
|
||||||
|
],
|
||||||
|
"decoded_record_count": 1,
|
||||||
|
"imported_runtime_record_count": 1,
|
||||||
|
"records": [
|
||||||
|
{
|
||||||
|
"record_index": 0,
|
||||||
|
"live_entry_id": 17,
|
||||||
|
"payload_offset": 29186,
|
||||||
|
"payload_len": 64,
|
||||||
|
"decode_status": "executable",
|
||||||
|
"payload_family": "synthetic_harness",
|
||||||
|
"trigger_kind": 7,
|
||||||
|
"active": true,
|
||||||
|
"marks_collection_dirty": false,
|
||||||
|
"one_shot": false,
|
||||||
|
"text_bands": [],
|
||||||
|
"standalone_condition_row_count": 0,
|
||||||
|
"standalone_condition_rows": [],
|
||||||
|
"grouped_effect_row_counts": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"grouped_effect_rows": [],
|
||||||
|
"decoded_actions": [
|
||||||
|
{
|
||||||
|
"kind": "set_named_locomotive_availability",
|
||||||
|
"name": "Big Boy",
|
||||||
|
"value": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "set_named_locomotive_availability",
|
||||||
|
"name": "Mikado",
|
||||||
|
"value": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"executable_import_ready": true,
|
||||||
|
"notes": [
|
||||||
|
"fixture packed-event record"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notes": [
|
||||||
|
"named locomotive availability import surface"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
},
|
},
|
||||||
"calendar_projection_source": "base-snapshot-preserved",
|
"calendar_projection_source": "base-snapshot-preserved",
|
||||||
"calendar_projection_is_placeholder": false,
|
"calendar_projection_is_placeholder": false,
|
||||||
"world_flag_count": 7,
|
"world_flag_count": 8,
|
||||||
"company_count": 1,
|
"company_count": 1,
|
||||||
"packed_event_collection_present": true,
|
"packed_event_collection_present": true,
|
||||||
"packed_event_record_count": 2,
|
"packed_event_record_count": 2,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue