diff --git a/backend/app/generator.py b/backend/app/generator.py index 623bccb..bf14c93 100644 --- a/backend/app/generator.py +++ b/backend/app/generator.py @@ -4,7 +4,7 @@ from typing import Dict, Any, List, Optional from .db import _conn, save_recommendation_dedup, get_latest_draw, get_all_draw_numbers from .recommender import recommend_numbers -from .main import calc_metrics, calc_recent_overlap # main에 있는 헬퍼 재사용(순환참조 주의 필요 -> 사실 헬퍼는 utils로 빼는게 좋으나 일단 진행) +from .utils import calc_metrics, calc_recent_overlap # 순환 참조 방지를 위해 main.py의 calc_metrics 등을 utils.py가 아닌 여기서 재정의하거나 # main.py에서 generator를 import할 때 함수 내부에서 하도록 처리. diff --git a/backend/app/main.py b/backend/app/main.py index fbd5bb8..f6813cf 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -12,7 +12,9 @@ from .db import ( from .recommender import recommend_numbers from .collector import sync_latest, sync_ensure_all from .generator import generate_smart_recommendations +from .generator import generate_smart_recommendations from .checker import check_results_for_draw +from .utils import calc_metrics, calc_recent_overlap app = FastAPI() scheduler = BackgroundScheduler(timezone=os.getenv("TZ", "Asia/Seoul")) @@ -20,64 +22,6 @@ scheduler = BackgroundScheduler(timezone=os.getenv("TZ", "Asia/Seoul")) ALL_URL = os.getenv("LOTTO_ALL_URL", "https://smok95.github.io/lotto/results/all.json") LATEST_URL = os.getenv("LOTTO_LATEST_URL", "https://smok95.github.io/lotto/results/latest.json") -def calc_metrics(numbers: List[int]) -> Dict[str, Any]: - nums = sorted(numbers) - s = sum(nums) - odd = sum(1 for x in nums if x % 2 == 1) - even = len(nums) - odd - mn, mx = nums[0], nums[-1] - rng = mx - mn - - # 1-10, 11-20, 21-30, 31-40, 41-45 - buckets = { - "1-10": 0, - "11-20": 0, - "21-30": 0, - "31-40": 0, - "41-45": 0, - } - for x in nums: - if 1 <= x <= 10: - buckets["1-10"] += 1 - elif 11 <= x <= 20: - buckets["11-20"] += 1 - elif 21 <= x <= 30: - buckets["21-30"] += 1 - elif 31 <= x <= 40: - buckets["31-40"] += 1 - else: - buckets["41-45"] += 1 - - return { - "sum": s, - "odd": odd, - "even": even, - "min": mn, - "max": mx, - "range": rng, - "buckets": buckets, - } - -def calc_recent_overlap(numbers: List[int], draws: List[Tuple[int, List[int]]], last_k: int) -> Dict[str, Any]: - """ - draws: [(drw_no, [n1..n6]), ...] 오름차순 - last_k: 최근 k회 기준 중복 - """ - if last_k <= 0: - return {"last_k": 0, "repeats": 0, "repeated_numbers": []} - - recent = draws[-last_k:] if len(draws) >= last_k else draws - recent_set = set() - for _, nums in recent: - recent_set.update(nums) - - repeated = sorted(set(numbers) & recent_set) - return { - "last_k": len(recent), - "repeats": len(repeated), - "repeated_numbers": repeated, - } - @app.on_event("startup") def on_startup(): init_db() diff --git a/backend/app/utils.py b/backend/app/utils.py new file mode 100644 index 0000000..07ddd98 --- /dev/null +++ b/backend/app/utils.py @@ -0,0 +1,59 @@ +from typing import List, Dict, Any, Tuple + +def calc_metrics(numbers: List[int]) -> Dict[str, Any]: + nums = sorted(numbers) + s = sum(nums) + odd = sum(1 for x in nums if x % 2 == 1) + even = len(nums) - odd + mn, mx = nums[0], nums[-1] + rng = mx - mn + + # 1-10, 11-20, 21-30, 31-40, 41-45 + buckets = { + "1-10": 0, + "11-20": 0, + "21-30": 0, + "31-40": 0, + "41-45": 0, + } + for x in nums: + if 1 <= x <= 10: + buckets["1-10"] += 1 + elif 11 <= x <= 20: + buckets["11-20"] += 1 + elif 21 <= x <= 30: + buckets["21-30"] += 1 + elif 31 <= x <= 40: + buckets["31-40"] += 1 + else: + buckets["41-45"] += 1 + + return { + "sum": s, + "odd": odd, + "even": even, + "min": mn, + "max": mx, + "range": rng, + "buckets": buckets, + } + +def calc_recent_overlap(numbers: List[int], draws: List[Tuple[int, List[int]]], last_k: int) -> Dict[str, Any]: + """ + draws: [(drw_no, [n1..n6]), ...] 오름차순 + last_k: 최근 k회 기준 중복 + """ + if last_k <= 0: + return {"last_k": 0, "repeats": 0, "repeated_numbers": []} + + recent = draws[-last_k:] if len(draws) >= last_k else draws + recent_set = set() + for _, nums in recent: + recent_set.update(nums) + + repeated = sorted(set(numbers) & recent_set) + return { + "last_k": len(recent), + "repeats": len(repeated), + "repeated_numbers": repeated, + }