Open voting for all groups by D-2 time + 30h-ahead AI gen; misc fixes
- domain: is_votable → all groups (voting gated by D-2 open ~ kickoff-60m time window, not group) - worker: AI generation selects matches by opens_at <= now+lookahead (all groups), pre-fills before D-2 open so picks aren't empty; only_missing keeps total calls = 3/match - config: ai_generate_lookahead_hours=30 (covers daily-only gen cadence) - Arena: default pick 0:0 (무승부) - frontend Dockerfile: install from package.json only (macOS-generated lock leaves rollup darwin-x64 stub w/o version → npm "Invalid Version" on linux) NOTE for deploy: set DEMO_FORCE_OPEN=false and real PUBLIC_ORIGIN in server .env. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>develop
parent
deb1332440
commit
955ffae4cf
|
|
@ -84,6 +84,9 @@ class Settings(BaseSettings):
|
|||
# 매일 AI 예측 생성 시각 (KST). 기능정의서: 매일 0시 1회 생성.
|
||||
ai_generate_hour: int = 0
|
||||
ai_generate_minute: int = 5
|
||||
# 투표 오픈(D-2) 선행 생성 시간(h). 1일 1회 생성이므로 다음 주기 전 오픈할
|
||||
# 경기를 미리 채우려면 ~24h 이상 필요. 30h = 하루치 + 여유. (only_missing 이라 총 호출 수 동일)
|
||||
ai_generate_lookahead_hours: int = 30
|
||||
|
||||
# ── 결과 자동 정산(관리자 입력 불필요) ───────────────────
|
||||
# 킥오프 + 이 시간(시) 경과 후, 외부 소스에서 스코어를 자동 수집해 채점·집계·메일.
|
||||
|
|
|
|||
|
|
@ -59,8 +59,9 @@ def compute_phase(m: Match, now: datetime | None = None) -> str:
|
|||
|
||||
|
||||
def is_votable(m: Match) -> bool:
|
||||
"""AI 예측·투표 대상 조인지. featured_group 만 투표 가능, 그 외는 일정/결과만."""
|
||||
return m.group == settings.featured_group
|
||||
"""투표 지원 경기 여부 — 전체 조 투표 가능.
|
||||
실제 오픈/마감은 is_open_for_voting 의 시간창(D-2 오픈 ~ 킥오프 60분 전 마감)이 결정."""
|
||||
return True
|
||||
|
||||
|
||||
def is_open_for_voting(m: Match, now: datetime | None = None) -> bool:
|
||||
|
|
|
|||
|
|
@ -83,17 +83,18 @@ async def generate_ai_predictions(only_missing: bool = True) -> None:
|
|||
only_missing=False: 전부 재생성(덮어쓰기) — 수동 재생성 스크립트용.
|
||||
"""
|
||||
async with SessionLocal() as db:
|
||||
# AI 예측·투표 대상 조(featured_group)만 생성. 그 외 조는 일정/결과만.
|
||||
matches = (
|
||||
# 투표 오픈(킥오프 D-2)이 임박/도래한 미종료 경기 — 조 무관.
|
||||
# lookahead_hours 만큼 선행 생성해 다음 생성 주기 전에 오픈할 경기도 미리 채운다
|
||||
# (1일 1회 생성 → 오픈 시점에 AI 가 비어 보이지 않도록). 더 먼 미래 경기는 제외.
|
||||
horizon = now_utc() + timedelta(hours=settings.ai_generate_lookahead_hours)
|
||||
rows = (
|
||||
await db.execute(
|
||||
select(Match)
|
||||
.where(
|
||||
Match.result_outcome.is_(None),
|
||||
Match.group == settings.featured_group,
|
||||
)
|
||||
.where(Match.result_outcome.is_(None))
|
||||
.options(selectinload(Match.predictions))
|
||||
)
|
||||
).scalars().all()
|
||||
matches = [m for m in rows if ensure_aware(m.opens_at) <= horizon]
|
||||
|
||||
for m in matches:
|
||||
ctx = MatchContext(
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
# TriplePick 프론트엔드 — Vite 빌드 → nginx 정적 서빙 + /api 프록시.
|
||||
FROM node:20-alpine AS build
|
||||
# lock은 macOS(arm64)에서 생성돼 rollup darwin-x64 optional dep가 version 없는
|
||||
# stub로 남는 npm 버그가 있어, linux 빌드에선 lock 없이 package.json만으로 설치한다.
|
||||
FROM node:24-alpine AS build
|
||||
WORKDIR /app
|
||||
COPY package.json package-lock.json* ./
|
||||
RUN npm install
|
||||
COPY package.json ./
|
||||
RUN npm install --no-audit --no-fund
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
|
|
|
|||
|
|
@ -39,9 +39,9 @@ export default function Arena({
|
|||
const t = dict(lang);
|
||||
const aShort = teamShort(match.teamA, lang);
|
||||
const bShort = teamShort(match.teamB, lang);
|
||||
const [outcome, setOutcome] = useState<Outcome | null>(null);
|
||||
const [scoreA, setScoreA] = useState(2);
|
||||
const [scoreB, setScoreB] = useState(1);
|
||||
const [outcome, setOutcome] = useState<Outcome | null>("DRAW");
|
||||
const [scoreA, setScoreA] = useState(0);
|
||||
const [scoreB, setScoreB] = useState(0);
|
||||
const [step, setStep] = useState<Step>("pick");
|
||||
const [email, setEmail] = useState("");
|
||||
const [notify, setNotify] = useState(true);
|
||||
|
|
|
|||
Loading…
Reference in New Issue