Implement real company-scoped event descriptors
This commit is contained in:
parent
eb6c4833af
commit
780e739daa
21 changed files with 1483 additions and 56 deletions
|
|
@ -299,6 +299,41 @@ fn apply_runtime_effects(
|
|||
mutated_company_ids.insert(company_id);
|
||||
}
|
||||
}
|
||||
RuntimeEffect::DeactivateCompany { target } => {
|
||||
let company_ids = resolve_company_target_ids(state, target)?;
|
||||
for company_id in company_ids {
|
||||
let company = state
|
||||
.companies
|
||||
.iter_mut()
|
||||
.find(|company| company.company_id == company_id)
|
||||
.ok_or_else(|| {
|
||||
format!(
|
||||
"missing company_id {company_id} while applying deactivate effect"
|
||||
)
|
||||
})?;
|
||||
company.active = false;
|
||||
mutated_company_ids.insert(company_id);
|
||||
if state.selected_company_id == Some(company_id) {
|
||||
state.selected_company_id = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
RuntimeEffect::SetCompanyTrackLayingCapacity { target, value } => {
|
||||
let company_ids = resolve_company_target_ids(state, target)?;
|
||||
for company_id in company_ids {
|
||||
let company = state
|
||||
.companies
|
||||
.iter_mut()
|
||||
.find(|company| company.company_id == company_id)
|
||||
.ok_or_else(|| {
|
||||
format!(
|
||||
"missing company_id {company_id} while applying track capacity effect"
|
||||
)
|
||||
})?;
|
||||
company.available_track_laying_capacity = *value;
|
||||
mutated_company_ids.insert(company_id);
|
||||
}
|
||||
}
|
||||
RuntimeEffect::AdjustCompanyCash { target, delta } => {
|
||||
let company_ids = resolve_company_target_ids(state, target)?;
|
||||
for company_id in company_ids {
|
||||
|
|
@ -429,6 +464,7 @@ fn resolve_company_target_ids(
|
|||
RuntimeCompanyTarget::AllActive => Ok(state
|
||||
.companies
|
||||
.iter()
|
||||
.filter(|company| company.active)
|
||||
.map(|company| company.company_id)
|
||||
.collect()),
|
||||
RuntimeCompanyTarget::Ids { ids } => {
|
||||
|
|
@ -458,7 +494,10 @@ fn resolve_company_target_ids(
|
|||
Ok(state
|
||||
.companies
|
||||
.iter()
|
||||
.filter(|company| company.controller_kind == RuntimeCompanyControllerKind::Human)
|
||||
.filter(|company| {
|
||||
company.active
|
||||
&& company.controller_kind == RuntimeCompanyControllerKind::Human
|
||||
})
|
||||
.map(|company| company.company_id)
|
||||
.collect())
|
||||
}
|
||||
|
|
@ -476,14 +515,27 @@ fn resolve_company_target_ids(
|
|||
Ok(state
|
||||
.companies
|
||||
.iter()
|
||||
.filter(|company| company.controller_kind == RuntimeCompanyControllerKind::Ai)
|
||||
.filter(|company| {
|
||||
company.active && company.controller_kind == RuntimeCompanyControllerKind::Ai
|
||||
})
|
||||
.map(|company| company.company_id)
|
||||
.collect())
|
||||
}
|
||||
RuntimeCompanyTarget::SelectedCompany => state
|
||||
.selected_company_id
|
||||
.map(|company_id| vec![company_id])
|
||||
.ok_or_else(|| "target requires selected_company_id context".to_string()),
|
||||
RuntimeCompanyTarget::SelectedCompany => {
|
||||
let selected_company_id = state
|
||||
.selected_company_id
|
||||
.ok_or_else(|| "target requires selected_company_id context".to_string())?;
|
||||
if state
|
||||
.companies
|
||||
.iter()
|
||||
.any(|company| company.company_id == selected_company_id && company.active)
|
||||
{
|
||||
Ok(vec![selected_company_id])
|
||||
} else {
|
||||
Err("target requires selected_company_id to reference an active company"
|
||||
.to_string())
|
||||
}
|
||||
}
|
||||
RuntimeCompanyTarget::ConditionTrueCompany => {
|
||||
Err("target requires condition-evaluation context".to_string())
|
||||
}
|
||||
|
|
@ -530,6 +582,8 @@ mod tests {
|
|||
controller_kind: RuntimeCompanyControllerKind::Unknown,
|
||||
current_cash: 10,
|
||||
debt: 0,
|
||||
active: true,
|
||||
available_track_laying_capacity: None,
|
||||
}],
|
||||
selected_company_id: None,
|
||||
packed_event_collection: None,
|
||||
|
|
@ -692,12 +746,16 @@ mod tests {
|
|||
controller_kind: RuntimeCompanyControllerKind::Unknown,
|
||||
current_cash: 10,
|
||||
debt: 5,
|
||||
active: true,
|
||||
available_track_laying_capacity: None,
|
||||
},
|
||||
RuntimeCompany {
|
||||
company_id: 2,
|
||||
controller_kind: RuntimeCompanyControllerKind::Unknown,
|
||||
current_cash: 20,
|
||||
debt: 8,
|
||||
active: true,
|
||||
available_track_laying_capacity: None,
|
||||
},
|
||||
],
|
||||
event_runtime_records: vec![RuntimeEventRecord {
|
||||
|
|
@ -744,12 +802,16 @@ mod tests {
|
|||
controller_kind: RuntimeCompanyControllerKind::Human,
|
||||
current_cash: 10,
|
||||
debt: 0,
|
||||
active: true,
|
||||
available_track_laying_capacity: None,
|
||||
},
|
||||
RuntimeCompany {
|
||||
company_id: 2,
|
||||
controller_kind: RuntimeCompanyControllerKind::Ai,
|
||||
current_cash: 20,
|
||||
debt: 2,
|
||||
active: true,
|
||||
available_track_laying_capacity: None,
|
||||
},
|
||||
],
|
||||
selected_company_id: Some(1),
|
||||
|
|
@ -866,6 +928,179 @@ mod tests {
|
|||
assert!(error.contains("controller_kind"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn all_active_and_role_targets_exclude_inactive_companies() {
|
||||
let mut state = RuntimeState {
|
||||
companies: vec![
|
||||
RuntimeCompany {
|
||||
company_id: 1,
|
||||
controller_kind: RuntimeCompanyControllerKind::Human,
|
||||
current_cash: 10,
|
||||
debt: 1,
|
||||
active: true,
|
||||
available_track_laying_capacity: None,
|
||||
},
|
||||
RuntimeCompany {
|
||||
company_id: 2,
|
||||
controller_kind: RuntimeCompanyControllerKind::Human,
|
||||
current_cash: 20,
|
||||
debt: 2,
|
||||
active: false,
|
||||
available_track_laying_capacity: None,
|
||||
},
|
||||
RuntimeCompany {
|
||||
company_id: 3,
|
||||
controller_kind: RuntimeCompanyControllerKind::Ai,
|
||||
current_cash: 30,
|
||||
debt: 3,
|
||||
active: true,
|
||||
available_track_laying_capacity: None,
|
||||
},
|
||||
],
|
||||
event_runtime_records: vec![
|
||||
RuntimeEventRecord {
|
||||
record_id: 16,
|
||||
trigger_kind: 7,
|
||||
active: true,
|
||||
service_count: 0,
|
||||
marks_collection_dirty: false,
|
||||
one_shot: false,
|
||||
has_fired: false,
|
||||
effects: vec![RuntimeEffect::AdjustCompanyCash {
|
||||
target: RuntimeCompanyTarget::AllActive,
|
||||
delta: 5,
|
||||
}],
|
||||
},
|
||||
RuntimeEventRecord {
|
||||
record_id: 17,
|
||||
trigger_kind: 7,
|
||||
active: true,
|
||||
service_count: 0,
|
||||
marks_collection_dirty: false,
|
||||
one_shot: false,
|
||||
has_fired: false,
|
||||
effects: vec![RuntimeEffect::AdjustCompanyDebt {
|
||||
target: RuntimeCompanyTarget::HumanCompanies,
|
||||
delta: 4,
|
||||
}],
|
||||
},
|
||||
RuntimeEventRecord {
|
||||
record_id: 18,
|
||||
trigger_kind: 7,
|
||||
active: true,
|
||||
service_count: 0,
|
||||
marks_collection_dirty: false,
|
||||
one_shot: false,
|
||||
has_fired: false,
|
||||
effects: vec![RuntimeEffect::AdjustCompanyDebt {
|
||||
target: RuntimeCompanyTarget::AiCompanies,
|
||||
delta: 6,
|
||||
}],
|
||||
},
|
||||
],
|
||||
..state()
|
||||
};
|
||||
|
||||
execute_step_command(
|
||||
&mut state,
|
||||
&StepCommand::ServiceTriggerKind { trigger_kind: 7 },
|
||||
)
|
||||
.expect("active-company filtering should succeed");
|
||||
|
||||
assert_eq!(state.companies[0].current_cash, 15);
|
||||
assert_eq!(state.companies[1].current_cash, 20);
|
||||
assert_eq!(state.companies[2].current_cash, 35);
|
||||
assert_eq!(state.companies[0].debt, 5);
|
||||
assert_eq!(state.companies[1].debt, 2);
|
||||
assert_eq!(state.companies[2].debt, 9);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deactivating_selected_company_clears_selection() {
|
||||
let mut state = RuntimeState {
|
||||
companies: vec![RuntimeCompany {
|
||||
company_id: 1,
|
||||
controller_kind: RuntimeCompanyControllerKind::Human,
|
||||
current_cash: 10,
|
||||
debt: 0,
|
||||
active: true,
|
||||
available_track_laying_capacity: Some(8),
|
||||
}],
|
||||
selected_company_id: Some(1),
|
||||
event_runtime_records: vec![RuntimeEventRecord {
|
||||
record_id: 19,
|
||||
trigger_kind: 7,
|
||||
active: true,
|
||||
service_count: 0,
|
||||
marks_collection_dirty: false,
|
||||
one_shot: false,
|
||||
has_fired: false,
|
||||
effects: vec![RuntimeEffect::DeactivateCompany {
|
||||
target: RuntimeCompanyTarget::SelectedCompany,
|
||||
}],
|
||||
}],
|
||||
..state()
|
||||
};
|
||||
|
||||
let result = execute_step_command(
|
||||
&mut state,
|
||||
&StepCommand::ServiceTriggerKind { trigger_kind: 7 },
|
||||
)
|
||||
.expect("deactivate company effect should succeed");
|
||||
|
||||
assert!(!state.companies[0].active);
|
||||
assert_eq!(state.selected_company_id, None);
|
||||
assert_eq!(result.service_events[0].mutated_company_ids, vec![1]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sets_track_laying_capacity_for_resolved_targets() {
|
||||
let mut state = RuntimeState {
|
||||
companies: vec![
|
||||
RuntimeCompany {
|
||||
company_id: 1,
|
||||
controller_kind: RuntimeCompanyControllerKind::Human,
|
||||
current_cash: 10,
|
||||
debt: 0,
|
||||
active: true,
|
||||
available_track_laying_capacity: None,
|
||||
},
|
||||
RuntimeCompany {
|
||||
company_id: 2,
|
||||
controller_kind: RuntimeCompanyControllerKind::Ai,
|
||||
current_cash: 20,
|
||||
debt: 0,
|
||||
active: true,
|
||||
available_track_laying_capacity: None,
|
||||
},
|
||||
],
|
||||
event_runtime_records: vec![RuntimeEventRecord {
|
||||
record_id: 20,
|
||||
trigger_kind: 7,
|
||||
active: true,
|
||||
service_count: 0,
|
||||
marks_collection_dirty: false,
|
||||
one_shot: false,
|
||||
has_fired: false,
|
||||
effects: vec![RuntimeEffect::SetCompanyTrackLayingCapacity {
|
||||
target: RuntimeCompanyTarget::Ids { ids: vec![2] },
|
||||
value: Some(14),
|
||||
}],
|
||||
}],
|
||||
..state()
|
||||
};
|
||||
|
||||
let result = execute_step_command(
|
||||
&mut state,
|
||||
&StepCommand::ServiceTriggerKind { trigger_kind: 7 },
|
||||
)
|
||||
.expect("track capacity effect should succeed");
|
||||
|
||||
assert_eq!(state.companies[0].available_track_laying_capacity, None);
|
||||
assert_eq!(state.companies[1].available_track_laying_capacity, Some(14));
|
||||
assert_eq!(result.service_events[0].mutated_company_ids, vec![2]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rejects_condition_true_company_target_without_condition_context() {
|
||||
let mut state = RuntimeState {
|
||||
|
|
@ -941,6 +1176,8 @@ mod tests {
|
|||
controller_kind: RuntimeCompanyControllerKind::Unknown,
|
||||
current_cash: 10,
|
||||
debt: 2,
|
||||
active: true,
|
||||
available_track_laying_capacity: None,
|
||||
}],
|
||||
event_runtime_records: vec![RuntimeEventRecord {
|
||||
record_id: 30,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue