o2o-triple-pick/backend/app/schedule_data.py

96 lines
3.2 KiB
Python

"""경기 일정 SSOT — lib/schedule.ts(Group A 정식 일정, KST) 와 동일.
투표 오픈 = 킥오프 - settings.vote_open_hours_before (D-5 = 120h)
투표 마감 = 킥오프 - settings.vote_lock_minutes_before (기본 0 = 킥오프 정각)
"""
from __future__ import annotations
from dataclasses import dataclass
from datetime import datetime, timedelta, timezone
from .config import settings
# 팀 정의 (코드 → 표시명/약식/이모지)
TEAMS = {
"KOR": {"name": "Korea Republic", "shortName": "한국", "code": "KOR", "flag": "🇰🇷"},
"CZE": {"name": "Czechia", "shortName": "체코", "code": "CZE", "flag": "🇨🇿"},
"MEX": {"name": "Mexico", "shortName": "멕시코", "code": "MEX", "flag": "🇲🇽"},
"RSA": {"name": "South Africa", "shortName": "남아공", "code": "RSA", "flag": "🇿🇦"},
}
# 외부 소스의 팀 표기 → 내부 코드 매핑 (openfootball / football-data 등 변형 포괄).
NAME_TO_CODE = {
"korea republic": "KOR",
"south korea": "KOR",
"korea": "KOR",
"czechia": "CZE",
"czech republic": "CZE",
"mexico": "MEX",
"south africa": "RSA",
}
def code_for(name: str) -> str | None:
return NAME_TO_CODE.get(name.strip().lower())
@dataclass(frozen=True)
class MatchSeed:
match_id: str
round_label: str
team_a: str # 코드
team_b: str
kickoff_iso: str # ISO with +09:00
venue: str
hook_text: str
# Group A 전체 6경기 (출처: lib/schedule.ts)
GROUP_A: list[MatchSeed] = [
MatchSeed(
"A_MEX_RSA_20260612", "Match 01 · 개막전", "MEX", "RSA",
"2026-06-12T04:00:00+09:00", "Estadio Azteca · Mexico City",
"글로벌 축구 개막전, AI는 개최국을 믿을까",
),
MatchSeed(
"A_KOR_CZE_20260612", "Match 01", "KOR", "CZE",
"2026-06-12T11:00:00+09:00", "Estadio Guadalajara (Akron)",
"한국 첫 경기, AI의 선택은 갈렸다",
),
MatchSeed(
"A_CZE_RSA_20260619", "Match 02", "CZE", "RSA",
"2026-06-19T01:00:00+09:00", "USA (TBD)",
"체코 vs 남아공, AI의 예측은",
),
MatchSeed(
"A_MEX_KOR_20260619", "Match 02", "MEX", "KOR",
"2026-06-19T10:00:00+09:00", "Estadio Guadalajara (Akron)",
"개최국 멕시코 vs 한국, AI는 누구 편",
),
MatchSeed(
"A_CZE_MEX_20260625", "Match 03", "CZE", "MEX",
"2026-06-25T10:00:00+09:00", "Estadio Azteca · Mexico City",
"체코 vs 멕시코, 운명의 최종전",
),
MatchSeed(
"A_RSA_KOR_20260625", "Match 03", "RSA", "KOR",
"2026-06-25T10:00:00+09:00", "Estadio BBVA · Monterrey",
"한국 16강의 갈림길, AI의 마지막 예측",
),
]
FEATURED_MATCH_ID = "A_KOR_CZE_20260612"
def parse_kickoff(iso: str) -> datetime:
# 저장은 UTC 로 통일 (DB 종류 무관하게 절대시점 일관). 출력 시 KST 로 직렬화.
return datetime.fromisoformat(iso).astimezone(timezone.utc)
def opens_at(kickoff: datetime) -> datetime:
return kickoff - timedelta(hours=settings.vote_open_hours_before)
def lock_at(kickoff: datetime) -> datetime:
return kickoff - timedelta(minutes=settings.vote_lock_minutes_before)