o2o-triple-pick/backend/app/scoring.py

43 lines
1.5 KiB
Python

"""채점 로직 — docs/SCORING.md (SSOT) 그대로 구현.
배점: 정확 스코어 5 · 근접(승패+득실차) 3 · 승패 2 · 부분(한 팀 득점 일치) 1 · 빗나감 0.
단조 증가(정확>근접>승패>부분>빗나감). 배점 수치는 SCORE 상수만 교체하면 됨.
"""
from __future__ import annotations
# 팀 확정 후 이 상수만 교체 (docs/SCORING.md §2)
SCORE = {"EXACT": 5, "CLOSE": 3, "OUTCOME": 2, "PARTIAL": 1, "MISS": 0}
def outcome_of(score_a: int, score_b: int) -> str:
if score_a > score_b:
return "TEAM_A_WIN"
if score_a < score_b:
return "TEAM_B_WIN"
return "DRAW"
def score_prediction(
pick_a: int, pick_b: int, result_a: int, result_b: int
) -> int:
"""내 예측 vs 실제 결과 → 적중 포인트 (결정론적)."""
if pick_a == result_a and pick_b == result_b:
return SCORE["EXACT"]
if outcome_of(pick_a, pick_b) == outcome_of(result_a, result_b):
if (pick_a - pick_b) == (result_a - result_b):
return SCORE["CLOSE"]
return SCORE["OUTCOME"]
if pick_a == result_a or pick_b == result_b:
return SCORE["PARTIAL"]
return SCORE["MISS"]
# ── 자격 · 배제 (docs/SCORING.md §4, P1 구현) ──────────────────
STAFF_EMAILS: set[str] = set() # 운영진/임직원 블록리스트
STAFF_DOMAINS = ["o2o.kr", "aio2o.kr"]
def is_excluded(email: str) -> bool:
e = email.strip().lower()
return e in STAFF_EMAILS or any(e.endswith("@" + d) for d in STAFF_DOMAINS)