95 lines
3.0 KiB
Python
95 lines
3.0 KiB
Python
"""경기 일정 SSOT — lib/schedule.ts(Group A 정식 일정, KST) 와 동일.
|
|
|
|
투표 오픈 = 킥오프 - settings.vote_open_hours_before (D-2 = 48h)
|
|
투표 마감 = 킥오프 - settings.vote_lock_minutes_before (기본 0 = 킥오프 정각)
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from datetime import datetime, timedelta
|
|
|
|
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:
|
|
return datetime.fromisoformat(iso)
|
|
|
|
|
|
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)
|