From 8dbb1abaeb37b6bf0170be7eacda7bc1b87f5e0a Mon Sep 17 00:00:00 2001 From: gahusb Date: Sun, 31 May 2026 16:50:28 +0900 Subject: [PATCH] =?UTF-8?q?feat(lotto):=20=ED=8B=B0=EC=BC=93=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=203=EC=A0=84=EB=9E=B5=20(engine=5Fw/random=5Fnull/cov?= =?UTF-8?q?erage)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- lotto/tests/test_backtest.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/lotto/tests/test_backtest.py b/lotto/tests/test_backtest.py index 2b0a48a..5fb19f6 100644 --- a/lotto/tests/test_backtest.py +++ b/lotto/tests/test_backtest.py @@ -2,6 +2,17 @@ from app import backtest as bt from app.analyzer import build_analysis_cache, score_combination +def _toy_draws(n=120): + # 결정적 가짜 회차: 분석 캐시 구성용 (오름차순 (drw_no, [6 nums])) + import random as _r + _r.seed(1) + out = [] + for i in range(1, n + 1): + nums = sorted(_r.sample(range(1, 46), 6)) + out.append((i, nums)) + return out + + def test_grade_tickets_histogram_and_prizes(): winning6 = [1, 2, 3, 4, 5, 6] bonus = 7 @@ -23,3 +34,26 @@ def test_grade_tickets_histogram_and_prizes(): # 등수 매핑 헬퍼 prizes = bt.prize_counts(r) assert prizes == {"1st": 1, "2nd": 1, "3rd": 1, "4th": 1, "5th": 1} + + +def test_purchase_tickets_distinct_and_count(): + draws = _toy_draws() + cache = bt.build_analysis_cache(draws) + nw = bt.build_number_weights(cache) + pool = bt.generate_pool(cache, nw, n=2000, seed=7) + W = [0.25, 0.30, 0.20, 0.15, 0.10] + bought = bt.purchase_tickets(pool, cache, W, k=50) + assert len(bought) == 50 + assert len({tuple(t) for t in bought}) == 50 # distinct + # W로 랭킹된 상위 → 평균 분석치가 풀 평균보다 높아야 + avg_bought = sum(score_combination(t, cache, W)["score_total"] for t in bought) / 50 + assert avg_bought > 0 + + +def test_random_null_and_coverage_distinct(): + rnd = bt.random_null_tickets(k=50, seed=3) + assert len(rnd) == 50 and len({tuple(t) for t in rnd}) == 50 + cov = bt.coverage_tickets(k=9, seed=3) # 9장 = 54슬롯 ≥ 45번호 전수 커버 가능 + flat = {n for t in cov for n in t} + assert len(cov) == 9 and len({tuple(t) for t in cov}) == 9 + assert len(flat) >= 40 # 커버리지 전략은 번호를 넓게 퍼뜨림