{"slate_id":"soccer-showdown-draftkings-2026-10-29-seriea","sport":"soccer","site":"draftkings","slate_date":"2026-10-29","slate_type":"showdown","slate_subtype":null,"tour":null,"competition":"ita.1","league_label":"Serie A","is_draft":false,"config":{"$comment":"SCORING TABLE REBUILT AND VERIFIED 2026-08-21 against https://www.draftkings.com/help/rules/8 (read in a browser; the page is an SPA behind bot protection and returns a shell to curl). It is now generated from apps/api/src/dfs_api/projection/scoring/soccer_cards.py, which is the single source of truth for every soccer weight in this repo, and apps/api/tests/test_soccer_scoring.py asserts this block equals that card exactly. What was wrong here before: goals paid 10/12/13 by position where DK pays 10 flat at every position; cross 0.6 (0.7); clean_sheet_d 4 (3); clean_sheet_gk 7 (5); gk_save 1 (2); pk_save 8 (3, on top of the 2 for the save); win 3 (5); yellow -2 (-1.5); red -5 (-3); own_goal -5 (DK charges the scorer nothing); a gk_high_claim category DK does not have; and accurate_pass, tackle_won, interception, fouls and the keeper's goal_conceded were missing entirely. Soccer's card is position-dependent, so the flat block below carries clean_sheet_def / clean_sheet_gk (and, on FanDuel, goal_conceded_def) rather than one clean_sheet that silently paid every position the goalkeeper's bonus. NOT changed by that pass, and still inherited: roster shape, max_per_team, min_teams, min_games. Note DraftKings' own rules state only 'at least 3 different teams' with NO per-team maximum, so max_per_team=4 is a house constraint rather than a site rule. || EARLIER: CAPTAIN-MODE VOCABULARY CORRECTED 2026-07-30. DraftKings captain-mode exports carry Roster Position = CPT / FLEX, and the importer reads Roster Position FIRST for DraftKings (DK_COLUMNS['position'] = ['Roster Position', 'Position', 'Pos'] in services/slate_import.py — the FanDuel override is the exception, not the rule). Each player appears TWICE in the export, once per slot label, and finalize_import unions the positions on dedupe — so the optimizer sees positions ['CPT', 'FLEX'], never the sport's own position token. This config listed only the sport token, so EVERY player matched zero slots and the slate produced no lineups. Verified against the real exports committed under apps/api/tests/fixtures/ (soccer showdown: 104 rows -> 52 players, all carrying exactly ['CPT','FLEX'], 6 of 6 slots unfillable). CPT and FLEX are now accepted alongside the sport tokens, which is also semantically right for captain mode: any player may occupy any slot, and the captain premium is expressed by the slot's multipliers rather than by eligibility. Note the cs config's own comment already recorded that DK ships 'Position=P with Roster Position=CPT/FLEX' — the fact was known, but the config was written against the Position column the importer does not use for DraftKings.","site":"draftkings","sport":"soccer","slate_type":"showdown","salary_cap":50000,"roster_slots":[{"name":"CPT","eligible":["GK","D","M","F","M/F","CPT","FLEX","A-CPT"],"salary_multiplier":1.5,"score_multiplier":1.5},{"name":"FLEX1","eligible":["GK","D","M","F","M/F","CPT","FLEX","A-CPT"]},{"name":"FLEX2","eligible":["GK","D","M","F","M/F","CPT","FLEX","A-CPT"]},{"name":"FLEX3","eligible":["GK","D","M","F","M/F","CPT","FLEX","A-CPT"]},{"name":"FLEX4","eligible":["GK","D","M","F","M/F","CPT","FLEX","A-CPT"]},{"name":"FLEX5","eligible":["GK","D","M","F","M/F","CPT","FLEX","A-CPT"]}],"max_per_team":5,"min_teams":2,"min_games":1,"scoring":{"accurate_pass":0.02,"assist":6,"chance_created":1,"clean_sheet_def":3,"clean_sheet_gk":5,"cross":0.7,"foul_conceded":-0.5,"foul_drawn":1,"goal":10,"goal_conceded":-2,"interception":0.5,"own_goal":0,"penalty_missed":0,"penalty_save":3,"red_card":-3,"save":2,"shootout_goal":1.5,"shootout_miss":-1,"shootout_save":1.5,"shot":1,"shot_on_target":1,"tackle_won":1,"win":5,"yellow_card":-1.5},"export_format":{"header":["CPT","FLEX","FLEX","FLEX","FLEX","FLEX"],"id_format":"{name} ({site_player_id})"}},"locked_at":null,"first_game_start":"2026-10-29T17:30:00Z","last_game_start":"2026-10-29T17:30:00Z","late_swap_enabled":true,"display_name":null,"is_free":false,"group_key":"8ac8ad915cd79cb6","group_slate_type":"showdown","projection_window":null}