# TriplePick — 아키텍처 (에이전트용 안내)

"AI(GPT·Claude·Gemini) vs 너" 글로벌 축구 승부예측 서비스. 모바일 우선.

## 스택 (2026 리팩토링)
- **frontend/** — React 19 + Vite + TypeScript + Tailwind v4, react-router. nginx 정적 서빙.
- **backend/** — Python FastAPI + SQLAlchemy(async) + PostgreSQL. 별도 워커(APScheduler).
- **docker-compose.yml** (루트) — db · api · worker · frontend 를 한 번에 실행.

## 디렉토리
```
backend/app/
  config.py        설정(.env): DB·투표윈도우·스케줄러시각·외부키
  database.py      async 엔진/세션, init_db
  models.py        ORM: matches / ai_predictions / crowd_stats / user_predictions
  schemas.py       Pydantic API 계약 (프론트 lib/types.ts 와 정합)
  scoring.py       채점(docs/SCORING.md SSOT) + 임직원 배제
  schedule_data.py 경기 일정 SSOT (Group A 6경기, KST)
  seed_data.py     부트스트랩(결정론적) 예측/crowd 생성기
  seed.py          DB 시드 (idempotent)
  domain.py        phase 계산 + ORM→응답 직렬화
  services/        ai.py(3모델 실연동) · email.py(SMTP) · grading.py
  routers/         matches · predictions · leaderboard · admin
  main.py          FastAPI 앱(API)
  worker.py        APScheduler 워커(상태전이·AI생성·결과메일)
frontend/src/
  lib/             types · i18n · format · api(백엔드 호출) · useLang
  components/      Hero · MatchupHUD · Arena · ScheduleBoard · TeamFlag · …
  pages/           Dashboard · MatchDetail · Leaderboard · NotFound
```

## 시간/스케줄 규칙 (워커가 자동 처리)
- 투표 오픈 = 킥오프 − 120h(D-5, `VOTE_OPEN_HOURS_BEFORE`)
- 투표 마감 = 킥오프 정각(`VOTE_LOCK_MINUTES_BEFORE=0`)
- 상태 전이: scheduled → open → locked → finished (`STATUS_TICK_SECONDS` 주기)
- AI 예측 생성: 매일 KST `AI_GENERATE_HOUR:MINUTE` (실 LLM API 호출)
- 결과 메일: 경기 종료 후 `RESULT_EMAIL_DELAY_MINUTES`(기본 180=3h) 경과 시 발송
- `DEMO_FORCE_OPEN=true` 면 마감 전까지 항상 투표 가능(운영 시 false)

## SSOT 문서
- `docs/SCORING.md` — 채점·심사(100만원) 단일 기준
- `docs/DESIGN.md` — 룩앤필/디자인 토큰 (변경 시 먼저 갱신)
- `docs/BACKEND.md` — 초기 백엔드 설계 메모(원본 Firebase 기준 — 현 구현은 FastAPI)

## 실행
`cp backend/.env.example backend/.env` → 키 채우기 → `docker compose up --build` → http://localhost:8080
