Rehost selected-year gap scalar owner state
This commit is contained in:
parent
4623a05156
commit
534c827dca
8 changed files with 180 additions and 10 deletions
|
|
@ -120,6 +120,8 @@ action label, and the grounded debt/share payload totals used by the shell news
|
||||||
Calendar stepping now also starts to use that same seam directly: `StepCount` and `AdvanceTo`
|
Calendar stepping now also starts to use that same seam directly: `StepCount` and `AdvanceTo`
|
||||||
invoke the periodic-boundary service automatically on year rollover, so shellless calendar advance
|
invoke the periodic-boundary service automatically on year rollover, so shellless calendar advance
|
||||||
can drive the annual finance stack instead of requiring a separate manual service command.
|
can drive the annual finance stack instead of requiring a separate manual service command.
|
||||||
|
That stepped world-time path now also refreshes the rehosted selected-year gap scalar owner lane
|
||||||
|
instead of leaving `[world+0x4ca2]` as a frozen load-time residue.
|
||||||
Those bankruptcy branches now follow the grounded owner semantics too: they stamp the bankruptcy
|
Those bankruptcy branches now follow the grounded owner semantics too: they stamp the bankruptcy
|
||||||
year and halve live bond principals in place instead of treating bankruptcy as a liquidation path.
|
year and halve live bond principals in place instead of treating bankruptcy as a liquidation path.
|
||||||
The same save-native live bond-slot surface now also carries per-slot maturity years all the way
|
The same save-native live bond-slot surface now also carries per-slot maturity years all the way
|
||||||
|
|
|
||||||
|
|
@ -324,6 +324,7 @@ pub fn project_save_slice_to_runtime_state_import(
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let mut state = state;
|
let mut state = state;
|
||||||
|
state.refresh_derived_world_state();
|
||||||
state.refresh_derived_market_state();
|
state.refresh_derived_market_state();
|
||||||
state.validate()?;
|
state.validate()?;
|
||||||
|
|
||||||
|
|
@ -459,6 +460,7 @@ pub fn project_save_slice_overlay_to_runtime_state_import(
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let mut state = state;
|
let mut state = state;
|
||||||
|
state.refresh_derived_world_state();
|
||||||
state.refresh_derived_market_state();
|
state.refresh_derived_market_state();
|
||||||
state.validate()?;
|
state.validate()?;
|
||||||
|
|
||||||
|
|
@ -932,6 +934,8 @@ fn project_save_slice_components(
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|state| state.lane_value_f32_text.clone())
|
.map(|state| state.lane_value_f32_text.clone())
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
|
selected_year_gap_scalar_raw_u32: None,
|
||||||
|
selected_year_gap_scalar_value_f32_text: None,
|
||||||
absolute_counter_restore_kind: Some(
|
absolute_counter_restore_kind: Some(
|
||||||
if save_slice.world_finance_neighborhood_state.is_some() {
|
if save_slice.world_finance_neighborhood_state.is_some() {
|
||||||
"save-direct-world-absolute-counter".to_string()
|
"save-direct-world-absolute-counter".to_string()
|
||||||
|
|
|
||||||
|
|
@ -1398,6 +1398,10 @@ pub struct RuntimeWorldRestoreState {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub economic_tuning_lane_value_f32_text: Vec<String>,
|
pub economic_tuning_lane_value_f32_text: Vec<String>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
pub selected_year_gap_scalar_raw_u32: Option<u32>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub selected_year_gap_scalar_value_f32_text: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
pub absolute_counter_restore_kind: Option<String>,
|
pub absolute_counter_restore_kind: Option<String>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub absolute_counter_adjustment_context: Option<String>,
|
pub absolute_counter_adjustment_context: Option<String>,
|
||||||
|
|
@ -2352,6 +2356,35 @@ impl RuntimeState {
|
||||||
.max(profile.net_worth_total);
|
.max(profile.net_worth_total);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn refresh_derived_world_state(&mut self) {
|
||||||
|
let year_word = self
|
||||||
|
.world_restore
|
||||||
|
.packed_year_word_raw_u16
|
||||||
|
.map(u32::from)
|
||||||
|
.or_else(|| {
|
||||||
|
self.world_restore
|
||||||
|
.current_calendar_tuple_word_raw_u32
|
||||||
|
.zip(self.world_restore.current_calendar_tuple_word_2_raw_u32)
|
||||||
|
.map(|(word_0, word_1)| {
|
||||||
|
u32::from(runtime_decode_packed_calendar_tuple(word_0, word_1).year_word)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.unwrap_or(self.calendar.year);
|
||||||
|
if let Some(value) = runtime_world_selected_year_gap_scalar_from_year_word(year_word) {
|
||||||
|
self.world_restore.selected_year_gap_scalar_raw_u32 = Some(value.to_bits());
|
||||||
|
self.world_restore.selected_year_gap_scalar_value_f32_text =
|
||||||
|
Some(format!("{value:.6}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn runtime_world_selected_year_gap_scalar_from_year_word(year_word: u32) -> Option<f32> {
|
||||||
|
let normalized = (year_word as f64 - 1850.0) / 150.0;
|
||||||
|
if !normalized.is_finite() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some(normalized.clamp(1.0 / 3.0, 1.0) as f32)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn runtime_company_stat_value(
|
pub fn runtime_company_stat_value(
|
||||||
|
|
@ -4968,6 +5001,8 @@ mod tests {
|
||||||
economic_tuning_mirror_value_f32_text: None,
|
economic_tuning_mirror_value_f32_text: None,
|
||||||
economic_tuning_lane_raw_u32: Vec::new(),
|
economic_tuning_lane_raw_u32: Vec::new(),
|
||||||
economic_tuning_lane_value_f32_text: Vec::new(),
|
economic_tuning_lane_value_f32_text: Vec::new(),
|
||||||
|
selected_year_gap_scalar_raw_u32: None,
|
||||||
|
selected_year_gap_scalar_value_f32_text: None,
|
||||||
absolute_counter_restore_kind: Some(
|
absolute_counter_restore_kind: Some(
|
||||||
"mode-adjusted-selected-year-lane".to_string(),
|
"mode-adjusted-selected-year-lane".to_string(),
|
||||||
),
|
),
|
||||||
|
|
@ -7954,6 +7989,86 @@ mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn derives_selected_year_gap_scalar_from_year_word() {
|
||||||
|
assert_eq!(
|
||||||
|
runtime_world_selected_year_gap_scalar_from_year_word(1830),
|
||||||
|
Some((1.0f32 / 3.0).clamp(1.0 / 3.0, 1.0))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
runtime_world_selected_year_gap_scalar_from_year_word(1900),
|
||||||
|
Some((50.0f32 / 150.0).clamp(1.0 / 3.0, 1.0))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
runtime_world_selected_year_gap_scalar_from_year_word(2000),
|
||||||
|
Some(1.0)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn refreshes_selected_year_gap_scalar_from_world_restore_calendar() {
|
||||||
|
let mut 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 {
|
||||||
|
packed_year_word_raw_u16: Some(1900),
|
||||||
|
..RuntimeWorldRestoreState::default()
|
||||||
|
},
|
||||||
|
metadata: BTreeMap::new(),
|
||||||
|
companies: Vec::new(),
|
||||||
|
selected_company_id: None,
|
||||||
|
players: Vec::new(),
|
||||||
|
selected_player_id: None,
|
||||||
|
chairman_profiles: Vec::new(),
|
||||||
|
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::default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
state.refresh_derived_world_state();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
state.world_restore.selected_year_gap_scalar_raw_u32,
|
||||||
|
Some(((50.0f32 / 150.0).clamp(1.0 / 3.0, 1.0)).to_bits())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
state
|
||||||
|
.world_restore
|
||||||
|
.selected_year_gap_scalar_value_f32_text
|
||||||
|
.as_deref(),
|
||||||
|
Some("0.333333")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn derives_company_unassigned_share_pool_from_market_state_and_holdings() {
|
fn derives_company_unassigned_share_pool_from_market_state_and_holdings() {
|
||||||
let state = RuntimeState {
|
let state = RuntimeState {
|
||||||
|
|
|
||||||
|
|
@ -140,6 +140,7 @@ pub fn execute_step_command(
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
state.refresh_derived_world_state();
|
||||||
state.refresh_derived_market_state();
|
state.refresh_derived_market_state();
|
||||||
let final_summary = RuntimeSummary::from_state(state);
|
let final_summary = RuntimeSummary::from_state(state);
|
||||||
|
|
||||||
|
|
@ -2968,6 +2969,17 @@ mod tests {
|
||||||
state.world_restore.absolute_counter_mirror_raw_u32,
|
state.world_restore.absolute_counter_mirror_raw_u32,
|
||||||
Some(885_427_240)
|
Some(885_427_240)
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
state.world_restore.selected_year_gap_scalar_raw_u32,
|
||||||
|
Some((1.0f32 / 3.0).to_bits())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
state
|
||||||
|
.world_restore
|
||||||
|
.selected_year_gap_scalar_value_f32_text
|
||||||
|
.as_deref(),
|
||||||
|
Some("0.333333")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -3038,6 +3050,17 @@ mod tests {
|
||||||
state.world_restore.absolute_counter_mirror_raw_u32,
|
state.world_restore.absolute_counter_mirror_raw_u32,
|
||||||
Some(885_911_040)
|
Some(885_911_040)
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
state.world_restore.selected_year_gap_scalar_raw_u32,
|
||||||
|
Some((1.0f32 / 3.0).to_bits())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
state
|
||||||
|
.world_restore
|
||||||
|
.selected_year_gap_scalar_value_f32_text
|
||||||
|
.as_deref(),
|
||||||
|
Some("0.333333")
|
||||||
|
);
|
||||||
assert!(
|
assert!(
|
||||||
result
|
result
|
||||||
.service_events
|
.service_events
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,8 @@ pub struct RuntimeSummary {
|
||||||
pub world_restore_economic_tuning_mirror_value_f32_text: Option<String>,
|
pub world_restore_economic_tuning_mirror_value_f32_text: Option<String>,
|
||||||
pub world_restore_economic_tuning_lane_count: usize,
|
pub world_restore_economic_tuning_lane_count: usize,
|
||||||
pub world_restore_economic_tuning_lane_value_f32_text: Vec<String>,
|
pub world_restore_economic_tuning_lane_value_f32_text: Vec<String>,
|
||||||
|
pub world_restore_selected_year_gap_scalar_raw_u32: Option<u32>,
|
||||||
|
pub world_restore_selected_year_gap_scalar_value_f32_text: Option<String>,
|
||||||
pub world_restore_absolute_counter_restore_kind: Option<String>,
|
pub world_restore_absolute_counter_restore_kind: Option<String>,
|
||||||
pub world_restore_absolute_counter_adjustment_context: Option<String>,
|
pub world_restore_absolute_counter_adjustment_context: Option<String>,
|
||||||
pub metadata_count: usize,
|
pub metadata_count: usize,
|
||||||
|
|
@ -428,6 +430,13 @@ impl RuntimeSummary {
|
||||||
.world_restore
|
.world_restore
|
||||||
.economic_tuning_lane_value_f32_text
|
.economic_tuning_lane_value_f32_text
|
||||||
.clone(),
|
.clone(),
|
||||||
|
world_restore_selected_year_gap_scalar_raw_u32: state
|
||||||
|
.world_restore
|
||||||
|
.selected_year_gap_scalar_raw_u32,
|
||||||
|
world_restore_selected_year_gap_scalar_value_f32_text: state
|
||||||
|
.world_restore
|
||||||
|
.selected_year_gap_scalar_value_f32_text
|
||||||
|
.clone(),
|
||||||
world_restore_absolute_counter_restore_kind: state
|
world_restore_absolute_counter_restore_kind: state
|
||||||
.world_restore
|
.world_restore
|
||||||
.absolute_counter_restore_kind
|
.absolute_counter_restore_kind
|
||||||
|
|
@ -1747,6 +1756,8 @@ mod tests {
|
||||||
"0.01".to_string(),
|
"0.01".to_string(),
|
||||||
"0.01".to_string(),
|
"0.01".to_string(),
|
||||||
],
|
],
|
||||||
|
selected_year_gap_scalar_raw_u32: Some(0x3eaaaaab),
|
||||||
|
selected_year_gap_scalar_value_f32_text: Some("0.333333".to_string()),
|
||||||
..RuntimeWorldRestoreState::default()
|
..RuntimeWorldRestoreState::default()
|
||||||
},
|
},
|
||||||
metadata: BTreeMap::new(),
|
metadata: BTreeMap::new(),
|
||||||
|
|
@ -1862,6 +1873,16 @@ mod tests {
|
||||||
summary.world_restore_economic_tuning_lane_value_f32_text,
|
summary.world_restore_economic_tuning_lane_value_f32_text,
|
||||||
vec!["0.75", "0.007", "0.008", "0.009", "0.01", "0.01"]
|
vec!["0.75", "0.007", "0.008", "0.009", "0.01", "0.01"]
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
summary.world_restore_selected_year_gap_scalar_raw_u32,
|
||||||
|
Some(0x3eaaaaab)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
summary
|
||||||
|
.world_restore_selected_year_gap_scalar_value_f32_text
|
||||||
|
.as_deref(),
|
||||||
|
Some("0.333333")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -166,6 +166,9 @@ The highest-value next passes are now:
|
||||||
- shellless calendar advance now also drives that annual seam directly: `StepCount` and `AdvanceTo`
|
- shellless calendar advance now also drives that annual seam directly: `StepCount` and `AdvanceTo`
|
||||||
invoke periodic-boundary service automatically on year rollover instead of requiring a second
|
invoke periodic-boundary service automatically on year rollover instead of requiring a second
|
||||||
manual service pass to make the annual finance stack run
|
manual service pass to make the annual finance stack run
|
||||||
|
- that stepped world-time path now also refreshes the derived selected-year gap scalar owner lane
|
||||||
|
`[world+0x4ca2]`, so later selected-year and periodic-boundary world work can build on runtime
|
||||||
|
state instead of a frozen load-time scalar
|
||||||
- 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
|
||||||
|
|
|
||||||
|
|
@ -9,15 +9,13 @@ Working rule:
|
||||||
|
|
||||||
## Next
|
## Next
|
||||||
|
|
||||||
- Rehost world time owner-state progression from `CalendarPoint` into `world_restore`:
|
- Rehost the next selected-year periodic-boundary world seam under
|
||||||
sync `packed_year_word_raw_u16`, `partial_year_progress_raw_u8`, packed calendar tuple words,
|
`simulation_service_periodic_boundary_work`, starting with the save-world economic tuning mirror
|
||||||
and absolute counter so shellless stepping advances the same finance/economy reader inputs used
|
`[world+0x0bde]` and any directly adjacent selected-year companion bands that can be refreshed
|
||||||
by periodic service.
|
from stepped world time without shell ownership.
|
||||||
- Make automatic year-rollover periodic service run against a consistent end-of-year world-time
|
- Expand the selected-year world-owner surface beyond the new stepped calendar and gap-scalar
|
||||||
snapshot, then refresh into the new-year snapshot after service commits.
|
lanes when the owning reader/rebuild family is grounded strongly enough to avoid one-off leaf
|
||||||
- Rehost the next shellless periodic-boundary world work under
|
guesses.
|
||||||
`simulation_service_periodic_boundary_work`, starting with any bounded non-dialog queue/state
|
|
||||||
family that can execute without shell ownership.
|
|
||||||
|
|
||||||
## In Progress
|
## In Progress
|
||||||
|
|
||||||
|
|
@ -43,6 +41,8 @@ Working rule:
|
||||||
|
|
||||||
## Recently Done
|
## Recently Done
|
||||||
|
|
||||||
|
- Stepped calendar progression now also refreshes save-world owner time fields, including packed
|
||||||
|
year, packed tuple words, absolute counter, and the derived selected-year gap scalar.
|
||||||
- Automatic year-rollover calendar stepping now invokes periodic-boundary service.
|
- Automatic year-rollover calendar stepping now invokes periodic-boundary service.
|
||||||
- Company cash, confiscation, and major governance effects now write through owner state instead of
|
- Company cash, confiscation, and major governance effects now write through owner state instead of
|
||||||
drifting from market/cache readers.
|
drifting from market/cache readers.
|
||||||
|
|
|
||||||
|
|
@ -215,7 +215,9 @@ flows through save-slice/runtime restore state, so later credit / prime / manage
|
||||||
build on owned issue state instead of another narrow probe; that same owner surface now also carries
|
build on owned issue state instead of another narrow probe; that same owner surface now also carries
|
||||||
the saved world absolute counter as first-class runtime restore state instead of shell-context
|
the saved world absolute counter as first-class runtime restore state instead of shell-context
|
||||||
metadata, plus the packed year word and partial-year progress lane that feed the annual-finance
|
metadata, plus the packed year word and partial-year progress lane that feed the annual-finance
|
||||||
recent-history weighting path. The same owned company annual-finance state
|
recent-history weighting path. Stepped world time now also refreshes the derived selected-year gap
|
||||||
|
scalar owner lane `[world+0x4ca2]`, so later selected-year periodic-boundary world work can build
|
||||||
|
on runtime state instead of a frozen load-time scalar. The same owned company annual-finance state
|
||||||
now also drives a shared company market reader seam for stock-capital, salary, bonus, and the full
|
now also drives a shared company market reader seam for stock-capital, salary, bonus, and the full
|
||||||
two-word current/prior issue-calendar tuples, which is a better base for shellless finance
|
two-word current/prior issue-calendar tuples, which is a better base for shellless finance
|
||||||
simulation than summary-only helpers. That same owned annual-finance state now also derives elapsed
|
simulation than summary-only helpers. That same owned annual-finance state now also derives elapsed
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue