Rehost company largest live bond principal

This commit is contained in:
Jan Petykiewicz 2026-04-17 21:24:53 -07:00
commit d57deb0e13
9 changed files with 135 additions and 34 deletions

View file

@ -75,7 +75,10 @@ instead of leaving that logic spread across summary helpers. The same annual-fin
derives elapsed years since founding, last dividend, and last bankruptcy from the runtime calendar, derives elapsed years since founding, last dividend, and last bankruptcy from the runtime calendar,
which lines up directly with the grounded annual finance-policy gates in the atlas. Live bond-slot which lines up directly with the grounded annual finance-policy gates in the atlas. Live bond-slot
count is now carried through the same owned company market and annual-finance state too, which count is now carried through the same owned company market and annual-finance state too, which
matches the stock-capital branch gate that requires at least two live bonds. A checked-in matches the stock-capital branch gate that requires at least two live bonds. The same grounded
bond table now also contributes the largest live bond principal into owned company market and
annual-finance state, so the stock-capital approval ladder can extend one rehosted owner-state
surface instead of hunting another isolated finance leaf. A checked-in
The working rule on the remaining frontier is explicit now too: when a lane is still ambiguous, we The working rule on the remaining frontier is explicit now too: when a lane is still ambiguous, we
should prefer rehosting the owning source state or the real reader/setter family rather than should prefer rehosting the owning source state or the real reader/setter family rather than
guessing one more derived leaf field from nearby offsets. A checked-in guessing one more derived leaf field from nearby offsets. A checked-in

View file

@ -94,6 +94,8 @@ pub struct ExpectedRuntimeSummary {
#[serde(default)] #[serde(default)]
pub selected_company_bond_count: Option<u8>, pub selected_company_bond_count: Option<u8>,
#[serde(default)] #[serde(default)]
pub selected_company_largest_live_bond_principal: Option<u32>,
#[serde(default)]
pub selected_company_assigned_share_pool: Option<u32>, pub selected_company_assigned_share_pool: Option<u32>,
#[serde(default)] #[serde(default)]
pub selected_company_unassigned_share_pool: Option<u32>, pub selected_company_unassigned_share_pool: Option<u32>,
@ -619,6 +621,14 @@ impl ExpectedRuntimeSummary {
)); ));
} }
} }
if let Some(value) = self.selected_company_largest_live_bond_principal {
if actual.selected_company_largest_live_bond_principal != Some(value) {
mismatches.push(format!(
"selected_company_largest_live_bond_principal mismatch: expected {value}, got {:?}",
actual.selected_company_largest_live_bond_principal
));
}
}
if let Some(value) = self.selected_company_assigned_share_pool { if let Some(value) = self.selected_company_assigned_share_pool {
if actual.selected_company_assigned_share_pool != Some(value) { if actual.selected_company_assigned_share_pool != Some(value) {
mismatches.push(format!( mismatches.push(format!(

View file

@ -5042,6 +5042,7 @@ mod tests {
market_state: Some(crate::RuntimeCompanyMarketState { market_state: Some(crate::RuntimeCompanyMarketState {
outstanding_shares: 20_000, outstanding_shares: 20_000,
bond_count: 2, bond_count: 2,
largest_live_bond_principal: Some(500_000),
mutable_support_scalar_raw_u32: 0x3f99999a, mutable_support_scalar_raw_u32: 0x3f99999a,
young_company_support_scalar_raw_u32: 0x42700000, young_company_support_scalar_raw_u32: 0x42700000,
support_progress_word: 12, support_progress_word: 12,
@ -5089,6 +5090,7 @@ mod tests {
market_state: Some(crate::RuntimeCompanyMarketState { market_state: Some(crate::RuntimeCompanyMarketState {
outstanding_shares: 18_000, outstanding_shares: 18_000,
bond_count: 1, bond_count: 1,
largest_live_bond_principal: Some(300_000),
mutable_support_scalar_raw_u32: 0x3f4ccccd, mutable_support_scalar_raw_u32: 0x3f4ccccd,
young_company_support_scalar_raw_u32: 0x42580000, young_company_support_scalar_raw_u32: 0x42580000,
support_progress_word: 9, support_progress_word: 9,
@ -6379,6 +6381,7 @@ mod tests {
crate::RuntimeCompanyMarketState { crate::RuntimeCompanyMarketState {
outstanding_shares: 30_000, outstanding_shares: 30_000,
bond_count: 3, bond_count: 3,
largest_live_bond_principal: Some(750_000),
mutable_support_scalar_raw_u32: 0x3f19999a, mutable_support_scalar_raw_u32: 0x3f19999a,
young_company_support_scalar_raw_u32: 0x42580000, young_company_support_scalar_raw_u32: 0x42580000,
support_progress_word: 8, support_progress_word: 8,

View file

@ -44,6 +44,8 @@ pub use pk4::{
extract_pk4_entry_bytes, extract_pk4_entry_file, inspect_pk4_bytes, inspect_pk4_file, extract_pk4_entry_bytes, extract_pk4_entry_file, inspect_pk4_bytes, inspect_pk4_file,
}; };
pub use runtime::{ pub use runtime::{
RUNTIME_COMPANY_STAT_FAMILY_CONTROL_TRANSFER, RUNTIME_COMPANY_STAT_SLOT_BOOK_VALUE_PER_SHARE,
RUNTIME_COMPANY_STAT_SLOT_CURRENT_CASH, RUNTIME_WORLD_ISSUE_INVESTOR_CONFIDENCE,
RuntimeCargoCatalogEntry, RuntimeCargoClass, RuntimeCargoPriceTarget, RuntimeCargoCatalogEntry, RuntimeCargoClass, RuntimeCargoPriceTarget,
RuntimeCargoProductionTarget, RuntimeChairmanMetric, RuntimeChairmanProfile, RuntimeCargoProductionTarget, RuntimeChairmanMetric, RuntimeChairmanProfile,
RuntimeChairmanTarget, RuntimeCompany, RuntimeCompanyAnnualFinanceState, RuntimeChairmanTarget, RuntimeCompany, RuntimeCompanyAnnualFinanceState,
@ -51,19 +53,16 @@ pub use runtime::{
RuntimeCompanyMarketState, RuntimeCompanyMetric, RuntimeCompanyStatBandCandidate, RuntimeCompanyMarketState, RuntimeCompanyMetric, RuntimeCompanyStatBandCandidate,
RuntimeCompanyStatSelector, RuntimeCompanyTarget, RuntimeCompanyTerritoryAccess, RuntimeCompanyStatSelector, RuntimeCompanyTarget, RuntimeCompanyTerritoryAccess,
RuntimeCompanyTerritoryTrackPieceCount, RuntimeCondition, RuntimeConditionComparator, RuntimeCompanyTerritoryTrackPieceCount, RuntimeCondition, RuntimeConditionComparator,
RuntimeEffect, RuntimeEventRecord, RuntimeEventRecordTemplate, RuntimeEffect, RuntimeEventRecord, RuntimeEventRecordTemplate, RuntimeLocomotiveCatalogEntry,
RuntimeLocomotiveCatalogEntry, RuntimePackedEventCollectionSummary, RuntimePackedEventCollectionSummary, RuntimePackedEventCompactControlSummary,
RuntimePackedEventCompactControlSummary, RuntimePackedEventConditionRowSummary, RuntimePackedEventConditionRowSummary, RuntimePackedEventGroupedEffectRowSummary,
RuntimePackedEventGroupedEffectRowSummary, RuntimePackedEventNegativeSentinelScopeSummary, RuntimePackedEventNegativeSentinelScopeSummary, RuntimePackedEventRecordSummary,
RuntimePackedEventRecordSummary, RuntimePackedEventTextBandSummary, RuntimePlayer, RuntimePackedEventTextBandSummary, RuntimePlayer, RuntimePlayerConditionTestScope,
RuntimePlayerConditionTestScope, RuntimePlayerTarget, RuntimeSaveProfileState, RuntimePlayerTarget, RuntimeSaveProfileState, RuntimeServiceState, RuntimeState,
RuntimeServiceState, RuntimeState, RuntimeTerritory, RuntimeTerritoryMetric, RuntimeTerritory, RuntimeTerritoryMetric, RuntimeTerritoryTarget, RuntimeTrackMetric,
RuntimeTerritoryTarget, RuntimeTrackMetric, RuntimeTrackPieceCounts, RuntimeTrain, RuntimeTrackPieceCounts, RuntimeTrain, RuntimeWorldFinanceNeighborhoodCandidate,
RuntimeWorldFinanceNeighborhoodCandidate, RuntimeWorldIssueState, RuntimeWorldRestoreState, RuntimeWorldIssueState, RuntimeWorldRestoreState, runtime_company_annual_finance_state,
RUNTIME_COMPANY_STAT_FAMILY_CONTROL_TRANSFER, RUNTIME_COMPANY_STAT_SLOT_BOOK_VALUE_PER_SHARE, runtime_company_assigned_share_pool, runtime_company_market_value, runtime_company_stat_value,
RUNTIME_COMPANY_STAT_SLOT_CURRENT_CASH, RUNTIME_WORLD_ISSUE_INVESTOR_CONFIDENCE,
runtime_company_annual_finance_state, runtime_company_assigned_share_pool,
runtime_company_market_value, runtime_company_stat_value,
runtime_company_unassigned_share_pool, runtime_world_issue_state, runtime_company_unassigned_share_pool, runtime_world_issue_state,
}; };
pub use smp::{ pub use smp::{

View file

@ -55,6 +55,8 @@ pub struct RuntimeCompanyMarketState {
#[serde(default)] #[serde(default)]
pub bond_count: u8, pub bond_count: u8,
#[serde(default)] #[serde(default)]
pub largest_live_bond_principal: Option<u32>,
#[serde(default)]
pub mutable_support_scalar_raw_u32: u32, pub mutable_support_scalar_raw_u32: u32,
#[serde(default)] #[serde(default)]
pub young_company_support_scalar_raw_u32: u32, pub young_company_support_scalar_raw_u32: u32,
@ -99,6 +101,8 @@ pub struct RuntimeCompanyAnnualFinanceState {
pub company_id: u32, pub company_id: u32,
pub outstanding_shares: u32, pub outstanding_shares: u32,
pub bond_count: u8, pub bond_count: u8,
#[serde(default)]
pub largest_live_bond_principal: Option<u32>,
pub assigned_share_pool: u32, pub assigned_share_pool: u32,
pub unassigned_share_pool: u32, pub unassigned_share_pool: u32,
#[serde(default)] #[serde(default)]
@ -356,6 +360,7 @@ pub enum RuntimeCompanyMetric {
pub enum RuntimeCompanyMarketMetric { pub enum RuntimeCompanyMarketMetric {
OutstandingShares, OutstandingShares,
BondCount, BondCount,
LargestLiveBondPrincipal,
AssignedSharePool, AssignedSharePool,
UnassignedSharePool, UnassignedSharePool,
CachedSharePrice, CachedSharePrice,
@ -1855,7 +1860,10 @@ pub fn runtime_company_stat_value(
company_id: u32, company_id: u32,
selector: RuntimeCompanyStatSelector, selector: RuntimeCompanyStatSelector,
) -> Option<i64> { ) -> Option<i64> {
let company = state.companies.iter().find(|company| company.company_id == company_id)?; let company = state
.companies
.iter()
.find(|company| company.company_id == company_id)?;
match (selector.family_id, selector.slot_id) { match (selector.family_id, selector.slot_id) {
(RUNTIME_COMPANY_STAT_FAMILY_CONTROL_TRANSFER, RUNTIME_COMPANY_STAT_SLOT_CURRENT_CASH) => { (RUNTIME_COMPANY_STAT_FAMILY_CONTROL_TRANSFER, RUNTIME_COMPANY_STAT_SLOT_CURRENT_CASH) => {
Some(company.current_cash) Some(company.current_cash)
@ -1868,7 +1876,10 @@ pub fn runtime_company_stat_value(
} }
} }
pub fn runtime_world_issue_state(state: &RuntimeState, issue_id: u32) -> Option<RuntimeWorldIssueState> { pub fn runtime_world_issue_state(
state: &RuntimeState,
issue_id: u32,
) -> Option<RuntimeWorldIssueState> {
match issue_id { match issue_id {
RUNTIME_WORLD_ISSUE_INVESTOR_CONFIDENCE => Some(RuntimeWorldIssueState { RUNTIME_WORLD_ISSUE_INVESTOR_CONFIDENCE => Some(RuntimeWorldIssueState {
issue_id, issue_id,
@ -1894,10 +1905,7 @@ pub fn runtime_company_unassigned_share_pool(state: &RuntimeState, company_id: u
} }
pub fn runtime_company_assigned_share_pool(state: &RuntimeState, company_id: u32) -> Option<u32> { pub fn runtime_company_assigned_share_pool(state: &RuntimeState, company_id: u32) -> Option<u32> {
state state.service_state.company_market_state.get(&company_id)?;
.service_state
.company_market_state
.get(&company_id)?;
Some( Some(
state state
.chairman_profiles .chairman_profiles
@ -1920,14 +1928,13 @@ pub fn runtime_company_annual_finance_state(
state.calendar.year, state.calendar.year,
market_state.last_bankruptcy_year, market_state.last_bankruptcy_year,
); );
let years_since_last_dividend = derive_runtime_company_elapsed_years( let years_since_last_dividend =
state.calendar.year, derive_runtime_company_elapsed_years(state.calendar.year, market_state.last_dividend_year);
market_state.last_dividend_year,
);
Some(RuntimeCompanyAnnualFinanceState { Some(RuntimeCompanyAnnualFinanceState {
company_id, company_id,
outstanding_shares: market_state.outstanding_shares, outstanding_shares: market_state.outstanding_shares,
bond_count: market_state.bond_count, bond_count: market_state.bond_count,
largest_live_bond_principal: market_state.largest_live_bond_principal,
assigned_share_pool, assigned_share_pool,
unassigned_share_pool, unassigned_share_pool,
cached_share_price: rounded_cached_share_price_i64(market_state.cached_share_price_raw_u32), cached_share_price: rounded_cached_share_price_i64(market_state.cached_share_price_raw_u32),
@ -1959,6 +1966,9 @@ pub fn runtime_company_market_value(
Some(annual_finance_state.outstanding_shares as i64) Some(annual_finance_state.outstanding_shares as i64)
} }
RuntimeCompanyMarketMetric::BondCount => Some(annual_finance_state.bond_count as i64), RuntimeCompanyMarketMetric::BondCount => Some(annual_finance_state.bond_count as i64),
RuntimeCompanyMarketMetric::LargestLiveBondPrincipal => annual_finance_state
.largest_live_bond_principal
.map(|value| value as i64),
RuntimeCompanyMarketMetric::AssignedSharePool => { RuntimeCompanyMarketMetric::AssignedSharePool => {
Some(annual_finance_state.assigned_share_pool as i64) Some(annual_finance_state.assigned_share_pool as i64)
} }
@ -4137,7 +4147,10 @@ mod tests {
}, },
}; };
assert_eq!(runtime_company_unassigned_share_pool(&state, 4), Some(4_500)); assert_eq!(
runtime_company_unassigned_share_pool(&state, 4),
Some(4_500)
);
assert_eq!(runtime_company_unassigned_share_pool(&state, 99), None); assert_eq!(runtime_company_unassigned_share_pool(&state, 99), None);
} }
@ -4229,6 +4242,7 @@ mod tests {
RuntimeCompanyMarketState { RuntimeCompanyMarketState {
outstanding_shares: 20_000, outstanding_shares: 20_000,
bond_count: 3, bond_count: 3,
largest_live_bond_principal: Some(650_000),
cached_share_price_raw_u32: 0x42200000, cached_share_price_raw_u32: 0x42200000,
chairman_salary_baseline: 24, chairman_salary_baseline: 24,
chairman_salary_current: 30, chairman_salary_current: 30,
@ -4255,6 +4269,7 @@ mod tests {
company_id: 4, company_id: 4,
outstanding_shares: 20_000, outstanding_shares: 20_000,
bond_count: 3, bond_count: 3,
largest_live_bond_principal: Some(650_000),
assigned_share_pool: 15_500, assigned_share_pool: 15_500,
unassigned_share_pool: 4_500, unassigned_share_pool: 4_500,
cached_share_price: Some(40), cached_share_price: Some(40),
@ -4353,6 +4368,7 @@ mod tests {
RuntimeCompanyMarketState { RuntimeCompanyMarketState {
outstanding_shares: 20_000, outstanding_shares: 20_000,
bond_count: 2, bond_count: 2,
largest_live_bond_principal: Some(500_000),
cached_share_price_raw_u32: 0x42200000, cached_share_price_raw_u32: 0x42200000,
chairman_salary_baseline: 18, chairman_salary_baseline: 18,
chairman_salary_current: 27, chairman_salary_current: 27,
@ -4378,12 +4394,24 @@ mod tests {
runtime_company_market_value(&state, 7, RuntimeCompanyMarketMetric::BondCount), runtime_company_market_value(&state, 7, RuntimeCompanyMarketMetric::BondCount),
Some(2) Some(2)
); );
assert_eq!(
runtime_company_market_value(
&state,
7,
RuntimeCompanyMarketMetric::LargestLiveBondPrincipal
),
Some(500_000)
);
assert_eq!( assert_eq!(
runtime_company_market_value(&state, 7, RuntimeCompanyMarketMetric::AssignedSharePool), runtime_company_market_value(&state, 7, RuntimeCompanyMarketMetric::AssignedSharePool),
Some(12_000) Some(12_000)
); );
assert_eq!( assert_eq!(
runtime_company_market_value(&state, 7, RuntimeCompanyMarketMetric::UnassignedSharePool), runtime_company_market_value(
&state,
7,
RuntimeCompanyMarketMetric::UnassignedSharePool
),
Some(8_000) Some(8_000)
); );
assert_eq!( assert_eq!(

View file

@ -2329,6 +2329,8 @@ pub struct SmpSaveCompanyRecordAnalysisEntry {
pub debt: u64, pub debt: u64,
pub bond_count: u8, pub bond_count: u8,
#[serde(default)] #[serde(default)]
pub largest_live_bond_principal: Option<u32>,
#[serde(default)]
pub available_track_laying_capacity: Option<u32>, pub available_track_laying_capacity: Option<u32>,
pub company_value_scalar_f32: f32, pub company_value_scalar_f32: f32,
pub cached_share_support_scalar_f32: f32, pub cached_share_support_scalar_f32: f32,
@ -3002,6 +3004,8 @@ pub fn inspect_save_company_and_chairman_analysis_bytes(
&bytes, &bytes,
record_offset + SAVE_COMPANY_RECORD_BOND_COUNT_OFFSET, record_offset + SAVE_COMPANY_RECORD_BOND_COUNT_OFFSET,
)?; )?;
let largest_live_bond_principal =
parse_save_company_largest_live_bond_principal(&bytes, record_offset)?;
let available_track_laying_capacity = let available_track_laying_capacity =
parse_save_company_available_track_laying_capacity(&bytes, record_offset)?; parse_save_company_available_track_laying_capacity(&bytes, record_offset)?;
let company_value_scalar_f32 = read_f32_at( let company_value_scalar_f32 = read_f32_at(
@ -3101,6 +3105,7 @@ pub fn inspect_save_company_and_chairman_analysis_bytes(
outstanding_shares, outstanding_shares,
debt, debt,
bond_count, bond_count,
largest_live_bond_principal,
available_track_laying_capacity, available_track_laying_capacity,
company_value_scalar_f32, company_value_scalar_f32,
cached_share_support_scalar_f32, cached_share_support_scalar_f32,
@ -3582,6 +3587,8 @@ fn parse_save_company_roster_probe(
)?; )?;
let debt = parse_save_company_total_debt(bytes, record_offset)?; let debt = parse_save_company_total_debt(bytes, record_offset)?;
let bond_count = read_u8_at(bytes, record_offset + SAVE_COMPANY_RECORD_BOND_COUNT_OFFSET)?; let bond_count = read_u8_at(bytes, record_offset + SAVE_COMPANY_RECORD_BOND_COUNT_OFFSET)?;
let largest_live_bond_principal =
parse_save_company_largest_live_bond_principal(bytes, record_offset)?;
let available_track_laying_capacity = let available_track_laying_capacity =
parse_save_company_available_track_laying_capacity(bytes, record_offset)?; parse_save_company_available_track_laying_capacity(bytes, record_offset)?;
let mutable_support_scalar_raw_u32 = read_u32_at( let mutable_support_scalar_raw_u32 = read_u32_at(
@ -3696,6 +3703,7 @@ fn parse_save_company_roster_probe(
market_state: Some(RuntimeCompanyMarketState { market_state: Some(RuntimeCompanyMarketState {
outstanding_shares, outstanding_shares,
bond_count, bond_count,
largest_live_bond_principal,
mutable_support_scalar_raw_u32, mutable_support_scalar_raw_u32,
young_company_support_scalar_raw_u32, young_company_support_scalar_raw_u32,
support_progress_word, support_progress_word,
@ -3874,6 +3882,29 @@ fn parse_save_company_total_debt(bytes: &[u8], record_offset: usize) -> Option<u
Some(total) Some(total)
} }
fn parse_save_company_largest_live_bond_principal(
bytes: &[u8],
record_offset: usize,
) -> Option<Option<u32>> {
let bond_count =
read_u8_at(bytes, record_offset + SAVE_COMPANY_RECORD_BOND_COUNT_OFFSET)? as usize;
let mut largest_live_principal: Option<u32> = None;
for slot_index in 0..bond_count {
let slot_offset = record_offset
.checked_add(SAVE_COMPANY_RECORD_BOND_TABLE_OFFSET)?
.checked_add(slot_index.checked_mul(SAVE_COMPANY_RECORD_BOND_SLOT_STRIDE)?)?;
let principal = read_i32_at(bytes, slot_offset)?;
if principal > 0 {
let principal = principal as u32;
largest_live_principal = Some(match largest_live_principal {
Some(current) => current.max(principal),
None => principal,
});
}
}
Some(largest_live_principal)
}
fn parse_save_company_available_track_laying_capacity( fn parse_save_company_available_track_laying_capacity(
bytes: &[u8], bytes: &[u8],
record_offset: usize, record_offset: usize,
@ -15490,10 +15521,16 @@ mod tests {
); );
assert_eq!(probe.dword_candidates[9].relative_offset_hex, "0x35"); assert_eq!(probe.dword_candidates[9].relative_offset_hex, "0x35");
assert_eq!(probe.dword_candidates[9].value_i32, 10); assert_eq!(probe.dword_candidates[9].value_i32, 10);
assert_eq!(probe.dword_candidates[10].label, "finance_neighborhood_word_11"); assert_eq!(
probe.dword_candidates[10].label,
"finance_neighborhood_word_11"
);
assert_eq!(probe.dword_candidates[10].relative_offset_hex, "0x39"); assert_eq!(probe.dword_candidates[10].relative_offset_hex, "0x39");
assert_eq!(probe.dword_candidates[10].value_i32, 11); assert_eq!(probe.dword_candidates[10].value_i32, 11);
assert_eq!(probe.dword_candidates[15].label, "finance_neighborhood_word_16"); assert_eq!(
probe.dword_candidates[15].label,
"finance_neighborhood_word_16"
);
assert_eq!(probe.dword_candidates[15].relative_offset_hex, "0x4d"); assert_eq!(probe.dword_candidates[15].relative_offset_hex, "0x4d");
assert_eq!(probe.dword_candidates[15].value_i32, 16); assert_eq!(probe.dword_candidates[15].value_i32, 16);
} }
@ -15954,7 +15991,12 @@ mod tests {
let slot_offset = record_offset let slot_offset = record_offset
+ SAVE_COMPANY_RECORD_BOND_TABLE_OFFSET + SAVE_COMPANY_RECORD_BOND_TABLE_OFFSET
+ slot_index * SAVE_COMPANY_RECORD_BOND_SLOT_STRIDE; + slot_index * SAVE_COMPANY_RECORD_BOND_SLOT_STRIDE;
bytes[slot_offset..slot_offset + 4].copy_from_slice(&(500_000i32).to_le_bytes()); let principal = if index == 0 && slot_index == 1 {
650_000i32
} else {
500_000i32
};
bytes[slot_offset..slot_offset + 4].copy_from_slice(&principal.to_le_bytes());
bytes[slot_offset + 4..slot_offset + 8] bytes[slot_offset + 4..slot_offset + 8]
.copy_from_slice(&(1894u32 + slot_index as u32).to_le_bytes()); .copy_from_slice(&(1894u32 + slot_index as u32).to_le_bytes());
bytes[slot_offset + 8..slot_offset + 12].copy_from_slice(&(0.10f32).to_le_bytes()); bytes[slot_offset + 8..slot_offset + 12].copy_from_slice(&(0.10f32).to_le_bytes());
@ -16055,7 +16097,7 @@ mod tests {
assert_eq!(roster.entries.len(), 2); assert_eq!(roster.entries.len(), 2);
assert_eq!(roster.entries[0].company_id, 1); assert_eq!(roster.entries[0].company_id, 1);
assert_eq!(roster.entries[0].linked_chairman_profile_id, Some(1)); assert_eq!(roster.entries[0].linked_chairman_profile_id, Some(1));
assert_eq!(roster.entries[0].debt, 1_000_000); assert_eq!(roster.entries[0].debt, 1_150_000);
assert_eq!(roster.entries[0].available_track_laying_capacity, Some(603)); assert_eq!(roster.entries[0].available_track_laying_capacity, Some(603));
assert_eq!(roster.entries[0].merger_cooldown_year, Some(1862)); assert_eq!(roster.entries[0].merger_cooldown_year, Some(1862));
let market_state = roster.entries[0] let market_state = roster.entries[0]
@ -16063,6 +16105,7 @@ mod tests {
.as_ref() .as_ref()
.expect("company market state should load"); .expect("company market state should load");
assert_eq!(market_state.outstanding_shares, 20_000); assert_eq!(market_state.outstanding_shares, 20_000);
assert_eq!(market_state.largest_live_bond_principal, Some(650_000));
assert_eq!(market_state.mutable_support_scalar_raw_u32, 0x3f800000); assert_eq!(market_state.mutable_support_scalar_raw_u32, 0x3f800000);
assert_eq!( assert_eq!(
market_state.young_company_support_scalar_raw_u32, market_state.young_company_support_scalar_raw_u32,
@ -16091,6 +16134,10 @@ mod tests {
.market_state .market_state
.as_ref() .as_ref()
.expect("second company market state should load"); .expect("second company market state should load");
assert_eq!(
second_market_state.largest_live_bond_principal,
Some(500_000)
);
assert_eq!(second_market_state.chairman_bonus_year, 0); assert_eq!(second_market_state.chairman_bonus_year, 0);
assert_eq!(second_market_state.chairman_bonus_amount, 0); assert_eq!(second_market_state.chairman_bonus_amount, 0);
assert_eq!(second_market_state.last_dividend_year, 1850); assert_eq!(second_market_state.last_dividend_year, 1850);

View file

@ -1,8 +1,8 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
runtime_company_annual_finance_state, runtime_company_unassigned_share_pool, CalendarPoint, CalendarPoint, RuntimeState, runtime_company_annual_finance_state,
RuntimeState, runtime_company_unassigned_share_pool,
}; };
fn raw_u32_to_f32_text(raw: u32) -> String { fn raw_u32_to_f32_text(raw: u32) -> String {
@ -51,6 +51,7 @@ pub struct RuntimeSummary {
pub company_market_state_owner_count: usize, pub company_market_state_owner_count: usize,
pub selected_company_outstanding_shares: Option<u32>, pub selected_company_outstanding_shares: Option<u32>,
pub selected_company_bond_count: Option<u8>, pub selected_company_bond_count: Option<u8>,
pub selected_company_largest_live_bond_principal: Option<u32>,
pub selected_company_assigned_share_pool: Option<u32>, pub selected_company_assigned_share_pool: Option<u32>,
pub selected_company_unassigned_share_pool: Option<u32>, pub selected_company_unassigned_share_pool: Option<u32>,
pub selected_company_cached_share_price: Option<i64>, pub selected_company_cached_share_price: Option<i64>,
@ -261,6 +262,8 @@ impl RuntimeSummary {
.map(|market_state| market_state.outstanding_shares), .map(|market_state| market_state.outstanding_shares),
selected_company_bond_count: selected_company_market_state selected_company_bond_count: selected_company_market_state
.map(|market_state| market_state.bond_count), .map(|market_state| market_state.bond_count),
selected_company_largest_live_bond_principal: selected_company_market_state
.and_then(|market_state| market_state.largest_live_bond_principal),
selected_company_assigned_share_pool: selected_company_annual_finance_state selected_company_assigned_share_pool: selected_company_annual_finance_state
.as_ref() .as_ref()
.map(|finance_state| finance_state.assigned_share_pool), .map(|finance_state| finance_state.assigned_share_pool),
@ -1960,6 +1963,7 @@ mod tests {
crate::RuntimeCompanyMarketState { crate::RuntimeCompanyMarketState {
outstanding_shares: 20_000, outstanding_shares: 20_000,
bond_count: 2, bond_count: 2,
largest_live_bond_principal: Some(500_000),
mutable_support_scalar_raw_u32: 0x3f800000, mutable_support_scalar_raw_u32: 0x3f800000,
young_company_support_scalar_raw_u32: 0x42340000, young_company_support_scalar_raw_u32: 0x42340000,
support_progress_word: 12, support_progress_word: 12,
@ -2028,6 +2032,10 @@ mod tests {
assert_eq!(summary.company_market_state_owner_count, 1); assert_eq!(summary.company_market_state_owner_count, 1);
assert_eq!(summary.selected_company_outstanding_shares, Some(20_000)); assert_eq!(summary.selected_company_outstanding_shares, Some(20_000));
assert_eq!(summary.selected_company_bond_count, Some(2)); assert_eq!(summary.selected_company_bond_count, Some(2));
assert_eq!(
summary.selected_company_largest_live_bond_principal,
Some(500_000)
);
assert_eq!(summary.selected_company_assigned_share_pool, Some(5_000)); assert_eq!(summary.selected_company_assigned_share_pool, Some(5_000));
assert_eq!(summary.selected_company_unassigned_share_pool, Some(15_000)); assert_eq!(summary.selected_company_unassigned_share_pool, Some(15_000));
assert_eq!(summary.selected_company_cached_share_price, Some(40)); assert_eq!(summary.selected_company_cached_share_price, Some(40));

View file

@ -127,7 +127,8 @@ The highest-value next passes are now:
feeds a shared company market reader for stock-capital, salary, bonus, and issue-calendar values, feeds a shared company market reader for stock-capital, salary, bonus, and issue-calendar values,
and now derives elapsed years since founding, last dividend, and last bankruptcy for later annual and now derives elapsed years since founding, last dividend, and last bankruptcy for later annual
finance-policy rehosting; live bond-slot count now travels through that same owned annual-finance finance-policy rehosting; live bond-slot count now travels through that same owned annual-finance
state for the stock-capital branch gate state for the stock-capital branch gate, and the grounded bond table now also contributes the
largest live bond principal into that same owner-state surface
- the project rule on the remaining closure work is now explicit too: when one runtime-facing field - the project rule on the remaining closure work is now explicit too: when one runtime-facing field
is still ambiguous, prefer rehosting the owning source state or real reader/setter family first is still ambiguous, prefer rehosting the owning source state or real reader/setter family first
instead of guessing another derived leaf field from neighboring raw offsets instead of guessing another derived leaf field from neighboring raw offsets

View file

@ -218,7 +218,9 @@ helpers. That same owned annual-finance state now also derives elapsed years sin
dividend, and last bankruptcy from the runtime calendar, which lines up directly with the grounded dividend, and last bankruptcy from the runtime calendar, which lines up directly with the grounded
annual finance-policy gates in the atlas. Live bond-slot count now also flows through that same annual finance-policy gates in the atlas. Live bond-slot count now also flows through that same
owned company market and annual-finance state, matching the stock-capital branch gate that needs owned company market and annual-finance state, matching the stock-capital branch gate that needs
at least two live bonds. at least two live bonds. The same grounded bond table now also contributes the largest live bond
principal into owned company market and annual-finance state, so later stock-capital gates can
extend a rehosted owner-state seam instead of guessing another finance leaf.
## Why This Boundary ## Why This Boundary