Broaden chairman governance event coverage
This commit is contained in:
parent
86cf89b26c
commit
f8350a48c5
18 changed files with 1939 additions and 13 deletions
|
|
@ -405,6 +405,14 @@ fn apply_runtime_effects(
|
|||
state.selected_chairman_profile_id = None;
|
||||
}
|
||||
if let Some(linked_company_id) = linked_company_id {
|
||||
if let Some(company) = state
|
||||
.companies
|
||||
.iter_mut()
|
||||
.find(|company| company.company_id == linked_company_id)
|
||||
{
|
||||
company.linked_chairman_profile_id = None;
|
||||
mutated_company_ids.insert(linked_company_id);
|
||||
}
|
||||
for other in &mut state.chairman_profiles {
|
||||
if other.profile_id != profile_id
|
||||
&& other.linked_company_id == Some(linked_company_id)
|
||||
|
|
@ -1222,6 +1230,9 @@ fn company_metric_value(company: &crate::RuntimeCompany, metric: RuntimeCompanyM
|
|||
RuntimeCompanyMetric::TotalDebt => company.debt as i64,
|
||||
RuntimeCompanyMetric::CreditRating => company.credit_rating_score.unwrap_or(0),
|
||||
RuntimeCompanyMetric::PrimeRate => company.prime_rate.unwrap_or(0),
|
||||
RuntimeCompanyMetric::BookValuePerShare => company.book_value_per_share,
|
||||
RuntimeCompanyMetric::InvestorConfidence => company.investor_confidence,
|
||||
RuntimeCompanyMetric::ManagementAttitude => company.management_attitude,
|
||||
RuntimeCompanyMetric::TrackPiecesTotal => i64::from(company.track_piece_counts.total),
|
||||
RuntimeCompanyMetric::TrackPiecesSingle => i64::from(company.track_piece_counts.single),
|
||||
RuntimeCompanyMetric::TrackPiecesDouble => i64::from(company.track_piece_counts.double),
|
||||
|
|
@ -1402,10 +1413,11 @@ mod tests {
|
|||
|
||||
use super::*;
|
||||
use crate::{
|
||||
CalendarPoint, RuntimeCompany, RuntimeCompanyControllerKind, RuntimeCompanyTarget,
|
||||
RuntimeEffect, RuntimeEventRecord, RuntimeEventRecordTemplate, RuntimePlayer,
|
||||
RuntimeSaveProfileState, RuntimeServiceState, RuntimeTerritory, RuntimeTerritoryTarget,
|
||||
RuntimeTrackPieceCounts, RuntimeTrain, RuntimeWorldRestoreState,
|
||||
CalendarPoint, RuntimeChairmanMetric, RuntimeChairmanProfile, RuntimeChairmanTarget,
|
||||
RuntimeCompany, RuntimeCompanyControllerKind, RuntimeCompanyTarget, RuntimeCondition,
|
||||
RuntimeConditionComparator, RuntimeEffect, RuntimeEventRecord, RuntimeEventRecordTemplate,
|
||||
RuntimePlayer, RuntimeSaveProfileState, RuntimeServiceState, RuntimeTerritory,
|
||||
RuntimeTerritoryTarget, RuntimeTrackPieceCounts, RuntimeTrain, RuntimeWorldRestoreState,
|
||||
};
|
||||
|
||||
fn state() -> RuntimeState {
|
||||
|
|
@ -1430,6 +1442,12 @@ mod tests {
|
|||
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,
|
||||
}],
|
||||
selected_company_id: None,
|
||||
players: Vec::new(),
|
||||
|
|
@ -1613,6 +1631,12 @@ mod tests {
|
|||
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,
|
||||
},
|
||||
RuntimeCompany {
|
||||
company_id: 2,
|
||||
|
|
@ -1624,6 +1648,12 @@ mod tests {
|
|||
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,
|
||||
},
|
||||
],
|
||||
event_runtime_records: vec![RuntimeEventRecord {
|
||||
|
|
@ -1824,6 +1854,12 @@ mod tests {
|
|||
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,
|
||||
},
|
||||
RuntimeCompany {
|
||||
company_id: 2,
|
||||
|
|
@ -1835,6 +1871,12 @@ mod tests {
|
|||
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,
|
||||
},
|
||||
],
|
||||
selected_company_id: Some(1),
|
||||
|
|
@ -1970,6 +2012,12 @@ mod tests {
|
|||
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,
|
||||
},
|
||||
RuntimeCompany {
|
||||
company_id: 2,
|
||||
|
|
@ -1981,6 +2029,12 @@ mod tests {
|
|||
track_piece_counts: RuntimeTrackPieceCounts::default(),
|
||||
active: false,
|
||||
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,
|
||||
},
|
||||
RuntimeCompany {
|
||||
company_id: 3,
|
||||
|
|
@ -1992,6 +2046,12 @@ mod tests {
|
|||
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,
|
||||
},
|
||||
],
|
||||
event_runtime_records: vec![
|
||||
|
|
@ -2068,6 +2128,12 @@ mod tests {
|
|||
track_piece_counts: RuntimeTrackPieceCounts::default(),
|
||||
active: true,
|
||||
available_track_laying_capacity: Some(8),
|
||||
linked_chairman_profile_id: None,
|
||||
book_value_per_share: 0,
|
||||
investor_confidence: 0,
|
||||
management_attitude: 0,
|
||||
takeover_cooldown_year: None,
|
||||
merger_cooldown_year: None,
|
||||
}],
|
||||
selected_company_id: Some(1),
|
||||
event_runtime_records: vec![RuntimeEventRecord {
|
||||
|
|
@ -2148,6 +2214,12 @@ mod tests {
|
|||
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,
|
||||
},
|
||||
RuntimeCompany {
|
||||
company_id: 2,
|
||||
|
|
@ -2159,6 +2231,12 @@ mod tests {
|
|||
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,
|
||||
},
|
||||
],
|
||||
event_runtime_records: vec![RuntimeEventRecord {
|
||||
|
|
@ -2203,6 +2281,12 @@ mod tests {
|
|||
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,
|
||||
},
|
||||
RuntimeCompany {
|
||||
company_id: 2,
|
||||
|
|
@ -2214,6 +2298,12 @@ mod tests {
|
|||
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,
|
||||
},
|
||||
],
|
||||
territories: vec![
|
||||
|
|
@ -2588,6 +2678,12 @@ mod tests {
|
|||
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,
|
||||
}],
|
||||
event_runtime_records: vec![RuntimeEventRecord {
|
||||
record_id: 30,
|
||||
|
|
@ -2982,6 +3078,12 @@ mod tests {
|
|||
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,
|
||||
},
|
||||
RuntimeCompany {
|
||||
company_id: 2,
|
||||
|
|
@ -2993,6 +3095,12 @@ mod tests {
|
|||
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,
|
||||
},
|
||||
],
|
||||
selected_company_id: Some(1),
|
||||
|
|
@ -3114,4 +3222,280 @@ mod tests {
|
|||
assert!(!state.trains[1].retired);
|
||||
assert!(!state.trains[2].retired);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_chairman_cash_supports_all_active_target() {
|
||||
let mut state = RuntimeState {
|
||||
chairman_profiles: vec![
|
||||
RuntimeChairmanProfile {
|
||||
profile_id: 1,
|
||||
name: "Chairman One".to_string(),
|
||||
active: true,
|
||||
current_cash: 10,
|
||||
linked_company_id: None,
|
||||
company_holdings: BTreeMap::new(),
|
||||
holdings_value_total: 0,
|
||||
net_worth_total: 0,
|
||||
purchasing_power_total: 0,
|
||||
},
|
||||
RuntimeChairmanProfile {
|
||||
profile_id: 2,
|
||||
name: "Chairman Two".to_string(),
|
||||
active: true,
|
||||
current_cash: 20,
|
||||
linked_company_id: None,
|
||||
company_holdings: BTreeMap::new(),
|
||||
holdings_value_total: 0,
|
||||
net_worth_total: 0,
|
||||
purchasing_power_total: 0,
|
||||
},
|
||||
RuntimeChairmanProfile {
|
||||
profile_id: 3,
|
||||
name: "Chairman Three".to_string(),
|
||||
active: false,
|
||||
current_cash: 30,
|
||||
linked_company_id: None,
|
||||
company_holdings: BTreeMap::new(),
|
||||
holdings_value_total: 0,
|
||||
net_worth_total: 0,
|
||||
purchasing_power_total: 0,
|
||||
},
|
||||
],
|
||||
event_runtime_records: vec![RuntimeEventRecord {
|
||||
record_id: 93,
|
||||
trigger_kind: 6,
|
||||
active: true,
|
||||
service_count: 0,
|
||||
marks_collection_dirty: false,
|
||||
one_shot: false,
|
||||
has_fired: false,
|
||||
conditions: Vec::new(),
|
||||
effects: vec![RuntimeEffect::SetChairmanCash {
|
||||
target: RuntimeChairmanTarget::AllActive,
|
||||
value: 77,
|
||||
}],
|
||||
}],
|
||||
..state()
|
||||
};
|
||||
|
||||
execute_step_command(
|
||||
&mut state,
|
||||
&StepCommand::ServiceTriggerKind { trigger_kind: 6 },
|
||||
)
|
||||
.expect("all-active chairman cash effect should succeed");
|
||||
|
||||
assert_eq!(state.chairman_profiles[0].current_cash, 77);
|
||||
assert_eq!(state.chairman_profiles[1].current_cash, 77);
|
||||
assert_eq!(state.chairman_profiles[2].current_cash, 30);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deactivate_chairman_clears_selected_and_company_links_for_ids_target() {
|
||||
let mut state = RuntimeState {
|
||||
companies: vec![
|
||||
RuntimeCompany {
|
||||
company_id: 1,
|
||||
controller_kind: RuntimeCompanyControllerKind::Human,
|
||||
current_cash: 100,
|
||||
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: Some(1),
|
||||
book_value_per_share: 0,
|
||||
investor_confidence: 0,
|
||||
management_attitude: 0,
|
||||
takeover_cooldown_year: None,
|
||||
merger_cooldown_year: None,
|
||||
},
|
||||
RuntimeCompany {
|
||||
company_id: 2,
|
||||
controller_kind: RuntimeCompanyControllerKind::Ai,
|
||||
current_cash: 80,
|
||||
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: Some(2),
|
||||
book_value_per_share: 0,
|
||||
investor_confidence: 0,
|
||||
management_attitude: 0,
|
||||
takeover_cooldown_year: None,
|
||||
merger_cooldown_year: None,
|
||||
},
|
||||
],
|
||||
chairman_profiles: vec![
|
||||
RuntimeChairmanProfile {
|
||||
profile_id: 1,
|
||||
name: "Chairman One".to_string(),
|
||||
active: true,
|
||||
current_cash: 10,
|
||||
linked_company_id: Some(1),
|
||||
company_holdings: BTreeMap::new(),
|
||||
holdings_value_total: 0,
|
||||
net_worth_total: 0,
|
||||
purchasing_power_total: 0,
|
||||
},
|
||||
RuntimeChairmanProfile {
|
||||
profile_id: 2,
|
||||
name: "Chairman Two".to_string(),
|
||||
active: true,
|
||||
current_cash: 20,
|
||||
linked_company_id: Some(2),
|
||||
company_holdings: BTreeMap::new(),
|
||||
holdings_value_total: 0,
|
||||
net_worth_total: 0,
|
||||
purchasing_power_total: 0,
|
||||
},
|
||||
],
|
||||
selected_chairman_profile_id: Some(2),
|
||||
event_runtime_records: vec![RuntimeEventRecord {
|
||||
record_id: 94,
|
||||
trigger_kind: 6,
|
||||
active: true,
|
||||
service_count: 0,
|
||||
marks_collection_dirty: false,
|
||||
one_shot: false,
|
||||
has_fired: false,
|
||||
conditions: Vec::new(),
|
||||
effects: vec![RuntimeEffect::DeactivateChairman {
|
||||
target: RuntimeChairmanTarget::Ids { ids: vec![2] },
|
||||
}],
|
||||
}],
|
||||
..state()
|
||||
};
|
||||
|
||||
execute_step_command(
|
||||
&mut state,
|
||||
&StepCommand::ServiceTriggerKind { trigger_kind: 6 },
|
||||
)
|
||||
.expect("ids-target chairman deactivation should succeed");
|
||||
|
||||
assert!(state.chairman_profiles[0].active);
|
||||
assert!(!state.chairman_profiles[1].active);
|
||||
assert_eq!(state.chairman_profiles[1].linked_company_id, None);
|
||||
assert_eq!(state.selected_chairman_profile_id, None);
|
||||
assert_eq!(state.companies[0].linked_chairman_profile_id, Some(1));
|
||||
assert_eq!(state.companies[1].linked_chairman_profile_id, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn company_governance_metric_conditions_gate_execution() {
|
||||
let mut state = RuntimeState {
|
||||
companies: vec![RuntimeCompany {
|
||||
company_id: 1,
|
||||
controller_kind: RuntimeCompanyControllerKind::Human,
|
||||
current_cash: 100,
|
||||
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: 2620,
|
||||
investor_confidence: 37,
|
||||
management_attitude: 58,
|
||||
takeover_cooldown_year: Some(1844),
|
||||
merger_cooldown_year: Some(1845),
|
||||
}],
|
||||
selected_company_id: Some(1),
|
||||
event_runtime_records: vec![RuntimeEventRecord {
|
||||
record_id: 95,
|
||||
trigger_kind: 6,
|
||||
active: true,
|
||||
service_count: 0,
|
||||
marks_collection_dirty: false,
|
||||
one_shot: false,
|
||||
has_fired: false,
|
||||
conditions: vec![RuntimeCondition::CompanyNumericThreshold {
|
||||
target: RuntimeCompanyTarget::SelectedCompany,
|
||||
metric: crate::RuntimeCompanyMetric::BookValuePerShare,
|
||||
comparator: RuntimeConditionComparator::Eq,
|
||||
value: 2620,
|
||||
}],
|
||||
effects: vec![RuntimeEffect::SetWorldFlag {
|
||||
key: "world.book_value_gate_passed".to_string(),
|
||||
value: true,
|
||||
}],
|
||||
}],
|
||||
..state()
|
||||
};
|
||||
|
||||
execute_step_command(
|
||||
&mut state,
|
||||
&StepCommand::ServiceTriggerKind { trigger_kind: 6 },
|
||||
)
|
||||
.expect("book-value company condition should gate execution");
|
||||
|
||||
assert_eq!(
|
||||
state.world_flags.get("world.book_value_gate_passed"),
|
||||
Some(&true)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn chairman_metric_conditions_support_all_active_target() {
|
||||
let mut state = RuntimeState {
|
||||
chairman_profiles: vec![
|
||||
RuntimeChairmanProfile {
|
||||
profile_id: 1,
|
||||
name: "Chairman One".to_string(),
|
||||
active: true,
|
||||
current_cash: 20,
|
||||
linked_company_id: None,
|
||||
company_holdings: BTreeMap::new(),
|
||||
holdings_value_total: 500,
|
||||
net_worth_total: 700,
|
||||
purchasing_power_total: 900,
|
||||
},
|
||||
RuntimeChairmanProfile {
|
||||
profile_id: 2,
|
||||
name: "Chairman Two".to_string(),
|
||||
active: true,
|
||||
current_cash: 30,
|
||||
linked_company_id: None,
|
||||
company_holdings: BTreeMap::new(),
|
||||
holdings_value_total: 600,
|
||||
net_worth_total: 800,
|
||||
purchasing_power_total: 1000,
|
||||
},
|
||||
],
|
||||
event_runtime_records: vec![RuntimeEventRecord {
|
||||
record_id: 96,
|
||||
trigger_kind: 6,
|
||||
active: true,
|
||||
service_count: 0,
|
||||
marks_collection_dirty: false,
|
||||
one_shot: false,
|
||||
has_fired: false,
|
||||
conditions: vec![RuntimeCondition::ChairmanNumericThreshold {
|
||||
target: RuntimeChairmanTarget::AllActive,
|
||||
metric: RuntimeChairmanMetric::PurchasingPowerTotal,
|
||||
comparator: RuntimeConditionComparator::Ge,
|
||||
value: 900,
|
||||
}],
|
||||
effects: vec![RuntimeEffect::SetWorldFlag {
|
||||
key: "world.chairman_gate_passed".to_string(),
|
||||
value: true,
|
||||
}],
|
||||
}],
|
||||
..state()
|
||||
};
|
||||
|
||||
execute_step_command(
|
||||
&mut state,
|
||||
&StepCommand::ServiceTriggerKind { trigger_kind: 6 },
|
||||
)
|
||||
.expect("all-active chairman condition should gate execution");
|
||||
|
||||
assert_eq!(
|
||||
state.world_flags.get("world.chairman_gate_passed"),
|
||||
Some(&true)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue