Carry annual finance news family candidates

This commit is contained in:
Jan Petykiewicz 2026-04-18 05:38:37 -07:00
commit fb78879fac
5 changed files with 174 additions and 1 deletions

View file

@ -13997,6 +13997,7 @@ mod tests {
annual_bond_last_issued_principal_total: 0,
annual_stock_repurchase_last_share_count: 0,
annual_stock_issue_last_share_count: 0,
annual_finance_last_news_family_candidates: BTreeMap::new(),
chairman_issue_opinion_terms_raw_i32: BTreeMap::new(),
chairman_personality_raw_u8: BTreeMap::new(),
},

View file

@ -70,7 +70,8 @@ pub use runtime::{
RuntimeTerritory, RuntimeTerritoryMetric, RuntimeTerritoryTarget, RuntimeTrackMetric,
RuntimeTrackPieceCounts, RuntimeTrain, RuntimeWorldFinanceNeighborhoodCandidate,
RuntimeWorldIssueState, RuntimeWorldRestoreState,
runtime_annual_bond_principal_flow_relation_label, runtime_company_annual_bond_policy_state,
runtime_annual_bond_principal_flow_relation_label,
runtime_annual_finance_news_family_candidate_label, runtime_company_annual_bond_policy_state,
runtime_company_annual_creditor_pressure_state, runtime_company_annual_deep_distress_state,
runtime_company_annual_dividend_policy_state,
runtime_company_annual_finance_policy_action_label,

View file

@ -1245,6 +1245,8 @@ pub struct RuntimeServiceState {
#[serde(default)]
pub annual_stock_issue_last_share_count: u64,
#[serde(default)]
pub annual_finance_last_news_family_candidates: BTreeMap<u32, String>,
#[serde(default)]
pub chairman_issue_opinion_terms_raw_i32: BTreeMap<u32, Vec<i32>>,
#[serde(default)]
pub chairman_personality_raw_u8: BTreeMap<u32, u8>,
@ -2155,6 +2157,18 @@ impl RuntimeState {
));
}
}
for company_id in self
.service_state
.annual_finance_last_news_family_candidates
.keys()
{
if !seen_company_ids.contains(company_id) {
return Err(format!(
"service_state.annual_finance_last_news_family_candidates references unknown company_id {}",
company_id
));
}
}
for chairman_profile_id in self
.service_state
.chairman_issue_opinion_terms_raw_i32
@ -3649,6 +3663,33 @@ pub fn runtime_annual_bond_principal_flow_relation_label(
}
}
pub fn runtime_annual_finance_news_family_candidate_label(
action: RuntimeCompanyAnnualFinancePolicyAction,
retired_principal_total: u64,
issued_principal_total: u64,
repurchased_share_count: u64,
issued_share_count: u64,
) -> Option<&'static str> {
match action {
RuntimeCompanyAnnualFinancePolicyAction::CreditorPressureBankruptcy
| RuntimeCompanyAnnualFinancePolicyAction::DeepDistressBankruptcyFallback => Some("2881"),
RuntimeCompanyAnnualFinancePolicyAction::BondIssue => {
runtime_annual_bond_principal_flow_relation_label(
retired_principal_total,
issued_principal_total,
)
.map(|_| "2882_2886")
}
RuntimeCompanyAnnualFinancePolicyAction::StockRepurchase => {
(repurchased_share_count > 0).then_some("2887")
}
RuntimeCompanyAnnualFinancePolicyAction::StockIssue => {
(issued_share_count > 0).then_some("4053")
}
_ => None,
}
}
fn runtime_company_stock_issue_price_to_book_ratio_f64(
pressured_support_adjusted_share_price_scalar: f64,
book_value_per_share: f64,

View file

@ -15,6 +15,7 @@ use crate::{
RuntimeConditionComparator, RuntimeEffect, RuntimeEventRecordTemplate, RuntimePlayerTarget,
RuntimeState, RuntimeSummary, RuntimeTerritoryMetric, RuntimeTerritoryTarget,
RuntimeTrackMetric, RuntimeTrackPieceCounts, calendar::BoundaryEventKind,
runtime_annual_finance_news_family_candidate_label,
runtime_company_annual_dividend_policy_state, runtime_company_annual_finance_policy_state,
runtime_company_annual_stock_issue_state, runtime_company_annual_stock_repurchase_state,
runtime_company_book_value_per_share, runtime_company_credit_rating,
@ -499,6 +500,10 @@ fn service_company_annual_finance_policy(
.service_state
.annual_finance_last_actions
.retain(|company_id, _| active_company_id_set.contains(company_id));
state
.service_state
.annual_finance_last_news_family_candidates
.retain(|company_id, _| active_company_id_set.contains(company_id));
state.service_state.annual_finance_service_calls += 1;
state.service_state.annual_bond_last_retired_principal_total = 0;
state.service_state.annual_bond_last_issued_principal_total = 0;
@ -517,6 +522,10 @@ fn service_company_annual_finance_policy(
.service_state
.annual_finance_last_actions
.insert(company_id, policy_state.action);
state
.service_state
.annual_finance_last_news_family_candidates
.remove(&company_id);
*state
.service_state
.annual_finance_action_counts
@ -554,6 +563,18 @@ fn service_company_annual_finance_policy(
crate::RuntimeCompanyAnnualFinancePolicyAction::CreditorPressureBankruptcy
| crate::RuntimeCompanyAnnualFinancePolicyAction::DeepDistressBankruptcyFallback => {
if service_apply_company_bankruptcy(state, company_id) {
if let Some(label) = runtime_annual_finance_news_family_candidate_label(
policy_state.action,
state.service_state.annual_bond_last_retired_principal_total,
state.service_state.annual_bond_last_issued_principal_total,
state.service_state.annual_stock_repurchase_last_share_count,
state.service_state.annual_stock_issue_last_share_count,
) {
state
.service_state
.annual_finance_last_news_family_candidates
.insert(company_id, label.to_string());
}
applied_effect_count += 1;
mutated_company_ids.insert(company_id);
}
@ -626,6 +647,18 @@ fn service_company_annual_finance_policy(
market_state.current_issue_calendar_word = current_tuple_word_0;
market_state.current_issue_calendar_word_2 = current_tuple_word_1;
if mutated {
if let Some(label) = runtime_annual_finance_news_family_candidate_label(
policy_state.action,
state.service_state.annual_bond_last_retired_principal_total,
state.service_state.annual_bond_last_issued_principal_total,
state.service_state.annual_stock_repurchase_last_share_count,
state.service_state.annual_stock_issue_last_share_count,
) {
state
.service_state
.annual_finance_last_news_family_candidates
.insert(company_id, label.to_string());
}
applied_effect_count += 1;
mutated_company_ids.insert(company_id);
}
@ -773,6 +806,18 @@ fn service_company_annual_finance_policy(
.unwrap_or(company.debt);
}
if mutated {
if let Some(label) = runtime_annual_finance_news_family_candidate_label(
policy_state.action,
state.service_state.annual_bond_last_retired_principal_total,
state.service_state.annual_bond_last_issued_principal_total,
state.service_state.annual_stock_repurchase_last_share_count,
state.service_state.annual_stock_issue_last_share_count,
) {
state
.service_state
.annual_finance_last_news_family_candidates
.insert(company_id, label.to_string());
}
applied_effect_count += 1;
mutated_company_ids.insert(company_id);
}
@ -850,6 +895,18 @@ fn service_company_annual_finance_policy(
.saturating_add(u64::from(batch_size));
}
if mutated {
if let Some(label) = runtime_annual_finance_news_family_candidate_label(
policy_state.action,
state.service_state.annual_bond_last_retired_principal_total,
state.service_state.annual_bond_last_issued_principal_total,
state.service_state.annual_stock_repurchase_last_share_count,
state.service_state.annual_stock_issue_last_share_count,
) {
state
.service_state
.annual_finance_last_news_family_candidates
.insert(company_id, label.to_string());
}
applied_effect_count += 1;
mutated_company_ids.insert(company_id);
}
@ -2909,6 +2966,13 @@ mod tests {
state.service_state.annual_finance_last_actions.get(&22),
Some(&crate::RuntimeCompanyAnnualFinancePolicyAction::StockIssue)
);
assert_eq!(
state
.service_state
.annual_finance_last_news_family_candidates
.get(&22),
Some(&"4053".to_string())
);
assert_eq!(
state.service_state.annual_stock_issue_last_share_count,
4_000
@ -3077,6 +3141,13 @@ mod tests {
state.service_state.annual_finance_last_actions.get(&23),
Some(&crate::RuntimeCompanyAnnualFinancePolicyAction::StockRepurchase)
);
assert_eq!(
state
.service_state
.annual_finance_last_news_family_candidates
.get(&23),
Some(&"2887".to_string())
);
assert_eq!(state.service_state.annual_stock_issue_last_share_count, 0);
assert_eq!(
state.service_state.annual_stock_repurchase_last_share_count,
@ -3199,6 +3270,13 @@ mod tests {
state.service_state.annual_finance_last_actions.get(&24),
Some(&crate::RuntimeCompanyAnnualFinancePolicyAction::BondIssue)
);
assert_eq!(
state
.service_state
.annual_finance_last_news_family_candidates
.get(&24),
Some(&"2882_2886".to_string())
);
assert_eq!(state.companies[0].current_cash, 100_000);
assert_eq!(state.service_state.company_market_state[&24].bond_count, 1);
assert_eq!(
@ -3356,6 +3434,13 @@ mod tests {
state.service_state.annual_finance_last_actions.get(&25),
Some(&crate::RuntimeCompanyAnnualFinancePolicyAction::BondIssue)
);
assert_eq!(
state
.service_state
.annual_finance_last_news_family_candidates
.get(&25),
Some(&"2882_2886".to_string())
);
assert_eq!(state.companies[0].current_cash, 550_000);
assert_eq!(state.companies[0].debt, 0);
assert_eq!(
@ -3511,6 +3596,13 @@ mod tests {
state.service_state.annual_finance_last_actions.get(&26),
Some(&crate::RuntimeCompanyAnnualFinancePolicyAction::BondIssue)
);
assert_eq!(
state
.service_state
.annual_finance_last_news_family_candidates
.get(&26),
Some(&"2882_2886".to_string())
);
assert_eq!(state.companies[0].current_cash, 250_000);
assert_eq!(state.companies[0].debt, 1_000_000);
assert_eq!(
@ -3691,6 +3783,13 @@ mod tests {
state.service_state.annual_finance_last_actions.get(&31),
Some(&crate::RuntimeCompanyAnnualFinancePolicyAction::CreditorPressureBankruptcy)
);
assert_eq!(
state
.service_state
.annual_finance_last_news_family_candidates
.get(&31),
Some(&"2881".to_string())
);
assert_eq!(state.companies[0].current_cash, 0);
assert_eq!(state.companies[0].debt, 250_000);
assert!(state.companies[0].active);
@ -3859,6 +3958,13 @@ mod tests {
state.service_state.annual_finance_last_actions.get(&32),
Some(&crate::RuntimeCompanyAnnualFinancePolicyAction::DeepDistressBankruptcyFallback)
);
assert_eq!(
state
.service_state
.annual_finance_last_news_family_candidates
.get(&32),
Some(&"2881".to_string())
);
assert_eq!(state.companies[0].current_cash, 0);
assert_eq!(state.companies[0].debt, 125_000);
assert!(state.companies[0].active);

View file

@ -174,6 +174,7 @@ pub struct RuntimeSummary {
pub selected_company_dividend_proposed_per_share_tenths: Option<i64>,
pub selected_company_dividend_eligible_for_adjustment_branch: Option<bool>,
pub selected_company_annual_finance_policy_action: Option<String>,
pub selected_company_annual_finance_news_family_candidate: Option<String>,
pub selected_company_annual_finance_policy_creditor_pressure_bankruptcy_eligible: Option<bool>,
pub selected_company_annual_finance_policy_deep_distress_bankruptcy_fallback_eligible:
Option<bool>,
@ -808,6 +809,15 @@ impl RuntimeSummary {
runtime_company_annual_finance_policy_action_label(policy_state.action)
.to_string()
}),
selected_company_annual_finance_news_family_candidate: state
.selected_company_id
.and_then(|company_id| {
state
.service_state
.annual_finance_last_news_family_candidates
.get(&company_id)
})
.cloned(),
selected_company_annual_finance_policy_creditor_pressure_bankruptcy_eligible:
selected_company_annual_finance_policy_state
.as_ref()
@ -3374,6 +3384,14 @@ mod tests {
service_state: RuntimeServiceState {
world_issue_opinion_base_terms_raw_i32: vec![0; 0x3b],
chairman_personality_raw_u8: BTreeMap::from([(8, 20)]),
annual_finance_last_actions: BTreeMap::from([(
14,
crate::RuntimeCompanyAnnualFinancePolicyAction::StockIssue,
)]),
annual_finance_last_news_family_candidates: BTreeMap::from([(
14,
"4053".to_string(),
)]),
company_market_state: BTreeMap::from([(
14,
crate::RuntimeCompanyMarketState {
@ -3493,6 +3511,12 @@ mod tests {
summary.selected_company_stock_issue_eligible_for_double_tranche,
Some(true)
);
assert_eq!(
summary
.selected_company_annual_finance_news_family_candidate
.as_deref(),
Some("4053")
);
}
#[test]