Refresh company periodic side latches at boundary
This commit is contained in:
parent
b1c6dad723
commit
6fc8da2153
3 changed files with 215 additions and 13 deletions
|
|
@ -2395,13 +2395,14 @@ impl RuntimeState {
|
|||
}
|
||||
}
|
||||
|
||||
let known_company_ids = self
|
||||
.companies
|
||||
.iter()
|
||||
.map(|company| company.company_id)
|
||||
.collect::<BTreeSet<_>>();
|
||||
self.service_state
|
||||
.company_periodic_side_latch_state
|
||||
.retain(|company_id, _| {
|
||||
self.service_state
|
||||
.company_market_state
|
||||
.contains_key(company_id)
|
||||
});
|
||||
.retain(|company_id, _| known_company_ids.contains(company_id));
|
||||
for (company_id, market_state) in &self.service_state.company_market_state {
|
||||
self.service_state
|
||||
.company_periodic_side_latch_state
|
||||
|
|
@ -6818,6 +6819,93 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn preserves_company_periodic_side_latch_state_without_market_projection() {
|
||||
let mut state = RuntimeState {
|
||||
calendar: CalendarPoint {
|
||||
year: 1830,
|
||||
month_slot: 0,
|
||||
phase_slot: 0,
|
||||
tick_slot: 0,
|
||||
},
|
||||
world_flags: BTreeMap::new(),
|
||||
save_profile: RuntimeSaveProfileState::default(),
|
||||
world_restore: RuntimeWorldRestoreState::default(),
|
||||
metadata: BTreeMap::new(),
|
||||
companies: vec![RuntimeCompany {
|
||||
company_id: 1,
|
||||
current_cash: 0,
|
||||
debt: 0,
|
||||
credit_rating_score: None,
|
||||
prime_rate: None,
|
||||
track_piece_counts: RuntimeTrackPieceCounts::default(),
|
||||
active: true,
|
||||
available_track_laying_capacity: None,
|
||||
linked_chairman_profile_id: None,
|
||||
book_value_per_share: 0,
|
||||
investor_confidence: 0,
|
||||
management_attitude: 0,
|
||||
takeover_cooldown_year: None,
|
||||
merger_cooldown_year: None,
|
||||
controller_kind: RuntimeCompanyControllerKind::Unknown,
|
||||
}],
|
||||
selected_company_id: Some(1),
|
||||
players: Vec::new(),
|
||||
selected_player_id: None,
|
||||
chairman_profiles: Vec::new(),
|
||||
selected_chairman_profile_id: None,
|
||||
trains: Vec::new(),
|
||||
locomotive_catalog: Vec::new(),
|
||||
cargo_catalog: Vec::new(),
|
||||
territories: Vec::new(),
|
||||
company_territory_track_piece_counts: Vec::new(),
|
||||
company_territory_access: Vec::new(),
|
||||
packed_event_collection: None,
|
||||
event_runtime_records: Vec::new(),
|
||||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::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_runtime_variables: BTreeMap::new(),
|
||||
company_runtime_variables: BTreeMap::new(),
|
||||
player_runtime_variables: BTreeMap::new(),
|
||||
territory_runtime_variables: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState {
|
||||
company_periodic_side_latch_state: BTreeMap::from([(
|
||||
1,
|
||||
RuntimeCompanyPeriodicSideLatchState {
|
||||
preferred_locomotive_engine_type_raw_u8: Some(2),
|
||||
city_connection_latch: true,
|
||||
linked_transit_latch: false,
|
||||
},
|
||||
)]),
|
||||
..RuntimeServiceState::default()
|
||||
},
|
||||
};
|
||||
|
||||
state.refresh_derived_market_state();
|
||||
|
||||
assert_eq!(
|
||||
state
|
||||
.service_state
|
||||
.company_periodic_side_latch_state
|
||||
.get(&1),
|
||||
Some(&RuntimeCompanyPeriodicSideLatchState {
|
||||
preferred_locomotive_engine_type_raw_u8: Some(2),
|
||||
city_connection_latch: true,
|
||||
linked_transit_latch: false,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reads_grounded_company_stat_family_slots_from_runtime_state() {
|
||||
let mut year_stat_family_qword_bits = vec![
|
||||
|
|
|
|||
|
|
@ -247,6 +247,7 @@ fn service_periodic_boundary(
|
|||
service_events: &mut Vec<ServiceEvent>,
|
||||
) -> Result<(), String> {
|
||||
state.service_state.periodic_boundary_calls += 1;
|
||||
service_refresh_company_periodic_side_latch_state(state);
|
||||
|
||||
for trigger_kind in PERIODIC_TRIGGER_KIND_ORDER {
|
||||
service_trigger_kind(state, trigger_kind, service_events)?;
|
||||
|
|
@ -256,6 +257,52 @@ fn service_periodic_boundary(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn service_refresh_company_periodic_side_latch_state(state: &mut RuntimeState) {
|
||||
let active_company_ids = state
|
||||
.companies
|
||||
.iter()
|
||||
.filter(|company| company.active)
|
||||
.map(|company| company.company_id)
|
||||
.collect::<BTreeSet<_>>();
|
||||
state
|
||||
.service_state
|
||||
.company_periodic_side_latch_state
|
||||
.retain(|company_id, _| active_company_ids.contains(company_id));
|
||||
|
||||
for company_id in active_company_ids {
|
||||
match (
|
||||
state
|
||||
.service_state
|
||||
.company_periodic_side_latch_state
|
||||
.get_mut(&company_id),
|
||||
state.service_state.company_market_state.get(&company_id),
|
||||
) {
|
||||
(Some(latch_state), Some(market_state)) => {
|
||||
latch_state.preferred_locomotive_engine_type_raw_u8 = None;
|
||||
latch_state.city_connection_latch = market_state.city_connection_latch;
|
||||
latch_state.linked_transit_latch = market_state.linked_transit_latch;
|
||||
}
|
||||
(Some(latch_state), None) => {
|
||||
latch_state.preferred_locomotive_engine_type_raw_u8 = None;
|
||||
}
|
||||
(None, Some(market_state)) => {
|
||||
state
|
||||
.service_state
|
||||
.company_periodic_side_latch_state
|
||||
.insert(
|
||||
company_id,
|
||||
crate::RuntimeCompanyPeriodicSideLatchState {
|
||||
preferred_locomotive_engine_type_raw_u8: None,
|
||||
city_connection_latch: market_state.city_connection_latch,
|
||||
linked_transit_latch: market_state.linked_transit_latch,
|
||||
},
|
||||
);
|
||||
}
|
||||
(None, None) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn service_decode_saved_f64_bits(raw_bits: u64) -> Option<f64> {
|
||||
let value = f64::from_bits(raw_bits);
|
||||
value.is_finite().then_some(value)
|
||||
|
|
@ -2884,11 +2931,11 @@ mod tests {
|
|||
use crate::{
|
||||
CalendarPoint, RuntimeCargoPriceTarget, RuntimeCargoProductionTarget,
|
||||
RuntimeChairmanMetric, RuntimeChairmanProfile, RuntimeChairmanTarget, RuntimeCompany,
|
||||
RuntimeCompanyControllerKind, RuntimeCompanyTarget, RuntimeCondition,
|
||||
RuntimeConditionComparator, RuntimeEffect, RuntimeEventRecord, RuntimeEventRecordTemplate,
|
||||
RuntimePlayer, RuntimePlayerTarget, RuntimeSaveProfileState, RuntimeServiceState,
|
||||
RuntimeTerritory, RuntimeTerritoryTarget, RuntimeTrackPieceCounts, RuntimeTrain,
|
||||
RuntimeWorldRestoreState,
|
||||
RuntimeCompanyControllerKind, RuntimeCompanyPeriodicSideLatchState, RuntimeCompanyTarget,
|
||||
RuntimeCondition, RuntimeConditionComparator, RuntimeEffect, RuntimeEventRecord,
|
||||
RuntimeEventRecordTemplate, RuntimePlayer, RuntimePlayerTarget, RuntimeSaveProfileState,
|
||||
RuntimeServiceState, RuntimeTerritory, RuntimeTerritoryTarget, RuntimeTrackPieceCounts,
|
||||
RuntimeTrain, RuntimeWorldRestoreState,
|
||||
};
|
||||
|
||||
fn state() -> RuntimeState {
|
||||
|
|
@ -3227,6 +3274,70 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn periodic_boundary_clears_transient_preferred_locomotive_side_latch() {
|
||||
let mut state = state();
|
||||
state.service_state.company_periodic_side_latch_state = BTreeMap::from([(
|
||||
1,
|
||||
RuntimeCompanyPeriodicSideLatchState {
|
||||
preferred_locomotive_engine_type_raw_u8: Some(2),
|
||||
city_connection_latch: true,
|
||||
linked_transit_latch: false,
|
||||
},
|
||||
)]);
|
||||
|
||||
execute_step_command(&mut state, &StepCommand::ServicePeriodicBoundary)
|
||||
.expect("periodic boundary should refresh periodic side latches");
|
||||
|
||||
assert_eq!(
|
||||
state
|
||||
.service_state
|
||||
.company_periodic_side_latch_state
|
||||
.get(&1),
|
||||
Some(&RuntimeCompanyPeriodicSideLatchState {
|
||||
preferred_locomotive_engine_type_raw_u8: None,
|
||||
city_connection_latch: true,
|
||||
linked_transit_latch: false,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn periodic_boundary_reseeds_finance_side_latches_from_market_state() {
|
||||
let mut state = state();
|
||||
state.service_state.company_market_state = BTreeMap::from([(
|
||||
1,
|
||||
crate::RuntimeCompanyMarketState {
|
||||
city_connection_latch: false,
|
||||
linked_transit_latch: true,
|
||||
..crate::RuntimeCompanyMarketState::default()
|
||||
},
|
||||
)]);
|
||||
state.service_state.company_periodic_side_latch_state = BTreeMap::from([(
|
||||
1,
|
||||
RuntimeCompanyPeriodicSideLatchState {
|
||||
preferred_locomotive_engine_type_raw_u8: Some(2),
|
||||
city_connection_latch: true,
|
||||
linked_transit_latch: false,
|
||||
},
|
||||
)]);
|
||||
|
||||
execute_step_command(&mut state, &StepCommand::ServicePeriodicBoundary)
|
||||
.expect("periodic boundary should reseed finance latches from market state");
|
||||
|
||||
assert_eq!(
|
||||
state
|
||||
.service_state
|
||||
.company_periodic_side_latch_state
|
||||
.get(&1),
|
||||
Some(&RuntimeCompanyPeriodicSideLatchState {
|
||||
preferred_locomotive_engine_type_raw_u8: None,
|
||||
city_connection_latch: false,
|
||||
linked_transit_latch: true,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn periodic_boundary_applies_dividend_adjustment_from_annual_finance_policy() {
|
||||
let mut year_stat_family_qword_bits = vec![
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue