""" 구매 이력 관리 + 결과 체크 모듈. - 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 def get_recent_performance(limit: int = 3) -> list: """최근 N회차 내 구매 성과 요약. 없으면 빈 리스트.""" from . import db purchases = db.get_purchases(days=None) or [] by_draw: dict = {} for p in purchases: d = p.get("draw_no") if not d: continue by_draw.setdefault(d, {"draw_no": d, "purchased_sets": 0, "best_match": 0}) by_draw[d]["purchased_sets"] += int(p.get("sets") or 1) by_draw[d]["best_match"] = max(by_draw[d]["best_match"], int(p.get("correct_count") or 0)) return sorted(by_draw.values(), key=lambda x: -x["draw_no"])[:limit]