Reformat code to pythonic standards

This commit is contained in:
chris committed 2026-05-27 08:20:30 -04:00
1 parent ea62bdfc0b
commit b1732c07c5
5 files changed
+123 -51

No files matched your search

+3 -4
View File
@@ -1,6 +1,3 @@
import re
class InvalidStringException(Exception): class InvalidStringException(Exception):
"""Raised when a string cannot be converted to an integer.""" """Raised when a string cannot be converted to an integer."""
pass pass
@@ -25,4 +22,6 @@ def convert_string_to_integer(data: str) -> int | Exception:
else: else:
return int(data) return int(data)
except ValueError as exc: except ValueError as exc:
raise InvalidStringException("The string could not be converted to an integer.") from exc raise InvalidStringException(
"The string could not be converted to an integer.",
) from exc
+45 -21
View File
@@ -4,11 +4,12 @@
Utility functions for drawing data processing Utility functions for drawing data processing
""" """
import os import os
from datetime import datetime, timedelta from datetime import datetime, timedelta
from dotenv import load_dotenv from dotenv import load_dotenv
from data.database import PowerballDraw, MegaMillionsDraw, Table from data.database import MegaMillionsDraw, PowerballDraw, Table
load_dotenv() load_dotenv()
@@ -38,13 +39,17 @@ def check_table_name2(table_name: Table) -> dict | None:
return game_dict[table_name] if table_name in game_dict.keys() else None return game_dict[table_name] if table_name in game_dict.keys() else None
def get_next_draw_date(game: str | None, from_date: str | None = None) -> str | None: def get_next_draw_date(
game: str | None, from_date: str | None = None,
) -> str | None:
""" """
Gets the next drawing date from the current or specified date for the given game Gets the next drawing date from the current or specified date for the
given game
If the current date is the next drawing date, the current date is returned If the current date is the next drawing date, the current date is returned
:param game: megamillions or powerball :param game: megamillions or powerball
:param from_date: date to get next drawing date from, if omitted the current date is used :param from_date: date to get next drawing date from, if omitted the
current date is used
:return: next drawing date :return: next drawing date
Examples: Examples:
@@ -55,7 +60,7 @@ def get_next_draw_date(game: str | None, from_date: str | None = None) -> str |
""" """
target_days = { target_days = {
"powerball": [0, 2, 5], "powerball": [0, 2, 5],
"mega-millions": [1, 4] "mega-millions": [1, 4],
} }
return_date = None return_date = None
@@ -77,13 +82,18 @@ def get_next_draw_date(game: str | None, from_date: str | None = None) -> str |
return return_date.strftime(return_date_format) return return_date.strftime(return_date_format)
def get_previous_draw_date(game: str | None, from_date: str | None = None) -> str | None: def get_previous_draw_date(
game: str | None, from_date: str | None = None,
) -> str | None:
""" """
Gets the previous drawing date from the current or specified date for the given game Gets the previous drawing date from the current or specified date for the
If the current date is a drawing date, the next previous date will be returned given game
If the current date is a drawing date, the next previous date will be
returned
:param game: megamillions or powerball :param game: megamillions or powerball
:param from_date: date to get previous drawing date from, if omitted the current date is used :param from_date: date to get previous drawing date from, if omitted the
current date is used
:return: previous drawing date :return: previous drawing date
Examples: Examples:
@@ -94,7 +104,7 @@ def get_previous_draw_date(game: str | None, from_date: str | None = None) -> st
""" """
target_days = { target_days = {
"powerball": [0, 2, 5], "powerball": [0, 2, 5],
"mega-millions": [1, 4] "mega-millions": [1, 4],
} }
return_date = None return_date = None
@@ -110,7 +120,8 @@ def get_previous_draw_date(game: str | None, from_date: str | None = None) -> st
else: else:
return_date = datetime.strptime(from_date, return_date_format) return_date = datetime.strptime(from_date, return_date_format)
# to ensure the current date is not returned if it is a draw date, subtract a day first # to ensure the current date is not returned if it is a draw date,
# subtract a day first
return_date -= timedelta(days=1) return_date -= timedelta(days=1)
while return_date.weekday() not in target_days[game]: while return_date.weekday() not in target_days[game]:
@@ -126,32 +137,45 @@ def get_powerball_object(draw_date: str, draw_result: dict) -> PowerballDraw:
:return: PowerballDraw object :return: PowerballDraw object
Examples: Examples:
>>> get_powerball_object(draw_date='2026-02-28', draw_result={'main_balls': [6, 20, 35, 54, 65], 'powerball': 10, 'multiplier': 4}) >>> get_powerball_object(draw_date='2026-02-28', draw_result={
PowerballDraw(draw_date=datetime(2026, 2, 28), main_ball1=6, main_ball2=20, main_ball3=35, main_ball4=54, main_ball5=65, powerball=10, power_play=4) 'main_balls': [6, 20, 35, 54, 65], 'powerball': 10, 'multiplier': 4})
PowerballDraw(draw_date=datetime(2026, 2, 28), main_ball1=6,
main_ball2=20, main_ball3=35, main_ball4=54, main_ball5=65, powerball=10,
power_play=4)
""" """
draw_date = datetime.strptime(draw_date, '%Y-%m-%d').date() draw_date = datetime.strptime(draw_date, '%Y-%m-%d').date()
mb1, mb2, mb3, mb4, mb5 = draw_result['main_balls'] mb1, mb2, mb3, mb4, mb5 = draw_result['main_balls']
pb = draw_result['powerball'] pb = draw_result['powerball']
power_play = draw_result['multiplier'] power_play = draw_result['multiplier']
return PowerballDraw(draw_date=draw_date,main_ball1=mb1, main_ball2=mb2, main_ball3=mb3, main_ball4=mb4, return PowerballDraw(
main_ball5=mb5, powerball=pb, power_play=power_play) draw_date=draw_date, main_ball1=mb1, main_ball2=mb2, main_ball3=mb3,
main_ball4=mb4,
main_ball5=mb5, powerball=pb, power_play=power_play,
)
def get_mega_millions_object(draw_date: str, draw_result: dict) -> MegaMillionsDraw: def get_mega_millions_object(
draw_date: str, draw_result: dict,
) -> MegaMillionsDraw:
""" """
:param draw_date: date for the drawing data :param draw_date: date for the drawing data
:param draw_result: drawing results for the draw_date :param draw_result: drawing results for the draw_date
:return: MegaMillionsDraw object :return: MegaMillionsDraw object
Examples: Examples:
>>> get_mega_millions_object(draw_date='2010-02-02', draw_result={'main_balls': [6, 7, 26, 27, 49], 'mega-ball': 9, 'megaplier': 4}) >>> get_mega_millions_object(draw_date='2010-02-02', draw_result={
MegaMillionsDraw(draw_date=date, main_ball1=6, main_ball2=7, main_ball3=26, main_ball4=27, main_ball5=49, mega_ball=9, megaplier=4) 'main_balls': [6, 7, 26, 27, 49], 'mega-ball': 9, 'megaplier': 4})
MegaMillionsDraw(draw_date=date, main_ball1=6, main_ball2=7,
main_ball3=26, main_ball4=27, main_ball5=49, mega_ball=9, megaplier=4)
""" """
draw_date = datetime.strptime(draw_date, '%Y-%m-%d').date() draw_date = datetime.strptime(draw_date, '%Y-%m-%d').date()
mb1, mb2, mb3, mb4, mb5 = draw_result['main_balls'] mb1, mb2, mb3, mb4, mb5 = draw_result['main_balls']
mega = draw_result['mega-ball'] mega = draw_result['mega-ball']
megaplier = draw_result['multiplier'] megaplier = draw_result['multiplier']
return MegaMillionsDraw(draw_date=draw_date, main_ball1=mb1, main_ball2=mb2, main_ball3=mb3, main_ball4=mb4, return MegaMillionsDraw(
main_ball5=mb5, mega_ball=mega, megaplier=megaplier) draw_date=draw_date, main_ball1=mb1, main_ball2=mb2, main_ball3=mb3,
main_ball4=mb4,
main_ball5=mb5, mega_ball=mega, megaplier=megaplier,
)
+3
View File
@@ -4,10 +4,13 @@
Utility function for loading project environment variables Utility function for loading project environment variables
""" """
import os import os
from dotenv import load_dotenv from dotenv import load_dotenv
load_dotenv() load_dotenv()
def load_environment_variables() -> dict: def load_environment_variables() -> dict:
return { return {
k: v for k, v in os.environ.items() k: v for k, v in os.environ.items()
+29 -12
View File
@@ -9,15 +9,18 @@ from math import comb
def calculate_odds(pool_size: int, draw_count: int) -> int: def calculate_odds(pool_size: int, draw_count: int) -> int:
""" """
Calculate the total number of possible combinations in a set of numbers with a specific draw count. Calculate the total number of possible combinations in a set of numbers
with a specific draw count.
:param pool_size: Total count of numbers in the pool :param pool_size: Total count of numbers in the pool
:param draw_count: The count of numbers to draw from the pool :param draw_count: The count of numbers to draw from the pool
:return: The total number of possible combinations :return: The total number of possible combinations
Example: Example:
If a lottery game has a main ball pool of 49 numbers from which 5 numbers are drawn and a pool of If a lottery game has a main ball pool of 49 numbers from which 5
18 numbers from which 1 number is drawn (game ball), calculate the odds of winning that game. numbers are drawn and a pool of
18 numbers from which 1 number is drawn (game ball), calculate the
odds of winning that game.
>>> calculate_odds(pool_size=49, draw_count=5) >>> calculate_odds(pool_size=49, draw_count=5)
1906884 1906884
@@ -26,7 +29,10 @@ def calculate_odds(pool_size: int, draw_count: int) -> int:
""" """
if draw_count < 0 or draw_count > pool_size: if draw_count < 0 or draw_count > pool_size:
raise ValueError('Integer values must be positive and draw counts must be less than pool size.') raise ValueError(
'Integer values must be positive and draw counts must be less '
'than pool size.',
)
total_combinations = comb(pool_size, draw_count) total_combinations = comb(pool_size, draw_count)
return total_combinations return total_combinations
@@ -35,29 +41,40 @@ def get_odds_of_winning(
main_ball_draw_pool: int, main_ball_draw_pool: int,
main_ball_draw_count: int, main_ball_draw_count: int,
game_ball_draw_pool: int, game_ball_draw_pool: int,
game_ball_draw_count: int game_ball_draw_count: int,
) -> str: ) -> str:
""" """
Calculate the odds of winning a specific lottery game with one draw Calculate the odds of winning a specific lottery game with one draw
:param main_ball_draw_pool: Total count of numbers in the main ball pool :param main_ball_draw_pool: Total count of numbers in the main ball pool
:param main_ball_draw_count: The count of numbers to draw from the main ball pool :param main_ball_draw_count: The count of numbers to draw from the
main ball pool
:param game_ball_draw_pool: Total count of numbers in the game ball pool :param game_ball_draw_pool: Total count of numbers in the game ball pool
:param game_ball_draw_count: The count of numbers to draw from the game ball pool :param game_ball_draw_count: The count of numbers to draw from the
game ball pool
:return: The odds of winning a specific lottery game with one draw :return: The odds of winning a specific lottery game with one draw
Example: Example:
To calculate the odds of winning a lottery game with 5 numbers drawn from a main ball pool of 49 and To calculate the odds of winning a lottery game with 5 numbers
drawn from a main ball pool of 49 and
1 number drawn from a game ball pool of 19 numbers. 1 number drawn from a game ball pool of 19 numbers.
>>> get_odds_of_winning(main_ball_draw_pool=49, main_ball_draw_count=5, game_ball_draw_pool=18, game_ball_draw_count=1) >>> get_odds_of_winning(main_ball_draw_pool=49,
main_ball_draw_count=5, game_ball_draw_pool=18,
game_ball_draw_count=1)
'The odds of winning are 1 in 34,323,912' 'The odds of winning are 1 in 34,323,912'
""" """
if (main_ball_draw_count < 0 or main_ball_draw_count > main_ball_draw_pool or if (
game_ball_draw_count < 0 or game_ball_draw_count > game_ball_draw_pool): main_ball_draw_count < 0 or main_ball_draw_count >
raise ValueError('Integer values must be positive and draw counts must be less than pool size.') main_ball_draw_pool or
game_ball_draw_count < 0 or game_ball_draw_count >
game_ball_draw_pool):
raise ValueError(
'Integer values must be positive and draw counts must be less '
'than pool size.',
)
main_ball_odds = calculate_odds(main_ball_draw_pool, main_ball_draw_count) main_ball_odds = calculate_odds(main_ball_draw_pool, main_ball_draw_count)
game_ball_odds = calculate_odds(game_ball_draw_pool, game_ball_draw_count) game_ball_odds = calculate_odds(game_ball_draw_pool, game_ball_draw_count)
+43 -14
View File
@@ -4,19 +4,23 @@
Utility functions for scraping web data relative to selected games Utility functions for scraping web data relative to selected games
""" """
import httpx import httpx
from dateutil import parser, utils
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from dateutil import parser, utils
from util.environment import load_environment_variables from util.environment import load_environment_variables
project_variables: dict = load_environment_variables() project_variables: dict = load_environment_variables()
def scrape_game_history(game: str, year: int = utils.today().year) -> dict: def scrape_game_history(game: str, year: int = utils.today().year) -> dict:
""" """
Scrape game data from the url provided. This function requires specific environment variables be present Scrape game data from the url provided. This function requires
specific environment variables be present
in order to function properly. in order to function properly.
:param:game The target game to scrape. :param:game The target game to scrape.
:param:year The year to scrape. If no year is provided, scrapes games from the current year. :param:year The year to scrape. If no year is provided, scrapes
games from the current year.
:return: dict() :return: dict()
@@ -32,18 +36,37 @@ def scrape_game_history(game: str, year: int = utils.today().year) -> dict:
url = f"{project_variables['LP_BASE_SCRAPE_URL']}{game}/numbers/{year}" url = f"{project_variables['LP_BASE_SCRAPE_URL']}{game}/numbers/{year}"
page = httpx.get(url) page = httpx.get(url)
soup = BeautifulSoup(page.text, 'html.parser') soup = BeautifulSoup(page.text, 'html.parser')
results = soup.find_all(project_variables['LP_RESULT_CONTAINER'], class_=project_variables['LP_RESULT_CLASS']) results = soup.find_all(
project_variables['LP_RESULT_CONTAINER'],
class_=project_variables['LP_RESULT_CLASS'],
)
for result in results: for result in results:
pick5 = [] pick5 = []
draw_date = parser.parse(result.find(project_variables['LP_DRAW_DATE_CONTAINER'], draw_date = parser.parse(
class_=project_variables['LP_DRAW_DATE_CLASS']).text).date().strftime('%Y-%m-%d') result.find(
main_balls = result.find_all(project_variables['LP_BALL_CONTAINER'], class_=project_variables['LP_BALL_CLASS']) project_variables['LP_DRAW_DATE_CONTAINER'],
game_ball = result.find(project_variables['LP_BALL_CONTAINER'], class_=project_variables['LP_DRAW_DATE_CLASS'],
class_=[project_variables['LP_POWERBALL_CLASS'], project_variables['LP_MEGABALL_CLASS']]) ).text,
multiplier = result.find(project_variables['LP_BALL_CONTAINER'], ).date().strftime('%Y-%m-%d')
class_=[project_variables['LP_POWERBALL_MULTIPLIER_CLASS'], main_balls = result.find_all(
project_variables['LP_MEGA_MILLIONS_MULTIPLIER_CLASS']]) project_variables['LP_BALL_CONTAINER'],
class_=project_variables['LP_BALL_CLASS'],
)
game_ball = result.find(
project_variables['LP_BALL_CONTAINER'],
class_=[
project_variables['LP_POWERBALL_CLASS'],
project_variables['LP_MEGABALL_CLASS'],
],
)
multiplier = result.find(
project_variables['LP_BALL_CONTAINER'],
class_=[
project_variables['LP_POWERBALL_MULTIPLIER_CLASS'],
project_variables['LP_MEGA_MILLIONS_MULTIPLIER_CLASS'],
],
)
for ball in main_balls: for ball in main_balls:
pick5.append(int(ball.text.strip())) pick5.append(int(ball.text.strip()))
@@ -55,8 +78,14 @@ def scrape_game_history(game: str, year: int = utils.today().year) -> dict:
multiplier = 1 multiplier = 1
if game == 'mega-millions': if game == 'mega-millions':
drawings[draw_date] = {'main_balls': pick5, 'mega-ball': game_ball, 'multiplier': multiplier} drawings[draw_date] = {
'main_balls': pick5, 'mega-ball': game_ball,
'multiplier': multiplier,
}
elif game == 'powerball': elif game == 'powerball':
drawings[draw_date] = {'main_balls': pick5, 'powerball': game_ball, 'multiplier': multiplier} drawings[draw_date] = {
'main_balls': pick5, 'powerball': game_ball,
'multiplier': multiplier,
}
return drawings return drawings