Execute aggregate cargo economics descriptors
This commit is contained in:
parent
51a7bbd756
commit
f623c6dcc9
18 changed files with 1599 additions and 63 deletions
|
|
@ -45,7 +45,12 @@ descriptor residue. The recovered whole-game scalar economy/performance strip `5
|
|||
bounded runtime landing surface too: representative descriptors import into
|
||||
`RuntimeState.world_scalar_overrides` through stable normalized keys such as
|
||||
`world.build_stations_cost`, `world.track_maintenance_cost`, `world.all_engine_speeds`, and
|
||||
`world.hotel_revenue`. The first grounded
|
||||
`world.hotel_revenue`. The grounded aggregate cargo-economics descriptors now have bounded
|
||||
runtime landing surfaces too: descriptor `105` `All Cargo Prices` plus descriptors `177..179`
|
||||
`All Cargo Production` / `All Factory Production` / `All Farm/Mine Production` import into
|
||||
event-owned cargo override state, while the named cargo-price and named cargo-production strips
|
||||
remain explicit `blocked_evidence_blocked_descriptor` parity until descriptor ordering is pinned
|
||||
more strongly. The first grounded
|
||||
condition-side unlock now exists for negative-sentinel `raw_condition_id = -1` company scopes, and
|
||||
the first ordinary nonnegative condition batch now executes too: numeric-threshold company
|
||||
finance, company track, aggregate territory track, and company-territory track rows can import
|
||||
|
|
|
|||
|
|
@ -954,8 +954,8 @@
|
|||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"runtime_key": null,
|
||||
"runtime_status": "evidence_blocked",
|
||||
"executable_in_runtime": false
|
||||
"runtime_status": "executable",
|
||||
"executable_in_runtime": true
|
||||
},
|
||||
{
|
||||
"descriptor_id": 106,
|
||||
|
|
@ -1602,8 +1602,8 @@
|
|||
"target_mask_bits": 15,
|
||||
"parameter_family": "cargo_production_scalar",
|
||||
"runtime_key": null,
|
||||
"runtime_status": "evidence_blocked",
|
||||
"executable_in_runtime": false
|
||||
"runtime_status": "executable",
|
||||
"executable_in_runtime": true
|
||||
},
|
||||
{
|
||||
"descriptor_id": 178,
|
||||
|
|
@ -1611,8 +1611,8 @@
|
|||
"target_mask_bits": 15,
|
||||
"parameter_family": "cargo_production_scalar",
|
||||
"runtime_key": null,
|
||||
"runtime_status": "evidence_blocked",
|
||||
"executable_in_runtime": false
|
||||
"runtime_status": "executable",
|
||||
"executable_in_runtime": true
|
||||
},
|
||||
{
|
||||
"descriptor_id": 179,
|
||||
|
|
@ -1620,8 +1620,8 @@
|
|||
"target_mask_bits": 15,
|
||||
"parameter_family": "cargo_production_scalar",
|
||||
"runtime_key": null,
|
||||
"runtime_status": "evidence_blocked",
|
||||
"executable_in_runtime": false
|
||||
"runtime_status": "executable",
|
||||
"executable_in_runtime": true
|
||||
},
|
||||
{
|
||||
"descriptor_id": 180,
|
||||
|
|
@ -2079,8 +2079,8 @@
|
|||
"target_mask_bits": 15,
|
||||
"parameter_family": "cargo_production_scalar",
|
||||
"runtime_key": null,
|
||||
"runtime_status": "evidence_blocked",
|
||||
"executable_in_runtime": false
|
||||
"runtime_status": "executable",
|
||||
"executable_in_runtime": true
|
||||
},
|
||||
{
|
||||
"descriptor_id": 231,
|
||||
|
|
@ -2088,8 +2088,8 @@
|
|||
"target_mask_bits": 15,
|
||||
"parameter_family": "cargo_production_scalar",
|
||||
"runtime_key": null,
|
||||
"runtime_status": "evidence_blocked",
|
||||
"executable_in_runtime": false
|
||||
"runtime_status": "executable",
|
||||
"executable_in_runtime": true
|
||||
},
|
||||
{
|
||||
"descriptor_id": 232,
|
||||
|
|
@ -2097,8 +2097,8 @@
|
|||
"target_mask_bits": 15,
|
||||
"parameter_family": "cargo_production_scalar",
|
||||
"runtime_key": null,
|
||||
"runtime_status": "evidence_blocked",
|
||||
"executable_in_runtime": false
|
||||
"runtime_status": "executable",
|
||||
"executable_in_runtime": true
|
||||
},
|
||||
{
|
||||
"descriptor_id": 233,
|
||||
|
|
@ -2106,8 +2106,8 @@
|
|||
"target_mask_bits": 15,
|
||||
"parameter_family": "cargo_production_scalar",
|
||||
"runtime_key": null,
|
||||
"runtime_status": "evidence_blocked",
|
||||
"executable_in_runtime": false
|
||||
"runtime_status": "executable",
|
||||
"executable_in_runtime": true
|
||||
},
|
||||
{
|
||||
"descriptor_id": 234,
|
||||
|
|
@ -2115,8 +2115,8 @@
|
|||
"target_mask_bits": 15,
|
||||
"parameter_family": "cargo_production_scalar",
|
||||
"runtime_key": null,
|
||||
"runtime_status": "evidence_blocked",
|
||||
"executable_in_runtime": false
|
||||
"runtime_status": "executable",
|
||||
"executable_in_runtime": true
|
||||
},
|
||||
{
|
||||
"descriptor_id": 235,
|
||||
|
|
@ -2124,8 +2124,8 @@
|
|||
"target_mask_bits": 15,
|
||||
"parameter_family": "cargo_production_scalar",
|
||||
"runtime_key": null,
|
||||
"runtime_status": "evidence_blocked",
|
||||
"executable_in_runtime": false
|
||||
"runtime_status": "executable",
|
||||
"executable_in_runtime": true
|
||||
},
|
||||
{
|
||||
"descriptor_id": 236,
|
||||
|
|
@ -2133,8 +2133,8 @@
|
|||
"target_mask_bits": 15,
|
||||
"parameter_family": "cargo_production_scalar",
|
||||
"runtime_key": null,
|
||||
"runtime_status": "evidence_blocked",
|
||||
"executable_in_runtime": false
|
||||
"runtime_status": "executable",
|
||||
"executable_in_runtime": true
|
||||
},
|
||||
{
|
||||
"descriptor_id": 237,
|
||||
|
|
@ -2142,8 +2142,8 @@
|
|||
"target_mask_bits": 15,
|
||||
"parameter_family": "cargo_production_scalar",
|
||||
"runtime_key": null,
|
||||
"runtime_status": "evidence_blocked",
|
||||
"executable_in_runtime": false
|
||||
"runtime_status": "executable",
|
||||
"executable_in_runtime": true
|
||||
},
|
||||
{
|
||||
"descriptor_id": 238,
|
||||
|
|
@ -2151,8 +2151,8 @@
|
|||
"target_mask_bits": 15,
|
||||
"parameter_family": "cargo_production_scalar",
|
||||
"runtime_key": null,
|
||||
"runtime_status": "evidence_blocked",
|
||||
"executable_in_runtime": false
|
||||
"runtime_status": "executable",
|
||||
"executable_in_runtime": true
|
||||
},
|
||||
{
|
||||
"descriptor_id": 239,
|
||||
|
|
@ -2160,8 +2160,8 @@
|
|||
"target_mask_bits": 15,
|
||||
"parameter_family": "cargo_production_scalar",
|
||||
"runtime_key": null,
|
||||
"runtime_status": "evidence_blocked",
|
||||
"executable_in_runtime": false
|
||||
"runtime_status": "executable",
|
||||
"executable_in_runtime": true
|
||||
},
|
||||
{
|
||||
"descriptor_id": 240,
|
||||
|
|
@ -2169,8 +2169,8 @@
|
|||
"target_mask_bits": 15,
|
||||
"parameter_family": "cargo_production_scalar",
|
||||
"runtime_key": null,
|
||||
"runtime_status": "evidence_blocked",
|
||||
"executable_in_runtime": false
|
||||
"runtime_status": "executable",
|
||||
"executable_in_runtime": true
|
||||
},
|
||||
{
|
||||
"descriptor_id": 241,
|
||||
|
|
|
|||
|
|
@ -4479,6 +4479,11 @@ mod tests {
|
|||
let world_scalar_override_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(
|
||||
"../../fixtures/runtime/packed-event-world-scalar-override-save-slice-fixture.json",
|
||||
);
|
||||
let cargo_economics_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("../../fixtures/runtime/packed-event-cargo-economics-save-slice-fixture.json");
|
||||
let cargo_economics_parity_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(
|
||||
"../../fixtures/runtime/packed-event-cargo-economics-parity-save-slice-fixture.json",
|
||||
);
|
||||
let world_scalar_condition_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(
|
||||
"../../fixtures/runtime/packed-event-world-scalar-condition-save-slice-fixture.json",
|
||||
);
|
||||
|
|
@ -4590,6 +4595,10 @@ mod tests {
|
|||
.expect("save-slice-backed executable world-scalar fixture should summarize");
|
||||
run_runtime_summarize_fixture(&world_scalar_override_fixture)
|
||||
.expect("save-slice-backed world-scalar override fixture should summarize");
|
||||
run_runtime_summarize_fixture(&cargo_economics_fixture)
|
||||
.expect("save-slice-backed cargo-economics fixture should summarize");
|
||||
run_runtime_summarize_fixture(&cargo_economics_parity_fixture)
|
||||
.expect("save-slice-backed cargo-economics parity fixture should summarize");
|
||||
run_runtime_summarize_fixture(&world_scalar_condition_fixture)
|
||||
.expect("save-slice-backed executable world-scalar condition fixture should summarize");
|
||||
run_runtime_summarize_fixture(&world_scalar_condition_parity_fixture)
|
||||
|
|
|
|||
|
|
@ -189,6 +189,12 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
@ -377,6 +383,12 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
|
|||
|
|
@ -5,10 +5,11 @@ use serde::{Deserialize, Serialize};
|
|||
|
||||
use crate::persistence::{load_runtime_snapshot_document, validate_runtime_snapshot_document};
|
||||
use crate::{
|
||||
CalendarPoint, RuntimeCargoCatalogEntry, RuntimeChairmanProfile, RuntimeChairmanTarget,
|
||||
RuntimeCompany, RuntimeCompanyConditionTestScope, RuntimeCompanyControllerKind,
|
||||
RuntimeCompanyTarget, RuntimeCondition, RuntimeEffect, RuntimeEventRecord,
|
||||
RuntimeEventRecordTemplate, RuntimeLocomotiveCatalogEntry, RuntimePackedEventCollectionSummary,
|
||||
CalendarPoint, RuntimeCargoCatalogEntry, RuntimeCargoPriceTarget, RuntimeCargoProductionTarget,
|
||||
RuntimeChairmanProfile, RuntimeChairmanTarget, RuntimeCompany,
|
||||
RuntimeCompanyConditionTestScope, RuntimeCompanyControllerKind, RuntimeCompanyTarget,
|
||||
RuntimeCondition, RuntimeEffect, RuntimeEventRecord, RuntimeEventRecordTemplate,
|
||||
RuntimeLocomotiveCatalogEntry, RuntimePackedEventCollectionSummary,
|
||||
RuntimePackedEventCompactControlSummary, RuntimePackedEventConditionRowSummary,
|
||||
RuntimePackedEventGroupedEffectRowSummary, RuntimePackedEventNegativeSentinelScopeSummary,
|
||||
RuntimePackedEventRecordSummary, RuntimePackedEventTextBandSummary,
|
||||
|
|
@ -105,6 +106,12 @@ struct SaveSliceProjection {
|
|||
locomotive_catalog: Option<Vec<RuntimeLocomotiveCatalogEntry>>,
|
||||
cargo_catalog: Option<Vec<RuntimeCargoCatalogEntry>>,
|
||||
named_locomotive_cost: BTreeMap<String, u32>,
|
||||
all_cargo_price_override: Option<u32>,
|
||||
named_cargo_price_overrides: BTreeMap<String, u32>,
|
||||
all_cargo_production_override: Option<u32>,
|
||||
factory_cargo_production_override: Option<u32>,
|
||||
farm_mine_cargo_production_override: Option<u32>,
|
||||
named_cargo_production_overrides: BTreeMap<String, u32>,
|
||||
cargo_production_overrides: BTreeMap<u32, u32>,
|
||||
world_scalar_overrides: BTreeMap<String, i64>,
|
||||
special_conditions: BTreeMap<String, u32>,
|
||||
|
|
@ -277,6 +284,12 @@ pub fn project_save_slice_to_runtime_state_import(
|
|||
candidate_availability: projection.candidate_availability,
|
||||
named_locomotive_availability: projection.named_locomotive_availability,
|
||||
named_locomotive_cost: projection.named_locomotive_cost,
|
||||
all_cargo_price_override: projection.all_cargo_price_override,
|
||||
named_cargo_price_overrides: projection.named_cargo_price_overrides,
|
||||
all_cargo_production_override: projection.all_cargo_production_override,
|
||||
factory_cargo_production_override: projection.factory_cargo_production_override,
|
||||
farm_mine_cargo_production_override: projection.farm_mine_cargo_production_override,
|
||||
named_cargo_production_overrides: projection.named_cargo_production_overrides,
|
||||
cargo_production_overrides: projection.cargo_production_overrides,
|
||||
world_scalar_overrides: projection.world_scalar_overrides,
|
||||
special_conditions: projection.special_conditions,
|
||||
|
|
@ -365,6 +378,12 @@ pub fn project_save_slice_overlay_to_runtime_state_import(
|
|||
candidate_availability: projection.candidate_availability,
|
||||
named_locomotive_availability: projection.named_locomotive_availability,
|
||||
named_locomotive_cost: base_state.named_locomotive_cost.clone(),
|
||||
all_cargo_price_override: base_state.all_cargo_price_override,
|
||||
named_cargo_price_overrides: base_state.named_cargo_price_overrides.clone(),
|
||||
all_cargo_production_override: base_state.all_cargo_production_override,
|
||||
factory_cargo_production_override: base_state.factory_cargo_production_override,
|
||||
farm_mine_cargo_production_override: base_state.farm_mine_cargo_production_override,
|
||||
named_cargo_production_overrides: base_state.named_cargo_production_overrides.clone(),
|
||||
cargo_production_overrides: base_state.cargo_production_overrides.clone(),
|
||||
world_scalar_overrides: base_state.world_scalar_overrides.clone(),
|
||||
special_conditions: projection.special_conditions,
|
||||
|
|
@ -874,6 +893,12 @@ fn project_save_slice_components(
|
|||
};
|
||||
|
||||
let named_locomotive_cost = BTreeMap::new();
|
||||
let all_cargo_price_override = None;
|
||||
let named_cargo_price_overrides = BTreeMap::new();
|
||||
let all_cargo_production_override = None;
|
||||
let factory_cargo_production_override = None;
|
||||
let farm_mine_cargo_production_override = None;
|
||||
let named_cargo_production_overrides = BTreeMap::new();
|
||||
let cargo_production_overrides = BTreeMap::new();
|
||||
let world_scalar_overrides = BTreeMap::new();
|
||||
|
||||
|
|
@ -951,6 +976,12 @@ fn project_save_slice_components(
|
|||
locomotive_catalog,
|
||||
cargo_catalog,
|
||||
named_locomotive_cost,
|
||||
all_cargo_price_override,
|
||||
named_cargo_price_overrides,
|
||||
all_cargo_production_override,
|
||||
factory_cargo_production_override,
|
||||
farm_mine_cargo_production_override,
|
||||
named_cargo_production_overrides,
|
||||
cargo_production_overrides,
|
||||
world_scalar_overrides,
|
||||
special_conditions,
|
||||
|
|
@ -1321,6 +1352,10 @@ fn lower_contextual_real_grouped_effects(
|
|||
if real_grouped_row_is_unsupported_chairman_target_scope(row) {
|
||||
return Err(ImportBlocker::ChairmanTargetScope);
|
||||
}
|
||||
if let Some(effect) = lower_contextual_cargo_price_effect(row)? {
|
||||
effects.push(effect);
|
||||
continue;
|
||||
}
|
||||
if let Some(effect) = lower_contextual_world_scalar_override_effect(row)? {
|
||||
effects.push(effect);
|
||||
continue;
|
||||
|
|
@ -1356,6 +1391,27 @@ fn lower_contextual_real_grouped_effects(
|
|||
Ok(effects)
|
||||
}
|
||||
|
||||
fn lower_contextual_cargo_price_effect(
|
||||
row: &SmpLoadedPackedEventGroupedEffectRowSummary,
|
||||
) -> Result<Option<RuntimeEffect>, ImportBlocker> {
|
||||
if row.parameter_family.as_deref() != Some("cargo_price_scalar") {
|
||||
return Ok(None);
|
||||
}
|
||||
if row.row_shape != "scalar_assignment" {
|
||||
return Ok(None);
|
||||
}
|
||||
let Some(value) = u32::try_from(row.raw_scalar_value).ok() else {
|
||||
return Ok(None);
|
||||
};
|
||||
if row.descriptor_id != 105 {
|
||||
return Ok(None);
|
||||
}
|
||||
Ok(Some(RuntimeEffect::SetCargoPriceOverride {
|
||||
target: RuntimeCargoPriceTarget::All,
|
||||
value,
|
||||
}))
|
||||
}
|
||||
|
||||
fn lower_contextual_world_scalar_override_effect(
|
||||
row: &SmpLoadedPackedEventGroupedEffectRowSummary,
|
||||
) -> Result<Option<RuntimeEffect>, ImportBlocker> {
|
||||
|
|
@ -1419,13 +1475,27 @@ fn lower_contextual_cargo_production_effect(
|
|||
let Some(value) = u32::try_from(row.raw_scalar_value).ok() else {
|
||||
return Ok(None);
|
||||
};
|
||||
let Some(slot) = row.descriptor_id.checked_sub(229) else {
|
||||
return Ok(None);
|
||||
};
|
||||
if !(1..=11).contains(&slot) {
|
||||
return Ok(None);
|
||||
match row.descriptor_id {
|
||||
177 => Ok(Some(RuntimeEffect::SetCargoProductionOverride {
|
||||
target: RuntimeCargoProductionTarget::All,
|
||||
value,
|
||||
})),
|
||||
178 => Ok(Some(RuntimeEffect::SetCargoProductionOverride {
|
||||
target: RuntimeCargoProductionTarget::Factory,
|
||||
value,
|
||||
})),
|
||||
179 => Ok(Some(RuntimeEffect::SetCargoProductionOverride {
|
||||
target: RuntimeCargoProductionTarget::FarmMine,
|
||||
value,
|
||||
})),
|
||||
230..=240 => {
|
||||
let Some(slot) = row.descriptor_id.checked_sub(229) else {
|
||||
return Ok(None);
|
||||
};
|
||||
Ok(Some(RuntimeEffect::SetCargoProductionSlot { slot, value }))
|
||||
}
|
||||
_ => Ok(None),
|
||||
}
|
||||
Ok(Some(RuntimeEffect::SetCargoProductionSlot { slot, value }))
|
||||
}
|
||||
|
||||
fn lower_contextual_territory_access_cost_effect(
|
||||
|
|
@ -1736,6 +1806,18 @@ fn lower_condition_targets_in_effect(
|
|||
value: *value,
|
||||
}
|
||||
}
|
||||
RuntimeEffect::SetCargoPriceOverride { target, value } => {
|
||||
RuntimeEffect::SetCargoPriceOverride {
|
||||
target: target.clone(),
|
||||
value: *value,
|
||||
}
|
||||
}
|
||||
RuntimeEffect::SetCargoProductionOverride { target, value } => {
|
||||
RuntimeEffect::SetCargoProductionOverride {
|
||||
target: target.clone(),
|
||||
value: *value,
|
||||
}
|
||||
}
|
||||
RuntimeEffect::SetCargoProductionSlot { slot, value } => {
|
||||
RuntimeEffect::SetCargoProductionSlot {
|
||||
slot: *slot,
|
||||
|
|
@ -2383,6 +2465,18 @@ fn smp_runtime_effect_to_runtime_effect(
|
|||
value: *value,
|
||||
})
|
||||
}
|
||||
RuntimeEffect::SetCargoPriceOverride { target, value } => {
|
||||
Ok(RuntimeEffect::SetCargoPriceOverride {
|
||||
target: target.clone(),
|
||||
value: *value,
|
||||
})
|
||||
}
|
||||
RuntimeEffect::SetCargoProductionOverride { target, value } => {
|
||||
Ok(RuntimeEffect::SetCargoProductionOverride {
|
||||
target: target.clone(),
|
||||
value: *value,
|
||||
})
|
||||
}
|
||||
RuntimeEffect::SetWorldScalarOverride { key, value } => {
|
||||
Ok(RuntimeEffect::SetWorldScalarOverride {
|
||||
key: key.clone(),
|
||||
|
|
@ -2888,10 +2982,21 @@ fn real_grouped_row_is_unsupported_executable_descriptor_variant(
|
|||
8 | 108 | 109 | 122 => row.row_shape != "scalar_assignment",
|
||||
13 | 14 => !(row.row_shape == "bool_toggle" && row.raw_scalar_value != 0),
|
||||
56 | 57 => row.row_shape != "scalar_assignment",
|
||||
_ => {
|
||||
row.parameter_family.as_deref() == Some("world_scalar_override")
|
||||
&& row.row_shape != "scalar_assignment"
|
||||
}
|
||||
_ => match row.parameter_family.as_deref() {
|
||||
Some("world_scalar_override") => row.row_shape != "scalar_assignment",
|
||||
Some("cargo_price_scalar") => {
|
||||
row.descriptor_id == 105
|
||||
&& !(row.row_shape == "scalar_assignment" && row.raw_scalar_value >= 0)
|
||||
}
|
||||
Some("cargo_production_scalar") => {
|
||||
matches!(row.descriptor_id, 177 | 178 | 179 | 230..=240)
|
||||
&& !(row.row_shape == "scalar_assignment" && row.raw_scalar_value >= 0)
|
||||
}
|
||||
Some("territory_access_cost_scalar") => {
|
||||
!(row.row_shape == "scalar_assignment" && row.raw_scalar_value >= 0)
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3093,6 +3198,8 @@ fn runtime_effect_uses_condition_true_company(effect: &RuntimeEffect) -> bool {
|
|||
| RuntimeEffect::SetNamedLocomotiveAvailability { .. }
|
||||
| RuntimeEffect::SetNamedLocomotiveAvailabilityValue { .. }
|
||||
| RuntimeEffect::SetNamedLocomotiveCost { .. }
|
||||
| RuntimeEffect::SetCargoPriceOverride { .. }
|
||||
| RuntimeEffect::SetCargoProductionOverride { .. }
|
||||
| RuntimeEffect::SetCargoProductionSlot { .. }
|
||||
| RuntimeEffect::SetTerritoryAccessCost { .. }
|
||||
| RuntimeEffect::SetSpecialCondition { .. }
|
||||
|
|
@ -3203,6 +3310,8 @@ fn runtime_effect_company_target_import_blocker(
|
|||
| RuntimeEffect::SetNamedLocomotiveAvailability { .. }
|
||||
| RuntimeEffect::SetNamedLocomotiveAvailabilityValue { .. }
|
||||
| RuntimeEffect::SetNamedLocomotiveCost { .. }
|
||||
| RuntimeEffect::SetCargoPriceOverride { .. }
|
||||
| RuntimeEffect::SetCargoProductionOverride { .. }
|
||||
| RuntimeEffect::SetCargoProductionSlot { .. }
|
||||
| RuntimeEffect::SetTerritoryAccessCost { .. }
|
||||
| RuntimeEffect::SetSpecialCondition { .. }
|
||||
|
|
@ -3552,6 +3661,12 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
@ -4299,6 +4414,145 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
fn real_all_cargo_price_row(value: i32) -> crate::SmpLoadedPackedEventGroupedEffectRowSummary {
|
||||
crate::SmpLoadedPackedEventGroupedEffectRowSummary {
|
||||
group_index: 0,
|
||||
row_index: 0,
|
||||
descriptor_id: 105,
|
||||
descriptor_label: Some("All Cargo Prices".to_string()),
|
||||
target_mask_bits: Some(0x08),
|
||||
parameter_family: Some("cargo_price_scalar".to_string()),
|
||||
grouped_target_subject: None,
|
||||
grouped_target_scope: None,
|
||||
opcode: 3,
|
||||
raw_scalar_value: value,
|
||||
value_byte_0x09: 0,
|
||||
value_dword_0x0d: 0,
|
||||
value_byte_0x11: 0,
|
||||
value_byte_0x12: 0,
|
||||
value_word_0x14: 0,
|
||||
value_word_0x16: 0,
|
||||
row_shape: "scalar_assignment".to_string(),
|
||||
semantic_family: Some("scalar_assignment".to_string()),
|
||||
semantic_preview: Some(format!("Set All Cargo Prices to {value}")),
|
||||
recovered_cargo_slot: None,
|
||||
recovered_cargo_class: None,
|
||||
recovered_locomotive_id: None,
|
||||
locomotive_name: None,
|
||||
notes: vec![
|
||||
"descriptor recovered from checked-in EventEffects semantic catalog".to_string(),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
fn real_named_cargo_price_row(
|
||||
descriptor_id: u32,
|
||||
value: i32,
|
||||
) -> crate::SmpLoadedPackedEventGroupedEffectRowSummary {
|
||||
crate::SmpLoadedPackedEventGroupedEffectRowSummary {
|
||||
group_index: 0,
|
||||
row_index: 0,
|
||||
descriptor_id,
|
||||
descriptor_label: Some("Unknown Cargo Price".to_string()),
|
||||
target_mask_bits: Some(0x08),
|
||||
parameter_family: Some("cargo_price_scalar".to_string()),
|
||||
grouped_target_subject: None,
|
||||
grouped_target_scope: None,
|
||||
opcode: 3,
|
||||
raw_scalar_value: value,
|
||||
value_byte_0x09: 0,
|
||||
value_dword_0x0d: 0,
|
||||
value_byte_0x11: 0,
|
||||
value_byte_0x12: 0,
|
||||
value_word_0x14: 0,
|
||||
value_word_0x16: 0,
|
||||
row_shape: "scalar_assignment".to_string(),
|
||||
semantic_family: Some("scalar_assignment".to_string()),
|
||||
semantic_preview: Some(format!("Set Unknown Cargo Price to {value}")),
|
||||
recovered_cargo_slot: None,
|
||||
recovered_cargo_class: None,
|
||||
recovered_locomotive_id: None,
|
||||
locomotive_name: None,
|
||||
notes: vec![
|
||||
"descriptor recovered from checked-in EventEffects semantic catalog".to_string(),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
fn real_aggregate_cargo_production_row(
|
||||
descriptor_id: u32,
|
||||
value: i32,
|
||||
) -> crate::SmpLoadedPackedEventGroupedEffectRowSummary {
|
||||
let (label, recovered_cargo_class) = match descriptor_id {
|
||||
177 => ("All Cargo Production", None),
|
||||
178 => ("All Factory Production", Some("factory".to_string())),
|
||||
179 => ("All Farm/Mine Production", Some("farm_mine".to_string())),
|
||||
_ => ("Unknown Cargo Production", None),
|
||||
};
|
||||
crate::SmpLoadedPackedEventGroupedEffectRowSummary {
|
||||
group_index: 0,
|
||||
row_index: 0,
|
||||
descriptor_id,
|
||||
descriptor_label: Some(label.to_string()),
|
||||
target_mask_bits: Some(0x08),
|
||||
parameter_family: Some("cargo_production_scalar".to_string()),
|
||||
grouped_target_subject: None,
|
||||
grouped_target_scope: None,
|
||||
opcode: 3,
|
||||
raw_scalar_value: value,
|
||||
value_byte_0x09: 0,
|
||||
value_dword_0x0d: 0,
|
||||
value_byte_0x11: 0,
|
||||
value_byte_0x12: 0,
|
||||
value_word_0x14: 0,
|
||||
value_word_0x16: 0,
|
||||
row_shape: "scalar_assignment".to_string(),
|
||||
semantic_family: Some("scalar_assignment".to_string()),
|
||||
semantic_preview: Some(format!("Set {label} to {value}")),
|
||||
recovered_cargo_slot: None,
|
||||
recovered_cargo_class,
|
||||
recovered_locomotive_id: None,
|
||||
locomotive_name: None,
|
||||
notes: vec![
|
||||
"descriptor recovered from checked-in EventEffects semantic catalog".to_string(),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
fn real_named_cargo_production_row(
|
||||
descriptor_id: u32,
|
||||
value: i32,
|
||||
) -> crate::SmpLoadedPackedEventGroupedEffectRowSummary {
|
||||
crate::SmpLoadedPackedEventGroupedEffectRowSummary {
|
||||
group_index: 0,
|
||||
row_index: 0,
|
||||
descriptor_id,
|
||||
descriptor_label: Some("Unknown Cargo Production".to_string()),
|
||||
target_mask_bits: Some(0x08),
|
||||
parameter_family: Some("cargo_production_scalar".to_string()),
|
||||
grouped_target_subject: None,
|
||||
grouped_target_scope: None,
|
||||
opcode: 3,
|
||||
raw_scalar_value: value,
|
||||
value_byte_0x09: 0,
|
||||
value_dword_0x0d: 0,
|
||||
value_byte_0x11: 0,
|
||||
value_byte_0x12: 0,
|
||||
value_word_0x14: 0,
|
||||
value_word_0x16: 0,
|
||||
row_shape: "scalar_assignment".to_string(),
|
||||
semantic_family: Some("scalar_assignment".to_string()),
|
||||
semantic_preview: Some(format!("Set Unknown Cargo Production to {value}")),
|
||||
recovered_cargo_slot: None,
|
||||
recovered_cargo_class: None,
|
||||
recovered_locomotive_id: None,
|
||||
locomotive_name: None,
|
||||
notes: vec![
|
||||
"descriptor recovered from checked-in EventEffects semantic catalog".to_string(),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
fn real_territory_access_cost_row(
|
||||
value: i32,
|
||||
) -> crate::SmpLoadedPackedEventGroupedEffectRowSummary {
|
||||
|
|
@ -6738,6 +6992,12 @@ mod tests {
|
|||
("Locomotive 112".to_string(), 1),
|
||||
]),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
@ -7144,6 +7404,12 @@ mod tests {
|
|||
("Locomotive 1".to_string(), 100000),
|
||||
("Locomotive 101".to_string(), 200000),
|
||||
]),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
@ -7409,6 +7675,337 @@ mod tests {
|
|||
assert_eq!(import.state.cargo_production_overrides.get(&1), Some(&125));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn imports_aggregate_cargo_economics_rows_into_runtime_records() {
|
||||
let save_slice = SmpLoadedSaveSlice {
|
||||
file_extension_hint: Some("gms".to_string()),
|
||||
container_profile_family: Some("rt3-classic-save-container-v1".to_string()),
|
||||
mechanism_family: "classic-save-rehydrate-v1".to_string(),
|
||||
mechanism_confidence: "grounded".to_string(),
|
||||
trailer_family: None,
|
||||
bridge_family: None,
|
||||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
cargo_catalog: None,
|
||||
company_roster: None,
|
||||
chairman_profile_table: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
mechanism_family: "classic-save-rehydrate-v1".to_string(),
|
||||
mechanism_confidence: "grounded".to_string(),
|
||||
container_profile_family: Some("rt3-classic-save-container-v1".to_string()),
|
||||
metadata_tag_offset: 0x7100,
|
||||
records_tag_offset: 0x7200,
|
||||
close_tag_offset: 0x7600,
|
||||
packed_state_version: 0x3e9,
|
||||
packed_state_version_hex: "0x000003e9".to_string(),
|
||||
live_id_bound: 38,
|
||||
live_record_count: 1,
|
||||
live_entry_ids: vec![38],
|
||||
decoded_record_count: 1,
|
||||
imported_runtime_record_count: 0,
|
||||
records: vec![crate::SmpLoadedPackedEventRecordSummary {
|
||||
record_index: 0,
|
||||
live_entry_id: 38,
|
||||
payload_offset: Some(0x7202),
|
||||
payload_len: Some(144),
|
||||
decode_status: "parity_only".to_string(),
|
||||
payload_family: "real_packed_v1".to_string(),
|
||||
trigger_kind: Some(7),
|
||||
active: None,
|
||||
marks_collection_dirty: None,
|
||||
one_shot: Some(false),
|
||||
compact_control: Some(real_compact_control()),
|
||||
text_bands: vec![],
|
||||
standalone_condition_row_count: 0,
|
||||
standalone_condition_rows: vec![],
|
||||
negative_sentinel_scope: None,
|
||||
grouped_effect_row_counts: vec![4, 0, 0, 0],
|
||||
grouped_effect_rows: vec![
|
||||
real_all_cargo_price_row(180),
|
||||
real_aggregate_cargo_production_row(177, 210),
|
||||
real_aggregate_cargo_production_row(178, 225),
|
||||
real_aggregate_cargo_production_row(179, 175),
|
||||
],
|
||||
decoded_conditions: Vec::new(),
|
||||
decoded_actions: vec![],
|
||||
executable_import_ready: false,
|
||||
notes: vec![
|
||||
"grounded aggregate cargo economics descriptors import through bounded override surfaces"
|
||||
.to_string(),
|
||||
],
|
||||
}],
|
||||
}),
|
||||
notes: vec![],
|
||||
};
|
||||
|
||||
let mut import = project_save_slice_to_runtime_state_import(
|
||||
&save_slice,
|
||||
"packed-events-aggregate-cargo-economics",
|
||||
None,
|
||||
)
|
||||
.expect("save slice should project");
|
||||
|
||||
assert_eq!(import.state.event_runtime_records.len(), 1);
|
||||
assert_eq!(
|
||||
import
|
||||
.state
|
||||
.packed_event_collection
|
||||
.as_ref()
|
||||
.and_then(|summary| summary.records[0].import_outcome.as_deref()),
|
||||
Some("imported")
|
||||
);
|
||||
|
||||
execute_step_command(
|
||||
&mut import.state,
|
||||
&StepCommand::ServiceTriggerKind { trigger_kind: 7 },
|
||||
)
|
||||
.expect("aggregate cargo economics runtime record should run");
|
||||
|
||||
assert_eq!(import.state.all_cargo_price_override, Some(180));
|
||||
assert_eq!(import.state.all_cargo_production_override, Some(210));
|
||||
assert_eq!(import.state.factory_cargo_production_override, Some(225));
|
||||
assert_eq!(import.state.farm_mine_cargo_production_override, Some(175));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keeps_named_cargo_price_rows_evidence_blocked() {
|
||||
let save_slice = SmpLoadedSaveSlice {
|
||||
file_extension_hint: Some("gms".to_string()),
|
||||
container_profile_family: Some("rt3-classic-save-container-v1".to_string()),
|
||||
mechanism_family: "classic-save-rehydrate-v1".to_string(),
|
||||
mechanism_confidence: "grounded".to_string(),
|
||||
trailer_family: None,
|
||||
bridge_family: None,
|
||||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
cargo_catalog: None,
|
||||
company_roster: None,
|
||||
chairman_profile_table: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
mechanism_family: "classic-save-rehydrate-v1".to_string(),
|
||||
mechanism_confidence: "grounded".to_string(),
|
||||
container_profile_family: Some("rt3-classic-save-container-v1".to_string()),
|
||||
metadata_tag_offset: 0x7100,
|
||||
records_tag_offset: 0x7200,
|
||||
close_tag_offset: 0x7600,
|
||||
packed_state_version: 0x3e9,
|
||||
packed_state_version_hex: "0x000003e9".to_string(),
|
||||
live_id_bound: 39,
|
||||
live_record_count: 1,
|
||||
live_entry_ids: vec![39],
|
||||
decoded_record_count: 1,
|
||||
imported_runtime_record_count: 0,
|
||||
records: vec![crate::SmpLoadedPackedEventRecordSummary {
|
||||
record_index: 0,
|
||||
live_entry_id: 39,
|
||||
payload_offset: Some(0x7202),
|
||||
payload_len: Some(96),
|
||||
decode_status: "parity_only".to_string(),
|
||||
payload_family: "real_packed_v1".to_string(),
|
||||
trigger_kind: Some(7),
|
||||
active: None,
|
||||
marks_collection_dirty: None,
|
||||
one_shot: Some(false),
|
||||
compact_control: Some(real_compact_control()),
|
||||
text_bands: vec![],
|
||||
standalone_condition_row_count: 0,
|
||||
standalone_condition_rows: vec![],
|
||||
negative_sentinel_scope: None,
|
||||
grouped_effect_row_counts: vec![1, 0, 0, 0],
|
||||
grouped_effect_rows: vec![real_named_cargo_price_row(106, 140)],
|
||||
decoded_conditions: Vec::new(),
|
||||
decoded_actions: vec![],
|
||||
executable_import_ready: false,
|
||||
notes: vec!["named cargo price descriptors remain evidence-blocked until cargo ordering is pinned"
|
||||
.to_string()],
|
||||
}],
|
||||
}),
|
||||
notes: vec![],
|
||||
};
|
||||
|
||||
let import = project_save_slice_to_runtime_state_import(
|
||||
&save_slice,
|
||||
"packed-events-named-cargo-price-parity",
|
||||
None,
|
||||
)
|
||||
.expect("save slice should project");
|
||||
|
||||
assert!(import.state.event_runtime_records.is_empty());
|
||||
assert_eq!(
|
||||
import
|
||||
.state
|
||||
.packed_event_collection
|
||||
.as_ref()
|
||||
.and_then(|summary| summary.records[0].import_outcome.as_deref()),
|
||||
Some("blocked_evidence_blocked_descriptor")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keeps_named_cargo_production_rows_evidence_blocked() {
|
||||
let save_slice = SmpLoadedSaveSlice {
|
||||
file_extension_hint: Some("gms".to_string()),
|
||||
container_profile_family: Some("rt3-classic-save-container-v1".to_string()),
|
||||
mechanism_family: "classic-save-rehydrate-v1".to_string(),
|
||||
mechanism_confidence: "grounded".to_string(),
|
||||
trailer_family: None,
|
||||
bridge_family: None,
|
||||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
cargo_catalog: None,
|
||||
company_roster: None,
|
||||
chairman_profile_table: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
mechanism_family: "classic-save-rehydrate-v1".to_string(),
|
||||
mechanism_confidence: "grounded".to_string(),
|
||||
container_profile_family: Some("rt3-classic-save-container-v1".to_string()),
|
||||
metadata_tag_offset: 0x7100,
|
||||
records_tag_offset: 0x7200,
|
||||
close_tag_offset: 0x7600,
|
||||
packed_state_version: 0x3e9,
|
||||
packed_state_version_hex: "0x000003e9".to_string(),
|
||||
live_id_bound: 40,
|
||||
live_record_count: 1,
|
||||
live_entry_ids: vec![40],
|
||||
decoded_record_count: 1,
|
||||
imported_runtime_record_count: 0,
|
||||
records: vec![crate::SmpLoadedPackedEventRecordSummary {
|
||||
record_index: 0,
|
||||
live_entry_id: 40,
|
||||
payload_offset: Some(0x7202),
|
||||
payload_len: Some(96),
|
||||
decode_status: "parity_only".to_string(),
|
||||
payload_family: "real_packed_v1".to_string(),
|
||||
trigger_kind: Some(7),
|
||||
active: None,
|
||||
marks_collection_dirty: None,
|
||||
one_shot: Some(false),
|
||||
compact_control: Some(real_compact_control()),
|
||||
text_bands: vec![],
|
||||
standalone_condition_row_count: 0,
|
||||
standalone_condition_rows: vec![],
|
||||
negative_sentinel_scope: None,
|
||||
grouped_effect_row_counts: vec![1, 0, 0, 0],
|
||||
grouped_effect_rows: vec![real_named_cargo_production_row(180, 160)],
|
||||
decoded_conditions: Vec::new(),
|
||||
decoded_actions: vec![],
|
||||
executable_import_ready: false,
|
||||
notes: vec!["named cargo production descriptors remain evidence-blocked until cargo ordering is pinned"
|
||||
.to_string()],
|
||||
}],
|
||||
}),
|
||||
notes: vec![],
|
||||
};
|
||||
|
||||
let import = project_save_slice_to_runtime_state_import(
|
||||
&save_slice,
|
||||
"packed-events-named-cargo-production-parity",
|
||||
None,
|
||||
)
|
||||
.expect("save slice should project");
|
||||
|
||||
assert!(import.state.event_runtime_records.is_empty());
|
||||
assert_eq!(
|
||||
import
|
||||
.state
|
||||
.packed_event_collection
|
||||
.as_ref()
|
||||
.and_then(|summary| summary.records[0].import_outcome.as_deref()),
|
||||
Some("blocked_evidence_blocked_descriptor")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keeps_negative_all_cargo_price_rows_variant_blocked() {
|
||||
let save_slice = SmpLoadedSaveSlice {
|
||||
file_extension_hint: Some("gms".to_string()),
|
||||
container_profile_family: Some("rt3-classic-save-container-v1".to_string()),
|
||||
mechanism_family: "classic-save-rehydrate-v1".to_string(),
|
||||
mechanism_confidence: "grounded".to_string(),
|
||||
trailer_family: None,
|
||||
bridge_family: None,
|
||||
profile: None,
|
||||
candidate_availability_table: None,
|
||||
named_locomotive_availability_table: None,
|
||||
locomotive_catalog: None,
|
||||
cargo_catalog: None,
|
||||
company_roster: None,
|
||||
chairman_profile_table: None,
|
||||
special_conditions_table: None,
|
||||
event_runtime_collection: Some(crate::SmpLoadedEventRuntimeCollectionSummary {
|
||||
source_kind: "packed-event-runtime-collection".to_string(),
|
||||
mechanism_family: "classic-save-rehydrate-v1".to_string(),
|
||||
mechanism_confidence: "grounded".to_string(),
|
||||
container_profile_family: Some("rt3-classic-save-container-v1".to_string()),
|
||||
metadata_tag_offset: 0x7100,
|
||||
records_tag_offset: 0x7200,
|
||||
close_tag_offset: 0x7600,
|
||||
packed_state_version: 0x3e9,
|
||||
packed_state_version_hex: "0x000003e9".to_string(),
|
||||
live_id_bound: 41,
|
||||
live_record_count: 1,
|
||||
live_entry_ids: vec![41],
|
||||
decoded_record_count: 1,
|
||||
imported_runtime_record_count: 0,
|
||||
records: vec![crate::SmpLoadedPackedEventRecordSummary {
|
||||
record_index: 0,
|
||||
live_entry_id: 41,
|
||||
payload_offset: Some(0x7202),
|
||||
payload_len: Some(96),
|
||||
decode_status: "parity_only".to_string(),
|
||||
payload_family: "real_packed_v1".to_string(),
|
||||
trigger_kind: Some(7),
|
||||
active: None,
|
||||
marks_collection_dirty: None,
|
||||
one_shot: Some(false),
|
||||
compact_control: Some(real_compact_control()),
|
||||
text_bands: vec![],
|
||||
standalone_condition_row_count: 0,
|
||||
standalone_condition_rows: vec![],
|
||||
negative_sentinel_scope: None,
|
||||
grouped_effect_row_counts: vec![1, 0, 0, 0],
|
||||
grouped_effect_rows: vec![real_all_cargo_price_row(-1)],
|
||||
decoded_conditions: Vec::new(),
|
||||
decoded_actions: vec![],
|
||||
executable_import_ready: false,
|
||||
notes: vec![
|
||||
"negative aggregate cargo price variants remain parity-only".to_string(),
|
||||
],
|
||||
}],
|
||||
}),
|
||||
notes: vec![],
|
||||
};
|
||||
|
||||
let import = project_save_slice_to_runtime_state_import(
|
||||
&save_slice,
|
||||
"packed-events-negative-all-cargo-price",
|
||||
None,
|
||||
)
|
||||
.expect("save slice should project");
|
||||
|
||||
assert!(import.state.event_runtime_records.is_empty());
|
||||
assert_eq!(
|
||||
import
|
||||
.state
|
||||
.packed_event_collection
|
||||
.as_ref()
|
||||
.and_then(|summary| summary.records[0].import_outcome.as_deref()),
|
||||
Some("blocked_variant_or_scope_blocked_descriptor")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn imports_recovered_territory_access_cost_rows_into_runtime_records() {
|
||||
let save_slice = SmpLoadedSaveSlice {
|
||||
|
|
@ -7545,6 +8142,12 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
@ -9820,6 +10423,12 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
@ -9994,6 +10603,12 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
@ -11683,6 +12298,12 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
@ -11868,6 +12489,12 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
|
|||
|
|
@ -35,7 +35,8 @@ pub use pk4::{
|
|||
extract_pk4_entry_bytes, extract_pk4_entry_file, inspect_pk4_bytes, inspect_pk4_file,
|
||||
};
|
||||
pub use runtime::{
|
||||
RuntimeCargoCatalogEntry, RuntimeCargoClass, RuntimeChairmanMetric, RuntimeChairmanProfile,
|
||||
RuntimeCargoCatalogEntry, RuntimeCargoClass, RuntimeCargoPriceTarget,
|
||||
RuntimeCargoProductionTarget, RuntimeChairmanMetric, RuntimeChairmanProfile,
|
||||
RuntimeChairmanTarget, RuntimeCompany, RuntimeCompanyConditionTestScope,
|
||||
RuntimeCompanyControllerKind, RuntimeCompanyMetric, RuntimeCompanyTarget,
|
||||
RuntimeCompanyTerritoryAccess, RuntimeCompanyTerritoryTrackPieceCount, RuntimeCondition,
|
||||
|
|
|
|||
|
|
@ -109,6 +109,12 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
|
|||
|
|
@ -203,6 +203,22 @@ pub enum RuntimeChairmanTarget {
|
|||
Ids { ids: Vec<u32> },
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(tag = "kind", rename_all = "snake_case")]
|
||||
pub enum RuntimeCargoPriceTarget {
|
||||
All,
|
||||
Named { name: String },
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(tag = "kind", rename_all = "snake_case")]
|
||||
pub enum RuntimeCargoProductionTarget {
|
||||
All,
|
||||
Factory,
|
||||
FarmMine,
|
||||
Named { name: String },
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(tag = "kind", rename_all = "snake_case")]
|
||||
pub enum RuntimeTerritoryTarget {
|
||||
|
|
@ -463,6 +479,14 @@ pub enum RuntimeEffect {
|
|||
name: String,
|
||||
value: u32,
|
||||
},
|
||||
SetCargoPriceOverride {
|
||||
target: RuntimeCargoPriceTarget,
|
||||
value: u32,
|
||||
},
|
||||
SetCargoProductionOverride {
|
||||
target: RuntimeCargoProductionTarget,
|
||||
value: u32,
|
||||
},
|
||||
SetCargoProductionSlot {
|
||||
slot: u32,
|
||||
value: u32,
|
||||
|
|
@ -844,6 +868,18 @@ pub struct RuntimeState {
|
|||
#[serde(default)]
|
||||
pub named_locomotive_cost: BTreeMap<String, u32>,
|
||||
#[serde(default)]
|
||||
pub all_cargo_price_override: Option<u32>,
|
||||
#[serde(default)]
|
||||
pub named_cargo_price_overrides: BTreeMap<String, u32>,
|
||||
#[serde(default)]
|
||||
pub all_cargo_production_override: Option<u32>,
|
||||
#[serde(default)]
|
||||
pub factory_cargo_production_override: Option<u32>,
|
||||
#[serde(default)]
|
||||
pub farm_mine_cargo_production_override: Option<u32>,
|
||||
#[serde(default)]
|
||||
pub named_cargo_production_overrides: BTreeMap<String, u32>,
|
||||
#[serde(default)]
|
||||
pub cargo_production_overrides: BTreeMap<u32, u32>,
|
||||
#[serde(default)]
|
||||
pub world_scalar_overrides: BTreeMap<String, i64>,
|
||||
|
|
@ -1487,6 +1523,16 @@ impl RuntimeState {
|
|||
return Err("named_locomotive_cost contains an empty key".to_string());
|
||||
}
|
||||
}
|
||||
for key in self.named_cargo_price_overrides.keys() {
|
||||
if key.trim().is_empty() {
|
||||
return Err("named_cargo_price_overrides contains an empty key".to_string());
|
||||
}
|
||||
}
|
||||
for key in self.named_cargo_production_overrides.keys() {
|
||||
if key.trim().is_empty() {
|
||||
return Err("named_cargo_production_overrides contains an empty key".to_string());
|
||||
}
|
||||
}
|
||||
for slot in self.cargo_production_overrides.keys() {
|
||||
if !(1..=11).contains(slot) {
|
||||
return Err(format!(
|
||||
|
|
@ -1600,6 +1646,24 @@ fn validate_runtime_effect(
|
|||
return Err("name must not be empty".to_string());
|
||||
}
|
||||
}
|
||||
RuntimeEffect::SetCargoPriceOverride { target, .. } => match target {
|
||||
RuntimeCargoPriceTarget::All => {}
|
||||
RuntimeCargoPriceTarget::Named { name } => {
|
||||
if name.trim().is_empty() {
|
||||
return Err("name must not be empty".to_string());
|
||||
}
|
||||
}
|
||||
},
|
||||
RuntimeEffect::SetCargoProductionOverride { target, .. } => match target {
|
||||
RuntimeCargoProductionTarget::All
|
||||
| RuntimeCargoProductionTarget::Factory
|
||||
| RuntimeCargoProductionTarget::FarmMine => {}
|
||||
RuntimeCargoProductionTarget::Named { name } => {
|
||||
if name.trim().is_empty() {
|
||||
return Err("name must not be empty".to_string());
|
||||
}
|
||||
}
|
||||
},
|
||||
RuntimeEffect::SetCargoProductionSlot { slot, .. } => {
|
||||
if !(1..=11).contains(slot) {
|
||||
return Err("slot must be in 1..=11".to_string());
|
||||
|
|
@ -1916,6 +1980,12 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
@ -1979,7 +2049,13 @@ mod tests {
|
|||
event_runtime_records: Vec::new(),
|
||||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
@ -2048,6 +2124,12 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
@ -2126,6 +2208,12 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
@ -2229,6 +2317,12 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
@ -2284,6 +2378,12 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
@ -2339,6 +2439,12 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
@ -2411,6 +2517,12 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
@ -2473,6 +2585,12 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
@ -2539,6 +2657,12 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
@ -2601,6 +2725,12 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
@ -2669,6 +2799,12 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
@ -2731,6 +2867,12 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
@ -2793,6 +2935,12 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
@ -2848,6 +2996,12 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
@ -2913,6 +3067,12 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
|
|||
|
|
@ -7,11 +7,12 @@ use serde::{Deserialize, Serialize};
|
|||
use sha2::{Digest, Sha256};
|
||||
|
||||
use crate::{
|
||||
RuntimeCargoClass, RuntimeChairmanMetric, RuntimeChairmanTarget,
|
||||
RuntimeCompanyConditionTestScope, RuntimeCompanyControllerKind, RuntimeCompanyMetric,
|
||||
RuntimeCompanyTarget, RuntimeCondition, RuntimeConditionComparator, RuntimeEffect,
|
||||
RuntimeEventRecordTemplate, RuntimePlayerConditionTestScope, RuntimePlayerTarget,
|
||||
RuntimeTerritoryMetric, RuntimeTerritoryTarget, RuntimeTrackMetric, RuntimeTrackPieceCounts,
|
||||
RuntimeCargoClass, RuntimeCargoPriceTarget, RuntimeCargoProductionTarget,
|
||||
RuntimeChairmanMetric, RuntimeChairmanTarget, RuntimeCompanyConditionTestScope,
|
||||
RuntimeCompanyControllerKind, RuntimeCompanyMetric, RuntimeCompanyTarget, RuntimeCondition,
|
||||
RuntimeConditionComparator, RuntimeEffect, RuntimeEventRecordTemplate,
|
||||
RuntimePlayerConditionTestScope, RuntimePlayerTarget, RuntimeTerritoryMetric,
|
||||
RuntimeTerritoryTarget, RuntimeTrackMetric, RuntimeTrackPieceCounts,
|
||||
};
|
||||
|
||||
pub const SMP_FOUR_SIDECAR_BYTE_PLANES_MIN_BUNDLE_VERSION: u32 = 0x03ec;
|
||||
|
|
@ -3656,7 +3657,9 @@ fn real_condition_chairman_target(
|
|||
fn real_grouped_effect_descriptor_metadata(
|
||||
descriptor_id: u32,
|
||||
) -> Option<RealGroupedEffectDescriptorMetadata> {
|
||||
recovered_cargo_production_descriptor_metadata(descriptor_id)
|
||||
recovered_cargo_price_descriptor_metadata(descriptor_id)
|
||||
.or_else(|| recovered_cargo_economics_descriptor_metadata(descriptor_id))
|
||||
.or_else(|| recovered_cargo_production_descriptor_metadata(descriptor_id))
|
||||
.or_else(|| recovered_locomotive_availability_descriptor_metadata(descriptor_id))
|
||||
.or_else(|| recovered_locomotive_cost_descriptor_metadata(descriptor_id))
|
||||
.or_else(|| recovered_territory_access_cost_descriptor_metadata(descriptor_id))
|
||||
|
|
@ -3676,6 +3679,55 @@ fn real_grouped_effect_descriptor_metadata(
|
|||
})
|
||||
}
|
||||
|
||||
fn recovered_cargo_price_descriptor_metadata(
|
||||
descriptor_id: u32,
|
||||
) -> Option<RealGroupedEffectDescriptorMetadata> {
|
||||
(descriptor_id == 105).then_some(RealGroupedEffectDescriptorMetadata {
|
||||
descriptor_id,
|
||||
label: "All Cargo Prices",
|
||||
target_mask_bits: 0x08,
|
||||
parameter_family: "cargo_price_scalar",
|
||||
runtime_key: None,
|
||||
runtime_status: RealGroupedEffectRuntimeStatus::Executable,
|
||||
executable_in_runtime: true,
|
||||
})
|
||||
}
|
||||
|
||||
fn recovered_cargo_economics_descriptor_metadata(
|
||||
descriptor_id: u32,
|
||||
) -> Option<RealGroupedEffectDescriptorMetadata> {
|
||||
match descriptor_id {
|
||||
177 => Some(RealGroupedEffectDescriptorMetadata {
|
||||
descriptor_id,
|
||||
label: "All Cargo Production",
|
||||
target_mask_bits: 0x08,
|
||||
parameter_family: "cargo_production_scalar",
|
||||
runtime_key: None,
|
||||
runtime_status: RealGroupedEffectRuntimeStatus::Executable,
|
||||
executable_in_runtime: true,
|
||||
}),
|
||||
178 => Some(RealGroupedEffectDescriptorMetadata {
|
||||
descriptor_id,
|
||||
label: "All Factory Production",
|
||||
target_mask_bits: 0x08,
|
||||
parameter_family: "cargo_production_scalar",
|
||||
runtime_key: None,
|
||||
runtime_status: RealGroupedEffectRuntimeStatus::Executable,
|
||||
executable_in_runtime: true,
|
||||
}),
|
||||
179 => Some(RealGroupedEffectDescriptorMetadata {
|
||||
descriptor_id,
|
||||
label: "All Farm/Mine Production",
|
||||
target_mask_bits: 0x08,
|
||||
parameter_family: "cargo_production_scalar",
|
||||
runtime_key: None,
|
||||
runtime_status: RealGroupedEffectRuntimeStatus::Executable,
|
||||
executable_in_runtime: true,
|
||||
}),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn recovered_cargo_production_descriptor_metadata(
|
||||
descriptor_id: u32,
|
||||
) -> Option<RealGroupedEffectDescriptorMetadata> {
|
||||
|
|
@ -4260,16 +4312,45 @@ fn decode_real_grouped_effect_action(
|
|||
});
|
||||
}
|
||||
|
||||
if descriptor_metadata.executable_in_runtime
|
||||
&& descriptor_metadata.parameter_family == "cargo_price_scalar"
|
||||
&& row.row_shape == "scalar_assignment"
|
||||
&& row.raw_scalar_value >= 0
|
||||
&& row.descriptor_id == 105
|
||||
{
|
||||
return Some(RuntimeEffect::SetCargoPriceOverride {
|
||||
target: RuntimeCargoPriceTarget::All,
|
||||
value: row.raw_scalar_value as u32,
|
||||
});
|
||||
}
|
||||
|
||||
if descriptor_metadata.executable_in_runtime
|
||||
&& descriptor_metadata.parameter_family == "cargo_production_scalar"
|
||||
&& row.row_shape == "scalar_assignment"
|
||||
&& row.raw_scalar_value >= 0
|
||||
{
|
||||
let slot = descriptor_metadata.descriptor_id.checked_sub(229)?;
|
||||
return Some(RuntimeEffect::SetCargoProductionSlot {
|
||||
slot,
|
||||
value: row.raw_scalar_value as u32,
|
||||
});
|
||||
return match descriptor_metadata.descriptor_id {
|
||||
177 => Some(RuntimeEffect::SetCargoProductionOverride {
|
||||
target: RuntimeCargoProductionTarget::All,
|
||||
value: row.raw_scalar_value as u32,
|
||||
}),
|
||||
178 => Some(RuntimeEffect::SetCargoProductionOverride {
|
||||
target: RuntimeCargoProductionTarget::Factory,
|
||||
value: row.raw_scalar_value as u32,
|
||||
}),
|
||||
179 => Some(RuntimeEffect::SetCargoProductionOverride {
|
||||
target: RuntimeCargoProductionTarget::FarmMine,
|
||||
value: row.raw_scalar_value as u32,
|
||||
}),
|
||||
230..=240 => {
|
||||
let slot = descriptor_metadata.descriptor_id.checked_sub(229)?;
|
||||
Some(RuntimeEffect::SetCargoProductionSlot {
|
||||
slot,
|
||||
value: row.raw_scalar_value as u32,
|
||||
})
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
|
||||
if descriptor_metadata.executable_in_runtime
|
||||
|
|
@ -4563,6 +4644,8 @@ fn runtime_effect_supported_for_save_import(effect: &RuntimeEffect) -> bool {
|
|||
| RuntimeEffect::SetNamedLocomotiveAvailability { .. }
|
||||
| RuntimeEffect::SetNamedLocomotiveAvailabilityValue { .. }
|
||||
| RuntimeEffect::SetNamedLocomotiveCost { .. }
|
||||
| RuntimeEffect::SetCargoPriceOverride { .. }
|
||||
| RuntimeEffect::SetCargoProductionOverride { .. }
|
||||
| RuntimeEffect::SetCargoProductionSlot { .. }
|
||||
| RuntimeEffect::SetWorldScalarOverride { .. }
|
||||
| RuntimeEffect::SetTerritoryAccessCost { .. }
|
||||
|
|
@ -11248,6 +11331,30 @@ mod tests {
|
|||
assert!(metadata.executable_in_runtime);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn looks_up_recovered_all_cargo_price_descriptor_metadata() {
|
||||
let metadata =
|
||||
real_grouped_effect_descriptor_metadata(105).expect("descriptor metadata should exist");
|
||||
|
||||
assert_eq!(metadata.label, "All Cargo Prices");
|
||||
assert_eq!(metadata.target_mask_bits, 0x08);
|
||||
assert_eq!(metadata.parameter_family, "cargo_price_scalar");
|
||||
assert_eq!(metadata.runtime_key, None);
|
||||
assert!(metadata.executable_in_runtime);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn looks_up_recovered_aggregate_cargo_production_descriptor_metadata() {
|
||||
let metadata =
|
||||
real_grouped_effect_descriptor_metadata(177).expect("descriptor metadata should exist");
|
||||
|
||||
assert_eq!(metadata.label, "All Cargo Production");
|
||||
assert_eq!(metadata.target_mask_bits, 0x08);
|
||||
assert_eq!(metadata.parameter_family, "cargo_production_scalar");
|
||||
assert_eq!(metadata.runtime_key, None);
|
||||
assert!(metadata.executable_in_runtime);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn looks_up_recovered_lower_band_locomotive_cost_descriptor_metadata() {
|
||||
let metadata =
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ use std::collections::BTreeSet;
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
RuntimeCargoClass, RuntimeChairmanMetric, RuntimeChairmanTarget, RuntimeCompanyControllerKind,
|
||||
RuntimeCargoClass, RuntimeCargoPriceTarget, RuntimeCargoProductionTarget,
|
||||
RuntimeChairmanMetric, RuntimeChairmanTarget, RuntimeCompanyControllerKind,
|
||||
RuntimeCompanyMetric, RuntimeCompanyTarget, RuntimeCondition, RuntimeConditionComparator,
|
||||
RuntimeEffect, RuntimeEventRecordTemplate, RuntimePlayerTarget, RuntimeState, RuntimeSummary,
|
||||
RuntimeTerritoryMetric, RuntimeTerritoryTarget, RuntimeTrackMetric, RuntimeTrackPieceCounts,
|
||||
|
|
@ -606,6 +607,32 @@ fn apply_runtime_effects(
|
|||
RuntimeEffect::SetNamedLocomotiveCost { name, value } => {
|
||||
state.named_locomotive_cost.insert(name.clone(), *value);
|
||||
}
|
||||
RuntimeEffect::SetCargoPriceOverride { target, value } => match target {
|
||||
RuntimeCargoPriceTarget::All => {
|
||||
state.all_cargo_price_override = Some(*value);
|
||||
}
|
||||
RuntimeCargoPriceTarget::Named { name } => {
|
||||
state
|
||||
.named_cargo_price_overrides
|
||||
.insert(name.clone(), *value);
|
||||
}
|
||||
},
|
||||
RuntimeEffect::SetCargoProductionOverride { target, value } => match target {
|
||||
RuntimeCargoProductionTarget::All => {
|
||||
state.all_cargo_production_override = Some(*value);
|
||||
}
|
||||
RuntimeCargoProductionTarget::Factory => {
|
||||
state.factory_cargo_production_override = Some(*value);
|
||||
}
|
||||
RuntimeCargoProductionTarget::FarmMine => {
|
||||
state.farm_mine_cargo_production_override = Some(*value);
|
||||
}
|
||||
RuntimeCargoProductionTarget::Named { name } => {
|
||||
state
|
||||
.named_cargo_production_overrides
|
||||
.insert(name.clone(), *value);
|
||||
}
|
||||
},
|
||||
RuntimeEffect::SetCargoProductionSlot { slot, value } => {
|
||||
state.cargo_production_overrides.insert(*slot, *value);
|
||||
}
|
||||
|
|
@ -1509,8 +1536,9 @@ mod tests {
|
|||
|
||||
use super::*;
|
||||
use crate::{
|
||||
CalendarPoint, RuntimeChairmanMetric, RuntimeChairmanProfile, RuntimeChairmanTarget,
|
||||
RuntimeCompany, RuntimeCompanyControllerKind, RuntimeCompanyTarget, RuntimeCondition,
|
||||
CalendarPoint, RuntimeCargoPriceTarget, RuntimeCargoProductionTarget,
|
||||
RuntimeChairmanMetric, RuntimeChairmanProfile, RuntimeChairmanTarget, RuntimeCompany,
|
||||
RuntimeCompanyControllerKind, RuntimeCompanyTarget, RuntimeCondition,
|
||||
RuntimeConditionComparator, RuntimeEffect, RuntimeEventRecord, RuntimeEventRecordTemplate,
|
||||
RuntimePlayer, RuntimeSaveProfileState, RuntimeServiceState, RuntimeTerritory,
|
||||
RuntimeTerritoryTarget, RuntimeTrackPieceCounts, RuntimeTrain, RuntimeWorldRestoreState,
|
||||
|
|
@ -1561,6 +1589,12 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
@ -1920,6 +1954,26 @@ mod tests {
|
|||
key: "world.build_stations_cost".to_string(),
|
||||
value: 350000,
|
||||
},
|
||||
RuntimeEffect::SetCargoPriceOverride {
|
||||
target: RuntimeCargoPriceTarget::All,
|
||||
value: 180,
|
||||
},
|
||||
RuntimeEffect::SetCargoPriceOverride {
|
||||
target: RuntimeCargoPriceTarget::Named {
|
||||
name: "Coal".to_string(),
|
||||
},
|
||||
value: 95,
|
||||
},
|
||||
RuntimeEffect::SetCargoProductionOverride {
|
||||
target: RuntimeCargoProductionTarget::Factory,
|
||||
value: 225,
|
||||
},
|
||||
RuntimeEffect::SetCargoProductionOverride {
|
||||
target: RuntimeCargoProductionTarget::Named {
|
||||
name: "Corn".to_string(),
|
||||
},
|
||||
value: 140,
|
||||
},
|
||||
RuntimeEffect::SetCargoProductionSlot {
|
||||
slot: 1,
|
||||
value: 125,
|
||||
|
|
@ -1942,9 +1996,16 @@ mod tests {
|
|||
.get("world.build_stations_cost"),
|
||||
Some(&350000)
|
||||
);
|
||||
assert_eq!(state.all_cargo_price_override, Some(180));
|
||||
assert_eq!(state.named_cargo_price_overrides.get("Coal"), Some(&95));
|
||||
assert_eq!(state.factory_cargo_production_override, Some(225));
|
||||
assert_eq!(
|
||||
state.named_cargo_production_overrides.get("Corn"),
|
||||
Some(&140)
|
||||
);
|
||||
assert_eq!(state.cargo_production_overrides.get(&1), Some(&125));
|
||||
assert_eq!(state.world_restore.territory_access_cost, Some(750000));
|
||||
assert_eq!(result.service_events[0].applied_effect_count, 3);
|
||||
assert_eq!(result.service_events[0].applied_effect_count, 7);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -934,6 +934,12 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
@ -1051,6 +1057,12 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
@ -1105,6 +1117,12 @@ mod tests {
|
|||
("Mikado".to_string(), 0),
|
||||
]),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
@ -1151,6 +1169,12 @@ mod tests {
|
|||
("Big Boy".to_string(), 250000),
|
||||
("GP7".to_string(), 175000),
|
||||
]),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
@ -1195,6 +1219,12 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::from([(1, 125), (2, 250)]),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
@ -1301,6 +1331,12 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
@ -1385,6 +1421,12 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
@ -1465,6 +1507,12 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
|
|
|
|||
|
|
@ -113,6 +113,11 @@ The highest-value next passes are now:
|
|||
landing surface too: representative rows execute into `RuntimeState.world_scalar_overrides`
|
||||
through stable normalized keys such as `world.build_stations_cost` and
|
||||
`world.track_maintenance_cost`
|
||||
- the grounded aggregate cargo-economics descriptors now execute too: descriptor `105`
|
||||
`All Cargo Prices` and descriptors `177..179` `All Cargo Production` / `All Factory Production`
|
||||
/ `All Farm/Mine Production` land on bounded event-owned cargo override state, while the named
|
||||
cargo-price and named cargo-production strips remain explicit
|
||||
`blocked_evidence_blocked_descriptor` parity until descriptor ordering is pinned more strongly
|
||||
- widen real packed-event executable coverage descriptor by descriptor after identity, target mask,
|
||||
and normalized effect semantics are all grounded, not just after row framing is parsed
|
||||
- the first grounded condition-side unlock now exists for negative-sentinel `raw_condition_id = -1`
|
||||
|
|
|
|||
|
|
@ -75,6 +75,11 @@ Implemented today:
|
|||
- the recovered whole-game scalar economy/performance strip `59..104` now has a bounded runtime
|
||||
landing surface too: representative descriptors import as `SetWorldScalarOverride` and land in
|
||||
`RuntimeState.world_scalar_overrides`
|
||||
- the grounded aggregate cargo-economics descriptors now execute too: descriptor `105`
|
||||
`All Cargo Prices` and descriptors `177..179` `All Cargo Production` / `All Factory Production`
|
||||
/ `All Farm/Mine Production` import through bounded cargo override surfaces, while the named
|
||||
cargo-price and named cargo-production strips now sit on explicit
|
||||
`blocked_evidence_blocked_descriptor` parity instead of generic unmapped-descriptor frontier
|
||||
- a minimal event-owned train surface and an opaque economic-status lane now exist in runtime
|
||||
state, and real descriptors `8` = `Economic Status`, `9` = `Confiscate All`, and `15` =
|
||||
`Retire Train` now import and execute through the ordinary runtime path when overlay context
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
{
|
||||
"format_version": 1,
|
||||
"fixture_id": "packed-event-cargo-economics-parity-save-slice-fixture",
|
||||
"source": {
|
||||
"kind": "captured-runtime",
|
||||
"description": "Fixture pinning the remaining named cargo-economics descriptor strips on explicit evidence-blocked parity."
|
||||
},
|
||||
"state_save_slice_path": "packed-event-cargo-economics-parity-save-slice.json",
|
||||
"commands": [
|
||||
{
|
||||
"kind": "step_count",
|
||||
"steps": 1
|
||||
}
|
||||
],
|
||||
"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": 0,
|
||||
"packed_event_blocked_evidence_blocked_descriptor_count": 1,
|
||||
"packed_event_blocked_unmapped_real_descriptor_count": 0,
|
||||
"packed_event_blocked_unmapped_world_descriptor_count": 0,
|
||||
"event_runtime_record_count": 0
|
||||
},
|
||||
"expected_state_fragment": {
|
||||
"packed_event_collection": {
|
||||
"records": [
|
||||
{
|
||||
"import_outcome": "blocked_evidence_blocked_descriptor",
|
||||
"grouped_effect_rows": [
|
||||
{
|
||||
"descriptor_id": 106,
|
||||
"descriptor_label": "Unknown Cargo Price",
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"semantic_family": "scalar_assignment"
|
||||
},
|
||||
{
|
||||
"descriptor_id": 180,
|
||||
"descriptor_label": "Unknown Cargo Production",
|
||||
"parameter_family": "cargo_production_scalar",
|
||||
"semantic_family": "scalar_assignment"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"event_runtime_records": []
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
{
|
||||
"format_version": 1,
|
||||
"save_slice_id": "packed-event-cargo-economics-parity-save-slice",
|
||||
"source": {
|
||||
"description": "Tracked save-slice document pinning the remaining named cargo-economics descriptor strips on explicit evidence-blocked parity.",
|
||||
"original_save_filename": "captured-cargo-economics-parity.gms",
|
||||
"original_save_sha256": "cargo-economics-parity-sample-sha256",
|
||||
"notes": [
|
||||
"tracked as JSON save-slice document rather than raw .smp",
|
||||
"pins named cargo price and named cargo production rows until exact descriptor-to-cargo ordering is grounded strongly enough"
|
||||
]
|
||||
},
|
||||
"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": null,
|
||||
"locomotive_catalog": null,
|
||||
"cargo_catalog": null,
|
||||
"company_roster": null,
|
||||
"chairman_profile_table": null,
|
||||
"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": 33408,
|
||||
"records_tag_offset": 33664,
|
||||
"close_tag_offset": 34176,
|
||||
"packed_state_version": 1001,
|
||||
"packed_state_version_hex": "0x000003e9",
|
||||
"live_id_bound": 65,
|
||||
"live_record_count": 1,
|
||||
"live_entry_ids": [65],
|
||||
"decoded_record_count": 1,
|
||||
"imported_runtime_record_count": 0,
|
||||
"records": [
|
||||
{
|
||||
"record_index": 0,
|
||||
"live_entry_id": 65,
|
||||
"payload_offset": 33696,
|
||||
"payload_len": 128,
|
||||
"decode_status": "parity_only",
|
||||
"payload_family": "real_packed_v1",
|
||||
"trigger_kind": 7,
|
||||
"one_shot": false,
|
||||
"compact_control": {
|
||||
"mode_byte_0x7ef": 7,
|
||||
"primary_selector_0x7f0": 0,
|
||||
"grouped_mode_0x7f4": 2,
|
||||
"one_shot_header_0x7f5": 0,
|
||||
"modifier_flag_0x7f9": 0,
|
||||
"modifier_flag_0x7fa": 0,
|
||||
"grouped_target_scope_ordinals_0x7fb": [0, 0, 0, 0],
|
||||
"grouped_scope_checkboxes_0x7ff": [1, 0, 0, 0],
|
||||
"summary_toggle_0x800": 1,
|
||||
"grouped_territory_selectors_0x80f": [-1, -1, -1, -1]
|
||||
},
|
||||
"text_bands": [],
|
||||
"standalone_condition_row_count": 0,
|
||||
"standalone_condition_rows": [],
|
||||
"grouped_effect_row_counts": [2, 0, 0, 0],
|
||||
"grouped_effect_rows": [
|
||||
{
|
||||
"group_index": 0,
|
||||
"row_index": 0,
|
||||
"descriptor_id": 106,
|
||||
"descriptor_label": "Unknown Cargo Price",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"opcode": 3,
|
||||
"raw_scalar_value": 140,
|
||||
"value_byte_0x09": 0,
|
||||
"value_dword_0x0d": 0,
|
||||
"value_byte_0x11": 0,
|
||||
"value_byte_0x12": 0,
|
||||
"value_word_0x14": 0,
|
||||
"value_word_0x16": 0,
|
||||
"row_shape": "scalar_assignment",
|
||||
"semantic_family": "scalar_assignment",
|
||||
"semantic_preview": "Set Unknown Cargo Price to 140",
|
||||
"recovered_cargo_slot": null,
|
||||
"recovered_cargo_class": null,
|
||||
"recovered_locomotive_id": null,
|
||||
"locomotive_name": null,
|
||||
"notes": [
|
||||
"descriptor recovered from checked-in EventEffects semantic catalog",
|
||||
"exact named cargo ordering for the price strip is not yet pinned"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group_index": 0,
|
||||
"row_index": 1,
|
||||
"descriptor_id": 180,
|
||||
"descriptor_label": "Unknown Cargo Production",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_production_scalar",
|
||||
"opcode": 3,
|
||||
"raw_scalar_value": 160,
|
||||
"value_byte_0x09": 0,
|
||||
"value_dword_0x0d": 0,
|
||||
"value_byte_0x11": 0,
|
||||
"value_byte_0x12": 0,
|
||||
"value_word_0x14": 0,
|
||||
"value_word_0x16": 0,
|
||||
"row_shape": "scalar_assignment",
|
||||
"semantic_family": "scalar_assignment",
|
||||
"semantic_preview": "Set Unknown Cargo Production to 160",
|
||||
"recovered_cargo_slot": null,
|
||||
"recovered_cargo_class": null,
|
||||
"recovered_locomotive_id": null,
|
||||
"locomotive_name": null,
|
||||
"notes": [
|
||||
"descriptor recovered from checked-in EventEffects semantic catalog",
|
||||
"exact named cargo ordering for the production strip is not yet pinned"
|
||||
]
|
||||
}
|
||||
],
|
||||
"decoded_actions": [],
|
||||
"executable_import_ready": false,
|
||||
"notes": [
|
||||
"named cargo-economics descriptor strips remain explicit evidence-blocked parity"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"notes": [
|
||||
"named cargo economics evidence-blocked parity sample"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
{
|
||||
"format_version": 1,
|
||||
"fixture_id": "packed-event-cargo-economics-save-slice-fixture",
|
||||
"source": {
|
||||
"kind": "captured-runtime",
|
||||
"description": "Fixture proving the grounded aggregate cargo-economics descriptors execute through bounded cargo override surfaces."
|
||||
},
|
||||
"state_save_slice_path": "packed-event-cargo-economics-save-slice.json",
|
||||
"commands": [
|
||||
{
|
||||
"kind": "service_trigger_kind",
|
||||
"trigger_kind": 7
|
||||
}
|
||||
],
|
||||
"expected_summary": {
|
||||
"calendar_projection_source": "default-1830-placeholder",
|
||||
"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,
|
||||
"total_event_record_service_count": 1,
|
||||
"total_trigger_dispatch_count": 1
|
||||
},
|
||||
"expected_state_fragment": {
|
||||
"all_cargo_price_override": 180,
|
||||
"all_cargo_production_override": 210,
|
||||
"factory_cargo_production_override": 225,
|
||||
"farm_mine_cargo_production_override": 175,
|
||||
"packed_event_collection": {
|
||||
"records": [
|
||||
{
|
||||
"import_outcome": "imported"
|
||||
}
|
||||
]
|
||||
},
|
||||
"event_runtime_records": [
|
||||
{
|
||||
"record_id": 64,
|
||||
"service_count": 1,
|
||||
"effects": [
|
||||
{
|
||||
"kind": "set_cargo_price_override",
|
||||
"target": {
|
||||
"kind": "all"
|
||||
},
|
||||
"value": 180
|
||||
},
|
||||
{
|
||||
"kind": "set_cargo_production_override",
|
||||
"target": {
|
||||
"kind": "all"
|
||||
},
|
||||
"value": 210
|
||||
},
|
||||
{
|
||||
"kind": "set_cargo_production_override",
|
||||
"target": {
|
||||
"kind": "factory"
|
||||
},
|
||||
"value": 225
|
||||
},
|
||||
{
|
||||
"kind": "set_cargo_production_override",
|
||||
"target": {
|
||||
"kind": "farm_mine"
|
||||
},
|
||||
"value": 175
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
216
fixtures/runtime/packed-event-cargo-economics-save-slice.json
Normal file
216
fixtures/runtime/packed-event-cargo-economics-save-slice.json
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
{
|
||||
"format_version": 1,
|
||||
"save_slice_id": "packed-event-cargo-economics-save-slice",
|
||||
"source": {
|
||||
"description": "Tracked save-slice document proving the grounded aggregate cargo-economics descriptors execute through bounded cargo override surfaces.",
|
||||
"original_save_filename": "captured-cargo-economics.gms",
|
||||
"original_save_sha256": "cargo-economics-sample-sha256",
|
||||
"notes": [
|
||||
"tracked as JSON save-slice document rather than raw .smp",
|
||||
"pins the grounded aggregate descriptors 105 and 177..179 while named cargo strips remain evidence-blocked"
|
||||
]
|
||||
},
|
||||
"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": null,
|
||||
"locomotive_catalog": null,
|
||||
"cargo_catalog": null,
|
||||
"company_roster": null,
|
||||
"chairman_profile_table": null,
|
||||
"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": 32512,
|
||||
"records_tag_offset": 32768,
|
||||
"close_tag_offset": 33280,
|
||||
"packed_state_version": 1001,
|
||||
"packed_state_version_hex": "0x000003e9",
|
||||
"live_id_bound": 64,
|
||||
"live_record_count": 1,
|
||||
"live_entry_ids": [64],
|
||||
"decoded_record_count": 1,
|
||||
"imported_runtime_record_count": 0,
|
||||
"records": [
|
||||
{
|
||||
"record_index": 0,
|
||||
"live_entry_id": 64,
|
||||
"payload_offset": 32800,
|
||||
"payload_len": 176,
|
||||
"decode_status": "executable",
|
||||
"payload_family": "real_packed_v1",
|
||||
"trigger_kind": 7,
|
||||
"one_shot": false,
|
||||
"compact_control": {
|
||||
"mode_byte_0x7ef": 7,
|
||||
"primary_selector_0x7f0": 0,
|
||||
"grouped_mode_0x7f4": 2,
|
||||
"one_shot_header_0x7f5": 0,
|
||||
"modifier_flag_0x7f9": 0,
|
||||
"modifier_flag_0x7fa": 0,
|
||||
"grouped_target_scope_ordinals_0x7fb": [0, 0, 0, 0],
|
||||
"grouped_scope_checkboxes_0x7ff": [1, 0, 0, 0],
|
||||
"summary_toggle_0x800": 1,
|
||||
"grouped_territory_selectors_0x80f": [-1, -1, -1, -1]
|
||||
},
|
||||
"text_bands": [],
|
||||
"standalone_condition_row_count": 0,
|
||||
"standalone_condition_rows": [],
|
||||
"grouped_effect_row_counts": [4, 0, 0, 0],
|
||||
"grouped_effect_rows": [
|
||||
{
|
||||
"group_index": 0,
|
||||
"row_index": 0,
|
||||
"descriptor_id": 105,
|
||||
"descriptor_label": "All Cargo Prices",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_price_scalar",
|
||||
"opcode": 3,
|
||||
"raw_scalar_value": 180,
|
||||
"value_byte_0x09": 0,
|
||||
"value_dword_0x0d": 0,
|
||||
"value_byte_0x11": 0,
|
||||
"value_byte_0x12": 0,
|
||||
"value_word_0x14": 0,
|
||||
"value_word_0x16": 0,
|
||||
"row_shape": "scalar_assignment",
|
||||
"semantic_family": "scalar_assignment",
|
||||
"semantic_preview": "Set All Cargo Prices to 180",
|
||||
"recovered_cargo_slot": null,
|
||||
"recovered_cargo_class": null,
|
||||
"recovered_locomotive_id": null,
|
||||
"locomotive_name": null,
|
||||
"notes": [
|
||||
"descriptor recovered from checked-in EventEffects semantic catalog"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group_index": 0,
|
||||
"row_index": 1,
|
||||
"descriptor_id": 177,
|
||||
"descriptor_label": "All Cargo Production",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_production_scalar",
|
||||
"opcode": 3,
|
||||
"raw_scalar_value": 210,
|
||||
"value_byte_0x09": 0,
|
||||
"value_dword_0x0d": 0,
|
||||
"value_byte_0x11": 0,
|
||||
"value_byte_0x12": 0,
|
||||
"value_word_0x14": 0,
|
||||
"value_word_0x16": 0,
|
||||
"row_shape": "scalar_assignment",
|
||||
"semantic_family": "scalar_assignment",
|
||||
"semantic_preview": "Set All Cargo Production to 210",
|
||||
"recovered_cargo_slot": null,
|
||||
"recovered_cargo_class": null,
|
||||
"recovered_locomotive_id": null,
|
||||
"locomotive_name": null,
|
||||
"notes": [
|
||||
"descriptor recovered from checked-in EventEffects semantic catalog"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group_index": 0,
|
||||
"row_index": 2,
|
||||
"descriptor_id": 178,
|
||||
"descriptor_label": "All Factory Production",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_production_scalar",
|
||||
"opcode": 3,
|
||||
"raw_scalar_value": 225,
|
||||
"value_byte_0x09": 0,
|
||||
"value_dword_0x0d": 0,
|
||||
"value_byte_0x11": 0,
|
||||
"value_byte_0x12": 0,
|
||||
"value_word_0x14": 0,
|
||||
"value_word_0x16": 0,
|
||||
"row_shape": "scalar_assignment",
|
||||
"semantic_family": "scalar_assignment",
|
||||
"semantic_preview": "Set All Factory Production to 225",
|
||||
"recovered_cargo_slot": null,
|
||||
"recovered_cargo_class": "factory",
|
||||
"recovered_locomotive_id": null,
|
||||
"locomotive_name": null,
|
||||
"notes": [
|
||||
"descriptor recovered from checked-in EventEffects semantic catalog"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group_index": 0,
|
||||
"row_index": 3,
|
||||
"descriptor_id": 179,
|
||||
"descriptor_label": "All Farm/Mine Production",
|
||||
"target_mask_bits": 8,
|
||||
"parameter_family": "cargo_production_scalar",
|
||||
"opcode": 3,
|
||||
"raw_scalar_value": 175,
|
||||
"value_byte_0x09": 0,
|
||||
"value_dword_0x0d": 0,
|
||||
"value_byte_0x11": 0,
|
||||
"value_byte_0x12": 0,
|
||||
"value_word_0x14": 0,
|
||||
"value_word_0x16": 0,
|
||||
"row_shape": "scalar_assignment",
|
||||
"semantic_family": "scalar_assignment",
|
||||
"semantic_preview": "Set All Farm/Mine Production to 175",
|
||||
"recovered_cargo_slot": null,
|
||||
"recovered_cargo_class": "farm_mine",
|
||||
"recovered_locomotive_id": null,
|
||||
"locomotive_name": null,
|
||||
"notes": [
|
||||
"descriptor recovered from checked-in EventEffects semantic catalog"
|
||||
]
|
||||
}
|
||||
],
|
||||
"decoded_actions": [
|
||||
{
|
||||
"kind": "set_cargo_price_override",
|
||||
"target": {
|
||||
"kind": "all"
|
||||
},
|
||||
"value": 180
|
||||
},
|
||||
{
|
||||
"kind": "set_cargo_production_override",
|
||||
"target": {
|
||||
"kind": "all"
|
||||
},
|
||||
"value": 210
|
||||
},
|
||||
{
|
||||
"kind": "set_cargo_production_override",
|
||||
"target": {
|
||||
"kind": "factory"
|
||||
},
|
||||
"value": 225
|
||||
},
|
||||
{
|
||||
"kind": "set_cargo_production_override",
|
||||
"target": {
|
||||
"kind": "farm_mine"
|
||||
},
|
||||
"value": 175
|
||||
}
|
||||
],
|
||||
"executable_import_ready": true,
|
||||
"notes": [
|
||||
"grounded aggregate cargo economics descriptors execute through bounded cargo override surfaces"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"notes": [
|
||||
"aggregate cargo economics executable sample"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -55,10 +55,22 @@ def classify(row: dict[str, object]) -> dict[str, object]:
|
|||
runtime_key = normalize_world_scalar_key(label)
|
||||
runtime_status = "executable"
|
||||
executable_in_runtime = True
|
||||
elif 105 <= descriptor_id <= 176:
|
||||
elif descriptor_id == 105:
|
||||
parameter_family = "cargo_price_scalar"
|
||||
elif 177 <= descriptor_id <= 240:
|
||||
runtime_status = "executable"
|
||||
executable_in_runtime = True
|
||||
elif 106 <= descriptor_id <= 176:
|
||||
parameter_family = "cargo_price_scalar"
|
||||
elif 177 <= descriptor_id <= 179:
|
||||
parameter_family = "cargo_production_scalar"
|
||||
runtime_status = "executable"
|
||||
executable_in_runtime = True
|
||||
elif 180 <= descriptor_id <= 229:
|
||||
parameter_family = "cargo_production_scalar"
|
||||
elif 230 <= descriptor_id <= 240:
|
||||
parameter_family = "cargo_production_scalar"
|
||||
runtime_status = "executable"
|
||||
executable_in_runtime = True
|
||||
elif 241 <= descriptor_id <= 351 or 457 <= descriptor_id <= 474:
|
||||
parameter_family = "locomotive_availability_scalar"
|
||||
elif 352 <= descriptor_id <= 451 or 475 <= descriptor_id <= 502:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue