feat(curator): build_retrospective + lotto review service proxy

This commit is contained in:
2026-05-11 08:49:58 +09:00
parent 95c5dc4217
commit ff3134b838
3 changed files with 125 additions and 0 deletions

View File

@@ -0,0 +1,50 @@
"""큐레이션 직전 호출 — review 1건 + 추세 3건 → 컨텍스트 dict."""
import json
from typing import Optional, Dict, Any
from .. import service_proxy
def _detect_bias(reviews: list) -> str:
"""3주↑ 같은 방향 패턴 편향이 유지되면 한 줄로."""
deltas = [r.get("pattern_delta") or "" for r in reviews if r.get("pattern_delta")]
if len(deltas) < 2:
return ""
# 단순 휴리스틱 — 같은 키워드("저번호" 등)가 2회 이상이면 지속 편향
keywords = ["저번호", "고번호", "합계", "홀짝"]
persistent = []
for kw in keywords:
cnt = sum(1 for d in deltas if kw in d)
if cnt >= max(2, len(deltas) - 1):
persistent.append(kw)
return " · ".join(persistent)
async def build_retrospective(target_draw_no: int) -> Optional[Dict[str, Any]]:
"""target_draw_no(이번 주) 직전 회차의 review + 그 앞 3회 추세."""
last = await service_proxy.lotto_review_by_draw(target_draw_no - 1)
if not last:
return None
history = await service_proxy.lotto_reviews_history(limit=4)
# history 는 desc 정렬 → last 와 그 이전 3건 분리
others = [r for r in history if r["draw_no"] < target_draw_no - 1][:3]
series = [last] + others
cur_avgs = [r["curator_avg_match"] for r in series if r.get("curator_avg_match") is not None]
usr_avgs = [r["user_avg_match"] for r in series if r.get("user_avg_match") is not None]
return {
"last_draw": {
"draw_no": last["draw_no"],
"curator_avg": last.get("curator_avg_match"),
"curator_best_tier": last.get("curator_best_tier"),
"user_avg": last.get("user_avg_match"),
"user_5plus": last.get("user_5plus_prizes"),
"pattern_delta": last.get("pattern_delta") or "",
},
"trend_4w": {
"curator_avg_4w": round(sum(cur_avgs) / len(cur_avgs), 2) if cur_avgs else None,
"user_avg_4w": round(sum(usr_avgs) / len(usr_avgs), 2) if usr_avgs else None,
"user_persistent_bias": _detect_bias(series),
},
}