From e72a52a950c3f6516ac93a05f40450535a46de5c Mon Sep 17 00:00:00 2001 From: gahusb Date: Wed, 20 May 2026 08:21:48 +0900 Subject: [PATCH] =?UTF-8?q?feat(lotto):=20/api/lotto/best=EC=97=90=205?= =?UTF-8?q?=EC=A2=85=20=EC=A0=90=EC=88=98=20array=20=EB=85=B8=EC=B6=9C=20(?= =?UTF-8?q?agent-office=20sim=5Fconsensus=20=EC=9E=85=EB=A0=A5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- lotto/app/db.py | 39 +++++++++++++++++++++++++++++---------- lotto/app/main.py | 1 + 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/lotto/app/db.py b/lotto/app/db.py index ae9f678..8862309 100644 --- a/lotto/app/db.py +++ b/lotto/app/db.py @@ -645,30 +645,49 @@ def replace_best_picks( def get_best_picks(limit: int = 20) -> List[Dict[str, Any]]: - """현재 활성화된 best_picks 조회 (점수 내림차순)""" + """현재 활성화된 best_picks 조회 (점수 내림차순). + + simulation_candidates와 LEFT JOIN하여 5종 점수 배열(scores)을 포함. + 매칭 키: sc.run_id = bp.source_run_id AND sc.numbers = bp.numbers + LEFT JOIN 미매칭(NULL) 시 scores는 [0.0, 0.0, 0.0, 0.0, 0.0] 반환. + """ with _conn() as conn: rows = conn.execute( """ - SELECT id, numbers, score_total, rank_in_run, source_run_id, based_on_draw, created_at - FROM best_picks - WHERE is_active = 1 - ORDER BY score_total DESC + SELECT bp.id, bp.numbers, bp.score_total, bp.rank_in_run, + bp.source_run_id, bp.based_on_draw, bp.created_at, + sc.score_frequency, sc.score_fingerprint, + sc.score_gap, sc.score_cooccur, sc.score_diversity + FROM best_picks bp + LEFT JOIN simulation_candidates sc + ON sc.run_id = bp.source_run_id + AND sc.numbers = bp.numbers + WHERE bp.is_active = 1 + ORDER BY bp.score_total DESC LIMIT ? """, (limit,), ).fetchall() - return [ - { + result = [] + for r in rows: + scores = [ + float(r["score_frequency"] or 0.0), + float(r["score_fingerprint"] or 0.0), + float(r["score_gap"] or 0.0), + float(r["score_cooccur"] or 0.0), + float(r["score_diversity"] or 0.0), + ] + result.append({ "id": int(r["id"]), "numbers": json.loads(r["numbers"]), "score_total": r["score_total"], + "scores": scores, "rank_in_run": r["rank_in_run"], "source_run_id": r["source_run_id"], "based_on_draw": r["based_on_draw"], "created_at": r["created_at"], - } - for r in rows - ] + }) + return result def get_simulation_runs(limit: int = 10) -> List[Dict[str, Any]]: diff --git a/lotto/app/main.py b/lotto/app/main.py index 4d8505d..7d2a581 100644 --- a/lotto/app/main.py +++ b/lotto/app/main.py @@ -435,6 +435,7 @@ def api_best_picks(limit: int = 20): "rank": p["rank_in_run"], "numbers": nums, "score_total": p["score_total"], + "scores": p["scores"], "based_on_draw": p["based_on_draw"], "simulation_run_id": p["source_run_id"], "created_at": p["created_at"],