feat(lotto): weekly_review 테이블 + CRUD 헬퍼
This commit is contained in:
105
lotto/app/db.py
105
lotto/app/db.py
@@ -259,6 +259,26 @@ def init_db() -> None:
|
||||
""")
|
||||
conn.execute("CREATE INDEX IF NOT EXISTS idx_briefings_draw ON lotto_briefings(draw_no DESC)")
|
||||
|
||||
# ── weekly_review 테이블 (큐레이터 자기 평가 + 사용자 패턴 갭) ────────
|
||||
conn.execute("""
|
||||
CREATE TABLE IF NOT EXISTS weekly_review (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
draw_no INTEGER UNIQUE NOT NULL,
|
||||
curator_avg_match REAL,
|
||||
curator_best_tier TEXT,
|
||||
curator_best_match INTEGER,
|
||||
curator_5plus_prizes INTEGER,
|
||||
user_avg_match REAL,
|
||||
user_best_match INTEGER,
|
||||
user_5plus_prizes INTEGER,
|
||||
user_pattern_summary TEXT,
|
||||
draw_pattern_summary TEXT,
|
||||
pattern_delta TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now','localtime'))
|
||||
)
|
||||
""")
|
||||
conn.execute("CREATE INDEX IF NOT EXISTS idx_review_draw ON weekly_review(draw_no DESC)")
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1052,3 +1072,88 @@ def get_curator_usage(days: int = 30) -> Dict[str, Any]:
|
||||
"avg_latency_ms": round(float(r["avg_latency"] or 0), 1),
|
||||
}
|
||||
|
||||
|
||||
def save_review(data: Dict[str, Any]) -> int:
|
||||
with _conn() as conn:
|
||||
cur = conn.execute(
|
||||
"""
|
||||
INSERT INTO weekly_review (
|
||||
draw_no,
|
||||
curator_avg_match, curator_best_tier, curator_best_match, curator_5plus_prizes,
|
||||
user_avg_match, user_best_match, user_5plus_prizes,
|
||||
user_pattern_summary, draw_pattern_summary, pattern_delta
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT(draw_no) DO UPDATE SET
|
||||
curator_avg_match=excluded.curator_avg_match,
|
||||
curator_best_tier=excluded.curator_best_tier,
|
||||
curator_best_match=excluded.curator_best_match,
|
||||
curator_5plus_prizes=excluded.curator_5plus_prizes,
|
||||
user_avg_match=excluded.user_avg_match,
|
||||
user_best_match=excluded.user_best_match,
|
||||
user_5plus_prizes=excluded.user_5plus_prizes,
|
||||
user_pattern_summary=excluded.user_pattern_summary,
|
||||
draw_pattern_summary=excluded.draw_pattern_summary,
|
||||
pattern_delta=excluded.pattern_delta
|
||||
""",
|
||||
(
|
||||
data["draw_no"],
|
||||
data.get("curator_avg_match"), data.get("curator_best_tier"),
|
||||
data.get("curator_best_match"), data.get("curator_5plus_prizes"),
|
||||
data.get("user_avg_match"), data.get("user_best_match"),
|
||||
data.get("user_5plus_prizes"),
|
||||
data.get("user_pattern_summary"), data.get("draw_pattern_summary"),
|
||||
data.get("pattern_delta"),
|
||||
),
|
||||
)
|
||||
return cur.lastrowid
|
||||
|
||||
|
||||
def _review_row(r) -> Optional[Dict[str, Any]]:
|
||||
if not r:
|
||||
return None
|
||||
return {
|
||||
"id": r["id"],
|
||||
"draw_no": r["draw_no"],
|
||||
"curator_avg_match": r["curator_avg_match"],
|
||||
"curator_best_tier": r["curator_best_tier"],
|
||||
"curator_best_match": r["curator_best_match"],
|
||||
"curator_5plus_prizes": r["curator_5plus_prizes"],
|
||||
"user_avg_match": r["user_avg_match"],
|
||||
"user_best_match": r["user_best_match"],
|
||||
"user_5plus_prizes": r["user_5plus_prizes"],
|
||||
"user_pattern_summary": r["user_pattern_summary"],
|
||||
"draw_pattern_summary": r["draw_pattern_summary"],
|
||||
"pattern_delta": r["pattern_delta"],
|
||||
"created_at": r["created_at"],
|
||||
}
|
||||
|
||||
|
||||
def get_review(draw_no: int) -> Optional[Dict[str, Any]]:
|
||||
with _conn() as conn:
|
||||
r = conn.execute("SELECT * FROM weekly_review WHERE draw_no=?", (draw_no,)).fetchone()
|
||||
return _review_row(r)
|
||||
|
||||
|
||||
def get_latest_review() -> Optional[Dict[str, Any]]:
|
||||
with _conn() as conn:
|
||||
r = conn.execute("SELECT * FROM weekly_review ORDER BY draw_no DESC LIMIT 1").fetchone()
|
||||
return _review_row(r)
|
||||
|
||||
|
||||
def get_reviews_range(start_drw: int, end_drw: int) -> List[Dict[str, Any]]:
|
||||
with _conn() as conn:
|
||||
rows = conn.execute(
|
||||
"SELECT * FROM weekly_review WHERE draw_no BETWEEN ? AND ? ORDER BY draw_no ASC",
|
||||
(start_drw, end_drw),
|
||||
).fetchall()
|
||||
return [_review_row(r) for r in rows]
|
||||
|
||||
|
||||
def list_reviews(limit: int = 10) -> List[Dict[str, Any]]:
|
||||
with _conn() as conn:
|
||||
rows = conn.execute(
|
||||
"SELECT * FROM weekly_review ORDER BY draw_no DESC LIMIT ?",
|
||||
(limit,),
|
||||
).fetchall()
|
||||
return [_review_row(r) for r in rows]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user