Files
2026-05-23 12:58:57 -04:00

109 lines
3.2 KiB
Python

"""
core/checker.py
---------------
Ticket checker — compare a user-supplied ticket against all historical draws.
Returns every draw where at least one number (main or bonus) matched,
sorted by match quality descending.
Prize tiers follow Powerball / Mega Millions conventions:
Jackpot 5 main + bonus
Match 5 5 main, no bonus
Match 4 + Bonus 4 main + bonus
Match 4 4 main
Match 3 + Bonus 3 main + bonus
Match 3 3 main
Match 2 + Bonus 2 main + bonus
Match 1 + Bonus 1 main + bonus
Bonus Only 0 main + bonus
"""
from db.models import get_all_draws_numbers, get_game_by_id
# (required_main_matches, requires_bonus_match, tier_label)
_TIERS = [
(5, True, "Jackpot"),
(5, False, "Match 5"),
(4, True, "Match 4 + Bonus"),
(4, False, "Match 4"),
(3, True, "Match 3 + Bonus"),
(3, False, "Match 3"),
(2, True, "Match 2 + Bonus"),
(1, True, "Match 1 + Bonus"),
(0, True, "Bonus Only"),
]
def prize_tier(main_matches: int, bonus_match: bool) -> str:
"""Return the prize tier label for a given match result."""
for req_main, req_bonus, label in _TIERS:
if main_matches == req_main:
if req_bonus and not bonus_match:
continue
return label
return "No Prize"
def check_ticket(game_id: int, numbers: list[int],
bonus: int | None = None) -> list[dict]:
"""
Compare *numbers* (and optional *bonus*) against all draws for *game_id*.
Returns a list of dicts for draws with ≥ 1 matched number (main or bonus),
sorted by (main_matches DESC, bonus_match DESC, draw_date DESC).
Each dict contains:
draw_date str
draw_numbers list[int]
draw_bonus int | None
main_matches int
bonus_match bool
prize_tier str
"""
draws = get_all_draws_numbers(game_id)
ticket_set = set(numbers)
results = []
for draw in draws:
draw_set = set(draw["numbers"])
main_matches = len(ticket_set & draw_set)
bonus_match = (
bonus is not None
and draw["bonus"] is not None
and bonus == draw["bonus"]
)
if main_matches == 0 and not bonus_match:
continue
results.append({
"draw_date": draw["draw_date"],
"draw_numbers": draw["numbers"],
"draw_bonus": draw["bonus"],
"main_matches": main_matches,
"bonus_match": bonus_match,
"prize_tier": prize_tier(main_matches, bonus_match),
})
results.sort(
key=lambda x: (x["main_matches"], x["bonus_match"], x["draw_date"]),
reverse=True,
)
return results
def parse_numbers(raw: str) -> list[int]:
"""
Parse a user-typed string of lottery numbers into a sorted list of ints.
Accepts space- or comma-separated input: '7 14 32 56 68' or '7,14,32,56,68'.
Raises ValueError if any token is not a positive integer.
"""
tokens = raw.replace(",", " ").split()
if not tokens:
raise ValueError("No numbers entered.")
nums = []
for t in tokens:
if not t.isdigit():
raise ValueError(f"'{t}' is not a valid number.")
nums.append(int(t))
return sorted(nums)