2026-04-10 01:22:47 -07:00
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
|
|
|
|
|
use crate::{CalendarPoint, RuntimeState};
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
|
|
|
pub struct RuntimeSummary {
|
|
|
|
|
pub calendar: CalendarPoint,
|
2026-04-11 18:12:25 -07:00
|
|
|
pub calendar_projection_source: Option<String>,
|
|
|
|
|
pub calendar_projection_is_placeholder: bool,
|
2026-04-10 01:22:47 -07:00
|
|
|
pub world_flag_count: usize,
|
2026-04-11 18:12:25 -07:00
|
|
|
pub world_restore_selected_year_profile_lane: Option<u8>,
|
|
|
|
|
pub world_restore_campaign_scenario_enabled: Option<bool>,
|
|
|
|
|
pub world_restore_sandbox_enabled: Option<bool>,
|
|
|
|
|
pub world_restore_seed_tuple_written_from_raw_lane: Option<bool>,
|
|
|
|
|
pub world_restore_absolute_counter_requires_shell_context: Option<bool>,
|
|
|
|
|
pub world_restore_absolute_counter_reconstructible_from_save: Option<bool>,
|
|
|
|
|
pub world_restore_disable_cargo_economy_special_condition_slot: Option<u8>,
|
|
|
|
|
pub world_restore_disable_cargo_economy_special_condition_reconstructible_from_save:
|
|
|
|
|
Option<bool>,
|
|
|
|
|
pub world_restore_disable_cargo_economy_special_condition_write_side_grounded: Option<bool>,
|
|
|
|
|
pub world_restore_disable_cargo_economy_special_condition_enabled: Option<bool>,
|
|
|
|
|
pub world_restore_use_bio_accelerator_cars_enabled: Option<bool>,
|
|
|
|
|
pub world_restore_use_wartime_cargos_enabled: Option<bool>,
|
|
|
|
|
pub world_restore_disable_train_crashes_enabled: Option<bool>,
|
|
|
|
|
pub world_restore_disable_train_crashes_and_breakdowns_enabled: Option<bool>,
|
|
|
|
|
pub world_restore_ai_ignore_territories_at_startup_enabled: Option<bool>,
|
|
|
|
|
pub world_restore_absolute_counter_restore_kind: Option<String>,
|
|
|
|
|
pub world_restore_absolute_counter_adjustment_context: Option<String>,
|
|
|
|
|
pub metadata_count: usize,
|
2026-04-10 01:22:47 -07:00
|
|
|
pub company_count: usize,
|
2026-04-15 12:11:29 -07:00
|
|
|
pub active_company_count: usize,
|
2026-04-14 20:01:43 -07:00
|
|
|
pub packed_event_collection_present: bool,
|
|
|
|
|
pub packed_event_record_count: usize,
|
2026-04-14 20:35:07 -07:00
|
|
|
pub packed_event_decoded_record_count: usize,
|
|
|
|
|
pub packed_event_imported_runtime_record_count: usize,
|
2026-04-14 20:51:27 -07:00
|
|
|
pub packed_event_parity_only_record_count: usize,
|
|
|
|
|
pub packed_event_unsupported_record_count: usize,
|
2026-04-14 21:19:08 -07:00
|
|
|
pub packed_event_blocked_missing_company_context_count: usize,
|
2026-04-15 09:13:51 -07:00
|
|
|
pub packed_event_blocked_missing_selection_context_count: usize,
|
|
|
|
|
pub packed_event_blocked_missing_company_role_context_count: usize,
|
|
|
|
|
pub packed_event_blocked_missing_condition_context_count: usize,
|
2026-04-14 23:01:18 -07:00
|
|
|
pub packed_event_blocked_missing_compact_control_count: usize,
|
|
|
|
|
pub packed_event_blocked_unmapped_real_descriptor_count: usize,
|
2026-04-14 22:09:09 -07:00
|
|
|
pub packed_event_blocked_structural_only_count: usize,
|
2026-04-10 01:22:47 -07:00
|
|
|
pub event_runtime_record_count: usize,
|
2026-04-11 18:12:25 -07:00
|
|
|
pub candidate_availability_count: usize,
|
|
|
|
|
pub zero_candidate_availability_count: usize,
|
|
|
|
|
pub special_condition_count: usize,
|
|
|
|
|
pub enabled_special_condition_count: usize,
|
|
|
|
|
pub save_profile_kind: Option<String>,
|
|
|
|
|
pub save_profile_family: Option<String>,
|
|
|
|
|
pub save_profile_map_path: Option<String>,
|
|
|
|
|
pub save_profile_display_name: Option<String>,
|
|
|
|
|
pub save_profile_selected_year_profile_lane: Option<u8>,
|
|
|
|
|
pub save_profile_sandbox_enabled: Option<bool>,
|
|
|
|
|
pub save_profile_campaign_scenario_enabled: Option<bool>,
|
|
|
|
|
pub save_profile_staged_profile_copy_on_restore: Option<bool>,
|
2026-04-10 01:22:47 -07:00
|
|
|
pub total_event_record_service_count: u64,
|
|
|
|
|
pub periodic_boundary_call_count: u64,
|
|
|
|
|
pub total_trigger_dispatch_count: u64,
|
|
|
|
|
pub dirty_rerun_count: u64,
|
|
|
|
|
pub total_company_cash: i64,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl RuntimeSummary {
|
|
|
|
|
pub fn from_state(state: &RuntimeState) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
calendar: state.calendar,
|
2026-04-11 18:12:25 -07:00
|
|
|
calendar_projection_source: state.metadata.get("save_slice.calendar_source").cloned(),
|
|
|
|
|
calendar_projection_is_placeholder: state
|
|
|
|
|
.metadata
|
|
|
|
|
.get("save_slice.calendar_source")
|
|
|
|
|
.is_some_and(|value| value == "default-1830-placeholder"),
|
2026-04-10 01:22:47 -07:00
|
|
|
world_flag_count: state.world_flags.len(),
|
2026-04-11 18:12:25 -07:00
|
|
|
world_restore_selected_year_profile_lane: state
|
|
|
|
|
.world_restore
|
|
|
|
|
.selected_year_profile_lane,
|
|
|
|
|
world_restore_campaign_scenario_enabled: state.world_restore.campaign_scenario_enabled,
|
|
|
|
|
world_restore_sandbox_enabled: state.world_restore.sandbox_enabled,
|
|
|
|
|
world_restore_seed_tuple_written_from_raw_lane: state
|
|
|
|
|
.world_restore
|
|
|
|
|
.seed_tuple_written_from_raw_lane,
|
|
|
|
|
world_restore_absolute_counter_requires_shell_context: state
|
|
|
|
|
.world_restore
|
|
|
|
|
.absolute_counter_requires_shell_context,
|
|
|
|
|
world_restore_absolute_counter_reconstructible_from_save: state
|
|
|
|
|
.world_restore
|
|
|
|
|
.absolute_counter_reconstructible_from_save,
|
|
|
|
|
world_restore_disable_cargo_economy_special_condition_slot: state
|
|
|
|
|
.world_restore
|
|
|
|
|
.disable_cargo_economy_special_condition_slot,
|
|
|
|
|
world_restore_disable_cargo_economy_special_condition_reconstructible_from_save: state
|
|
|
|
|
.world_restore
|
|
|
|
|
.disable_cargo_economy_special_condition_reconstructible_from_save,
|
|
|
|
|
world_restore_disable_cargo_economy_special_condition_write_side_grounded: state
|
|
|
|
|
.world_restore
|
|
|
|
|
.disable_cargo_economy_special_condition_write_side_grounded,
|
|
|
|
|
world_restore_disable_cargo_economy_special_condition_enabled: state
|
|
|
|
|
.world_restore
|
|
|
|
|
.disable_cargo_economy_special_condition_enabled,
|
|
|
|
|
world_restore_use_bio_accelerator_cars_enabled: state
|
|
|
|
|
.world_restore
|
|
|
|
|
.use_bio_accelerator_cars_enabled,
|
|
|
|
|
world_restore_use_wartime_cargos_enabled: state
|
|
|
|
|
.world_restore
|
|
|
|
|
.use_wartime_cargos_enabled,
|
|
|
|
|
world_restore_disable_train_crashes_enabled: state
|
|
|
|
|
.world_restore
|
|
|
|
|
.disable_train_crashes_enabled,
|
|
|
|
|
world_restore_disable_train_crashes_and_breakdowns_enabled: state
|
|
|
|
|
.world_restore
|
|
|
|
|
.disable_train_crashes_and_breakdowns_enabled,
|
|
|
|
|
world_restore_ai_ignore_territories_at_startup_enabled: state
|
|
|
|
|
.world_restore
|
|
|
|
|
.ai_ignore_territories_at_startup_enabled,
|
|
|
|
|
world_restore_absolute_counter_restore_kind: state
|
|
|
|
|
.world_restore
|
|
|
|
|
.absolute_counter_restore_kind
|
|
|
|
|
.clone(),
|
|
|
|
|
world_restore_absolute_counter_adjustment_context: state
|
|
|
|
|
.world_restore
|
|
|
|
|
.absolute_counter_adjustment_context
|
|
|
|
|
.clone(),
|
|
|
|
|
metadata_count: state.metadata.len(),
|
2026-04-10 01:22:47 -07:00
|
|
|
company_count: state.companies.len(),
|
2026-04-15 12:11:29 -07:00
|
|
|
active_company_count: state.companies.iter().filter(|company| company.active).count(),
|
2026-04-14 20:01:43 -07:00
|
|
|
packed_event_collection_present: state.packed_event_collection.is_some(),
|
|
|
|
|
packed_event_record_count: state
|
|
|
|
|
.packed_event_collection
|
|
|
|
|
.as_ref()
|
|
|
|
|
.map(|summary| summary.live_record_count)
|
|
|
|
|
.unwrap_or(0),
|
2026-04-14 20:35:07 -07:00
|
|
|
packed_event_decoded_record_count: state
|
|
|
|
|
.packed_event_collection
|
|
|
|
|
.as_ref()
|
|
|
|
|
.map(|summary| summary.decoded_record_count)
|
|
|
|
|
.unwrap_or(0),
|
|
|
|
|
packed_event_imported_runtime_record_count: state
|
|
|
|
|
.packed_event_collection
|
|
|
|
|
.as_ref()
|
|
|
|
|
.map(|summary| summary.imported_runtime_record_count)
|
|
|
|
|
.unwrap_or(0),
|
2026-04-14 20:51:27 -07:00
|
|
|
packed_event_parity_only_record_count: state
|
|
|
|
|
.packed_event_collection
|
|
|
|
|
.as_ref()
|
|
|
|
|
.map(|summary| {
|
|
|
|
|
summary
|
|
|
|
|
.records
|
|
|
|
|
.iter()
|
|
|
|
|
.filter(|record| record.decode_status == "parity_only")
|
|
|
|
|
.count()
|
|
|
|
|
})
|
|
|
|
|
.unwrap_or(0),
|
|
|
|
|
packed_event_unsupported_record_count: state
|
|
|
|
|
.packed_event_collection
|
|
|
|
|
.as_ref()
|
|
|
|
|
.map(|summary| {
|
|
|
|
|
summary
|
|
|
|
|
.records
|
|
|
|
|
.iter()
|
|
|
|
|
.filter(|record| record.decode_status == "unsupported_framing")
|
|
|
|
|
.count()
|
|
|
|
|
})
|
|
|
|
|
.unwrap_or(0),
|
2026-04-14 21:19:08 -07:00
|
|
|
packed_event_blocked_missing_company_context_count: state
|
|
|
|
|
.packed_event_collection
|
|
|
|
|
.as_ref()
|
|
|
|
|
.map(|summary| {
|
|
|
|
|
summary
|
|
|
|
|
.records
|
|
|
|
|
.iter()
|
|
|
|
|
.filter(|record| {
|
|
|
|
|
record.import_outcome.as_deref()
|
|
|
|
|
== Some("blocked_missing_company_context")
|
|
|
|
|
})
|
|
|
|
|
.count()
|
|
|
|
|
})
|
|
|
|
|
.unwrap_or(0),
|
2026-04-15 09:13:51 -07:00
|
|
|
packed_event_blocked_missing_selection_context_count: state
|
|
|
|
|
.packed_event_collection
|
|
|
|
|
.as_ref()
|
|
|
|
|
.map(|summary| {
|
|
|
|
|
summary
|
|
|
|
|
.records
|
|
|
|
|
.iter()
|
|
|
|
|
.filter(|record| {
|
|
|
|
|
record.import_outcome.as_deref()
|
|
|
|
|
== Some("blocked_missing_selection_context")
|
|
|
|
|
})
|
|
|
|
|
.count()
|
|
|
|
|
})
|
|
|
|
|
.unwrap_or(0),
|
|
|
|
|
packed_event_blocked_missing_company_role_context_count: state
|
|
|
|
|
.packed_event_collection
|
|
|
|
|
.as_ref()
|
|
|
|
|
.map(|summary| {
|
|
|
|
|
summary
|
|
|
|
|
.records
|
|
|
|
|
.iter()
|
|
|
|
|
.filter(|record| {
|
|
|
|
|
record.import_outcome.as_deref()
|
|
|
|
|
== Some("blocked_missing_company_role_context")
|
|
|
|
|
})
|
|
|
|
|
.count()
|
|
|
|
|
})
|
|
|
|
|
.unwrap_or(0),
|
|
|
|
|
packed_event_blocked_missing_condition_context_count: state
|
|
|
|
|
.packed_event_collection
|
|
|
|
|
.as_ref()
|
|
|
|
|
.map(|summary| {
|
|
|
|
|
summary
|
|
|
|
|
.records
|
|
|
|
|
.iter()
|
|
|
|
|
.filter(|record| {
|
|
|
|
|
record.import_outcome.as_deref()
|
|
|
|
|
== Some("blocked_missing_condition_context")
|
|
|
|
|
})
|
|
|
|
|
.count()
|
|
|
|
|
})
|
|
|
|
|
.unwrap_or(0),
|
2026-04-14 23:01:18 -07:00
|
|
|
packed_event_blocked_missing_compact_control_count: state
|
|
|
|
|
.packed_event_collection
|
|
|
|
|
.as_ref()
|
|
|
|
|
.map(|summary| {
|
|
|
|
|
summary
|
|
|
|
|
.records
|
|
|
|
|
.iter()
|
|
|
|
|
.filter(|record| {
|
|
|
|
|
record.import_outcome.as_deref()
|
|
|
|
|
== Some("blocked_missing_compact_control")
|
|
|
|
|
})
|
|
|
|
|
.count()
|
|
|
|
|
})
|
|
|
|
|
.unwrap_or(0),
|
|
|
|
|
packed_event_blocked_unmapped_real_descriptor_count: state
|
|
|
|
|
.packed_event_collection
|
|
|
|
|
.as_ref()
|
|
|
|
|
.map(|summary| {
|
|
|
|
|
summary
|
|
|
|
|
.records
|
|
|
|
|
.iter()
|
|
|
|
|
.filter(|record| {
|
|
|
|
|
record.import_outcome.as_deref()
|
|
|
|
|
== Some("blocked_unmapped_real_descriptor")
|
|
|
|
|
})
|
|
|
|
|
.count()
|
|
|
|
|
})
|
|
|
|
|
.unwrap_or(0),
|
2026-04-14 22:09:09 -07:00
|
|
|
packed_event_blocked_structural_only_count: state
|
|
|
|
|
.packed_event_collection
|
|
|
|
|
.as_ref()
|
|
|
|
|
.map(|summary| {
|
|
|
|
|
summary
|
|
|
|
|
.records
|
|
|
|
|
.iter()
|
|
|
|
|
.filter(|record| {
|
|
|
|
|
record.import_outcome.as_deref() == Some("blocked_structural_only")
|
|
|
|
|
})
|
|
|
|
|
.count()
|
|
|
|
|
})
|
|
|
|
|
.unwrap_or(0),
|
2026-04-10 01:22:47 -07:00
|
|
|
event_runtime_record_count: state.event_runtime_records.len(),
|
2026-04-11 18:12:25 -07:00
|
|
|
candidate_availability_count: state.candidate_availability.len(),
|
|
|
|
|
zero_candidate_availability_count: state
|
|
|
|
|
.candidate_availability
|
|
|
|
|
.values()
|
|
|
|
|
.filter(|value| **value == 0)
|
|
|
|
|
.count(),
|
|
|
|
|
special_condition_count: state.special_conditions.len(),
|
|
|
|
|
enabled_special_condition_count: state
|
|
|
|
|
.special_conditions
|
|
|
|
|
.values()
|
|
|
|
|
.filter(|value| **value != 0)
|
|
|
|
|
.count(),
|
|
|
|
|
save_profile_kind: state.save_profile.profile_kind.clone(),
|
|
|
|
|
save_profile_family: state.save_profile.profile_family.clone(),
|
|
|
|
|
save_profile_map_path: state.save_profile.map_path.clone(),
|
|
|
|
|
save_profile_display_name: state.save_profile.display_name.clone(),
|
|
|
|
|
save_profile_selected_year_profile_lane: state.save_profile.selected_year_profile_lane,
|
|
|
|
|
save_profile_sandbox_enabled: state.save_profile.sandbox_enabled,
|
|
|
|
|
save_profile_campaign_scenario_enabled: state.save_profile.campaign_scenario_enabled,
|
|
|
|
|
save_profile_staged_profile_copy_on_restore: state
|
|
|
|
|
.save_profile
|
|
|
|
|
.staged_profile_copy_on_restore,
|
2026-04-10 01:22:47 -07:00
|
|
|
total_event_record_service_count: state.service_state.total_event_record_services,
|
|
|
|
|
periodic_boundary_call_count: state.service_state.periodic_boundary_calls,
|
|
|
|
|
total_trigger_dispatch_count: state
|
|
|
|
|
.service_state
|
|
|
|
|
.trigger_dispatch_counts
|
|
|
|
|
.values()
|
|
|
|
|
.sum(),
|
|
|
|
|
dirty_rerun_count: state.service_state.dirty_rerun_count,
|
|
|
|
|
total_company_cash: state
|
|
|
|
|
.companies
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|company| company.current_cash)
|
|
|
|
|
.sum(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-04-14 22:09:09 -07:00
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests {
|
|
|
|
|
use std::collections::BTreeMap;
|
|
|
|
|
|
|
|
|
|
use crate::{
|
2026-04-15 12:11:29 -07:00
|
|
|
CalendarPoint, RuntimeCompany, RuntimeCompanyControllerKind,
|
|
|
|
|
RuntimePackedEventCollectionSummary, RuntimePackedEventRecordSummary,
|
2026-04-14 22:09:09 -07:00
|
|
|
RuntimeSaveProfileState, RuntimeServiceState, RuntimeState, RuntimeWorldRestoreState,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
use super::RuntimeSummary;
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn counts_structural_only_and_missing_context_frontiers() {
|
|
|
|
|
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::new(),
|
2026-04-15 09:13:51 -07:00
|
|
|
selected_company_id: None,
|
2026-04-14 22:09:09 -07:00
|
|
|
packed_event_collection: Some(RuntimePackedEventCollectionSummary {
|
|
|
|
|
source_kind: "packed-event-runtime-collection".to_string(),
|
|
|
|
|
mechanism_family: "classic-save-rehydrate-v1".to_string(),
|
|
|
|
|
mechanism_confidence: "grounded".to_string(),
|
|
|
|
|
container_profile_family: Some("rt3-classic-save-container-v1".to_string()),
|
|
|
|
|
packed_state_version: 0x3e9,
|
|
|
|
|
packed_state_version_hex: "0x000003e9".to_string(),
|
|
|
|
|
live_id_bound: 7,
|
|
|
|
|
live_record_count: 2,
|
|
|
|
|
live_entry_ids: vec![3, 7],
|
|
|
|
|
decoded_record_count: 2,
|
|
|
|
|
imported_runtime_record_count: 0,
|
|
|
|
|
records: vec![
|
|
|
|
|
RuntimePackedEventRecordSummary {
|
|
|
|
|
record_index: 0,
|
|
|
|
|
live_entry_id: 3,
|
|
|
|
|
payload_offset: Some(0x7202),
|
|
|
|
|
payload_len: Some(96),
|
|
|
|
|
decode_status: "parity_only".to_string(),
|
|
|
|
|
payload_family: "real_packed_v1".to_string(),
|
|
|
|
|
trigger_kind: None,
|
|
|
|
|
active: None,
|
|
|
|
|
marks_collection_dirty: None,
|
|
|
|
|
one_shot: None,
|
2026-04-14 23:01:18 -07:00
|
|
|
compact_control: None,
|
2026-04-14 22:09:09 -07:00
|
|
|
text_bands: Vec::new(),
|
|
|
|
|
standalone_condition_row_count: 0,
|
|
|
|
|
standalone_condition_rows: Vec::new(),
|
|
|
|
|
grouped_effect_row_counts: vec![0, 0, 0, 0],
|
|
|
|
|
grouped_effect_rows: Vec::new(),
|
2026-04-15 09:13:51 -07:00
|
|
|
grouped_company_targets: Vec::new(),
|
2026-04-14 22:09:09 -07:00
|
|
|
decoded_actions: Vec::new(),
|
|
|
|
|
executable_import_ready: false,
|
2026-04-14 23:01:18 -07:00
|
|
|
import_outcome: Some("blocked_missing_compact_control".to_string()),
|
2026-04-14 22:09:09 -07:00
|
|
|
notes: Vec::new(),
|
|
|
|
|
},
|
|
|
|
|
RuntimePackedEventRecordSummary {
|
|
|
|
|
record_index: 1,
|
|
|
|
|
live_entry_id: 7,
|
|
|
|
|
payload_offset: Some(0x7262),
|
|
|
|
|
payload_len: Some(48),
|
|
|
|
|
decode_status: "parity_only".to_string(),
|
|
|
|
|
payload_family: "synthetic_harness".to_string(),
|
|
|
|
|
trigger_kind: Some(7),
|
|
|
|
|
active: Some(true),
|
|
|
|
|
marks_collection_dirty: Some(false),
|
|
|
|
|
one_shot: Some(false),
|
2026-04-14 23:01:18 -07:00
|
|
|
compact_control: None,
|
2026-04-14 22:09:09 -07:00
|
|
|
text_bands: Vec::new(),
|
|
|
|
|
standalone_condition_row_count: 0,
|
|
|
|
|
standalone_condition_rows: Vec::new(),
|
|
|
|
|
grouped_effect_row_counts: vec![0, 0, 0, 0],
|
|
|
|
|
grouped_effect_rows: Vec::new(),
|
2026-04-15 09:13:51 -07:00
|
|
|
grouped_company_targets: Vec::new(),
|
2026-04-14 22:09:09 -07:00
|
|
|
decoded_actions: Vec::new(),
|
|
|
|
|
executable_import_ready: false,
|
|
|
|
|
import_outcome: Some("blocked_missing_company_context".to_string()),
|
|
|
|
|
notes: Vec::new(),
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
}),
|
|
|
|
|
event_runtime_records: Vec::new(),
|
|
|
|
|
candidate_availability: BTreeMap::new(),
|
|
|
|
|
special_conditions: BTreeMap::new(),
|
|
|
|
|
service_state: RuntimeServiceState::default(),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let summary = RuntimeSummary::from_state(&state);
|
2026-04-14 23:01:18 -07:00
|
|
|
assert_eq!(summary.packed_event_blocked_missing_compact_control_count, 1);
|
|
|
|
|
assert_eq!(summary.packed_event_blocked_unmapped_real_descriptor_count, 0);
|
|
|
|
|
assert_eq!(summary.packed_event_blocked_structural_only_count, 0);
|
2026-04-14 22:09:09 -07:00
|
|
|
assert_eq!(summary.packed_event_blocked_missing_company_context_count, 1);
|
2026-04-15 09:13:51 -07:00
|
|
|
assert_eq!(summary.packed_event_blocked_missing_selection_context_count, 0);
|
|
|
|
|
assert_eq!(summary.packed_event_blocked_missing_company_role_context_count, 0);
|
|
|
|
|
assert_eq!(summary.packed_event_blocked_missing_condition_context_count, 0);
|
2026-04-14 22:09:09 -07:00
|
|
|
}
|
2026-04-15 12:11:29 -07:00
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn counts_active_companies_separately_from_total_companies() {
|
|
|
|
|
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: 1,
|
|
|
|
|
current_cash: 10,
|
|
|
|
|
debt: 0,
|
|
|
|
|
active: true,
|
|
|
|
|
available_track_laying_capacity: None,
|
|
|
|
|
controller_kind: RuntimeCompanyControllerKind::Human,
|
|
|
|
|
},
|
|
|
|
|
RuntimeCompany {
|
|
|
|
|
company_id: 2,
|
|
|
|
|
current_cash: 20,
|
|
|
|
|
debt: 0,
|
|
|
|
|
active: false,
|
|
|
|
|
available_track_laying_capacity: Some(7),
|
|
|
|
|
controller_kind: RuntimeCompanyControllerKind::Ai,
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
selected_company_id: None,
|
|
|
|
|
packed_event_collection: None,
|
|
|
|
|
event_runtime_records: Vec::new(),
|
|
|
|
|
candidate_availability: BTreeMap::new(),
|
|
|
|
|
special_conditions: BTreeMap::new(),
|
|
|
|
|
service_state: RuntimeServiceState::default(),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let summary = RuntimeSummary::from_state(&state);
|
|
|
|
|
assert_eq!(summary.company_count, 2);
|
|
|
|
|
assert_eq!(summary.active_company_count, 1);
|
|
|
|
|
}
|
2026-04-14 22:09:09 -07:00
|
|
|
}
|