Commit Graph

73 Commits (fd8493ae2dbb076262e8f226509522798caf634b)

Author SHA1 Message Date
김성경 fd8493ae2d 사이트맵, 로봇txt, seo 페이지 추가 2026-06-24 13:19:34 +09:00
김성경 d6b7737955 Merge branch 'develop' of https://gitea.o2o.kr/castad/o2o-triple-pick into develop 2026-06-24 11:26:05 +09:00
김성경 ff7d84016a 네이버 사이트 확인 html 추가 2026-06-24 11:25:36 +09:00
jwkim 6fe52db8d1 기본 노래 볼륨 80% -> 40%로 하향 2026-06-24 08:13:28 +09:00
jwkim 7325c96f2c revert: 카드 썸네일(투표 픽 스코어) 기능 제거 — 16bd01f 상태로 복귀
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 14:50:17 +09:00
jwkim 198f20a0f6 한국 남아공 경기 공유 썸네일에 투표 픽 스코어 카드 생성 2026-06-23 14:26:21 +09:00
jwkim 39766bae55 한국 남아공 경기 공유 썸네일에 투표 픽 스코어 카드 생성 2026-06-23 14:19:31 +09:00
jwkim 16bd01fc95 남아공전 공유하기 한국이 왼쪽으로 오게끔 수정 2026-06-22 17:32:24 +09:00
jwkim 10b533af28 남아공전 응원가 3개 추가 2026-06-22 16:10:22 +09:00
jwkim d05e85e593 종료 경기 결과 외부 소스 재대조로 자동 정정 2026-06-22 15:06:19 +09:00
jwkim 90d00a817b 한국 경기 한국 좌측 고정, 국가명 한글 통일 2026-06-22 10:21:13 +09:00
jwkim 8580bbb713 Crowd Pick 비율 합이 항상 100% 되도록 반올림 보정 2026-06-19 11:05:13 +09:00
jwkim 0a64a220ca Crowd Pick 합 100% 초과 버그 수정 및 투표 오픈을 킥오프 7일 전으로 변경 2026-06-19 10:36:58 +09:00
jwkim 76eafceee8 날짜별 칩 첫 진입 시 오늘 날짜 가운데 정렬 2026-06-19 09:10:54 +09:00
jwkim f03d3e373c AI 모델 순위 부분 강조 수정 2026-06-18 17:18:14 +09:00
jwkim a8e20d5ac8 누적 랭킹 보기 탭 추가 2026-06-18 17:01:41 +09:00
jwkim 39c2003080 내 지난 예측을 투표 후에만 표시 2026-06-18 15:57:40 +09:00
jwkim b4fc96f299 내 지난 얘측 보기 기능 추가, 한국 멕시코 경기 응원가 1곡 추가 2026-06-18 15:41:39 +09:00
김성경 0e5a63a28b fix: 음악자동재생 + 버그수정 2026-06-18 13:08:51 +09:00
jwkim 2988a59749 투표 제출 CTA 단일 카드 통합 + Red Wave 2026 트랙 추가 2026-06-18 10:27:13 +09:00
김성경 7a68d27693 썸네일 변경 2026-06-17 17:27:44 +09:00
김성경 220eb946c1 Merge branch 'develop' of https://gitea.o2o.kr/castad/o2o-triple-pick into develop 2026-06-17 16:51:59 +09:00
김성경 7c42bd5277 feat: 사운드바 추가 2026-06-17 16:51:50 +09:00
jwkim bac505fa99 댓글 닉네임 새로고침 버튼 추가 2026-06-17 15:38:20 +09:00
jwkim b62bedc665 feat: 댓글 익명화 + 전 경기 적용
- 이메일/투표 게이트 제거 → 완전 익명
- 세션 단위 발급(sessionStorage 캐싱) — 탭 닫으면/시크릿이면 새 닉
2026-06-17 14:47:26 +09:00
jwkim 8a67094510 한국 멕시코 경기 댓글 기능 추가 2026-06-17 11:22:29 +09:00
jwkim 7625db36a0 API-Football 데이터 수집 로직 변경 2026-06-16 09:31:29 +09:00
jwkim 8140cd9e02 모바일 카톡 인앱 브라우저에서 공유링크 안 열리는 문제 해결 2026-06-16 08:48:12 +09:00
jwkim 48885ec80e remove: 경기 전용 비주얼 배너(한국-멕시코) 제거 2026-06-15 17:29:13 +09:00
jwkim 65e7c7571c 한국-멕시코전 전용 공유 카드 + 앱 배너 이미지 2026-06-15 17:22:38 +09:00
jwkim dc262009f9 Speed up football refresh (batch 24) + skip caching on API errors 2026-06-15 16:08:30 +09:00
jwkim 4246ad6936 Add data-driven AI predictions via API-Football
- football_data.py: 수집·캐싱·데이터블록 조립 (48팀 ID/FIFA랭킹)
- FootballCache 테이블: 폼·H2H·스쿼드 캐시 (외부 DB)
- 프롬프트에 랭킹·폼·H2H·스쿼드·WC실제결과 주입
- 키 없으면 기존(이름만) 동작 폴백, 무료 한도 점진 수집
2026-06-15 15:49:34 +09:00
jwkim 356706e1b4 Update OG/Twitter share card title 2026-06-15 11:59:34 +09:00
jwkim a031d60f3a Update OG/Twitter share card title 2026-06-15 11:51:23 +09:00
jwkim 6765e12054 Email autocomplete 2026-06-15 11:37:39 +09:00
jwkim 4a0188a443 Vote lock 5min + email autocomplete + detail-page UI tweaks 2026-06-15 11:28:41 +09:00
hbyang c77d014a01 Fix auto-settle for non-Group-A: map results by TLA, not full name
_results_football_data resolved team codes via code_for(full name), which
only covered Group A teams, so FINISHED matches in other groups (e.g.
Canada vs Bosnia-Herzegovina) were silently dropped and never settled.
Use tla -> code_for_tla (same as schedule ingestion; covers all 48), with
full-name fallback. Verified: source FINISHED 2 -> 3, CAN-BIH settles 1-1.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 10:58:33 +09:00
hbyang 1d406f6a4e Diversify AI predictions via per-model analyst personas
GPT (data-driven), Claude (tactical/upset-aware), Gemini (attacking-minded)
each get a distinct perspective so the 3 picks genuinely diverge instead of
producing identical scorelines. Honest: still each model's own judgment.
Finished matches are untouched (generation filters result_outcome IS NULL).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 17:33:59 +09:00
hbyang 0f055dace1 Voting opens at D-5 (120h before kickoff), was D-2
vote_open_hours_before 48 → 120. opensAt is recomputed on schedule sync,
so existing matches shift to the wider window on next worker run. AI 30h
lookahead is relative to opensAt, so pre-fill-before-open still holds.

