Add company market reader seam
This commit is contained in:
parent
a73a789bac
commit
53f1078a84
5 changed files with 212 additions and 9 deletions
|
|
@ -68,7 +68,10 @@ state too, deriving assigned shares, public float, and rounded cached share pric
|
|||
company market reader instead of scattering more finance helpers across the runtime. A checked-in
|
||||
The fixed-world finance neighborhood itself is now widened to 16 dwords rooted at `[world+0x11]`,
|
||||
so future issue-`0x38/0x39` closure can build on a broader owned restore-state window rather than
|
||||
another narrow one-off probe. A checked-in
|
||||
another narrow one-off probe. The next company-side seam is now bundled too: a shared company
|
||||
market reader now exposes outstanding shares, assigned shares, public float, rounded cached share
|
||||
price, salary lanes, bonus amount, and issue-calendar words from the owned annual-finance state
|
||||
instead of leaving that logic spread across summary helpers. A checked-in
|
||||
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
|
||||
guessing one more derived leaf field from nearby offsets. A checked-in
|
||||
|
|
|
|||
|
|
@ -47,11 +47,12 @@ pub use runtime::{
|
|||
RuntimeCargoCatalogEntry, RuntimeCargoClass, RuntimeCargoPriceTarget,
|
||||
RuntimeCargoProductionTarget, RuntimeChairmanMetric, RuntimeChairmanProfile,
|
||||
RuntimeChairmanTarget, RuntimeCompany, RuntimeCompanyAnnualFinanceState,
|
||||
RuntimeCompanyConditionTestScope, RuntimeCompanyControllerKind, RuntimeCompanyMarketState,
|
||||
RuntimeCompanyMetric, RuntimeCompanyStatBandCandidate, RuntimeCompanyStatSelector,
|
||||
RuntimeCompanyTarget, RuntimeCompanyTerritoryAccess, RuntimeCompanyTerritoryTrackPieceCount,
|
||||
RuntimeCondition, RuntimeConditionComparator, RuntimeEffect, RuntimeEventRecord,
|
||||
RuntimeEventRecordTemplate, RuntimeLocomotiveCatalogEntry, RuntimePackedEventCollectionSummary,
|
||||
RuntimeCompanyConditionTestScope, RuntimeCompanyControllerKind, RuntimeCompanyMarketMetric,
|
||||
RuntimeCompanyMarketState, RuntimeCompanyMetric, RuntimeCompanyStatBandCandidate,
|
||||
RuntimeCompanyStatSelector, RuntimeCompanyTarget, RuntimeCompanyTerritoryAccess,
|
||||
RuntimeCompanyTerritoryTrackPieceCount, RuntimeCondition, RuntimeConditionComparator,
|
||||
RuntimeEffect, RuntimeEventRecord, RuntimeEventRecordTemplate,
|
||||
RuntimeLocomotiveCatalogEntry, RuntimePackedEventCollectionSummary,
|
||||
RuntimePackedEventCompactControlSummary, RuntimePackedEventConditionRowSummary,
|
||||
RuntimePackedEventGroupedEffectRowSummary, RuntimePackedEventNegativeSentinelScopeSummary,
|
||||
RuntimePackedEventRecordSummary, RuntimePackedEventTextBandSummary, RuntimePlayer,
|
||||
|
|
@ -62,7 +63,8 @@ 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,
|
||||
runtime_company_annual_finance_state, runtime_company_assigned_share_pool,
|
||||
runtime_company_stat_value, runtime_company_unassigned_share_pool, runtime_world_issue_state,
|
||||
runtime_company_market_value, runtime_company_stat_value,
|
||||
runtime_company_unassigned_share_pool, runtime_world_issue_state,
|
||||
};
|
||||
pub use smp::{
|
||||
SMP_FOUR_SIDECAR_BYTE_PLANES_MIN_BUNDLE_VERSION, SmpAlignedRuntimeRuleBandLane,
|
||||
|
|
|
|||
|
|
@ -342,6 +342,20 @@ pub enum RuntimeCompanyMetric {
|
|||
TrackPiecesNonElectric,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum RuntimeCompanyMarketMetric {
|
||||
OutstandingShares,
|
||||
AssignedSharePool,
|
||||
UnassignedSharePool,
|
||||
CachedSharePrice,
|
||||
ChairmanSalaryBaseline,
|
||||
ChairmanSalaryCurrent,
|
||||
ChairmanBonusAmount,
|
||||
CurrentIssueCalendarWord,
|
||||
PriorIssueCalendarWord,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum RuntimeChairmanMetric {
|
||||
|
|
@ -1910,6 +1924,41 @@ pub fn runtime_company_annual_finance_state(
|
|||
})
|
||||
}
|
||||
|
||||
pub fn runtime_company_market_value(
|
||||
state: &RuntimeState,
|
||||
company_id: u32,
|
||||
metric: RuntimeCompanyMarketMetric,
|
||||
) -> Option<i64> {
|
||||
let annual_finance_state = runtime_company_annual_finance_state(state, company_id)?;
|
||||
match metric {
|
||||
RuntimeCompanyMarketMetric::OutstandingShares => {
|
||||
Some(annual_finance_state.outstanding_shares as i64)
|
||||
}
|
||||
RuntimeCompanyMarketMetric::AssignedSharePool => {
|
||||
Some(annual_finance_state.assigned_share_pool as i64)
|
||||
}
|
||||
RuntimeCompanyMarketMetric::UnassignedSharePool => {
|
||||
Some(annual_finance_state.unassigned_share_pool as i64)
|
||||
}
|
||||
RuntimeCompanyMarketMetric::CachedSharePrice => annual_finance_state.cached_share_price,
|
||||
RuntimeCompanyMarketMetric::ChairmanSalaryBaseline => {
|
||||
Some(annual_finance_state.chairman_salary_baseline as i64)
|
||||
}
|
||||
RuntimeCompanyMarketMetric::ChairmanSalaryCurrent => {
|
||||
Some(annual_finance_state.chairman_salary_current as i64)
|
||||
}
|
||||
RuntimeCompanyMarketMetric::ChairmanBonusAmount => {
|
||||
Some(annual_finance_state.chairman_bonus_amount as i64)
|
||||
}
|
||||
RuntimeCompanyMarketMetric::CurrentIssueCalendarWord => {
|
||||
Some(annual_finance_state.current_issue_calendar_word as i64)
|
||||
}
|
||||
RuntimeCompanyMarketMetric::PriorIssueCalendarWord => {
|
||||
Some(annual_finance_state.prior_issue_calendar_word as i64)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn rounded_cached_share_price_i64(raw_u32: u32) -> Option<i64> {
|
||||
let value = f32::from_bits(raw_u32);
|
||||
if !value.is_finite() {
|
||||
|
|
@ -4191,4 +4240,149 @@ mod tests {
|
|||
assert_eq!(runtime_company_assigned_share_pool(&state, 99), None);
|
||||
assert_eq!(runtime_company_annual_finance_state(&state, 99), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reads_company_market_metrics_from_annual_finance_reader() {
|
||||
let state = RuntimeState {
|
||||
calendar: CalendarPoint {
|
||||
year: 1830,
|
||||
month_slot: 0,
|
||||
phase_slot: 0,
|
||||
tick_slot: 0,
|
||||
},
|
||||
world_flags: BTreeMap::new(),
|
||||
save_profile: RuntimeSaveProfileState::default(),
|
||||
world_restore: RuntimeWorldRestoreState::default(),
|
||||
metadata: BTreeMap::new(),
|
||||
companies: vec![RuntimeCompany {
|
||||
company_id: 7,
|
||||
current_cash: 0,
|
||||
debt: 0,
|
||||
credit_rating_score: None,
|
||||
prime_rate: None,
|
||||
active: true,
|
||||
available_track_laying_capacity: None,
|
||||
controller_kind: RuntimeCompanyControllerKind::Unknown,
|
||||
linked_chairman_profile_id: None,
|
||||
book_value_per_share: 0,
|
||||
investor_confidence: 0,
|
||||
management_attitude: 0,
|
||||
takeover_cooldown_year: None,
|
||||
merger_cooldown_year: None,
|
||||
track_piece_counts: RuntimeTrackPieceCounts::default(),
|
||||
}],
|
||||
selected_company_id: None,
|
||||
players: Vec::new(),
|
||||
selected_player_id: None,
|
||||
chairman_profiles: vec![RuntimeChairmanProfile {
|
||||
profile_id: 1,
|
||||
name: "Chairman One".to_string(),
|
||||
active: true,
|
||||
current_cash: 0,
|
||||
linked_company_id: Some(7),
|
||||
company_holdings: BTreeMap::from([(7, 12_000)]),
|
||||
holdings_value_total: 0,
|
||||
net_worth_total: 0,
|
||||
purchasing_power_total: 0,
|
||||
}],
|
||||
selected_chairman_profile_id: None,
|
||||
trains: Vec::new(),
|
||||
locomotive_catalog: Vec::new(),
|
||||
cargo_catalog: Vec::new(),
|
||||
territories: Vec::new(),
|
||||
company_territory_track_piece_counts: Vec::new(),
|
||||
company_territory_access: Vec::new(),
|
||||
packed_event_collection: None,
|
||||
event_runtime_records: Vec::new(),
|
||||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
all_cargo_price_override: None,
|
||||
named_cargo_price_overrides: BTreeMap::new(),
|
||||
all_cargo_production_override: None,
|
||||
factory_cargo_production_override: None,
|
||||
farm_mine_cargo_production_override: None,
|
||||
named_cargo_production_overrides: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
world_runtime_variables: BTreeMap::new(),
|
||||
company_runtime_variables: BTreeMap::new(),
|
||||
player_runtime_variables: BTreeMap::new(),
|
||||
territory_runtime_variables: BTreeMap::new(),
|
||||
world_scalar_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState {
|
||||
company_market_state: BTreeMap::from([(
|
||||
7,
|
||||
RuntimeCompanyMarketState {
|
||||
outstanding_shares: 20_000,
|
||||
cached_share_price_raw_u32: 0x42200000,
|
||||
chairman_salary_baseline: 18,
|
||||
chairman_salary_current: 27,
|
||||
chairman_bonus_year: 1843,
|
||||
chairman_bonus_amount: 625,
|
||||
founding_year: 1832,
|
||||
last_bankruptcy_year: 0,
|
||||
last_dividend_year: 1842,
|
||||
current_issue_calendar_word: 9,
|
||||
prior_issue_calendar_word: 8,
|
||||
..RuntimeCompanyMarketState::default()
|
||||
},
|
||||
)]),
|
||||
..RuntimeServiceState::default()
|
||||
},
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
runtime_company_market_value(&state, 7, RuntimeCompanyMarketMetric::OutstandingShares),
|
||||
Some(20_000)
|
||||
);
|
||||
assert_eq!(
|
||||
runtime_company_market_value(&state, 7, RuntimeCompanyMarketMetric::AssignedSharePool),
|
||||
Some(12_000)
|
||||
);
|
||||
assert_eq!(
|
||||
runtime_company_market_value(&state, 7, RuntimeCompanyMarketMetric::UnassignedSharePool),
|
||||
Some(8_000)
|
||||
);
|
||||
assert_eq!(
|
||||
runtime_company_market_value(&state, 7, RuntimeCompanyMarketMetric::CachedSharePrice),
|
||||
Some(40)
|
||||
);
|
||||
assert_eq!(
|
||||
runtime_company_market_value(
|
||||
&state,
|
||||
7,
|
||||
RuntimeCompanyMarketMetric::CurrentIssueCalendarWord
|
||||
),
|
||||
Some(9)
|
||||
);
|
||||
assert_eq!(
|
||||
runtime_company_market_value(
|
||||
&state,
|
||||
7,
|
||||
RuntimeCompanyMarketMetric::PriorIssueCalendarWord
|
||||
),
|
||||
Some(8)
|
||||
);
|
||||
assert_eq!(
|
||||
runtime_company_market_value(
|
||||
&state,
|
||||
7,
|
||||
RuntimeCompanyMarketMetric::ChairmanSalaryCurrent
|
||||
),
|
||||
Some(27)
|
||||
);
|
||||
assert_eq!(
|
||||
runtime_company_market_value(
|
||||
&state,
|
||||
7,
|
||||
RuntimeCompanyMarketMetric::ChairmanBonusAmount
|
||||
),
|
||||
Some(625)
|
||||
);
|
||||
assert_eq!(
|
||||
runtime_company_market_value(&state, 99, RuntimeCompanyMarketMetric::OutstandingShares),
|
||||
None
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,7 +123,8 @@ The highest-value next passes are now:
|
|||
finance logic; that same owned company market state now also backs a bundled annual-finance
|
||||
reader seam for assigned shares, public float, and rounded cached share price; the fixed-world
|
||||
finance neighborhood is now widened to 16 dwords rooted at `[world+0x11]` so later issue-family
|
||||
closure can target a broader owned restore-state window
|
||||
closure can target a broader owned restore-state window; the same annual-finance state now also
|
||||
feeds a shared company market reader for stock-capital, salary, bonus, and issue-calendar values
|
||||
- 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
|
||||
instead of guessing another derived leaf field from neighboring raw offsets
|
||||
|
|
|
|||
|
|
@ -211,7 +211,10 @@ supports a bundled annual-finance reader seam for assigned shares, public float,
|
|||
cached share price, which is a better base for later dividend / issue-calendar simulation than
|
||||
scattered single-field helpers. The fixed-world finance neighborhood is now widened to 16 dwords
|
||||
rooted at `[world+0x11]`, so later issue-`0x38/0x39` closure can build on a broader owned
|
||||
restore-state window instead of another narrow probe.
|
||||
restore-state window instead of another narrow probe. The same owned company annual-finance state
|
||||
now also drives a shared company market reader seam for stock-capital, salary, bonus, and
|
||||
issue-calendar values, which is a better base for shellless finance simulation than summary-only
|
||||
helpers.
|
||||
|
||||
## Why This Boundary
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue