Files
web-page-backend/backend/app/purchase_manager.py
gahusb 598adcbeb5 fix(lotto-lab): 코드 리뷰 이슈 수정 — update_purchase JSON 직렬화, EMA 피드백 루프 연결
- update_purchase에서 numbers/is_real 타입 변환 추가 (런타임 에러 방지)
- purchase_manager에서 evolve_after_check 호출하여 EMA 피드백 루프 활성화
- checker.py 중복 recalculate_weights 호출 제거

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 21:25:27 +09:00

100 lines
3.1 KiB
Python

"""
구매 이력 관리 + 결과 체크 모듈.
- check_purchases_for_draw(): 특정 회차 구매 건들의 결과를 자동 체크
- 체커의 _calc_rank 재사용
- 결과 체크 후 strategy_performance 자동 갱신
"""
import logging
from .db import (
get_draw, get_purchases, update_purchase_results,
upsert_strategy_performance,
)
from .checker import _calc_rank
logger = logging.getLogger("lotto-backend")
RANK_PRIZE = {1: 0, 2: 0, 3: 1_500_000, 4: 50_000, 5: 5_000}
def check_purchases_for_draw(drw_no: int) -> int:
"""
특정 회차 결과로 해당 회차 구매 건들을 채점한다.
Returns: 채점한 구매 건 수
"""
win_row = get_draw(drw_no)
if not win_row:
return 0
win_nums = [win_row["n1"], win_row["n2"], win_row["n3"],
win_row["n4"], win_row["n5"], win_row["n6"]]
bonus = win_row["bonus"]
unchecked = get_purchases(draw_no=drw_no, checked=False)
strategy_agg = {}
count = 0
for purchase in unchecked:
numbers_list = purchase["numbers"]
if not numbers_list:
continue
results = []
for nums in numbers_list:
rank, correct, has_bonus = _calc_rank(nums, win_nums, bonus)
prize = RANK_PRIZE.get(rank, 0)
results.append({
"numbers": nums,
"rank": rank,
"correct": correct,
"has_bonus": has_bonus,
"prize": prize,
})
total_prize = sum(r["prize"] for r in results)
update_purchase_results(purchase["id"], results, total_prize)
strat = purchase["source_strategy"]
if strat not in strategy_agg:
strategy_agg[strat] = {
"sets_count": 0,
"total_correct": 0,
"max_correct": 0,
"prize_total": 0,
"scores": [],
"_results": [],
}
agg = strategy_agg[strat]
agg["_results"].extend(results)
for r in results:
agg["sets_count"] += 1
agg["total_correct"] += r["correct"]
agg["max_correct"] = max(agg["max_correct"], r["correct"])
agg["prize_total"] += r["prize"]
agg["scores"].append(r["correct"] / 6.0)
count += 1
for strat, agg in strategy_agg.items():
avg_score = sum(agg["scores"]) / len(agg["scores"]) if agg["scores"] else 0.0
upsert_strategy_performance(
strategy=strat,
draw_no=drw_no,
sets_count=agg["sets_count"],
total_correct=agg["total_correct"],
max_correct=agg["max_correct"],
prize_total=agg["prize_total"],
avg_score=round(avg_score, 4),
)
# EMA 피드백 루프: 전략 가중치 진화
try:
from .strategy_evolver import evolve_after_check
evolve_after_check(strat, drw_no, agg["_results"])
except Exception:
logger.debug(f"[purchase_manager] evolve_after_check 건너뜀: {strat}")
logger.info(f"[purchase_manager] {drw_no}회차 구매 {count}건 체크 완료")
return count