NOTE for deploy: set VOTE_OPEN_HOURS_BEFORE=120 in server .env (an existing
48 there would override the new default).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 17:24:29 +09:00
hbyang 3bcc47c0e8 Schedule chips: horizontal scroll with edge arrows (PC navigable)
Replace hidden-scrollbar row (inaccessible on desktop without touch) with
a ChipScroller: single-row scroll + left/right arrow buttons that auto-hide
at each end and a bg fade. Resets to start on tab switch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 17:00:24 +09:00
hbyang 955ffae4cf 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>
2026-06-12 16:43:28 +09:00
hbyang deb1332440 Load all 12 groups' schedule (72 matches) + Naver-style schedule UI
Backend
- teams_data.py: 48-team data (ko/short/en), TLA→FIFA code remap
- config: schedule_all_groups, featured_group("A") — only featured group is votable/AI-predicted
- schedule_fetch: fetch all GROUP_STAGE matches from football-data, KST serialize
- schedule_sync: ingest all groups, unordered-pair match to avoid Group A dup, derive votable from group
- worker: AI generation limited to featured group; settle still covers all
- domain/predictions: is_votable() + MatchOut.votable; reject non-votable submits with 403 MATCH_NOT_VOTABLE

Frontend
- types: Match.votable
- ScheduleBoard: Naver-style date/group tabs + chips; votable(A) cards link to detail with AI split + 참여수, others display-only

