fifa17 store: real 6-pack economy + full-DB pool; drop extPrice
- store_catalog: replace the invented catalogue with the real always-available FUT17 regular packs (Bronze/Prem Bronze/Silver/Prem Silver/Gold/Prem Gold) at real prices + tier composition; PackDef now carries per-tier quantities. - pack_body: drop extPrice (its mtx side-effect switched on the broken "or %1s" FIFA-Points tile line; plan-2026-08-05-store-subsystem.md section 3.4). - pack_content: tier-aware generator draws each pack bronze/silver/gold composition with special_chance bias + empty-tier fallback. - host: CoreAccess::all_definitions (GET /cards); build_content_pool draws the FULL card universe via non-minting catalog lookup, owned-inventory fallback. - economy_differential: store ops reclassified DIFFERENT-BY-DESIGN (Rust is the authoritative store; Python oracle stays the untouched rollback baseline). - fixtures/tests updated to the real catalogue. Odds are DESIGNED placeholders (FUT17 pack probabilities were never published); club items remain excluded (cardtype-9 mapping unknown). Full regression green; real prices + tier-correct draws verified server-side on staging.
This commit is contained in:
@@ -244,7 +244,11 @@ fn pack_open_body(pid: u64, pack: &PackDef) -> WireResponse {
|
||||
"firstPartyStoreId": 0,
|
||||
"groupName": "fifa17",
|
||||
"productId": pid.to_string(),
|
||||
"purchasePackType": if pack.gold { "GOLD" } else { "BRONZE" },
|
||||
"purchasePackType": match pack.category {
|
||||
"gold" => "GOLD",
|
||||
"silver" => "SILVER",
|
||||
_ => "BRONZE",
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -695,7 +699,7 @@ mod tests {
|
||||
// ── Store BUY ──────────────────────────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
fn buy_pack1_debits_mints_and_reveals_five_cards() {
|
||||
fn buy_pack1_debits_mints_and_reveals_twelve_cards() {
|
||||
let econ = RecEcon::new(10_000);
|
||||
let pool = pool();
|
||||
let assets = FakeAssets::for_pool(&pool);
|
||||
@@ -705,23 +709,23 @@ mod tests {
|
||||
assert_eq!(resp.status, 200);
|
||||
let b: Value = serde_json::from_slice(&resp.body).unwrap();
|
||||
let cpr = &b["createPackResponse"];
|
||||
assert_eq!(cpr["numberItems"], 5); // pack 1 count
|
||||
assert_eq!(cpr["itemList"].as_array().unwrap().len(), 5);
|
||||
assert_eq!(cpr["numberItems"], 12); // pack 1 count (10 bronze + 2 silver)
|
||||
assert_eq!(cpr["itemList"].as_array().unwrap().len(), 12);
|
||||
assert_eq!(cpr["purchasedPackId"], 1);
|
||||
assert_eq!(cpr["duplicateItemIdList"], json!([]));
|
||||
// Exactly one atomic debit of the pack price (400) minting 5 items.
|
||||
// Exactly one atomic debit of the pack price (400) minting 12 items.
|
||||
assert_eq!(econ.coins(), 10_000 - 400);
|
||||
let purchased = econ.purchased.lock();
|
||||
assert_eq!(purchased.len(), 1);
|
||||
assert_eq!(purchased[0].0, 400);
|
||||
assert_eq!(purchased[0].1.len(), 5);
|
||||
assert_eq!(purchased[0].1.len(), 12);
|
||||
for g in &purchased[0].1 {
|
||||
assert!(pool.iter().any(|c| c.card_id == g.card_id));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buy_pack5_debits_gold_price_and_mints_seven() {
|
||||
fn buy_pack5_debits_gold_price_and_mints_twelve() {
|
||||
let econ = RecEcon::new(10_000);
|
||||
let pool = pool();
|
||||
let assets = FakeAssets::for_pool(&pool);
|
||||
@@ -729,7 +733,7 @@ mod tests {
|
||||
let deps = store_deps(&econ, &assets, &ent, &pool);
|
||||
let resp = handle_store_buy(&body(json!({ "packId": 5 })), &deps, &mut rng(2));
|
||||
let b: Value = serde_json::from_slice(&resp.body).unwrap();
|
||||
assert_eq!(b["createPackResponse"]["numberItems"], 7); // pack 5 count
|
||||
assert_eq!(b["createPackResponse"]["numberItems"], 12); // pack 5 count (10 gold + 2 silver)
|
||||
assert_eq!(econ.coins(), 10_000 - 5000);
|
||||
}
|
||||
|
||||
@@ -860,7 +864,7 @@ mod tests {
|
||||
assert_eq!(b["firstPartyStoreId"], 0);
|
||||
assert_eq!(b["purchasePackType"], "GOLD"); // pack 5 is gold
|
||||
assert_eq!(econ.coins(), 10_000 - 5000);
|
||||
assert_eq!(econ.purchased.lock()[0].1.len(), 7);
|
||||
assert_eq!(econ.purchased.lock()[0].1.len(), 12);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user