lotto-lab: 구매/전략/스마트추천 API 엔드포인트 추가

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-06 21:19:28 +09:00
parent 28e3af12ec
commit 7eda717326

View File

@@ -27,6 +27,8 @@ from .db import (
save_weekly_report, get_weekly_report_list, get_weekly_report, save_weekly_report, get_weekly_report_list, get_weekly_report,
# Phase 2: 개인 패턴 분석 # Phase 2: 개인 패턴 분석
get_all_recommendation_numbers, get_all_recommendation_numbers,
# Phase 3: 전략 관련
get_strategy_performance as db_get_strategy_performance,
) )
from .recommender import recommend_numbers, recommend_with_heatmap from .recommender import recommend_numbers, recommend_with_heatmap
from .collector import sync_latest, sync_ensure_all from .collector import sync_latest, sync_ensure_all
@@ -34,6 +36,11 @@ from .generator import run_simulation, generate_smart_recommendations
from .checker import check_results_for_draw from .checker import check_results_for_draw
from .utils import calc_metrics, calc_recent_overlap from .utils import calc_metrics, calc_recent_overlap
from .analyzer import get_statistical_report, generate_weekly_report, analyze_personal_patterns, generate_combined_recommendation from .analyzer import get_statistical_report, generate_weekly_report, analyze_personal_patterns, generate_combined_recommendation
from .purchase_manager import check_purchases_for_draw
from .strategy_evolver import (
get_weights_with_trend, recalculate_weights,
generate_smart_recommendation,
)
app = FastAPI() app = FastAPI()
scheduler = BackgroundScheduler(timezone=os.getenv("TZ", "Asia/Seoul")) scheduler = BackgroundScheduler(timezone=os.getenv("TZ", "Asia/Seoul"))
@@ -257,6 +264,10 @@ class PurchaseCreate(BaseModel):
sets: int = 1 sets: int = 1
prize: int = 0 prize: int = 0
note: str = "" note: str = ""
numbers: List[List[int]] = []
is_real: bool = True
source_strategy: str = "manual"
source_detail: dict = {}
class PurchaseUpdate(BaseModel): class PurchaseUpdate(BaseModel):
@@ -265,6 +276,9 @@ class PurchaseUpdate(BaseModel):
sets: Optional[int] = None sets: Optional[int] = None
prize: Optional[int] = None prize: Optional[int] = None
note: Optional[str] = None note: Optional[str] = None
numbers: Optional[List[List[int]]] = None
is_real: Optional[bool] = None
source_strategy: Optional[str] = None
@app.get("/api/lotto/purchase/stats") @app.get("/api/lotto/purchase/stats")
@@ -274,15 +288,28 @@ def api_purchase_stats():
@app.get("/api/lotto/purchase") @app.get("/api/lotto/purchase")
def api_purchase_list(draw_no: Optional[int] = None, days: Optional[int] = None): def api_purchase_list(draw_no: Optional[int] = None, days: Optional[int] = None,
"""구매 이력 조회 (draw_no, days 필터 선택)""" is_real: Optional[bool] = None, strategy: Optional[str] = None):
return {"records": get_purchases(draw_no=draw_no, days=days)} """구매 이력 조회 (필터: draw_no, days, is_real, strategy)"""
return {"records": get_purchases(draw_no=draw_no, days=days, is_real=is_real, strategy=strategy)}
@app.post("/api/lotto/purchase", status_code=201) @app.post("/api/lotto/purchase", status_code=201)
def api_purchase_create(body: PurchaseCreate): def api_purchase_create(body: PurchaseCreate):
"""구매 이력 추가""" """구매 이력 추가 (실제/가상)"""
return add_purchase(body.draw_no, body.amount, body.sets, body.prize, body.note) sets = body.sets if body.sets > 0 else max(len(body.numbers), 1)
amount = body.amount if body.amount > 0 else sets * 1000
return add_purchase(
draw_no=body.draw_no,
amount=amount,
sets=sets,
prize=body.prize,
note=body.note,
numbers=body.numbers,
is_real=body.is_real,
source_strategy=body.source_strategy,
source_detail=body.source_detail,
)
@app.put("/api/lotto/purchase/{purchase_id}") @app.put("/api/lotto/purchase/{purchase_id}")
@@ -302,6 +329,40 @@ def api_purchase_delete(purchase_id: int):
return {"ok": True} return {"ok": True}
# ── 전략 진화 API ──────────────────────────────────────────────────────────
@app.get("/api/lotto/strategy/weights")
def api_strategy_weights():
"""현재 전략별 가중치 + 성과 요약 + trend"""
return get_weights_with_trend()
@app.get("/api/lotto/strategy/performance")
def api_strategy_performance(strategy: Optional[str] = None, days: Optional[int] = None):
"""전략별 회차 성과 이력 (차트용)"""
rows = db_get_strategy_performance(strategy=strategy, days=days)
return {"records": rows}
@app.post("/api/lotto/strategy/evolve")
def api_strategy_evolve():
"""수동 가중치 재계산 트리거"""
new_weights = recalculate_weights()
return {"ok": True, "weights": new_weights}
# ── 스마트 추천 API ────────────────────────────────────────────────────────
@app.get("/api/lotto/recommend/smart")
def api_recommend_smart(sets: int = 5):
"""전략 가중치 기반 메타 전략 추천"""
sets = max(1, min(sets, 10))
result = generate_smart_recommendation(sets=sets)
if "error" in result:
raise HTTPException(status_code=500, detail=result["error"])
return result
# ── 통계 분석 리포트 ──────────────────────────────────────────────────────── # ── 통계 분석 리포트 ────────────────────────────────────────────────────────
@app.get("/api/lotto/analysis") @app.get("/api/lotto/analysis")
def api_analysis(): def api_analysis():