From 96ca7c0484978e5180d448782e54c1858d49ef14 Mon Sep 17 00:00:00 2001 From: funman300 Date: Tue, 18 Aug 2026 03:33:42 +0000 Subject: [PATCH] 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. --- scripts/sold-staging-seed-squad.py | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/scripts/sold-staging-seed-squad.py b/scripts/sold-staging-seed-squad.py index 1afe8e5..0e4cae4 100755 --- a/scripts/sold-staging-seed-squad.py +++ b/scripts/sold-staging-seed-squad.py @@ -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": [], }