117 lines
3.9 KiB
Python
117 lines
3.9 KiB
Python
"""
|
|
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"]),
|
|
}
|