o2o-triple-pick/README.md

91 lines
3.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# TriplePick 2026
**"AI(GPT · Claude · Gemini) vs 너"** — 글로벌 축구 승부예측 서비스.
3개 AI 모델이 매 경기를 서로 다르게 예측하고, 유저는 픽을 찍어 AI와 겨룬다.
끝까지 가장 정확하게 맞힌 1인에게 100만원 챌린지.
## 아키텍처
```
o2o-triple-pick/
├── docker-compose.yml # db · api · worker · frontend 한 번에 실행
├── backend/ # FastAPI + SQLAlchemy(async) + PostgreSQL
│ ├── app/ # API · 워커(APScheduler) · AI/이메일 실연동
│ └── .env.example
└── frontend/ # React + Vite + TypeScript + Tailwind v4
├── src/ # pages · components · lib(api 연동)
└── .env.example
```
- **frontend** — React SPA. nginx 가 정적 파일 서빙 + `/api` 를 백엔드로 프록시.
- **backend (api)** — FastAPI. 경기/AI예측/crowd 읽기, 픽 제출, 채점, 리더보드, 관리자.
- **backend (worker)** — APScheduler 별도 프로세스. 아래 "시간 기반 작업" 자동 처리.
- **db** — PostgreSQL.
## 빠른 시작 (Docker)
```bash
cp backend/.env.example backend/.env # 키(선택) 채우기
docker compose up --build
# 프론트: http://localhost:8080
# API 문서: http://localhost:8000/docs
```
DB 는 최초 기동 시 6경기 + AI 예측(부트스트랩) + crowd baseline 으로 자동 시드된다.
AI/이메일 키가 없어도 전체 플로우(예측·제출·채점·리더보드)는 즉시 동작한다.
## 시간 기반 작업 (워커가 자동 처리)
조사된 "필요한 시간들"을 워커 단일 프로세스가 모두 담당한다:
| 작업 | 시점 | 설정 |
|---|---|---|
| 투표 오픈 | 킥오프 48h (D-2) | `VOTE_OPEN_HOURS_BEFORE` |
| 투표 마감 | 킥오프 5분 | `VOTE_LOCK_MINUTES_BEFORE` |
| 상태 전이 (scheduled→open→locked→finished) | 주기 틱 | `STATUS_TICK_SECONDS` (기본 60s) |
| AI 예측 생성 (3모델 실 API 호출) | 매일 KST 00:05 | `AI_GENERATE_HOUR` / `_MINUTE` |
| 결과 메일 발송 (구독자) | 경기 종료 +3h | `RESULT_EMAIL_DELAY_MINUTES` |
> 데모에서는 `DEMO_FORCE_OPEN=true` 로 마감 전까지 항상 투표 가능. **운영 배포 시 false**.
## 외부 연동 (실연동 — 키 없으면 해당 기능만 생략)
- **AI 3모델** — OpenAI(GPT) · Anthropic(Claude, `claude-opus-4-8`) · Google(Gemini).
`OPENAI_API_KEY` / `ANTHROPIC_API_KEY` / `GOOGLE_API_KEY`.
- **이메일** — SMTP. `SMTP_HOST``backend/.env` 참조.
## API 요약
| 메서드 | 경로 | 설명 |
|---|---|---|
| GET | `/api/matches?lang=ko` | 전체 경기 (예측·crowd 포함) |
| GET | `/api/matches/{id}` | 경기 상세 |
| POST | `/api/predictions` | 픽 제출 (1회 수정·crowd 증분·매칭 모델) |
| GET | `/api/leaderboard` | 누적 포인트 랭킹 |
| POST | `/api/admin/result` | (Bearer) 결과 입력 → 채점 |
| POST | `/api/admin/ai-predictions` | (Bearer) AI 예측 수동 upsert |
## 로컬 개발 (Docker 없이)
```bash
# 백엔드
cd backend && python3.12 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
# Postgres 띄우고 DATABASE_URL 지정 후:
uvicorn app.main:app --reload # API
python -m app.worker # 워커
# 프론트
cd frontend && npm install && npm run dev # http://localhost:5173 (/api → :8000 프록시)
```
## 채점 규칙
`docs/SCORING.md` (SSOT). 정확 스코어 5 · 근접 3 · 승패 2 · 부분 1 · 빗나감 0.
누적 포인트 1위에게 최종 상금. 임직원/운영진 배제.
## 문서
- `docs/SCORING.md` — 채점·심사 SSOT
- `docs/DESIGN.md` — 디자인 토큰 SSOT
- `docs/BACKEND.md` — 초기 백엔드 설계 메모(Firebase 기준 → 현 구현은 FastAPI)