Verified: 72 matches (12×6), Group A not duplicated, votable A=6/others=66; A submit 200, B submit 403

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 14:56:24 +09:00
hbyang c9244bc42d feat(predictions): 이메일도 중복 투표 방지 (이메일 우선 식별)
같은 이메일은 같은 경기에 1픽만 — 다른 기기에서 같은 이메일로 제출 시
새 픽 추가 대신 기존 픽 수정 + crowd 보정. 이메일은 소문자 정규화 저장.
모델에 (match_id, email) 유니크 제약 추가(신규 DB 적용, 기존 테이블은 앱 로직 보장).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 10:51:42 +09:00
hbyang 86290a7c69 feat(ui): AI 결과 배지 3단계 — 정확/적중/빗나감
스코어까지 맞으면 '정확 ✓'(강조), 승패만 맞으면 '적중 ✓', 그 외 '빗나감'.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 10:25:56 +09:00
hbyang 7a2affe10a feat(settle): 킥오프+3h 대기 제거 — 소스가 FINISHED 주면 즉시 정산
settle 게이트를 '킥오프 지남'으로 변경. football-data가 FINISHED 보고 시
다음 폴링(최대 5분) 내 자동 종료·채점·메일. 경기 중(IN_PLAY)엔 자동 스킵.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 10:25:56 +09:00
hbyang 54ed8bf10d feat(settle): 결과 소스를 일정 소스와 분리(RESULT_SOURCE) + 순서 무관 매칭
- RESULT_SOURCE(비우면 SCHEDULE_SOURCE) 추가 — 일정=openfootball, 결과=football-data 가능
- fetch_results 가 result_source 사용
- 자동 정산 매칭을 홈/원정 순서 무관하게 보강(소스 순서 달라도 스코어 정합)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 09:41:36 +09:00
hbyang 140e15fb9f feat(stats): 일별 방문자 집계 추가
page_visits 테이블((visit_date, device_id) 유니크) — 하루 1기기 1회 집계.
POST /api/visit(접속 기록), GET /api/admin/visits(일별 순수 방문자, Bearer).
프론트는 App 마운트 시 1회 recordVisit() 호출.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 17:31:23 +09:00
hbyang 51352c7c5c feat(ui): 100만원 챌린지 룰 설명 모달 추가
'100만 원에 도전하기' 버튼 클릭 시 모달 표시 — 배점표(정확5/근접3/승패2/부분1/빗나감0),
누적 1위 상금, 이메일 기준 참여·집계 안내. KO/EN 지원.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 17:22:02 +09:00
hbyang d8db7ed0f4 perf(ai): 자동 생성은 비어있는 예측만 채우도록(기존 보존)
generate_ai_predictions(only_missing=True 기본): 이미 있는 (경기×모델)
예측은 보존하고 누락분만 생성 — 매일/기동/새 경기 시 기존 데이터 불변,
API 비용↓, 실패했던 모델만 자동 보충. 수동 재생성 스크립트는 강제 전체(only_missing=False).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 16:17:12 +09:00
hbyang 4244518ffd feat(worker): 경기 결과 자동 정산 + '맞춘 사람만' 결과 메일
- 킥오프+result_settle_hours 경과 경기를 외부 스코어로 자동 채점(settle_matches)
- schedule_fetch.fetch_results: openfootball/football-data 확정 스코어 수집
- 결과 메일을 승패 적중자에게만 발송하는 옵션(result_email_correct_only)
- 스케줄러에 settle 잡 추가 + 기동 시 1회 밀린 경기 정산

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 14:25:23 +09:00