""" crawler/lineup_builder.py — 라인업 데이터 구성 relay 데이터와 preview 데이터에서 라인업 정보를 추출합니다. """ from __future__ import annotations from typing import Any from crawler.naver_api import get_team_names def get_starting_pitcher(pitchers: list[dict[str, Any]]) -> dict[str, Any] | None: """투수 리스트에서 선발투수 추출""" if not pitchers: return None return min(pitchers, key=lambda p: p.get("seqno", 999)) def get_starting_batters(batters: list[dict[str, Any]]) -> list[dict[str, Any]]: """타자 리스트에서 선발 라인업 추출""" starters_by_order: dict[int, dict[str, Any]] = {} for batter in sorted(batters, key=lambda b: (b.get("batOrder", 999), b.get("seqno", 999))): bat_order = batter.get("batOrder") if bat_order is None or bat_order in starters_by_order: continue starters_by_order[bat_order] = batter return [starters_by_order[order] for order in sorted(starters_by_order)] def build_lineup_team(team_name: str, lineup: dict[str, Any]) -> dict[str, Any]: """relay 데이터의 라인업 → 정규화된 팀 라인업 dict""" starter_pitcher = get_starting_pitcher(lineup.get("pitcher", [])) starting_batters = get_starting_batters(lineup.get("batter", [])) return { "team_name": team_name, "starter_pitcher": { "name": starter_pitcher.get("name"), "position": "투수", "number": starter_pitcher.get("backnum"), } if starter_pitcher else None, "players": [ { "bat_order": batter.get("batOrder"), "name": batter.get("name"), "position": batter.get("posName"), "number": batter.get("backnum"), } for batter in starting_batters ], } def build_preview_lineup_team( team_name: str, preview_lineup: dict[str, Any] | None, ) -> dict[str, Any] | None: """preview 데이터의 라인업 → 정규화된 팀 라인업 dict""" if not preview_lineup: return None full_lineup = preview_lineup.get("fullLineUp") or [] starter_pitcher = next( ( player for player in full_lineup if player.get("positionName") == "선발투수" or int(player.get("batorder", 0) or 0) == 0 ), None, ) batters = sorted( (player for player in full_lineup if int(player.get("batorder", 0) or 0) > 0), key=lambda p: int(p.get("batorder", 99) or 99), ) return { "team_name": team_name, "starter_pitcher": { "name": starter_pitcher.get("playerName"), "position": "투수", "number": starter_pitcher.get("backnum"), } if starter_pitcher else None, "players": [ { "bat_order": int(player.get("batorder")), "name": player.get("playerName"), "position": player.get("positionName"), "number": player.get("backnum"), } for player in batters ], } def build_lineup_summary( game_id: str, game_info: dict[str, Any], relay_data: dict[str, Any], preview_data: dict[str, Any] | None = None, ) -> dict[str, Any]: """전체 라인업 요약 생성 (preview 우선, relay 폴백)""" away_name, home_name = get_team_names(game_id, game_info) away_preview = build_preview_lineup_team( away_name, (preview_data or {}).get("awayTeamLineUp"), ) home_preview = build_preview_lineup_team( home_name, (preview_data or {}).get("homeTeamLineUp"), ) return { "away_team": away_preview or build_lineup_team(away_name, relay_data["awayLineup"]), "home_team": home_preview or build_lineup_team(home_name, relay_data["homeLineup"]), }