Rehost cargo selector analysis surfaces
This commit is contained in:
parent
517b01cd35
commit
cebcb8ad33
7 changed files with 2414 additions and 12 deletions
|
|
@ -67,8 +67,9 @@ corpus has `41`, so neither static set closes the `71`-row named price strip on
|
||||||
offline cargo-source inspector now pushes that groundwork further in rehosted code: the checked-in
|
offline cargo-source inspector now pushes that groundwork further in rehosted code: the checked-in
|
||||||
`artifacts/exports/rt3-1.06/economy-cargo-sources.json` report parses both `CargoTypes` and the
|
`artifacts/exports/rt3-1.06/economy-cargo-sources.json` report parses both `CargoTypes` and the
|
||||||
`Cargo106.PK4` `cargoSkin` descriptors, normalizes localized `~####Name` tokens into visible
|
`Cargo106.PK4` `cargoSkin` descriptors, normalizes localized `~####Name` tokens into visible
|
||||||
names, and shows that the current 1.06 visible-name union is `80`, not `71`, so source recovery
|
names, builds a merged live cargo registry, and derives an exact named cargo-production selector
|
||||||
alone still does not prove the live price-selector ordering. The
|
from the checked-in bindings. It also shows that the current 1.06 visible-name union is `80`, not
|
||||||
|
`71`, so source recovery alone still does not prove the live price-selector ordering. The
|
||||||
add-building strip `503..519` is now explicitly classified as recovered
|
add-building strip `503..519` is now explicitly classified as recovered
|
||||||
shell-owned descriptor parity rather than generic unresolved residue. The first grounded
|
shell-owned descriptor parity rather than generic unresolved residue. The first grounded
|
||||||
condition-side unlock now exists for negative-sentinel `raw_condition_id = -1` company scopes, and
|
condition-side unlock now exists for negative-sentinel `raw_condition_id = -1` company scopes, and
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -25,7 +25,7 @@ use rrt_runtime::{
|
||||||
SAVE_SLICE_DOCUMENT_FORMAT_VERSION, SNAPSHOT_FORMAT_VERSION, SmpClassicPackedProfileBlock,
|
SAVE_SLICE_DOCUMENT_FORMAT_VERSION, SNAPSHOT_FORMAT_VERSION, SmpClassicPackedProfileBlock,
|
||||||
SmpInspectionReport, SmpLoadedSaveSlice, SmpRt3105PackedProfileBlock, SmpSaveLoadSummary,
|
SmpInspectionReport, SmpLoadedSaveSlice, SmpRt3105PackedProfileBlock, SmpSaveLoadSummary,
|
||||||
WinInspectionReport, execute_step_command, extract_pk4_entry_file, inspect_campaign_exe_file,
|
WinInspectionReport, execute_step_command, extract_pk4_entry_file, inspect_campaign_exe_file,
|
||||||
inspect_cargo_economy_sources, inspect_cargo_skin_pk4, inspect_cargo_types_dir,
|
inspect_cargo_economy_sources_with_bindings, inspect_cargo_skin_pk4, inspect_cargo_types_dir,
|
||||||
inspect_pk4_file, inspect_smp_file, inspect_win_file, load_runtime_snapshot_document,
|
inspect_pk4_file, inspect_smp_file, inspect_win_file, load_runtime_snapshot_document,
|
||||||
load_runtime_state_import, load_save_slice_file, project_save_slice_to_runtime_state_import,
|
load_runtime_state_import, load_save_slice_file, project_save_slice_to_runtime_state_import,
|
||||||
save_runtime_overlay_import_document, save_runtime_save_slice_document,
|
save_runtime_overlay_import_document, save_runtime_save_slice_document,
|
||||||
|
|
@ -1583,10 +1583,16 @@ fn run_runtime_inspect_cargo_economy_sources(
|
||||||
cargo_types_dir: &Path,
|
cargo_types_dir: &Path,
|
||||||
cargo_skin_pk4_path: &Path,
|
cargo_skin_pk4_path: &Path,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let cargo_bindings_path =
|
||||||
|
Path::new("artifacts/exports/rt3-1.06/event-effects-cargo-bindings.json");
|
||||||
let report = RuntimeCargoEconomyInspectionOutput {
|
let report = RuntimeCargoEconomyInspectionOutput {
|
||||||
cargo_types_dir: cargo_types_dir.display().to_string(),
|
cargo_types_dir: cargo_types_dir.display().to_string(),
|
||||||
cargo_skin_pk4_path: cargo_skin_pk4_path.display().to_string(),
|
cargo_skin_pk4_path: cargo_skin_pk4_path.display().to_string(),
|
||||||
inspection: inspect_cargo_economy_sources(cargo_types_dir, cargo_skin_pk4_path)?,
|
inspection: inspect_cargo_economy_sources_with_bindings(
|
||||||
|
cargo_types_dir,
|
||||||
|
cargo_skin_pk4_path,
|
||||||
|
Some(cargo_bindings_path),
|
||||||
|
)?,
|
||||||
};
|
};
|
||||||
println!("{}", serde_json::to_string_pretty(&report)?);
|
println!("{}", serde_json::to_string_pretty(&report)?);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -67,11 +67,62 @@ pub struct CargoEconomySourceReport {
|
||||||
pub visible_name_union_count: usize,
|
pub visible_name_union_count: usize,
|
||||||
pub cargo_type_only_visible_names: Vec<String>,
|
pub cargo_type_only_visible_names: Vec<String>,
|
||||||
pub cargo_skin_only_visible_names: Vec<String>,
|
pub cargo_skin_only_visible_names: Vec<String>,
|
||||||
|
pub live_registry_count: usize,
|
||||||
|
pub live_registry_entries: Vec<CargoLiveRegistryEntry>,
|
||||||
|
pub production_selector: Option<CargoSelectorReport>,
|
||||||
|
pub price_selector: CargoSelectorReport,
|
||||||
pub notes: Vec<String>,
|
pub notes: Vec<String>,
|
||||||
pub cargo_type_entries: Vec<CargoTypeEntry>,
|
pub cargo_type_entries: Vec<CargoTypeEntry>,
|
||||||
pub cargo_skin_entries: Vec<CargoSkinDescriptorEntry>,
|
pub cargo_skin_entries: Vec<CargoSkinDescriptorEntry>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub enum CargoRegistrySourceKind {
|
||||||
|
CargoTypes,
|
||||||
|
CargoSkin,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct CargoLiveRegistryEntry {
|
||||||
|
pub visible_name: String,
|
||||||
|
pub raw_names: Vec<String>,
|
||||||
|
pub localized_string_ids: Vec<u32>,
|
||||||
|
pub source_kinds: Vec<CargoRegistrySourceKind>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct CargoSelectorEntry {
|
||||||
|
pub selector_index: usize,
|
||||||
|
#[serde(default)]
|
||||||
|
pub descriptor_id: Option<u32>,
|
||||||
|
pub visible_name: String,
|
||||||
|
pub source_kinds: Vec<CargoRegistrySourceKind>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct CargoSelectorReport {
|
||||||
|
pub selector_kind: String,
|
||||||
|
pub exact_resolution: bool,
|
||||||
|
pub selector_row_count: usize,
|
||||||
|
pub candidate_registry_count: usize,
|
||||||
|
pub notes: Vec<String>,
|
||||||
|
pub entries: Vec<CargoSelectorEntry>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
|
||||||
|
struct CargoBindingArtifact {
|
||||||
|
bindings: Vec<CargoBindingRow>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
|
||||||
|
struct CargoBindingRow {
|
||||||
|
descriptor_id: u32,
|
||||||
|
band: String,
|
||||||
|
cargo_name: String,
|
||||||
|
binding_index: usize,
|
||||||
|
}
|
||||||
|
|
||||||
pub fn inspect_cargo_types_dir(
|
pub fn inspect_cargo_types_dir(
|
||||||
path: &Path,
|
path: &Path,
|
||||||
) -> Result<CargoTypeInspectionReport, Box<dyn std::error::Error>> {
|
) -> Result<CargoTypeInspectionReport, Box<dyn std::error::Error>> {
|
||||||
|
|
@ -167,15 +218,29 @@ pub fn inspect_cargo_skin_pk4(
|
||||||
pub fn inspect_cargo_economy_sources(
|
pub fn inspect_cargo_economy_sources(
|
||||||
cargo_types_dir: &Path,
|
cargo_types_dir: &Path,
|
||||||
cargo_skin_pk4_path: &Path,
|
cargo_skin_pk4_path: &Path,
|
||||||
|
) -> Result<CargoEconomySourceReport, Box<dyn std::error::Error>> {
|
||||||
|
inspect_cargo_economy_sources_with_bindings(cargo_types_dir, cargo_skin_pk4_path, None)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn inspect_cargo_economy_sources_with_bindings(
|
||||||
|
cargo_types_dir: &Path,
|
||||||
|
cargo_skin_pk4_path: &Path,
|
||||||
|
cargo_bindings_path: Option<&Path>,
|
||||||
) -> Result<CargoEconomySourceReport, Box<dyn std::error::Error>> {
|
) -> Result<CargoEconomySourceReport, Box<dyn std::error::Error>> {
|
||||||
let cargo_types = inspect_cargo_types_dir(cargo_types_dir)?;
|
let cargo_types = inspect_cargo_types_dir(cargo_types_dir)?;
|
||||||
let cargo_skins = inspect_cargo_skin_pk4(cargo_skin_pk4_path)?;
|
let cargo_skins = inspect_cargo_skin_pk4(cargo_skin_pk4_path)?;
|
||||||
Ok(build_cargo_economy_source_report(cargo_types, cargo_skins))
|
let cargo_bindings = load_cargo_bindings(cargo_bindings_path)?;
|
||||||
|
Ok(build_cargo_economy_source_report(
|
||||||
|
cargo_types,
|
||||||
|
cargo_skins,
|
||||||
|
cargo_bindings.as_deref(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_cargo_economy_source_report(
|
fn build_cargo_economy_source_report(
|
||||||
cargo_types: CargoTypeInspectionReport,
|
cargo_types: CargoTypeInspectionReport,
|
||||||
cargo_skins: CargoSkinInspectionReport,
|
cargo_skins: CargoSkinInspectionReport,
|
||||||
|
cargo_bindings: Option<&[CargoBindingRow]>,
|
||||||
) -> CargoEconomySourceReport {
|
) -> CargoEconomySourceReport {
|
||||||
let cargo_type_visible_names = cargo_types
|
let cargo_type_visible_names = cargo_types
|
||||||
.entries
|
.entries
|
||||||
|
|
@ -202,6 +267,11 @@ fn build_cargo_economy_source_report(
|
||||||
.difference(&cargo_type_visible_names)
|
.difference(&cargo_type_visible_names)
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
let live_registry_entries =
|
||||||
|
build_live_registry_entries(&cargo_types.entries, &cargo_skins.entries);
|
||||||
|
let production_selector =
|
||||||
|
cargo_bindings.map(|bindings| build_production_selector(bindings, &live_registry_entries));
|
||||||
|
let price_selector = build_price_selector(&live_registry_entries);
|
||||||
|
|
||||||
let mut notes = Vec::new();
|
let mut notes = Vec::new();
|
||||||
notes.push(format!(
|
notes.push(format!(
|
||||||
|
|
@ -241,12 +311,187 @@ fn build_cargo_economy_source_report(
|
||||||
visible_name_union_count,
|
visible_name_union_count,
|
||||||
cargo_type_only_visible_names,
|
cargo_type_only_visible_names,
|
||||||
cargo_skin_only_visible_names,
|
cargo_skin_only_visible_names,
|
||||||
|
live_registry_count: live_registry_entries.len(),
|
||||||
|
live_registry_entries,
|
||||||
|
production_selector,
|
||||||
|
price_selector,
|
||||||
notes,
|
notes,
|
||||||
cargo_type_entries: cargo_types.entries,
|
cargo_type_entries: cargo_types.entries,
|
||||||
cargo_skin_entries: cargo_skins.entries,
|
cargo_skin_entries: cargo_skins.entries,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn build_live_registry_entries(
|
||||||
|
cargo_type_entries: &[CargoTypeEntry],
|
||||||
|
cargo_skin_entries: &[CargoSkinDescriptorEntry],
|
||||||
|
) -> Vec<CargoLiveRegistryEntry> {
|
||||||
|
let mut visible_names = cargo_type_entries
|
||||||
|
.iter()
|
||||||
|
.map(|entry| entry.name.visible_name.clone())
|
||||||
|
.chain(
|
||||||
|
cargo_skin_entries
|
||||||
|
.iter()
|
||||||
|
.map(|entry| entry.name.visible_name.clone()),
|
||||||
|
)
|
||||||
|
.collect::<BTreeSet<_>>()
|
||||||
|
.into_iter()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
visible_names.sort();
|
||||||
|
|
||||||
|
visible_names
|
||||||
|
.into_iter()
|
||||||
|
.map(|visible_name| {
|
||||||
|
let mut raw_names = cargo_type_entries
|
||||||
|
.iter()
|
||||||
|
.filter(|entry| entry.name.visible_name == visible_name)
|
||||||
|
.map(|entry| entry.name.raw_name.clone())
|
||||||
|
.chain(
|
||||||
|
cargo_skin_entries
|
||||||
|
.iter()
|
||||||
|
.filter(|entry| entry.name.visible_name == visible_name)
|
||||||
|
.map(|entry| entry.name.raw_name.clone()),
|
||||||
|
)
|
||||||
|
.collect::<BTreeSet<_>>()
|
||||||
|
.into_iter()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
raw_names.sort();
|
||||||
|
|
||||||
|
let localized_string_ids = cargo_type_entries
|
||||||
|
.iter()
|
||||||
|
.filter(|entry| entry.name.visible_name == visible_name)
|
||||||
|
.filter_map(|entry| entry.name.localized_string_id)
|
||||||
|
.chain(
|
||||||
|
cargo_skin_entries
|
||||||
|
.iter()
|
||||||
|
.filter(|entry| entry.name.visible_name == visible_name)
|
||||||
|
.filter_map(|entry| entry.name.localized_string_id),
|
||||||
|
)
|
||||||
|
.collect::<BTreeSet<_>>()
|
||||||
|
.into_iter()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let mut source_kinds = Vec::new();
|
||||||
|
if cargo_type_entries
|
||||||
|
.iter()
|
||||||
|
.any(|entry| entry.name.visible_name == visible_name)
|
||||||
|
{
|
||||||
|
source_kinds.push(CargoRegistrySourceKind::CargoTypes);
|
||||||
|
}
|
||||||
|
if cargo_skin_entries
|
||||||
|
.iter()
|
||||||
|
.any(|entry| entry.name.visible_name == visible_name)
|
||||||
|
{
|
||||||
|
source_kinds.push(CargoRegistrySourceKind::CargoSkin);
|
||||||
|
}
|
||||||
|
|
||||||
|
CargoLiveRegistryEntry {
|
||||||
|
visible_name,
|
||||||
|
raw_names,
|
||||||
|
localized_string_ids,
|
||||||
|
source_kinds,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_production_selector(
|
||||||
|
bindings: &[CargoBindingRow],
|
||||||
|
live_registry_entries: &[CargoLiveRegistryEntry],
|
||||||
|
) -> CargoSelectorReport {
|
||||||
|
let mut rows = bindings
|
||||||
|
.iter()
|
||||||
|
.filter(|binding| binding.band == "cargo_production_named")
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
rows.sort_by_key(|binding| binding.binding_index);
|
||||||
|
|
||||||
|
let entries = rows
|
||||||
|
.into_iter()
|
||||||
|
.map(|binding| CargoSelectorEntry {
|
||||||
|
selector_index: binding.binding_index,
|
||||||
|
descriptor_id: Some(binding.descriptor_id),
|
||||||
|
visible_name: binding.cargo_name.clone(),
|
||||||
|
source_kinds: live_registry_entries
|
||||||
|
.iter()
|
||||||
|
.find(|entry| entry.visible_name == binding.cargo_name)
|
||||||
|
.map(|entry| entry.source_kinds.clone())
|
||||||
|
.unwrap_or_default(),
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
CargoSelectorReport {
|
||||||
|
selector_kind: "named_cargo_production".to_string(),
|
||||||
|
exact_resolution: entries.len() == NAMED_CARGO_PRODUCTION_DESCRIPTOR_ROW_COUNT,
|
||||||
|
selector_row_count: NAMED_CARGO_PRODUCTION_DESCRIPTOR_ROW_COUNT,
|
||||||
|
candidate_registry_count: live_registry_entries.len(),
|
||||||
|
notes: vec![
|
||||||
|
"This selector is grounded from the checked-in named cargo production bindings artifact."
|
||||||
|
.to_string(),
|
||||||
|
"The current grounded order matches the 50-row named cargo-production descriptor strip."
|
||||||
|
.to_string(),
|
||||||
|
],
|
||||||
|
entries,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_price_selector(live_registry_entries: &[CargoLiveRegistryEntry]) -> CargoSelectorReport {
|
||||||
|
let entries = live_registry_entries
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(index, entry)| CargoSelectorEntry {
|
||||||
|
selector_index: index + 1,
|
||||||
|
descriptor_id: None,
|
||||||
|
visible_name: entry.visible_name.clone(),
|
||||||
|
source_kinds: entry.source_kinds.clone(),
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let candidate_registry_count = entries.len();
|
||||||
|
let exact_resolution = candidate_registry_count == NAMED_CARGO_PRICE_DESCRIPTOR_ROW_COUNT;
|
||||||
|
let mut notes = Vec::new();
|
||||||
|
notes.push(
|
||||||
|
"This is the current merged visible-name registry, sorted lexicographically, not a claimed reproduction of the original price selector."
|
||||||
|
.to_string(),
|
||||||
|
);
|
||||||
|
if exact_resolution {
|
||||||
|
notes.push(
|
||||||
|
"The merged visible-name registry cardinality matches the 71-row named cargo-price descriptor strip."
|
||||||
|
.to_string(),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
notes.push(format!(
|
||||||
|
"The merged visible-name registry has {} entries, so the exact 71-row price-selector binding remains unresolved by static source recovery alone.",
|
||||||
|
candidate_registry_count
|
||||||
|
));
|
||||||
|
let excess =
|
||||||
|
candidate_registry_count.saturating_sub(NAMED_CARGO_PRICE_DESCRIPTOR_ROW_COUNT);
|
||||||
|
notes.push(format!(
|
||||||
|
"Current unresolved gap is {} excess candidate names relative to the descriptor strip.",
|
||||||
|
excess
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
CargoSelectorReport {
|
||||||
|
selector_kind: "named_cargo_price_candidate_registry".to_string(),
|
||||||
|
exact_resolution,
|
||||||
|
selector_row_count: NAMED_CARGO_PRICE_DESCRIPTOR_ROW_COUNT,
|
||||||
|
candidate_registry_count,
|
||||||
|
notes,
|
||||||
|
entries,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_cargo_bindings(
|
||||||
|
path: Option<&Path>,
|
||||||
|
) -> Result<Option<Vec<CargoBindingRow>>, Box<dyn std::error::Error>> {
|
||||||
|
let Some(path) = path else {
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
if !path.exists() {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
let artifact: CargoBindingArtifact = serde_json::from_str(&fs::read_to_string(path)?)?;
|
||||||
|
Ok(Some(artifact.bindings))
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_cargo_type_entry(
|
fn parse_cargo_type_entry(
|
||||||
file_name: &str,
|
file_name: &str,
|
||||||
bytes: &[u8],
|
bytes: &[u8],
|
||||||
|
|
@ -402,9 +647,10 @@ mod tests {
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
let report = build_cargo_economy_source_report(cargo_types, cargo_skins);
|
let report = build_cargo_economy_source_report(cargo_types, cargo_skins, None);
|
||||||
assert_eq!(report.shared_visible_name_count, 1);
|
assert_eq!(report.shared_visible_name_count, 1);
|
||||||
assert_eq!(report.visible_name_union_count, 3);
|
assert_eq!(report.visible_name_union_count, 3);
|
||||||
|
assert_eq!(report.live_registry_count, 3);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
report.cargo_type_only_visible_names,
|
report.cargo_type_only_visible_names,
|
||||||
vec!["Coal".to_string()]
|
vec!["Coal".to_string()]
|
||||||
|
|
@ -413,5 +659,79 @@ mod tests {
|
||||||
report.cargo_skin_only_visible_names,
|
report.cargo_skin_only_visible_names,
|
||||||
vec!["Beer".to_string()]
|
vec!["Beer".to_string()]
|
||||||
);
|
);
|
||||||
|
assert!(!report.price_selector.exact_resolution);
|
||||||
|
assert_eq!(report.price_selector.candidate_registry_count, 3);
|
||||||
|
assert!(report.production_selector.is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn builds_exact_production_selector_from_bindings() {
|
||||||
|
let cargo_types = CargoTypeInspectionReport {
|
||||||
|
directory_path: "CargoTypes".to_string(),
|
||||||
|
entry_count: 2,
|
||||||
|
unique_visible_name_count: 2,
|
||||||
|
notes: Vec::new(),
|
||||||
|
entries: vec![
|
||||||
|
CargoTypeEntry {
|
||||||
|
file_name: "Alcohol.cty".to_string(),
|
||||||
|
file_size: 16,
|
||||||
|
file_size_hex: "0x10".to_string(),
|
||||||
|
header_magic: CARGO_TYPE_MAGIC,
|
||||||
|
header_magic_hex: format!("0x{CARGO_TYPE_MAGIC:08x}"),
|
||||||
|
name: parse_cargo_name_token("Alcohol"),
|
||||||
|
},
|
||||||
|
CargoTypeEntry {
|
||||||
|
file_name: "Coal.cty".to_string(),
|
||||||
|
file_size: 16,
|
||||||
|
file_size_hex: "0x10".to_string(),
|
||||||
|
header_magic: CARGO_TYPE_MAGIC,
|
||||||
|
header_magic_hex: format!("0x{CARGO_TYPE_MAGIC:08x}"),
|
||||||
|
name: parse_cargo_name_token("Coal"),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
let cargo_skins = CargoSkinInspectionReport {
|
||||||
|
pk4_path: "Cargo106.PK4".to_string(),
|
||||||
|
entry_count: 1,
|
||||||
|
unique_visible_name_count: 1,
|
||||||
|
notes: Vec::new(),
|
||||||
|
entries: vec![CargoSkinDescriptorEntry {
|
||||||
|
pk4_entry_name: "Alcohol.dsc".to_string(),
|
||||||
|
payload_len: 20,
|
||||||
|
payload_len_hex: "0x14".to_string(),
|
||||||
|
descriptor_kind: "cargoSkin".to_string(),
|
||||||
|
name: parse_cargo_name_token("Alcohol"),
|
||||||
|
}],
|
||||||
|
};
|
||||||
|
let bindings = vec![
|
||||||
|
CargoBindingRow {
|
||||||
|
descriptor_id: 180,
|
||||||
|
band: "cargo_production_named".to_string(),
|
||||||
|
cargo_name: "Alcohol".to_string(),
|
||||||
|
binding_index: 1,
|
||||||
|
},
|
||||||
|
CargoBindingRow {
|
||||||
|
descriptor_id: 181,
|
||||||
|
band: "cargo_production_named".to_string(),
|
||||||
|
cargo_name: "Coal".to_string(),
|
||||||
|
binding_index: 2,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let report = build_cargo_economy_source_report(cargo_types, cargo_skins, Some(&bindings));
|
||||||
|
let selector = report
|
||||||
|
.production_selector
|
||||||
|
.expect("production selector should exist");
|
||||||
|
assert_eq!(selector.entries.len(), 2);
|
||||||
|
assert_eq!(selector.entries[0].descriptor_id, Some(180));
|
||||||
|
assert_eq!(selector.entries[0].visible_name, "Alcohol");
|
||||||
|
assert_eq!(
|
||||||
|
selector.entries[0].source_kinds,
|
||||||
|
vec![
|
||||||
|
CargoRegistrySourceKind::CargoTypes,
|
||||||
|
CargoRegistrySourceKind::CargoSkin
|
||||||
|
]
|
||||||
|
);
|
||||||
|
assert_eq!(selector.entries[1].visible_name, "Coal");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,12 @@ pub use campaign_exe::{
|
||||||
OBSERVED_CAMPAIGN_SCENARIO_NAMES, inspect_campaign_exe_bytes, inspect_campaign_exe_file,
|
OBSERVED_CAMPAIGN_SCENARIO_NAMES, inspect_campaign_exe_bytes, inspect_campaign_exe_file,
|
||||||
};
|
};
|
||||||
pub use economy::{
|
pub use economy::{
|
||||||
CARGO_TYPE_MAGIC, CargoEconomySourceReport, CargoNameToken, CargoSkinDescriptorEntry,
|
CARGO_TYPE_MAGIC, CargoEconomySourceReport, CargoLiveRegistryEntry, CargoNameToken,
|
||||||
|
CargoRegistrySourceKind, CargoSelectorEntry, CargoSelectorReport, CargoSkinDescriptorEntry,
|
||||||
CargoSkinInspectionReport, CargoTypeEntry, CargoTypeInspectionReport,
|
CargoSkinInspectionReport, CargoTypeEntry, CargoTypeInspectionReport,
|
||||||
NAMED_CARGO_PRICE_DESCRIPTOR_ROW_COUNT, NAMED_CARGO_PRODUCTION_DESCRIPTOR_ROW_COUNT,
|
NAMED_CARGO_PRICE_DESCRIPTOR_ROW_COUNT, NAMED_CARGO_PRODUCTION_DESCRIPTOR_ROW_COUNT,
|
||||||
inspect_cargo_economy_sources, inspect_cargo_skin_pk4, inspect_cargo_types_dir,
|
inspect_cargo_economy_sources, inspect_cargo_economy_sources_with_bindings,
|
||||||
|
inspect_cargo_skin_pk4, inspect_cargo_types_dir,
|
||||||
};
|
};
|
||||||
pub use import::{
|
pub use import::{
|
||||||
OVERLAY_IMPORT_DOCUMENT_FORMAT_VERSION, RuntimeOverlayImportDocument,
|
OVERLAY_IMPORT_DOCUMENT_FORMAT_VERSION, RuntimeOverlayImportDocument,
|
||||||
|
|
|
||||||
|
|
@ -134,8 +134,10 @@ The highest-value next passes are now:
|
||||||
checked-in offline cargo-source report at
|
checked-in offline cargo-source report at
|
||||||
`artifacts/exports/rt3-1.06/economy-cargo-sources.json` now parses both `CargoTypes` and the
|
`artifacts/exports/rt3-1.06/economy-cargo-sources.json` now parses both `CargoTypes` and the
|
||||||
`Cargo106.PK4` `cargoSkin` descriptors through rehosted code, normalizes localized
|
`Cargo106.PK4` `cargoSkin` descriptors through rehosted code, normalizes localized
|
||||||
`~####Name` tokens into visible names, and shows that the current 1.06 visible-name union is
|
`~####Name` tokens into visible names, builds a merged live cargo registry, and derives an exact
|
||||||
`80`, so source recovery alone still does not prove the live price-selector ordering
|
named cargo-production selector from the checked-in bindings; it also shows that the current
|
||||||
|
1.06 visible-name union is `80`, so source recovery alone still does not prove the live
|
||||||
|
price-selector ordering
|
||||||
- the add-building strip `503..519` is now explicitly classified as recovered shell-owned parity,
|
- the add-building strip `503..519` is now explicitly classified as recovered shell-owned parity,
|
||||||
with tracked fixture coverage, instead of generic unresolved descriptor residue
|
with tracked fixture coverage, instead of generic unresolved descriptor residue
|
||||||
- widen real packed-event executable coverage descriptor by descriptor after identity, target mask,
|
- widen real packed-event executable coverage descriptor by descriptor after identity, target mask,
|
||||||
|
|
|
||||||
|
|
@ -95,8 +95,10 @@ Implemented today:
|
||||||
a new checked-in offline cargo-source report at
|
a new checked-in offline cargo-source report at
|
||||||
`artifacts/exports/rt3-1.06/economy-cargo-sources.json` now parses both `CargoTypes` and the
|
`artifacts/exports/rt3-1.06/economy-cargo-sources.json` now parses both `CargoTypes` and the
|
||||||
`Cargo106.PK4` `cargoSkin` descriptors through rehosted code, normalizes localized
|
`Cargo106.PK4` `cargoSkin` descriptors through rehosted code, normalizes localized
|
||||||
`~####Name` tokens into visible names, and shows that the current 1.06 visible-name union is
|
`~####Name` tokens into visible names, builds a merged live cargo registry, and derives an exact
|
||||||
`80`, so source recovery alone still does not prove the live price-selector ordering
|
named cargo-production selector from the checked-in bindings; it also shows that the current
|
||||||
|
1.06 visible-name union is `80`, so source recovery alone still does not prove the live
|
||||||
|
price-selector ordering
|
||||||
- the add-building strip `503..519` is now explicitly classified as recovered shell-owned parity
|
- the add-building strip `503..519` is now explicitly classified as recovered shell-owned parity
|
||||||
with tracked fixture coverage, not generic unresolved descriptor residue
|
with tracked fixture coverage, not generic unresolved descriptor residue
|
||||||
- a minimal event-owned train surface and an opaque economic-status lane now exist in runtime
|
- a minimal event-owned train surface and an opaque economic-status lane now exist in runtime
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue