""" Centralized configuration for the Lottery Investment Calculator. All magic numbers, URLs, tax rates, and tunable parameters live here. Values are loaded from environment variables with sensible defaults. """ import os from dataclasses import dataclass, field # --------------------------------------------------------------------------- # US State Tax Rates (2024-2025) # --------------------------------------------------------------------------- STATE_TAX_RATES: dict[str, dict] = { "AL": {"name": "Alabama", "rate": 0.05}, "AK": {"name": "Alaska", "rate": 0.0}, "AZ": {"name": "Arizona", "rate": 0.025}, "AR": {"name": "Arkansas", "rate": 0.044}, "CA": {"name": "California", "rate": 0.133}, "CO": {"name": "Colorado", "rate": 0.044}, "CT": {"name": "Connecticut", "rate": 0.0699}, "DE": {"name": "Delaware", "rate": 0.066}, "FL": {"name": "Florida", "rate": 0.0}, "GA": {"name": "Georgia", "rate": 0.055}, "HI": {"name": "Hawaii", "rate": 0.11}, "ID": {"name": "Idaho", "rate": 0.058}, "IL": {"name": "Illinois", "rate": 0.0495}, "IN": {"name": "Indiana", "rate": 0.0305}, "IA": {"name": "Iowa", "rate": 0.06}, "KS": {"name": "Kansas", "rate": 0.057}, "KY": {"name": "Kentucky", "rate": 0.04}, "LA": {"name": "Louisiana", "rate": 0.0425}, "ME": {"name": "Maine", "rate": 0.0715}, "MD": {"name": "Maryland", "rate": 0.0575}, "MA": {"name": "Massachusetts", "rate": 0.09}, "MI": {"name": "Michigan", "rate": 0.0425}, "MN": {"name": "Minnesota", "rate": 0.0985}, "MS": {"name": "Mississippi", "rate": 0.05}, "MO": {"name": "Missouri", "rate": 0.048}, "MT": {"name": "Montana", "rate": 0.059}, "NE": {"name": "Nebraska", "rate": 0.0564}, "NV": {"name": "Nevada", "rate": 0.0}, "NH": {"name": "New Hampshire", "rate": 0.0}, "NJ": {"name": "New Jersey", "rate": 0.1075}, "NM": {"name": "New Mexico", "rate": 0.059}, "NY": {"name": "New York", "rate": 0.109}, "NC": {"name": "North Carolina", "rate": 0.045}, "ND": {"name": "North Dakota", "rate": 0.0195}, "OH": {"name": "Ohio", "rate": 0.0357}, "OK": {"name": "Oklahoma", "rate": 0.0475}, "OR": {"name": "Oregon", "rate": 0.099}, "PA": {"name": "Pennsylvania", "rate": 0.0307}, "RI": {"name": "Rhode Island", "rate": 0.0599}, "SC": {"name": "South Carolina", "rate": 0.064}, "SD": {"name": "South Dakota", "rate": 0.0}, "TN": {"name": "Tennessee", "rate": 0.0}, "TX": {"name": "Texas", "rate": 0.0}, "UT": {"name": "Utah", "rate": 0.0465}, "VT": {"name": "Vermont", "rate": 0.0875}, "VA": {"name": "Virginia", "rate": 0.0575}, "WA": {"name": "Washington", "rate": 0.0}, "WV": {"name": "West Virginia", "rate": 0.055}, "WI": {"name": "Wisconsin", "rate": 0.0765}, "WY": {"name": "Wyoming", "rate": 0.0}, "DC": {"name": "District of Columbia", "rate": 0.105}, } # --------------------------------------------------------------------------- # Lottery Odds (1 in N for jackpot) # --------------------------------------------------------------------------- LOTTERY_ODDS: dict[str, dict] = { "powerball": { "name": "Powerball", "odds": 292_201_338, "ticket_cost": 2.0, "country": "us", }, "megaMillions": { "name": "Mega Millions", "odds": 302_575_350, "ticket_cost": 2.0, "country": "us", }, "lottoMax": { "name": "Lotto Max", "odds": 33_294_800, "ticket_cost": 5.0, "country": "canadian", }, "lotto649": { "name": "Lotto 6/49", "odds": 13_983_816, "ticket_cost": 3.0, "country": "canadian", }, } # Annuity constants ANNUITY_YEARS = 30 ANNUITY_ANNUAL_INCREASE = 0.05 # 5% annual increase (Powerball/MM standard) def _env_float(key: str, default: float) -> float: """Read a float from an environment variable with a fallback.""" raw = os.environ.get(key) if raw is None: return default try: return float(raw) except ValueError: return default def _env_str(key: str, default: str) -> str: return os.environ.get(key, default) def _env_int(key: str, default: int) -> int: raw = os.environ.get(key) if raw is None: return default try: return int(raw) except ValueError: return default def _env_bool(key: str, default: bool) -> bool: raw = os.environ.get(key, "").lower() if raw in ("1", "true", "yes"): return True if raw in ("0", "false", "no"): return False return default @dataclass(frozen=True) class ScraperURLs: """Target URLs for lottery scraping.""" powerball: str = "https://www.lotto.net/powerball" mega_millions: str = "https://www.lotto.net/mega-millions" olg: str = "https://www.olg.ca/" @dataclass(frozen=True) class TaxConfig: """Tax and financial parameters.""" lump_sum_rate: float = 0.52 federal_tax_rate: float = 0.37 default_state_tax_rate: float = 0.055 usd_cad_rate: float = 1.35 investment_income_tax_rate: float = 0.5353 personal_withdrawal_pct: float = 0.10 @dataclass(frozen=True) class InvestmentDefaults: """Default investment calculation parameters.""" invest_percentage: float = 0.90 annual_return: float = 0.045 cycles: int = 8 @dataclass(frozen=True) class AppConfig: """Top-level application configuration.""" # Flask debug: bool = False host: str = "0.0.0.0" port: int = 5000 allowed_origins: str = "*" # Sub-configs urls: ScraperURLs = field(default_factory=ScraperURLs) tax: TaxConfig = field(default_factory=TaxConfig) investment: InvestmentDefaults = field(default_factory=InvestmentDefaults) # Scraper cache TTL in seconds (default 6 hours) cache_ttl: int = 21600 def load_config() -> AppConfig: """Build an ``AppConfig`` from environment variables.""" return AppConfig( debug=_env_bool("FLASK_DEBUG", False), host=_env_str("FLASK_HOST", "0.0.0.0"), port=_env_int("FLASK_PORT", 5000), allowed_origins=_env_str("ALLOWED_ORIGINS", "*"), urls=ScraperURLs( powerball=_env_str("SCRAPER_URL_POWERBALL", ScraperURLs.powerball), mega_millions=_env_str("SCRAPER_URL_MEGA_MILLIONS", ScraperURLs.mega_millions), olg=_env_str("SCRAPER_URL_OLG", ScraperURLs.olg), ), tax=TaxConfig( lump_sum_rate=_env_float("LUMP_SUM_RATE", TaxConfig.lump_sum_rate), federal_tax_rate=_env_float("FEDERAL_TAX_RATE", TaxConfig.federal_tax_rate), default_state_tax_rate=_env_float("DEFAULT_STATE_TAX_RATE", TaxConfig.default_state_tax_rate), usd_cad_rate=_env_float("USD_CAD_RATE", TaxConfig.usd_cad_rate), investment_income_tax_rate=_env_float("INVESTMENT_INCOME_TAX_RATE", TaxConfig.investment_income_tax_rate), personal_withdrawal_pct=_env_float("PERSONAL_WITHDRAWAL_PCT", TaxConfig.personal_withdrawal_pct), ), investment=InvestmentDefaults( invest_percentage=_env_float("DEFAULT_INVEST_PCT", InvestmentDefaults.invest_percentage), annual_return=_env_float("DEFAULT_ANNUAL_RETURN", InvestmentDefaults.annual_return), cycles=_env_int("DEFAULT_CYCLES", InvestmentDefaults.cycles), ), cache_ttl=_env_int("CACHE_TTL_SECONDS", 21600), )