Recover whole-game packed event conditions

This commit is contained in:
Jan Petykiewicz 2026-04-15 22:38:13 -07:00
commit 5d779263d2
7 changed files with 414 additions and 117 deletions

View file

@ -214,127 +214,192 @@ enum RealOrdinaryConditionMetric {
CompanyTerritory(RuntimeTrackMetric),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum RealWorldConditionKind {
SpecialCondition { label: &'static str },
CandidateAvailability,
EconomicStatus,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum RealOrdinaryConditionKind {
Numeric(RealOrdinaryConditionMetric),
WorldState(RealWorldConditionKind),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct RealOrdinaryConditionMetadata {
raw_condition_id: i32,
label: &'static str,
metric: RealOrdinaryConditionMetric,
kind: RealOrdinaryConditionKind,
}
const REAL_ORDINARY_CONDITION_METADATA: [RealOrdinaryConditionMetadata; 22] = [
const REAL_CANDIDATE_AVAILABILITY_CONDITION_TEMPLATE_ID: i32 = 435;
const REAL_ORDINARY_CONDITION_METADATA: [RealOrdinaryConditionMetadata; 24] = [
RealOrdinaryConditionMetadata {
raw_condition_id: 1802,
label: "Current Cash",
metric: RealOrdinaryConditionMetric::Company(RuntimeCompanyMetric::CurrentCash),
kind: RealOrdinaryConditionKind::Numeric(RealOrdinaryConditionMetric::Company(
RuntimeCompanyMetric::CurrentCash,
)),
},
RealOrdinaryConditionMetadata {
raw_condition_id: 951,
label: "Total Debt",
metric: RealOrdinaryConditionMetric::Company(RuntimeCompanyMetric::TotalDebt),
kind: RealOrdinaryConditionKind::Numeric(RealOrdinaryConditionMetric::Company(
RuntimeCompanyMetric::TotalDebt,
)),
},
RealOrdinaryConditionMetadata {
raw_condition_id: 2366,
label: "Credit Rating",
metric: RealOrdinaryConditionMetric::Company(RuntimeCompanyMetric::CreditRating),
kind: RealOrdinaryConditionKind::Numeric(RealOrdinaryConditionMetric::Company(
RuntimeCompanyMetric::CreditRating,
)),
},
RealOrdinaryConditionMetadata {
raw_condition_id: 2368,
label: "Prime Rate",
metric: RealOrdinaryConditionMetric::Company(RuntimeCompanyMetric::PrimeRate),
kind: RealOrdinaryConditionKind::Numeric(RealOrdinaryConditionMetric::Company(
RuntimeCompanyMetric::PrimeRate,
)),
},
RealOrdinaryConditionMetadata {
raw_condition_id: 2293,
label: "Company Track Pieces",
metric: RealOrdinaryConditionMetric::Company(RuntimeCompanyMetric::TrackPiecesTotal),
kind: RealOrdinaryConditionKind::Numeric(RealOrdinaryConditionMetric::Company(
RuntimeCompanyMetric::TrackPiecesTotal,
)),
},
RealOrdinaryConditionMetadata {
raw_condition_id: 2294,
label: "Company Single Track Pieces",
metric: RealOrdinaryConditionMetric::Company(RuntimeCompanyMetric::TrackPiecesSingle),
kind: RealOrdinaryConditionKind::Numeric(RealOrdinaryConditionMetric::Company(
RuntimeCompanyMetric::TrackPiecesSingle,
)),
},
RealOrdinaryConditionMetadata {
raw_condition_id: 2295,
label: "Company Double Track Pieces",
metric: RealOrdinaryConditionMetric::Company(RuntimeCompanyMetric::TrackPiecesDouble),
kind: RealOrdinaryConditionKind::Numeric(RealOrdinaryConditionMetric::Company(
RuntimeCompanyMetric::TrackPiecesDouble,
)),
},
RealOrdinaryConditionMetadata {
raw_condition_id: 2296,
label: "Company Transition Track Pieces",
metric: RealOrdinaryConditionMetric::Company(RuntimeCompanyMetric::TrackPiecesTransition),
kind: RealOrdinaryConditionKind::Numeric(RealOrdinaryConditionMetric::Company(
RuntimeCompanyMetric::TrackPiecesTransition,
)),
},
RealOrdinaryConditionMetadata {
raw_condition_id: 2297,
label: "Company Electric Track Pieces",
metric: RealOrdinaryConditionMetric::Company(RuntimeCompanyMetric::TrackPiecesElectric),
kind: RealOrdinaryConditionKind::Numeric(RealOrdinaryConditionMetric::Company(
RuntimeCompanyMetric::TrackPiecesElectric,
)),
},
RealOrdinaryConditionMetadata {
raw_condition_id: 2298,
label: "Company Non-Electric Track Pieces",
metric: RealOrdinaryConditionMetric::Company(RuntimeCompanyMetric::TrackPiecesNonElectric),
kind: RealOrdinaryConditionKind::Numeric(RealOrdinaryConditionMetric::Company(
RuntimeCompanyMetric::TrackPiecesNonElectric,
)),
},
RealOrdinaryConditionMetadata {
raw_condition_id: 2313,
label: "Territory Track Pieces",
metric: RealOrdinaryConditionMetric::Territory(RuntimeTerritoryMetric::TrackPiecesTotal),
kind: RealOrdinaryConditionKind::Numeric(RealOrdinaryConditionMetric::Territory(
RuntimeTerritoryMetric::TrackPiecesTotal,
)),
},
RealOrdinaryConditionMetadata {
raw_condition_id: 2314,
label: "Territory Single Track Pieces",
metric: RealOrdinaryConditionMetric::Territory(RuntimeTerritoryMetric::TrackPiecesSingle),
kind: RealOrdinaryConditionKind::Numeric(RealOrdinaryConditionMetric::Territory(
RuntimeTerritoryMetric::TrackPiecesSingle,
)),
},
RealOrdinaryConditionMetadata {
raw_condition_id: 2315,
label: "Territory Double Track Pieces",
metric: RealOrdinaryConditionMetric::Territory(RuntimeTerritoryMetric::TrackPiecesDouble),
kind: RealOrdinaryConditionKind::Numeric(RealOrdinaryConditionMetric::Territory(
RuntimeTerritoryMetric::TrackPiecesDouble,
)),
},
RealOrdinaryConditionMetadata {
raw_condition_id: 2316,
label: "Territory Transition Track Pieces",
metric: RealOrdinaryConditionMetric::Territory(
kind: RealOrdinaryConditionKind::Numeric(RealOrdinaryConditionMetric::Territory(
RuntimeTerritoryMetric::TrackPiecesTransition,
),
)),
},
RealOrdinaryConditionMetadata {
raw_condition_id: 2317,
label: "Territory Electric Track Pieces",
metric: RealOrdinaryConditionMetric::Territory(RuntimeTerritoryMetric::TrackPiecesElectric),
kind: RealOrdinaryConditionKind::Numeric(RealOrdinaryConditionMetric::Territory(
RuntimeTerritoryMetric::TrackPiecesElectric,
)),
},
RealOrdinaryConditionMetadata {
raw_condition_id: 2318,
label: "Territory Non-Electric Track Pieces",
metric: RealOrdinaryConditionMetric::Territory(
kind: RealOrdinaryConditionKind::Numeric(RealOrdinaryConditionMetric::Territory(
RuntimeTerritoryMetric::TrackPiecesNonElectric,
),
)),
},
RealOrdinaryConditionMetadata {
raw_condition_id: 2323,
label: "Company-Territory Track Pieces",
metric: RealOrdinaryConditionMetric::CompanyTerritory(RuntimeTrackMetric::Total),
kind: RealOrdinaryConditionKind::Numeric(RealOrdinaryConditionMetric::CompanyTerritory(
RuntimeTrackMetric::Total,
)),
},
RealOrdinaryConditionMetadata {
raw_condition_id: 2324,
label: "Company-Territory Single Track Pieces",
metric: RealOrdinaryConditionMetric::CompanyTerritory(RuntimeTrackMetric::Single),
kind: RealOrdinaryConditionKind::Numeric(RealOrdinaryConditionMetric::CompanyTerritory(
RuntimeTrackMetric::Single,
)),
},
RealOrdinaryConditionMetadata {
raw_condition_id: 2325,
label: "Company-Territory Double Track Pieces",
metric: RealOrdinaryConditionMetric::CompanyTerritory(RuntimeTrackMetric::Double),
kind: RealOrdinaryConditionKind::Numeric(RealOrdinaryConditionMetric::CompanyTerritory(
RuntimeTrackMetric::Double,
)),
},
RealOrdinaryConditionMetadata {
raw_condition_id: 2326,
label: "Company-Territory Transition Track Pieces",
metric: RealOrdinaryConditionMetric::CompanyTerritory(RuntimeTrackMetric::Transition),
kind: RealOrdinaryConditionKind::Numeric(RealOrdinaryConditionMetric::CompanyTerritory(
RuntimeTrackMetric::Transition,
)),
},
RealOrdinaryConditionMetadata {
raw_condition_id: 2327,
label: "Company-Territory Electric Track Pieces",
metric: RealOrdinaryConditionMetric::CompanyTerritory(RuntimeTrackMetric::Electric),
kind: RealOrdinaryConditionKind::Numeric(RealOrdinaryConditionMetric::CompanyTerritory(
RuntimeTrackMetric::Electric,
)),
},
RealOrdinaryConditionMetadata {
raw_condition_id: 2328,
label: "Company-Territory Non-Electric Track Pieces",
metric: RealOrdinaryConditionMetric::CompanyTerritory(RuntimeTrackMetric::NonElectric),
kind: RealOrdinaryConditionKind::Numeric(RealOrdinaryConditionMetric::CompanyTerritory(
RuntimeTrackMetric::NonElectric,
)),
},
RealOrdinaryConditionMetadata {
raw_condition_id: REAL_CANDIDATE_AVAILABILITY_CONDITION_TEMPLATE_ID,
label: "%1 Avail.",
kind: RealOrdinaryConditionKind::WorldState(RealWorldConditionKind::CandidateAvailability),
},
RealOrdinaryConditionMetadata {
raw_condition_id: 2350,
label: "Economic Status",
kind: RealOrdinaryConditionKind::WorldState(RealWorldConditionKind::EconomicStatus),
},
];
@ -633,6 +698,15 @@ const KNOWN_TAG_DEFINITIONS: [KnownTagDefinition; 4] = [
},
];
fn known_special_condition_definition_for_label_id(
label_id: u32,
) -> Option<KnownSpecialConditionDefinition> {
KNOWN_SPECIAL_CONDITION_DEFINITIONS
.iter()
.copied()
.find(|definition| !definition.hidden && definition.label_id == label_id)
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SmpKnownTagHit {
pub tag_id: u16,
@ -2286,17 +2360,22 @@ fn parse_real_condition_row_summary(
let flag_bytes = row_bytes
.get(5..PACKED_EVENT_REAL_CONDITION_ROW_LEN)?
.to_vec();
let candidate_name_display = candidate_name.clone();
let candidate_name_ref = candidate_name_display.as_deref();
let ordinary_metadata = real_ordinary_condition_metadata(raw_condition_id);
let comparator = ordinary_metadata
.and_then(|_| decode_real_condition_comparator(subtype))
.map(condition_comparator_label);
let metric = ordinary_metadata.map(|metadata| metadata.label.to_string());
let metric =
ordinary_metadata.map(|metadata| real_ordinary_condition_metric_label(metadata, candidate_name_ref));
let threshold = ordinary_metadata.and_then(|_| decode_real_condition_threshold(&flag_bytes));
let requires_candidate_name_binding = ordinary_metadata.is_some_and(|metadata| {
matches!(
metadata.metric,
RealOrdinaryConditionMetric::Territory(_)
| RealOrdinaryConditionMetric::CompanyTerritory(_)
metadata.kind,
RealOrdinaryConditionKind::Numeric(
RealOrdinaryConditionMetric::Territory(_)
| RealOrdinaryConditionMetric::CompanyTerritory(_)
)
) && candidate_name.is_some()
});
let mut notes = Vec::new();
@ -2312,6 +2391,14 @@ fn parse_real_condition_row_summary(
.to_string(),
);
}
if ordinary_metadata.is_some_and(|metadata| {
matches!(
metadata.kind,
RealOrdinaryConditionKind::WorldState(RealWorldConditionKind::CandidateAvailability)
) && candidate_name.is_none()
}) {
notes.push("candidate-availability condition row is missing its candidate-name side string".to_string());
}
Some(SmpLoadedPackedEventConditionRowSummary {
row_index,
raw_condition_id,
@ -2320,13 +2407,16 @@ fn parse_real_condition_row_summary(
candidate_name,
comparator,
metric,
semantic_family: ordinary_metadata.map(|_| "numeric_threshold".to_string()),
semantic_family: ordinary_metadata
.map(|metadata| real_ordinary_condition_semantic_family(metadata).to_string()),
semantic_preview: ordinary_metadata.and_then(|metadata| {
threshold.map(|value| {
let comparator_text = decode_real_condition_comparator(subtype)
.map(condition_comparator_symbol)
.unwrap_or("?");
format!("Test {} {} {}", metadata.label, comparator_text, value)
let metric_label =
real_ordinary_condition_metric_label(metadata, candidate_name_ref);
format!("Test {} {} {}", metric_label, comparator_text, value)
})
}),
requires_candidate_name_binding,
@ -2384,6 +2474,47 @@ fn real_ordinary_condition_metadata(
.iter()
.copied()
.find(|metadata| metadata.raw_condition_id == raw_condition_id)
.or_else(|| {
known_special_condition_definition_for_label_id(raw_condition_id as u32).map(
|definition| RealOrdinaryConditionMetadata {
raw_condition_id,
label: definition.label,
kind: RealOrdinaryConditionKind::WorldState(
RealWorldConditionKind::SpecialCondition {
label: definition.label,
},
),
},
)
})
}
fn real_ordinary_condition_metric_label(
metadata: RealOrdinaryConditionMetadata,
candidate_name: Option<&str>,
) -> String {
match metadata.kind {
RealOrdinaryConditionKind::Numeric(_) => metadata.label.to_string(),
RealOrdinaryConditionKind::WorldState(RealWorldConditionKind::SpecialCondition { label }) => {
format!("Special Condition: {label}")
}
RealOrdinaryConditionKind::WorldState(RealWorldConditionKind::CandidateAvailability) => {
match candidate_name {
Some(name) => format!("Candidate Availability: {name}"),
None => "Candidate Availability".to_string(),
}
}
RealOrdinaryConditionKind::WorldState(RealWorldConditionKind::EconomicStatus) => {
"Economic Status".to_string()
}
}
}
fn real_ordinary_condition_semantic_family(metadata: RealOrdinaryConditionMetadata) -> &'static str {
match metadata.kind {
RealOrdinaryConditionKind::Numeric(_) => "numeric_threshold",
RealOrdinaryConditionKind::WorldState(_) => "world_state_threshold",
}
}
fn decode_real_condition_comparator(subtype: u8) -> Option<RuntimeConditionComparator> {
@ -2531,8 +2662,8 @@ fn decode_real_condition_row(
let metadata = real_ordinary_condition_metadata(row.raw_condition_id)?;
let comparator = decode_real_condition_comparator(row.subtype)?;
let value = decode_real_condition_threshold(&row.flag_bytes)?;
match metadata.metric {
RealOrdinaryConditionMetric::Company(metric) => {
match metadata.kind {
RealOrdinaryConditionKind::Numeric(RealOrdinaryConditionMetric::Company(metric)) => {
Some(RuntimeCondition::CompanyNumericThreshold {
target: RuntimeCompanyTarget::ConditionTrueCompany,
metric,
@ -2540,15 +2671,18 @@ fn decode_real_condition_row(
value,
})
}
RealOrdinaryConditionMetric::Territory(metric) => negative_sentinel_scope
RealOrdinaryConditionKind::Numeric(RealOrdinaryConditionMetric::Territory(metric)) => {
negative_sentinel_scope
.filter(|scope| scope.territory_scope_selector_is_0x63)
.map(|_| RuntimeCondition::TerritoryNumericThreshold {
target: RuntimeTerritoryTarget::AllTerritories,
metric,
comparator,
value,
}),
RealOrdinaryConditionMetric::CompanyTerritory(metric) => negative_sentinel_scope
})
}
RealOrdinaryConditionKind::Numeric(RealOrdinaryConditionMetric::CompanyTerritory(metric)) => {
negative_sentinel_scope
.filter(|scope| scope.territory_scope_selector_is_0x63)
.map(|_| RuntimeCondition::CompanyTerritoryNumericThreshold {
target: RuntimeCompanyTarget::ConditionTrueCompany,
@ -2556,7 +2690,27 @@ fn decode_real_condition_row(
metric,
comparator,
value,
}),
})
}
RealOrdinaryConditionKind::WorldState(RealWorldConditionKind::SpecialCondition {
label,
}) => Some(RuntimeCondition::SpecialConditionThreshold {
label: label.to_string(),
comparator,
value,
}),
RealOrdinaryConditionKind::WorldState(
RealWorldConditionKind::CandidateAvailability,
) => row.candidate_name.as_ref().map(|name| {
RuntimeCondition::CandidateAvailabilityThreshold {
name: name.clone(),
comparator,
value,
}
}),
RealOrdinaryConditionKind::WorldState(RealWorldConditionKind::EconomicStatus) => {
Some(RuntimeCondition::EconomicStatusCodeThreshold { comparator, value })
}
}
}
@ -7925,6 +8079,17 @@ mod tests {
bytes
}
fn build_real_condition_row_with_threshold(
raw_condition_id: i32,
subtype: u8,
threshold: i32,
candidate_name: Option<&str>,
) -> Vec<u8> {
let mut bytes = build_real_condition_row(raw_condition_id, subtype, 0, candidate_name);
bytes[5..9].copy_from_slice(&threshold.to_le_bytes());
bytes
}
struct RealGroupedEffectRowSpec<'a> {
descriptor_id: u32,
opcode: u8,
@ -8460,6 +8625,180 @@ mod tests {
assert!(summary.records[0].executable_import_ready);
}
#[test]
fn decodes_real_special_condition_threshold_from_checked_in_world_condition_metadata() {
let condition_row = build_real_condition_row_with_threshold(3835, 0, 1, None);
let record_body = build_real_event_record(
[b"World", b"", b"", b"", b"", b""],
Some(RealCompactControlSpec {
mode_byte_0x7ef: 7,
primary_selector_0x7f0: 0,
grouped_mode_0x7f4: 2,
one_shot_header_0x7f5: 0,
modifier_flag_0x7f9: 0,
modifier_flag_0x7fa: 0,
grouped_target_scope_ordinals_0x7fb: [0, 0, 0, 0],
grouped_scope_checkboxes_0x7ff: [0, 0, 0, 0],
summary_toggle_0x800: 1,
grouped_territory_selectors_0x80f: [-1, -1, -1, -1],
}),
&[condition_row],
[&[], &[], &[], &[]],
);
let mut bytes = Vec::new();
bytes.extend_from_slice(&EVENT_RUNTIME_COLLECTION_METADATA_TAG.to_le_bytes());
bytes.extend_from_slice(&EVENT_RUNTIME_COLLECTION_PACKED_STATE_VERSION.to_le_bytes());
let header_words = [1u32, 4, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
for word in header_words {
bytes.extend_from_slice(&word.to_le_bytes());
}
bytes.extend_from_slice(&[0x00, 0x00]);
bytes.extend_from_slice(&[0xaa, 0xbb, 0xcc, 0xdd]);
bytes.extend_from_slice(&EVENT_RUNTIME_COLLECTION_RECORDS_TAG.to_le_bytes());
bytes.extend_from_slice(&record_body);
bytes.extend_from_slice(&EVENT_RUNTIME_COLLECTION_CLOSE_TAG.to_le_bytes());
let report = inspect_smp_bytes(&bytes);
let summary = report
.event_runtime_collection_summary
.as_ref()
.expect("event runtime collection summary should parse");
assert_eq!(
summary.records[0].standalone_condition_rows[0]
.metric
.as_deref(),
Some("Special Condition: Use Wartime Cargos")
);
assert_eq!(
summary.records[0].standalone_condition_rows[0]
.semantic_family
.as_deref(),
Some("world_state_threshold")
);
assert_eq!(
summary.records[0].decoded_conditions,
vec![RuntimeCondition::SpecialConditionThreshold {
label: "Use Wartime Cargos".to_string(),
comparator: RuntimeConditionComparator::Ge,
value: 1,
}]
);
}
#[test]
fn decodes_real_candidate_availability_threshold_from_checked_in_world_condition_metadata() {
let condition_row =
build_real_condition_row_with_threshold(REAL_CANDIDATE_AVAILABILITY_CONDITION_TEMPLATE_ID, 0, 2, Some("Mogul"));
let record_body = build_real_event_record(
[b"World", b"", b"", b"", b"", b""],
Some(RealCompactControlSpec {
mode_byte_0x7ef: 7,
primary_selector_0x7f0: 0,
grouped_mode_0x7f4: 2,
one_shot_header_0x7f5: 0,
modifier_flag_0x7f9: 0,
modifier_flag_0x7fa: 0,
grouped_target_scope_ordinals_0x7fb: [0, 0, 0, 0],
grouped_scope_checkboxes_0x7ff: [0, 0, 0, 0],
summary_toggle_0x800: 1,
grouped_territory_selectors_0x80f: [-1, -1, -1, -1],
}),
&[condition_row],
[&[], &[], &[], &[]],
);
let mut bytes = Vec::new();
bytes.extend_from_slice(&EVENT_RUNTIME_COLLECTION_METADATA_TAG.to_le_bytes());
bytes.extend_from_slice(&EVENT_RUNTIME_COLLECTION_PACKED_STATE_VERSION.to_le_bytes());
let header_words = [1u32, 4, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
for word in header_words {
bytes.extend_from_slice(&word.to_le_bytes());
}
bytes.extend_from_slice(&[0x00, 0x00]);
bytes.extend_from_slice(&[0xaa, 0xbb, 0xcc, 0xdd]);
bytes.extend_from_slice(&EVENT_RUNTIME_COLLECTION_RECORDS_TAG.to_le_bytes());
bytes.extend_from_slice(&record_body);
bytes.extend_from_slice(&EVENT_RUNTIME_COLLECTION_CLOSE_TAG.to_le_bytes());
let report = inspect_smp_bytes(&bytes);
let summary = report
.event_runtime_collection_summary
.as_ref()
.expect("event runtime collection summary should parse");
assert_eq!(
summary.records[0].standalone_condition_rows[0]
.metric
.as_deref(),
Some("Candidate Availability: Mogul")
);
assert_eq!(
summary.records[0].decoded_conditions,
vec![RuntimeCondition::CandidateAvailabilityThreshold {
name: "Mogul".to_string(),
comparator: RuntimeConditionComparator::Ge,
value: 2,
}]
);
}
#[test]
fn decodes_real_economic_status_threshold_from_checked_in_world_condition_metadata() {
let condition_row = build_real_condition_row_with_threshold(2350, 0, 4, None);
let record_body = build_real_event_record(
[b"World", b"", b"", b"", b"", b""],
Some(RealCompactControlSpec {
mode_byte_0x7ef: 7,
primary_selector_0x7f0: 0,
grouped_mode_0x7f4: 2,
one_shot_header_0x7f5: 0,
modifier_flag_0x7f9: 0,
modifier_flag_0x7fa: 0,
grouped_target_scope_ordinals_0x7fb: [0, 0, 0, 0],
grouped_scope_checkboxes_0x7ff: [0, 0, 0, 0],
summary_toggle_0x800: 1,
grouped_territory_selectors_0x80f: [-1, -1, -1, -1],
}),
&[condition_row],
[&[], &[], &[], &[]],
);
let mut bytes = Vec::new();
bytes.extend_from_slice(&EVENT_RUNTIME_COLLECTION_METADATA_TAG.to_le_bytes());
bytes.extend_from_slice(&EVENT_RUNTIME_COLLECTION_PACKED_STATE_VERSION.to_le_bytes());
let header_words = [1u32, 4, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
for word in header_words {
bytes.extend_from_slice(&word.to_le_bytes());
}
bytes.extend_from_slice(&[0x00, 0x00]);
bytes.extend_from_slice(&[0xaa, 0xbb, 0xcc, 0xdd]);
bytes.extend_from_slice(&EVENT_RUNTIME_COLLECTION_RECORDS_TAG.to_le_bytes());
bytes.extend_from_slice(&record_body);
bytes.extend_from_slice(&EVENT_RUNTIME_COLLECTION_CLOSE_TAG.to_le_bytes());
let report = inspect_smp_bytes(&bytes);
let summary = report
.event_runtime_collection_summary
.as_ref()
.expect("event runtime collection summary should parse");
assert_eq!(
summary.records[0].standalone_condition_rows[0]
.metric
.as_deref(),
Some("Economic Status")
);
assert_eq!(
summary.records[0].decoded_conditions,
vec![RuntimeCondition::EconomicStatusCodeThreshold {
comparator: RuntimeConditionComparator::Ge,
value: 4,
}]
);
}
#[test]
fn keeps_real_world_flag_descriptor_parity_only_with_checked_in_metadata() {
let grouped_row = build_real_grouped_effect_row(RealGroupedEffectRowSpec {