Rehost company highest-coupon bond input

This commit is contained in:
Jan Petykiewicz 2026-04-17 21:31:28 -07:00
commit 3b99f6f626
8 changed files with 117 additions and 14 deletions

View file

@ -76,9 +76,10 @@ derives elapsed years since founding, last dividend, and last bankruptcy from th
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. The same grounded 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 bond table now also contributes both the largest live bond principal and the chosen
annual-finance state, so the stock-capital approval ladder can extend one rehosted owner-state highest-coupon live bond principal into owned company market and annual-finance state, so the
surface instead of hunting another isolated finance leaf. A checked-in 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

@ -96,6 +96,8 @@ pub struct ExpectedRuntimeSummary {
#[serde(default)] #[serde(default)]
pub selected_company_largest_live_bond_principal: Option<u32>, pub selected_company_largest_live_bond_principal: Option<u32>,
#[serde(default)] #[serde(default)]
pub selected_company_highest_coupon_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>,
@ -629,6 +631,14 @@ impl ExpectedRuntimeSummary {
)); ));
} }
} }
if let Some(value) = self.selected_company_highest_coupon_live_bond_principal {
if actual.selected_company_highest_coupon_live_bond_principal != Some(value) {
mismatches.push(format!(
"selected_company_highest_coupon_live_bond_principal mismatch: expected {value}, got {:?}",
actual.selected_company_highest_coupon_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

@ -5043,6 +5043,7 @@ mod tests {
outstanding_shares: 20_000, outstanding_shares: 20_000,
bond_count: 2, bond_count: 2,
largest_live_bond_principal: Some(500_000), largest_live_bond_principal: Some(500_000),
highest_coupon_live_bond_principal: Some(350_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,
@ -5091,6 +5092,7 @@ mod tests {
outstanding_shares: 18_000, outstanding_shares: 18_000,
bond_count: 1, bond_count: 1,
largest_live_bond_principal: Some(300_000), largest_live_bond_principal: Some(300_000),
highest_coupon_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,
@ -6382,6 +6384,7 @@ mod tests {
outstanding_shares: 30_000, outstanding_shares: 30_000,
bond_count: 3, bond_count: 3,
largest_live_bond_principal: Some(750_000), largest_live_bond_principal: Some(750_000),
highest_coupon_live_bond_principal: Some(500_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

@ -57,6 +57,8 @@ pub struct RuntimeCompanyMarketState {
#[serde(default)] #[serde(default)]
pub largest_live_bond_principal: Option<u32>, pub largest_live_bond_principal: Option<u32>,
#[serde(default)] #[serde(default)]
pub highest_coupon_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,
@ -103,6 +105,8 @@ pub struct RuntimeCompanyAnnualFinanceState {
pub bond_count: u8, pub bond_count: u8,
#[serde(default)] #[serde(default)]
pub largest_live_bond_principal: Option<u32>, pub largest_live_bond_principal: Option<u32>,
#[serde(default)]
pub highest_coupon_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)]
@ -361,6 +365,7 @@ pub enum RuntimeCompanyMarketMetric {
OutstandingShares, OutstandingShares,
BondCount, BondCount,
LargestLiveBondPrincipal, LargestLiveBondPrincipal,
HighestCouponLiveBondPrincipal,
AssignedSharePool, AssignedSharePool,
UnassignedSharePool, UnassignedSharePool,
CachedSharePrice, CachedSharePrice,
@ -1935,6 +1940,7 @@ pub fn runtime_company_annual_finance_state(
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, largest_live_bond_principal: market_state.largest_live_bond_principal,
highest_coupon_live_bond_principal: market_state.highest_coupon_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),
@ -1969,6 +1975,9 @@ pub fn runtime_company_market_value(
RuntimeCompanyMarketMetric::LargestLiveBondPrincipal => annual_finance_state RuntimeCompanyMarketMetric::LargestLiveBondPrincipal => annual_finance_state
.largest_live_bond_principal .largest_live_bond_principal
.map(|value| value as i64), .map(|value| value as i64),
RuntimeCompanyMarketMetric::HighestCouponLiveBondPrincipal => annual_finance_state
.highest_coupon_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)
} }
@ -4243,6 +4252,7 @@ mod tests {
outstanding_shares: 20_000, outstanding_shares: 20_000,
bond_count: 3, bond_count: 3,
largest_live_bond_principal: Some(650_000), largest_live_bond_principal: Some(650_000),
highest_coupon_live_bond_principal: Some(500_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,
@ -4270,6 +4280,7 @@ mod tests {
outstanding_shares: 20_000, outstanding_shares: 20_000,
bond_count: 3, bond_count: 3,
largest_live_bond_principal: Some(650_000), largest_live_bond_principal: Some(650_000),
highest_coupon_live_bond_principal: Some(500_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),
@ -4369,6 +4380,7 @@ mod tests {
outstanding_shares: 20_000, outstanding_shares: 20_000,
bond_count: 2, bond_count: 2,
largest_live_bond_principal: Some(500_000), largest_live_bond_principal: Some(500_000),
highest_coupon_live_bond_principal: Some(300_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,
@ -4402,6 +4414,14 @@ mod tests {
), ),
Some(500_000) Some(500_000)
); );
assert_eq!(
runtime_company_market_value(
&state,
7,
RuntimeCompanyMarketMetric::HighestCouponLiveBondPrincipal
),
Some(300_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)

View file

@ -2331,6 +2331,8 @@ pub struct SmpSaveCompanyRecordAnalysisEntry {
#[serde(default)] #[serde(default)]
pub largest_live_bond_principal: Option<u32>, pub largest_live_bond_principal: Option<u32>,
#[serde(default)] #[serde(default)]
pub highest_coupon_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,
@ -3006,6 +3008,8 @@ pub fn inspect_save_company_and_chairman_analysis_bytes(
)?; )?;
let largest_live_bond_principal = let largest_live_bond_principal =
parse_save_company_largest_live_bond_principal(&bytes, record_offset)?; parse_save_company_largest_live_bond_principal(&bytes, record_offset)?;
let highest_coupon_live_bond_principal =
parse_save_company_highest_coupon_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(
@ -3106,6 +3110,7 @@ pub fn inspect_save_company_and_chairman_analysis_bytes(
debt, debt,
bond_count, bond_count,
largest_live_bond_principal, largest_live_bond_principal,
highest_coupon_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,
@ -3589,6 +3594,8 @@ fn parse_save_company_roster_probe(
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 = let largest_live_bond_principal =
parse_save_company_largest_live_bond_principal(bytes, record_offset)?; parse_save_company_largest_live_bond_principal(bytes, record_offset)?;
let highest_coupon_live_bond_principal =
parse_save_company_highest_coupon_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(
@ -3704,6 +3711,7 @@ fn parse_save_company_roster_probe(
outstanding_shares, outstanding_shares,
bond_count, bond_count,
largest_live_bond_principal, largest_live_bond_principal,
highest_coupon_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,
@ -3905,6 +3913,46 @@ fn parse_save_company_largest_live_bond_principal(
Some(largest_live_principal) Some(largest_live_principal)
} }
fn parse_save_company_highest_coupon_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 highest_coupon_principal = None;
let mut highest_coupon_rate = 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 {
continue;
}
let coupon_rate_raw_u32 = read_u32_at(bytes, slot_offset + 8)?;
let coupon_rate = f32::from_bits(coupon_rate_raw_u32);
if !coupon_rate.is_finite() {
continue;
}
let principal = principal as u32;
match highest_coupon_rate {
Some(current_rate) if coupon_rate < current_rate => {}
Some(current_rate) if coupon_rate == current_rate => {
if let Some(current_principal) = highest_coupon_principal {
if principal > current_principal {
highest_coupon_principal = Some(principal);
}
}
}
_ => {
highest_coupon_rate = Some(coupon_rate);
highest_coupon_principal = Some(principal);
}
}
}
Some(highest_coupon_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,
@ -15991,15 +16039,18 @@ 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;
let principal = if index == 0 && slot_index == 1 { let (principal, coupon_rate) = if index == 0 && slot_index == 0 {
650_000i32 (900_000i32, 0.08f32)
} else if index == 0 && slot_index == 1 {
(650_000i32, 0.12f32)
} else { } else {
500_000i32 (500_000i32, 0.10f32)
}; };
bytes[slot_offset..slot_offset + 4].copy_from_slice(&principal.to_le_bytes()); 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(&coupon_rate.to_le_bytes());
} }
bytes[record_offset + SAVE_COMPANY_RECORD_MERGER_COOLDOWN_OFFSET bytes[record_offset + SAVE_COMPANY_RECORD_MERGER_COOLDOWN_OFFSET
..record_offset + SAVE_COMPANY_RECORD_MERGER_COOLDOWN_OFFSET + 4] ..record_offset + SAVE_COMPANY_RECORD_MERGER_COOLDOWN_OFFSET + 4]
@ -16097,7 +16148,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_150_000); assert_eq!(roster.entries[0].debt, 1_550_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]
@ -16105,7 +16156,11 @@ 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.largest_live_bond_principal, Some(900_000));
assert_eq!(
market_state.highest_coupon_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,
@ -16158,6 +16213,10 @@ mod tests {
second_market_state.largest_live_bond_principal, second_market_state.largest_live_bond_principal,
Some(500_000) Some(500_000)
); );
assert_eq!(
second_market_state.highest_coupon_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

@ -52,6 +52,7 @@ pub struct RuntimeSummary {
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_largest_live_bond_principal: Option<u32>,
pub selected_company_highest_coupon_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>,
@ -264,6 +265,8 @@ impl RuntimeSummary {
.map(|market_state| market_state.bond_count), .map(|market_state| market_state.bond_count),
selected_company_largest_live_bond_principal: selected_company_market_state selected_company_largest_live_bond_principal: selected_company_market_state
.and_then(|market_state| market_state.largest_live_bond_principal), .and_then(|market_state| market_state.largest_live_bond_principal),
selected_company_highest_coupon_live_bond_principal: selected_company_market_state
.and_then(|market_state| market_state.highest_coupon_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),
@ -1963,6 +1966,7 @@ mod tests {
crate::RuntimeCompanyMarketState { crate::RuntimeCompanyMarketState {
outstanding_shares: 20_000, outstanding_shares: 20_000,
bond_count: 2, bond_count: 2,
highest_coupon_live_bond_principal: Some(350_000),
largest_live_bond_principal: Some(500_000), 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,
@ -2036,6 +2040,10 @@ mod tests {
summary.selected_company_largest_live_bond_principal, summary.selected_company_largest_live_bond_principal,
Some(500_000) Some(500_000)
); );
assert_eq!(
summary.selected_company_highest_coupon_live_bond_principal,
Some(350_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,8 +127,9 @@ 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, and the grounded bond table now also contributes the state for the stock-capital branch gate, and the grounded bond table now also contributes both
largest live bond principal into that same owner-state surface the largest live bond principal and the chosen highest-coupon 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,9 +218,10 @@ 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. The same grounded bond table now also contributes the largest live bond at least two live bonds. The same grounded bond table now also contributes both the largest live
principal into owned company market and annual-finance state, so later stock-capital gates can bond principal and the chosen highest-coupon live bond principal into owned company market and
extend a rehosted owner-state seam instead of guessing another finance leaf. 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