diff --git a/crates/rrt-runtime/src/lib.rs b/crates/rrt-runtime/src/lib.rs index e0e736d..146bd83 100644 --- a/crates/rrt-runtime/src/lib.rs +++ b/crates/rrt-runtime/src/lib.rs @@ -124,7 +124,10 @@ pub use smp::{ inspect_save_company_and_chairman_analysis_file, inspect_smp_bytes, inspect_smp_file, load_save_slice_file, load_save_slice_from_report, }; -pub use step::{BoundaryEvent, ServiceEvent, StepCommand, StepResult, execute_step_command}; +pub use step::{ + AnnualFinanceNewsEvent, BoundaryEvent, ServiceEvent, StepCommand, StepResult, + execute_step_command, +}; pub use summary::RuntimeSummary; pub use win::{ WinAnonymousSelectorRecord, WinHeaderWord, WinInspectionReport, WinReferenceDeltaFrequency, diff --git a/crates/rrt-runtime/src/step.rs b/crates/rrt-runtime/src/step.rs index e633af9..4608211 100644 --- a/crates/rrt-runtime/src/step.rs +++ b/crates/rrt-runtime/src/step.rs @@ -59,6 +59,17 @@ pub struct BoundaryEvent { pub calendar: crate::CalendarPoint, } +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct AnnualFinanceNewsEvent { + pub company_id: u32, + pub selector_label: String, + pub action_label: String, + pub retired_principal_total: u64, + pub issued_principal_total: u64, + pub repurchased_share_count: u64, + pub issued_share_count: u64, +} + #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct ServiceEvent { pub kind: String, @@ -73,6 +84,8 @@ pub struct ServiceEvent { pub removed_record_ids: Vec, #[serde(default)] pub finance_news_family_candidates: BTreeMap, + #[serde(default)] + pub annual_finance_news_events: Vec, pub dirty_rerun: bool, } @@ -516,6 +529,7 @@ fn service_company_annual_finance_policy( let mut mutated_company_ids = BTreeSet::new(); let mut applied_effect_count = 0u32; let mut finance_news_family_candidates = BTreeMap::new(); + let mut annual_finance_news_events = Vec::new(); for company_id in active_company_ids { let Some(policy_state) = runtime_company_annual_finance_policy_state(state, company_id) @@ -579,6 +593,27 @@ fn service_company_annual_finance_policy( .annual_finance_last_news_family_candidates .insert(company_id, label.to_string()); finance_news_family_candidates.insert(company_id, label.to_string()); + annual_finance_news_events.push(AnnualFinanceNewsEvent { + company_id, + selector_label: label.to_string(), + action_label: + crate::runtime::runtime_company_annual_finance_policy_action_label( + policy_state.action, + ) + .to_string(), + retired_principal_total: state + .service_state + .annual_bond_last_retired_principal_total, + issued_principal_total: state + .service_state + .annual_bond_last_issued_principal_total, + repurchased_share_count: state + .service_state + .annual_stock_repurchase_last_share_count, + issued_share_count: state + .service_state + .annual_stock_issue_last_share_count, + }); } applied_effect_count += 1; mutated_company_ids.insert(company_id); @@ -664,6 +699,27 @@ fn service_company_annual_finance_policy( .annual_finance_last_news_family_candidates .insert(company_id, label.to_string()); finance_news_family_candidates.insert(company_id, label.to_string()); + annual_finance_news_events.push(AnnualFinanceNewsEvent { + company_id, + selector_label: label.to_string(), + action_label: + crate::runtime::runtime_company_annual_finance_policy_action_label( + policy_state.action, + ) + .to_string(), + retired_principal_total: state + .service_state + .annual_bond_last_retired_principal_total, + issued_principal_total: state + .service_state + .annual_bond_last_issued_principal_total, + repurchased_share_count: state + .service_state + .annual_stock_repurchase_last_share_count, + issued_share_count: state + .service_state + .annual_stock_issue_last_share_count, + }); } applied_effect_count += 1; mutated_company_ids.insert(company_id); @@ -824,6 +880,27 @@ fn service_company_annual_finance_policy( .annual_finance_last_news_family_candidates .insert(company_id, label.to_string()); finance_news_family_candidates.insert(company_id, label.to_string()); + annual_finance_news_events.push(AnnualFinanceNewsEvent { + company_id, + selector_label: label.to_string(), + action_label: + crate::runtime::runtime_company_annual_finance_policy_action_label( + policy_state.action, + ) + .to_string(), + retired_principal_total: state + .service_state + .annual_bond_last_retired_principal_total, + issued_principal_total: state + .service_state + .annual_bond_last_issued_principal_total, + repurchased_share_count: state + .service_state + .annual_stock_repurchase_last_share_count, + issued_share_count: state + .service_state + .annual_stock_issue_last_share_count, + }); } applied_effect_count += 1; mutated_company_ids.insert(company_id); @@ -914,6 +991,27 @@ fn service_company_annual_finance_policy( .annual_finance_last_news_family_candidates .insert(company_id, label.to_string()); finance_news_family_candidates.insert(company_id, label.to_string()); + annual_finance_news_events.push(AnnualFinanceNewsEvent { + company_id, + selector_label: label.to_string(), + action_label: + crate::runtime::runtime_company_annual_finance_policy_action_label( + policy_state.action, + ) + .to_string(), + retired_principal_total: state + .service_state + .annual_bond_last_retired_principal_total, + issued_principal_total: state + .service_state + .annual_bond_last_issued_principal_total, + repurchased_share_count: state + .service_state + .annual_stock_repurchase_last_share_count, + issued_share_count: state + .service_state + .annual_stock_issue_last_share_count, + }); } applied_effect_count += 1; mutated_company_ids.insert(company_id); @@ -935,6 +1033,7 @@ fn service_company_annual_finance_policy( deactivated_record_ids: Vec::new(), removed_record_ids: Vec::new(), finance_news_family_candidates, + annual_finance_news_events, dirty_rerun: false, }); @@ -1040,6 +1139,7 @@ fn service_trigger_kind( deactivated_record_ids, removed_record_ids, finance_news_family_candidates: BTreeMap::new(), + annual_finance_news_events: Vec::new(), dirty_rerun, }); @@ -3013,15 +3113,18 @@ mod tests { state.service_state.company_market_state[&22].current_issue_calendar_word_2, 0x0001_0001 ); - assert!( - result - .service_events - .iter() - .any(|event| event.kind == "annual_finance_policy" - && event.applied_effect_count == 1 - && event.mutated_company_ids == vec![22] - && event.finance_news_family_candidates.get(&22) == Some(&"4053".to_string())) - ); + assert!(result.service_events.iter().any(|event| { + event.kind == "annual_finance_policy" + && event.applied_effect_count == 1 + && event.mutated_company_ids == vec![22] + && event.finance_news_family_candidates.get(&22) == Some(&"4053".to_string()) + && event.annual_finance_news_events.iter().any(|news| { + news.company_id == 22 + && news.selector_label == "4053" + && news.action_label == "stock_issue" + && news.issued_share_count == 4_000 + }) + })); } #[test] @@ -3173,15 +3276,18 @@ mod tests { state.service_state.company_market_state[&23].outstanding_shares, 9_000 ); - assert!( - result - .service_events - .iter() - .any(|event| event.kind == "annual_finance_policy" - && event.applied_effect_count == 1 - && event.mutated_company_ids == vec![23] - && event.finance_news_family_candidates.get(&23) == Some(&"2887".to_string())) - ); + assert!(result.service_events.iter().any(|event| { + event.kind == "annual_finance_policy" + && event.applied_effect_count == 1 + && event.mutated_company_ids == vec![23] + && event.finance_news_family_candidates.get(&23) == Some(&"2887".to_string()) + && event.annual_finance_news_events.iter().any(|news| { + news.company_id == 23 + && news.selector_label == "2887" + && news.action_label == "stock_repurchase" + && news.repurchased_share_count == 1_000 + }) + })); } #[test] @@ -3317,15 +3423,19 @@ mod tests { coupon_rate_raw_u32: 0.09f32.to_bits(), }] ); - assert!( - result - .service_events - .iter() - .any(|event| event.kind == "annual_finance_policy" - && event.applied_effect_count == 1 - && event.mutated_company_ids == vec![24] - && event.finance_news_family_candidates.get(&24) == Some(&"2886".to_string())) - ); + assert!(result.service_events.iter().any(|event| { + event.kind == "annual_finance_policy" + && event.applied_effect_count == 1 + && event.mutated_company_ids == vec![24] + && event.finance_news_family_candidates.get(&24) == Some(&"2886".to_string()) + && event.annual_finance_news_events.iter().any(|news| { + news.company_id == 24 + && news.selector_label == "2886" + && news.action_label == "bond_issue" + && news.retired_principal_total == 0 + && news.issued_principal_total == 500_000 + }) + })); } #[test] @@ -3479,15 +3589,19 @@ mod tests { state.service_state.company_market_state[&25].highest_coupon_live_bond_principal, None ); - assert!( - result - .service_events - .iter() - .any(|event| event.kind == "annual_finance_policy" - && event.applied_effect_count == 1 - && event.mutated_company_ids == vec![25] - && event.finance_news_family_candidates.get(&25) == Some(&"2885".to_string())) - ); + assert!(result.service_events.iter().any(|event| { + event.kind == "annual_finance_policy" + && event.applied_effect_count == 1 + && event.mutated_company_ids == vec![25] + && event.finance_news_family_candidates.get(&25) == Some(&"2885".to_string()) + && event.annual_finance_news_events.iter().any(|news| { + news.company_id == 25 + && news.selector_label == "2885" + && news.action_label == "bond_issue" + && news.retired_principal_total == 350_000 + && news.issued_principal_total == 0 + }) + })); } #[test] @@ -3654,15 +3768,19 @@ mod tests { }, ] ); - assert!( - result - .service_events - .iter() - .any(|event| event.kind == "annual_finance_policy" - && event.applied_effect_count == 1 - && event.mutated_company_ids == vec![26] - && event.finance_news_family_candidates.get(&26) == Some(&"2883".to_string())) - ); + assert!(result.service_events.iter().any(|event| { + event.kind == "annual_finance_policy" + && event.applied_effect_count == 1 + && event.mutated_company_ids == vec![26] + && event.finance_news_family_candidates.get(&26) == Some(&"2883".to_string()) + && event.annual_finance_news_events.iter().any(|news| { + news.company_id == 26 + && news.selector_label == "2883" + && news.action_label == "bond_issue" + && news.retired_principal_total == 350_000 + && news.issued_principal_total == 1_000_000 + }) + })); } #[test]