refactor: extract utils to fix circular import and enable smart generator
This commit is contained in:
@@ -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 .db import _conn, save_recommendation_dedup, get_latest_draw, get_all_draw_numbers
|
||||||
from .recommender import recommend_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의 calc_metrics 등을 utils.py가 아닌 여기서 재정의하거나
|
||||||
# main.py에서 generator를 import할 때 함수 내부에서 하도록 처리.
|
# main.py에서 generator를 import할 때 함수 내부에서 하도록 처리.
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ from .db import (
|
|||||||
from .recommender import recommend_numbers
|
from .recommender import recommend_numbers
|
||||||
from .collector import sync_latest, sync_ensure_all
|
from .collector import sync_latest, sync_ensure_all
|
||||||
from .generator import generate_smart_recommendations
|
from .generator import generate_smart_recommendations
|
||||||
|
from .generator import 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
|
||||||
|
|
||||||
app = FastAPI()
|
app = FastAPI()
|
||||||
scheduler = BackgroundScheduler(timezone=os.getenv("TZ", "Asia/Seoul"))
|
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")
|
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")
|
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")
|
@app.on_event("startup")
|
||||||
def on_startup():
|
def on_startup():
|
||||||
init_db()
|
init_db()
|
||||||
|
|||||||
59
backend/app/utils.py
Normal file
59
backend/app/utils.py
Normal file
@@ -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,
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user