From 09924faea59a1eefd83954df910049bed840797b Mon Sep 17 00:00:00 2001 From: Cal Corum Date: Wed, 7 Jan 2026 12:00:45 -0600 Subject: [PATCH] Normalize Player.franchise to city-agnostic values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add SQL migration script to update all franchise values - Change AI roster queries from Team.lname to Team.sname - Add FRANCHISE_NORMALIZE helper for bulk imports - Update St Louis Cardinals hardcoded fix Enables cross-era player matching for AI rosters (fixes Oakland Athletics issue) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- app/routers_v2/players.py | 45 +++++++- app/routers_v2/teams.py | 6 +- main.py | 48 +++++++- migrations/2026-01-07_normalize_franchise.sql | 104 ++++++++++++++++++ 4 files changed, 197 insertions(+), 6 deletions(-) create mode 100644 migrations/2026-01-07_normalize_franchise.sql diff --git a/app/routers_v2/players.py b/app/routers_v2/players.py index eded10e..bd81765 100644 --- a/app/routers_v2/players.py +++ b/app/routers_v2/players.py @@ -18,6 +18,49 @@ from ..db_engine import db, Player, model_to_dict, fn, chunked, Paperdex, Cardse BattingCardRatings, PitchingCard, PitchingCardRatings, CardPosition, MlbPlayer from ..dependencies import oauth2_scheme, valid_token, LOG_DATA +# Franchise normalization: Convert city+team names to city-agnostic team names +# This enables cross-era player matching (e.g., 'Oakland Athletics' -> 'Athletics') +FRANCHISE_NORMALIZE = { + 'Arizona Diamondbacks': 'Diamondbacks', + 'Atlanta Braves': 'Braves', + 'Baltimore Orioles': 'Orioles', + 'Boston Red Sox': 'Red Sox', + 'Chicago Cubs': 'Cubs', + 'Chicago White Sox': 'White Sox', + 'Cincinnati Reds': 'Reds', + 'Cleveland Guardians': 'Guardians', + 'Colorado Rockies': 'Rockies', + 'Detroit Tigers': 'Tigers', + 'Houston Astros': 'Astros', + 'Kansas City Royals': 'Royals', + 'Los Angeles Angels': 'Angels', + 'Los Angeles Dodgers': 'Dodgers', + 'Miami Marlins': 'Marlins', + 'Milwaukee Brewers': 'Brewers', + 'Minnesota Twins': 'Twins', + 'New York Mets': 'Mets', + 'New York Yankees': 'Yankees', + 'Oakland Athletics': 'Athletics', + 'Philadelphia Phillies': 'Phillies', + 'Pittsburgh Pirates': 'Pirates', + 'San Diego Padres': 'Padres', + 'San Francisco Giants': 'Giants', + 'Seattle Mariners': 'Mariners', + 'St Louis Cardinals': 'Cardinals', + 'St. Louis Cardinals': 'Cardinals', + 'Tampa Bay Rays': 'Rays', + 'Texas Rangers': 'Rangers', + 'Toronto Blue Jays': 'Blue Jays', + 'Washington Nationals': 'Nationals', +} + + +def normalize_franchise(franchise: str) -> str: + """Convert city+team name to team-only (e.g., 'Oakland Athletics' -> 'Athletics')""" + titled = franchise.title() + return FRANCHISE_NORMALIZE.get(titled, titled) + + logging.basicConfig( filename=LOG_DATA['filename'], format=LOG_DATA['format'], @@ -736,7 +779,7 @@ async def put_players(players: PlayerModel, token: str = Depends(oauth2_scheme)) 'image': x.image, 'image2': x.image2, 'mlbclub': x.mlbclub.title(), - 'franchise': x.franchise.title(), + 'franchise': normalize_franchise(x.franchise), 'cardset_id': x.cardset_id, 'rarity_id': x.rarity_id, 'set_num': x.set_num, diff --git a/app/routers_v2/teams.py b/app/routers_v2/teams.py index 46533d4..b504d87 100644 --- a/app/routers_v2/teams.py +++ b/app/routers_v2/teams.py @@ -258,7 +258,7 @@ async def get_team_lineup( # all_players = Player.select().where( # (fn.Lower(Player.p_name) != pitcher_name.lower()) & (Player.mlbclub == this_team.lname) # ) - all_players = Player.select().where(Player.franchise == this_team.lname) + all_players = Player.select().where(Player.franchise == this_team.sname) if difficulty_name == 'exhibition': logging.info(f'pulling an exhibition lineup') @@ -519,7 +519,7 @@ async def get_team_sp( db.close() raise HTTPException(status_code=400, detail=f'Difficulty name {difficulty_name} not a valid check') - all_players = Player.select().where(Player.franchise == this_team.lname) + all_players = Player.select().where(Player.franchise == this_team.sname) if difficulty_name == 'exhibition': logging.info(f'pulling an exhibition lineup') @@ -619,7 +619,7 @@ async def get_team_rp( raise HTTPException(status_code=400, detail=f'Difficulty name {difficulty_name} not a valid check') all_players = Player.select().where( - (Player.franchise == this_team.lname) & (Player.player_id.not_in(used_pitcher_ids)) + (Player.franchise == this_team.sname) & (Player.player_id.not_in(used_pitcher_ids)) ) if difficulty_name == 'exhibition': diff --git a/main.py b/main.py index 5cb57ba..83a20ec 100644 --- a/main.py +++ b/main.py @@ -32,6 +32,50 @@ app = FastAPI() oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") DEFAULT_SEASON = 5 + +# Franchise normalization: Convert city+team names to city-agnostic team names +# This enables cross-era player matching (e.g., 'Oakland Athletics' -> 'Athletics') +FRANCHISE_NORMALIZE = { + 'Arizona Diamondbacks': 'Diamondbacks', + 'Atlanta Braves': 'Braves', + 'Baltimore Orioles': 'Orioles', + 'Boston Red Sox': 'Red Sox', + 'Chicago Cubs': 'Cubs', + 'Chicago White Sox': 'White Sox', + 'Cincinnati Reds': 'Reds', + 'Cleveland Guardians': 'Guardians', + 'Colorado Rockies': 'Rockies', + 'Detroit Tigers': 'Tigers', + 'Houston Astros': 'Astros', + 'Kansas City Royals': 'Royals', + 'Los Angeles Angels': 'Angels', + 'Los Angeles Dodgers': 'Dodgers', + 'Miami Marlins': 'Marlins', + 'Milwaukee Brewers': 'Brewers', + 'Minnesota Twins': 'Twins', + 'New York Mets': 'Mets', + 'New York Yankees': 'Yankees', + 'Oakland Athletics': 'Athletics', + 'Philadelphia Phillies': 'Phillies', + 'Pittsburgh Pirates': 'Pirates', + 'San Diego Padres': 'Padres', + 'San Francisco Giants': 'Giants', + 'Seattle Mariners': 'Mariners', + 'St Louis Cardinals': 'Cardinals', + 'St. Louis Cardinals': 'Cardinals', + 'Tampa Bay Rays': 'Rays', + 'Texas Rangers': 'Rangers', + 'Toronto Blue Jays': 'Blue Jays', + 'Washington Nationals': 'Nationals', +} + + +def normalize_franchise(franchise: str) -> str: + """Convert city+team name to team-only (e.g., 'Oakland Athletics' -> 'Athletics')""" + titled = franchise.title() + return FRANCHISE_NORMALIZE.get(titled, titled) + + SHEETS_AUTH = pygsheets.authorize(service_file='storage/paper-dynasty-service-creds.json', retries=1) @@ -1623,7 +1667,7 @@ async def v1_players_put(players: PlayerModel, token: str = Depends(oauth2_schem 'image': x.image, 'image2': x.image2, 'mlbclub': x.mlbclub.title(), - 'franchise': x.franchise.title(), + 'franchise': normalize_franchise(x.franchise), 'cardset_id': x.cardset_id, 'rarity_id': x.rarity_id, 'set_num': x.set_num, @@ -5109,7 +5153,7 @@ async def v1_stl_fix(token: str = Depends(oauth2_scheme)): detail='You are not authorized to post. This event has been logged.' ) - p_query = Player.update(mlbclub='St Louis Cardinals', franchise='St Louis Cardinals').where( + p_query = Player.update(mlbclub='St Louis Cardinals', franchise='Cardinals').where( Player.mlbclub == 'St. Louis Cardinals' ).execute() db.close() diff --git a/migrations/2026-01-07_normalize_franchise.sql b/migrations/2026-01-07_normalize_franchise.sql new file mode 100644 index 0000000..80bcca7 --- /dev/null +++ b/migrations/2026-01-07_normalize_franchise.sql @@ -0,0 +1,104 @@ +-- Migration: Normalize Player.franchise to city-agnostic values +-- Date: 2026-01-07 +-- Purpose: Enable cross-era player matching for AI rosters by normalizing +-- franchise values to match Team.sname (e.g., 'Oakland Athletics' -> 'Athletics') +-- +-- IMPORTANT: Backup database before running! +-- Run on dev first, verify with: SELECT DISTINCT franchise FROM player ORDER BY franchise; +-- Then run on prod. +-- +-- Rollback: See inverse statements at bottom of file + +-- ============================================ +-- FORWARD MIGRATION: Normalize franchise values +-- ============================================ + +-- National League West +UPDATE player SET franchise = 'Diamondbacks' WHERE franchise = 'Arizona Diamondbacks'; +UPDATE player SET franchise = 'Rockies' WHERE franchise = 'Colorado Rockies'; +UPDATE player SET franchise = 'Dodgers' WHERE franchise = 'Los Angeles Dodgers'; +UPDATE player SET franchise = 'Padres' WHERE franchise = 'San Diego Padres'; +UPDATE player SET franchise = 'Giants' WHERE franchise = 'San Francisco Giants'; + +-- National League Central +UPDATE player SET franchise = 'Cubs' WHERE franchise = 'Chicago Cubs'; +UPDATE player SET franchise = 'Reds' WHERE franchise = 'Cincinnati Reds'; +UPDATE player SET franchise = 'Brewers' WHERE franchise = 'Milwaukee Brewers'; +UPDATE player SET franchise = 'Pirates' WHERE franchise = 'Pittsburgh Pirates'; +UPDATE player SET franchise = 'Cardinals' WHERE franchise IN ('St Louis Cardinals', 'St. Louis Cardinals'); + +-- National League East +UPDATE player SET franchise = 'Braves' WHERE franchise = 'Atlanta Braves'; +UPDATE player SET franchise = 'Marlins' WHERE franchise = 'Miami Marlins'; +UPDATE player SET franchise = 'Mets' WHERE franchise = 'New York Mets'; +UPDATE player SET franchise = 'Phillies' WHERE franchise = 'Philadelphia Phillies'; +UPDATE player SET franchise = 'Nationals' WHERE franchise = 'Washington Nationals'; + +-- American League West +UPDATE player SET franchise = 'Astros' WHERE franchise = 'Houston Astros'; +UPDATE player SET franchise = 'Angels' WHERE franchise = 'Los Angeles Angels'; +UPDATE player SET franchise = 'Athletics' WHERE franchise = 'Oakland Athletics'; +UPDATE player SET franchise = 'Mariners' WHERE franchise = 'Seattle Mariners'; +UPDATE player SET franchise = 'Rangers' WHERE franchise = 'Texas Rangers'; + +-- American League Central +UPDATE player SET franchise = 'White Sox' WHERE franchise = 'Chicago White Sox'; +UPDATE player SET franchise = 'Guardians' WHERE franchise = 'Cleveland Guardians'; +UPDATE player SET franchise = 'Tigers' WHERE franchise = 'Detroit Tigers'; +UPDATE player SET franchise = 'Royals' WHERE franchise = 'Kansas City Royals'; +UPDATE player SET franchise = 'Twins' WHERE franchise = 'Minnesota Twins'; + +-- American League East +UPDATE player SET franchise = 'Orioles' WHERE franchise = 'Baltimore Orioles'; +UPDATE player SET franchise = 'Red Sox' WHERE franchise = 'Boston Red Sox'; +UPDATE player SET franchise = 'Yankees' WHERE franchise = 'New York Yankees'; +UPDATE player SET franchise = 'Rays' WHERE franchise = 'Tampa Bay Rays'; +UPDATE player SET franchise = 'Blue Jays' WHERE franchise = 'Toronto Blue Jays'; + +-- ============================================ +-- VERIFICATION QUERY +-- ============================================ +-- Run after migration to verify all 30 teams have correct values: +-- SELECT DISTINCT franchise FROM player ORDER BY franchise; +-- +-- Expected output (30 city-agnostic franchise names): +-- Angels, Athletics, Blue Jays, Braves, Brewers, Cardinals, Cubs, +-- Diamondbacks, Dodgers, Giants, Guardians, Mariners, Marlins, Mets, +-- Nationals, Orioles, Padres, Phillies, Pirates, Rangers, Rays, +-- Red Sox, Reds, Rockies, Royals, Tigers, Twins, White Sox, Yankees + +-- ============================================ +-- ROLLBACK MIGRATION (if needed) +-- ============================================ +-- Use these statements to revert to original values: +-- +-- UPDATE player SET franchise = 'Arizona Diamondbacks' WHERE franchise = 'Diamondbacks' AND mlbclub LIKE '%Arizona%'; +-- UPDATE player SET franchise = 'Atlanta Braves' WHERE franchise = 'Braves' AND mlbclub LIKE '%Atlanta%'; +-- UPDATE player SET franchise = 'Baltimore Orioles' WHERE franchise = 'Orioles' AND mlbclub LIKE '%Baltimore%'; +-- UPDATE player SET franchise = 'Boston Red Sox' WHERE franchise = 'Red Sox' AND mlbclub LIKE '%Boston%'; +-- UPDATE player SET franchise = 'Chicago Cubs' WHERE franchise = 'Cubs' AND mlbclub LIKE '%Chicago%'; +-- UPDATE player SET franchise = 'Chicago White Sox' WHERE franchise = 'White Sox' AND mlbclub LIKE '%Chicago%'; +-- UPDATE player SET franchise = 'Cincinnati Reds' WHERE franchise = 'Reds' AND mlbclub LIKE '%Cincinnati%'; +-- UPDATE player SET franchise = 'Cleveland Guardians' WHERE franchise = 'Guardians' AND mlbclub LIKE '%Cleveland%'; +-- UPDATE player SET franchise = 'Colorado Rockies' WHERE franchise = 'Rockies' AND mlbclub LIKE '%Colorado%'; +-- UPDATE player SET franchise = 'Detroit Tigers' WHERE franchise = 'Tigers' AND mlbclub LIKE '%Detroit%'; +-- UPDATE player SET franchise = 'Houston Astros' WHERE franchise = 'Astros' AND mlbclub LIKE '%Houston%'; +-- UPDATE player SET franchise = 'Kansas City Royals' WHERE franchise = 'Royals' AND mlbclub LIKE '%Kansas%'; +-- UPDATE player SET franchise = 'Los Angeles Angels' WHERE franchise = 'Angels' AND mlbclub LIKE '%Los Angeles%' AND mlbclub NOT LIKE '%Dodgers%'; +-- UPDATE player SET franchise = 'Los Angeles Dodgers' WHERE franchise = 'Dodgers' AND mlbclub LIKE '%Los Angeles%'; +-- UPDATE player SET franchise = 'Miami Marlins' WHERE franchise = 'Marlins' AND mlbclub LIKE '%Miami%'; +-- UPDATE player SET franchise = 'Milwaukee Brewers' WHERE franchise = 'Brewers' AND mlbclub LIKE '%Milwaukee%'; +-- UPDATE player SET franchise = 'Minnesota Twins' WHERE franchise = 'Twins' AND mlbclub LIKE '%Minnesota%'; +-- UPDATE player SET franchise = 'New York Mets' WHERE franchise = 'Mets' AND mlbclub LIKE '%New York%'; +-- UPDATE player SET franchise = 'New York Yankees' WHERE franchise = 'Yankees' AND mlbclub LIKE '%New York%'; +-- UPDATE player SET franchise = 'Oakland Athletics' WHERE franchise = 'Athletics' AND mlbclub LIKE '%Oakland%'; +-- UPDATE player SET franchise = 'Philadelphia Phillies' WHERE franchise = 'Phillies' AND mlbclub LIKE '%Philadelphia%'; +-- UPDATE player SET franchise = 'Pittsburgh Pirates' WHERE franchise = 'Pirates' AND mlbclub LIKE '%Pittsburgh%'; +-- UPDATE player SET franchise = 'San Diego Padres' WHERE franchise = 'Padres' AND mlbclub LIKE '%San Diego%'; +-- UPDATE player SET franchise = 'San Francisco Giants' WHERE franchise = 'Giants' AND mlbclub LIKE '%San Francisco%'; +-- UPDATE player SET franchise = 'Seattle Mariners' WHERE franchise = 'Mariners' AND mlbclub LIKE '%Seattle%'; +-- UPDATE player SET franchise = 'St Louis Cardinals' WHERE franchise = 'Cardinals' AND mlbclub LIKE '%St%Louis%'; +-- UPDATE player SET franchise = 'Tampa Bay Rays' WHERE franchise = 'Rays' AND mlbclub LIKE '%Tampa%'; +-- UPDATE player SET franchise = 'Texas Rangers' WHERE franchise = 'Rangers' AND mlbclub LIKE '%Texas%'; +-- UPDATE player SET franchise = 'Toronto Blue Jays' WHERE franchise = 'Blue Jays' AND mlbclub LIKE '%Toronto%'; +-- UPDATE player SET franchise = 'Washington Nationals' WHERE franchise = 'Nationals' AND mlbclub LIKE '%Washington%';