feat(fifa17): apply the rare all-six training card

Passes a null attribute slot for the rare card -- Core reads absence as
"every slot", so sending 0 would silently train pace alone -- and declares
the per-family ceiling rather than a single constant.

Tests pin the null-slot serialisation, both ceilings, and that all 36
single-attribute plus all 6 rare cards resolve.
This commit is contained in:
funman300
2026-08-22 23:33:43 +00:00
parent 3bb6b4fc9d
commit 3a038fe406
2 changed files with 48 additions and 7 deletions
+37 -4
View File
@@ -2653,7 +2653,7 @@ fn the_training_effect_matches_cores_closed_vocabulary() {
use openfut_utas_host::ApplyEffect;
let json = ApplyEffect::ApplyTraining {
attribute_index: 4,
attribute_index: Some(4),
amount: 10,
max_amount: 15,
}
@@ -2668,6 +2668,24 @@ fn the_training_effect_matches_cores_closed_vocabulary() {
})
);
// The rare all-six card MUST serialise a null slot. Sending 0 would train
// pace alone, and omitting the key would leave Core guessing.
let all_six = ApplyEffect::ApplyTraining {
attribute_index: None,
amount: 10,
max_amount: 10,
}
.to_json();
assert_eq!(
all_six,
serde_json::json!({
"kind": "apply_training",
"attribute_index": null,
"amount": 10,
"max_amount": 10,
})
);
// The contract arm must keep its own shape while sharing the enum.
let contract = ApplyEffect::AddContractMatches {
amount: 3,
@@ -2691,18 +2709,33 @@ fn the_training_effect_matches_cores_closed_vocabulary() {
/// refuses a legitimate card — a silent, family-wide outage.
#[test]
fn no_shipped_training_card_exceeds_the_declared_ceiling() {
use openfut_adapter_fifa17::fut::training_cards::{training_effect, TRAINING_MAX_AMOUNT};
use openfut_adapter_fifa17::fut::training_cards::{
ceiling_for, training_effect, TRAINING_ALL_MAX_AMOUNT, TRAINING_MAX_AMOUNT,
};
let mut resolved = 0;
for subtype in [51, 52, 53, 54, 55, 56, 61, 62, 63, 64, 65, 66] {
for amount in [5, 10, 15] {
let e = training_effect(subtype, Some(amount)).expect("shipped card resolves");
assert!(
e.amount <= TRAINING_MAX_AMOUNT,
e.amount <= ceiling_for(&e),
"subtype {subtype} amount {amount} exceeds the ceiling sent to Core"
);
assert_eq!(ceiling_for(&e), TRAINING_MAX_AMOUNT);
resolved += 1;
}
}
assert_eq!(resolved, 36, "all 36 attribute training cards must resolve");
assert_eq!(resolved, 36, "all 36 single-attribute cards must resolve");
// The six rare all-six cards carry their own, lower ceiling.
let mut rare = 0;
for subtype in [57, 67] {
for amount in [3, 6, 10] {
let e = training_effect(subtype, Some(amount)).expect("rare card resolves");
assert_eq!(e.attribute_index, None);
assert_eq!(ceiling_for(&e), TRAINING_ALL_MAX_AMOUNT);
rare += 1;
}
}
assert_eq!(rare, 6, "all 6 rare all-six cards must resolve");
}