feat(fifa17): project owned kits with active home/away designation
Closes the server side of the FUT kit selector. Ownership stays generic in
Core (submodule bump: club_kit_assignments + GET/PUT /club/kits); this
commit adds the FIFA17 representation, the host projection and importer
support.
adapter:
* ContentKind::Kit ("kit") so kits are classified alongside player/staff/
consumable instead of being mistaken for 0-rated players.
* Fifa17CardIdentity carries card_asset_id and team_id; RawCard keeps both
optional because the emitted catalog writes null for non-kit definitions.
* shape_kit_item emits only the fields the client's kit path reads
(id/resourceId/assetId/cardassetid/cardsubtypeid/itemState/owners/
untradeable/teamid) — no attributeList, no itemType.
* itemState on the wire is the STRING token activeHomeKit/activeAwayKit;
the 101/102 integers are the client's post-deserialisation runtime enum
(item+0x5c) and are never emitted.
* club_stats S_KITS (0x28) now counts owned kits instead of a hard zero.
host:
* CoreKitAssignments + CoreAccess::get_active_kits (GET /club/kits),
defaulting to no active kits so a Core without the endpoint degrades
instead of fabricating a designation.
* handle_club classifies type=player|kit, rejects any other type with an
empty page and outcome=unsupported_type, and now always fetches
unpaginated from Core: kind and transfer-pile membership are host-side
concepts Core cannot express, so filtering and pagination must both
happen after shaping or pages come back short.
importer:
* ItemClass::Kit (cardsubtypeid == 9 and resourceId in 6_300_000..=6_400_654),
kit counts/balances, and card_asset_id/team_id carried into the emitted
catalog and manifest.
* a kit group missing cardassetid == 35 or teamid is DEFERRED
(missing_kit_render_metadata) rather than defaulted; conflicting render
metadata across instances defers as render_metadata_conflict.
staging: sold-staging-up.py seeds two owned kits (6300006 home / 6400003
away, team 21) plus both active designations so the projection can be
verified over HTTP before involving the client.
This commit is contained in:
@@ -149,6 +149,14 @@ SELLER_SQUAD_CARDS = [
|
||||
DISPOSABLE_ITEM = "owned-a-disposable"
|
||||
DISPOSABLE_CARD = "fifa17_232273" # Nelson Atiagli LB 51, rareflag 1
|
||||
|
||||
# Two authoritative modern kit-card definitions for one real source team. These
|
||||
# are staging fixtures derived from fcc_kitcards, not synthetic FIFA identities.
|
||||
KIT_TEAM_ID = 21
|
||||
STAGING_KITS = [
|
||||
("home", "owned-a-kit-home", "fifa17_6300006", 6_300_006),
|
||||
("away", "owned-a-kit-away", "fifa17_6400003", 6_400_003),
|
||||
]
|
||||
|
||||
READY_TIMEOUT_S = 60.0
|
||||
|
||||
|
||||
@@ -439,6 +447,47 @@ def materialise(lay: Layout) -> None:
|
||||
shutil.copy2(safe_path(src), safe_path(dst))
|
||||
ok(f"FIFA17 content copied from {CONTENT_SRC} (outside production state)")
|
||||
|
||||
with open(safe_path(lay.cards)) as fh:
|
||||
definitions = json.load(fh)
|
||||
with open(safe_path(lay.catalog)) as fh:
|
||||
catalog = json.load(fh)
|
||||
existing = {definition["id"] for definition in definitions}
|
||||
for _slot, _owned_id, card_id, resource_id in STAGING_KITS:
|
||||
if card_id not in existing:
|
||||
definitions.append({
|
||||
"id": card_id,
|
||||
"name": "Kit",
|
||||
"overall": 0,
|
||||
"position": "",
|
||||
"nation": "",
|
||||
"league": "",
|
||||
"club": "",
|
||||
"pace": 0,
|
||||
"shooting": 0,
|
||||
"passing": 0,
|
||||
"dribbling": 0,
|
||||
"defending": 0,
|
||||
"physical": 0,
|
||||
"rarity": "bronze",
|
||||
"image_path": None,
|
||||
})
|
||||
catalog["cards"][card_id] = {
|
||||
"asset_id": resource_id,
|
||||
"version": 0,
|
||||
"rareflag": 0,
|
||||
"kind": "kit",
|
||||
"subtype": 9,
|
||||
"card_asset_id": 35,
|
||||
"team_id": KIT_TEAM_ID,
|
||||
}
|
||||
with open(safe_path(lay.cards), "w") as fh:
|
||||
json.dump(definitions, fh, indent=2)
|
||||
fh.write("\n")
|
||||
with open(safe_path(lay.catalog), "w") as fh:
|
||||
json.dump(catalog, fh, indent=2)
|
||||
fh.write("\n")
|
||||
ok("added ownership-backed home/away kit fixtures from fcc_kitcards")
|
||||
|
||||
|
||||
def assert_seed_cards_resolvable(lay: Layout) -> None:
|
||||
"""Core's content preflight rejects any owned card whose card_id is not a loaded
|
||||
@@ -448,7 +497,11 @@ def assert_seed_cards_resolvable(lay: Layout) -> None:
|
||||
pack_ids = {c["id"] for c in json.load(fh)}
|
||||
with open(safe_path(lay.catalog)) as fh:
|
||||
catalog_ids = set(json.load(fh)["cards"])
|
||||
wanted = [c for _, c in SELLER_SQUAD_CARDS] + [DISPOSABLE_CARD]
|
||||
wanted = (
|
||||
[card for _, card in SELLER_SQUAD_CARDS]
|
||||
+ [DISPOSABLE_CARD]
|
||||
+ [card for _, _, card, _ in STAGING_KITS]
|
||||
)
|
||||
missing_pack = sorted(set(wanted) - pack_ids)
|
||||
missing_cat = sorted(set(wanted) - catalog_ids)
|
||||
if missing_pack or missing_cat:
|
||||
@@ -587,7 +640,11 @@ def seed_core_db(lay: Layout) -> None:
|
||||
"INSERT INTO owned_cards (id, club_id, card_id, is_loan, "
|
||||
"acquired_at) VALUES (?, ?, ?, 0, ?)",
|
||||
[(item, SELLER_CLUB, card, TS) for item, card in SELLER_SQUAD_CARDS]
|
||||
+ [(DISPOSABLE_ITEM, SELLER_CLUB, DISPOSABLE_CARD, TS)],
|
||||
+ [(DISPOSABLE_ITEM, SELLER_CLUB, DISPOSABLE_CARD, TS)]
|
||||
+ [
|
||||
(owned_id, SELLER_CLUB, card_id, TS)
|
||||
for _slot, owned_id, card_id, _resource_id in STAGING_KITS
|
||||
],
|
||||
)
|
||||
conn.execute(
|
||||
"INSERT INTO squads (id, club_id, name, formation, created_at, "
|
||||
@@ -602,12 +659,20 @@ def seed_core_db(lay: Layout) -> None:
|
||||
for idx, (item, _) in enumerate(SELLER_SQUAD_CARDS)
|
||||
],
|
||||
)
|
||||
conn.executemany(
|
||||
"INSERT INTO club_kit_assignments (club_id, slot, owned_card_id, updated_at) "
|
||||
"VALUES (?, ?, ?, ?)",
|
||||
[
|
||||
(SELLER_CLUB, slot, owned_id, TS)
|
||||
for slot, owned_id, _card_id, _resource_id in STAGING_KITS
|
||||
],
|
||||
)
|
||||
finally:
|
||||
conn.close()
|
||||
ok(
|
||||
f"seeded Seller A ({PERSONA_NAME}, persona {PERSONA_ID}, {SELLER_COINS} coins, "
|
||||
f"{len(SELLER_SQUAD_CARDS)} starters + 1 disposable) and Buyer B "
|
||||
f"({BUYER_COINS} coins)"
|
||||
f"{len(SELLER_SQUAD_CARDS)} starters + 1 disposable + "
|
||||
f"{len(STAGING_KITS)} active kits) and Buyer B ({BUYER_COINS} coins)"
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user