fix(scripts): the seeded squad was structurally valid but the client still refused it

First seed sent only squadName/formation/captain/players. The host logged squad-active
200 outcome=ok and /squad/0 showed 11 occupied slots, yet the client still threw a FUT
squad update error -- a 200 with the right players is not proof the client accepts the
body.

Diffed against production's known-good squad, which the same client accepts, comparing
key presence and JSON TYPES rather than values. Staging returned null for exactly the
five fields the PUT never carried, because the extension stored nothing for them:
squadType (a string enum), chemistry, rating, starRating (ints) and custom (the opaque
33-int tactics array the client definitely parses). kicktakers was empty where
production carries five.

Now sends all of them: squadType REGULAR_SQUAD, chemistry, rating/starRating derived
from the XI's mean rating, production's custom array verbatim (opaque server-side, only
its shape matters), and five kicktakers. Re-diff leaves exactly one difference --
manager, which production points at owned staff instance 100000427 while the staging
club holds 11 players and zero staff. Left empty rather than inventing an id that
references a non-existent item; recorded in the code as the one known remaining gap.

Also fixes a KeyError from the rewrite dropping the players key.
This commit is contained in:
funman300
2026-08-18 03:33:42 +00:00
parent 202366611e
commit 96ca7c0484
+28 -1
View File
@@ -35,6 +35,12 @@ STARTERS = 11
# GK, RB, CB, CB, LB, CM, CM, CM, RW, ST, LW.
LINEUP = ["GK", "RB", "CB", "CB", "LB", "CM", "CM", "CM", "RW", "ST", "LW"]
FORMATION = "f433"
SQUAD_TYPE = "REGULAR_SQUAD"
CHEMISTRY = 50
# Production's opaque 33-int tactics array. Never parsed server-side; reused because
# only the shape (a JSON-encoded int array, not null) matters to the client.
CUSTOM = ("[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"
"50,50,0,50,40,65,0,65,50,50,1]")
def call(method, path, body=None):
@@ -90,14 +96,35 @@ def build_put(chosen):
"kitNumber": idx + 1 if occupant else 0,
})
captain = next((int(p["id"]) for p in chosen if p), 0)
ratings = [int(p.get("rating") or 0) for p in chosen if p]
mean_rating = sum(ratings) // len(ratings) if ratings else 0
return {
"id": 0,
"squadName": "Staging XI",
"formation": FORMATION,
"captain": captain,
"players": players,
# A first attempt sent only name/formation/captain/players and the client
# STILL refused the hub, while the host logged squad-active 200 ok -- the
# route was fine and the body was not. Diffing against production's
# known-good squad showed staging returning null for exactly these five,
# because the PUT never carried them and the extension stored nothing.
# Types matter here: the client wants scalars, not null.
"squadType": SQUAD_TYPE,
"chemistry": CHEMISTRY,
"rating": mean_rating,
"starRating": mean_rating,
# Opaque 33-int tactics array, carried verbatim and never interpreted
# server-side. Reused from production because only its SHAPE matters.
"custom": CUSTOM,
# Production carries five, all pointing at one player. Mirrored so the
# array is populated rather than empty.
"kicktakers": [{"index": i, "id": captain, "dream": False} for i in range(5)],
# Left empty deliberately: production references an owned staff instance
# (100000427) and the staging club holds 11 players and zero staff, so
# there is no manager to point at. Inventing an id would reference a
# non-existent item. This is the one remaining shape difference.
"manager": [],
"kicktakers": [],
}