mirror of
https://github.com/mblanke/Lottery-Tracker.git
synced 2026-03-01 14:10:22 -05:00
1.1.1
This commit is contained in:
203
updates.md
Normal file
203
updates.md
Normal file
@@ -0,0 +1,203 @@
|
||||
# Lottery Tracker — Update Log
|
||||
|
||||
## Overview
|
||||
|
||||
Complete codebase overhaul: cleanup, modernization, new features, and full Next.js frontend build.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Code Review & Cleanup
|
||||
|
||||
### Files Deleted
|
||||
- `email_sender.py` — Email sending logic (removed entire email system)
|
||||
- `send_email_now.py` — Manual email trigger
|
||||
- `test_email.py` — Email tests
|
||||
- `analyze_excel.py` — Excel analysis utility
|
||||
- `read_excel.py` — Excel reader utility
|
||||
- `import requests.py` — Misnamed utility script
|
||||
- `powerball_numbers.html` — Debug HTML file
|
||||
- `megamillions_debug.html` — Debug HTML file
|
||||
- `Dockerfile.email` — Email service Docker image
|
||||
- `EMAIL_SETUP.md` — Email configuration docs
|
||||
|
||||
### Issues Fixed
|
||||
- **Hardcoded credentials** removed (Gmail password in docker docs)
|
||||
- **`verify=False`** on all HTTP requests replaced with default SSL verification
|
||||
- **Code duplication** — scraping logic was copy-pasted across 3 files, consolidated into one
|
||||
- **No tests** — full test suite added
|
||||
- **No linting** — ruff configured
|
||||
- **Flask `debug=True`** hardcoded — replaced with env var
|
||||
- **Docker healthcheck** used `curl` (not installed in slim image) — switched to Python urllib
|
||||
- **`.dockerignore`** missing `.venv/` — build context was 456 MB, now much smaller
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Backend Rewrite
|
||||
|
||||
### New Modules
|
||||
|
||||
#### `config.py`
|
||||
- `AppConfig` dataclass with nested `ScraperURLs`, `TaxConfig`, `InvestmentDefaults`
|
||||
- `STATE_TAX_RATES` — all 51 US states + DC with 2024-2025 tax rates
|
||||
- `LOTTERY_ODDS` — odds and ticket costs for all 4 lotteries
|
||||
- `ANNUITY_YEARS`, `ANNUITY_ANNUAL_INCREASE` constants
|
||||
- `load_config()` reads from environment variables with sensible defaults
|
||||
|
||||
#### `scrapers.py`
|
||||
- Unified scraping with TTL cache (6-hour default via `cachetools`)
|
||||
- `scrape_powerball()` / `scrape_mega_millions()` — requests + BeautifulSoup from lotto.net
|
||||
- `scrape_canadian_lotteries()` — Playwright sync API from olg.ca
|
||||
- `get_all_jackpots()` — returns all 4 jackpots with cache
|
||||
- `clear_cache()` — force refresh
|
||||
|
||||
#### `app.py` (Rewritten)
|
||||
Flask app factory pattern (`create_app()`) with endpoints:
|
||||
| Endpoint | Method | Description |
|
||||
|----------|--------|-------------|
|
||||
| `/api/jackpots` | GET | Current jackpots (cached) |
|
||||
| `/api/jackpots/refresh` | POST | Force-refresh jackpots |
|
||||
| `/api/calculate` | POST | Full investment calculation with state tax |
|
||||
| `/api/states` | GET | All US states with tax rates |
|
||||
| `/api/states/<code>` | GET | Single state info |
|
||||
| `/api/compare` | GET | Side-by-side all 4 lotteries |
|
||||
| `/api/calculate/breakeven` | POST | Break-even jackpot analysis |
|
||||
| `/api/calculate/annuity` | POST | Annuity payment schedule |
|
||||
| `/api/calculate/group` | POST | Group play split |
|
||||
| `/api/odds` | GET | Probability data for all lotteries |
|
||||
| `/api/health` | GET | Health check |
|
||||
|
||||
#### `lottery_calculator.py` (Rewritten)
|
||||
Pure calculation functions with explicit parameters:
|
||||
- `_run_investment_cycles()` — shared 90-day reinvestment cycle logic
|
||||
- `calculate_us_lottery()` — lump sum + federal/state tax + CAD conversion + cycles
|
||||
- `calculate_canadian_lottery()` — tax-free + investment cycles
|
||||
- `calculate_break_even()` — EV formula: required jackpot for positive expected value
|
||||
- `calculate_annuity()` — 30-year schedule with configurable annual increase
|
||||
- `calculate_group_split()` — N-way split with custom share ratios
|
||||
|
||||
### Configuration Files
|
||||
- `requirements.txt` — pinned versions, removed openpyxl/pandas/schedule
|
||||
- `requirements-dev.txt` — pytest, pytest-mock, pytest-cov, httpx, ruff
|
||||
- `pyproject.toml` — ruff config (line-length=100, py311 target), pytest config
|
||||
- `.env.example` — all environment variables documented
|
||||
|
||||
### Test Suite (64 tests, all passing)
|
||||
- `tests/conftest.py` — Flask test fixtures
|
||||
- `tests/test_lottery_calculator.py` — ~25 tests (US calc, Canadian calc, break-even, annuity, group split)
|
||||
- `tests/test_api.py` — ~15 endpoint integration tests with mocked scrapers
|
||||
- `tests/test_config.py` — config loading, env override, state validation
|
||||
- `tests/test_scrapers.py` — parser tests, mocked HTTP, cache behavior
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Frontend (Next.js 15 + MUI 6)
|
||||
|
||||
### Scaffold
|
||||
- `frontend/package.json` — Next.js 15.1.4, MUI 6.3.1, Recharts 2.15, Axios
|
||||
- `frontend/tsconfig.json` — standard Next.js TypeScript config with `@/*` paths
|
||||
- `frontend/next.config.js` — standalone output, `/api/*` rewrite to backend
|
||||
- `frontend/.env.local` — `NEXT_PUBLIC_API_URL=http://localhost:5000`
|
||||
|
||||
### Shared Libraries
|
||||
- `frontend/lib/types.ts` — Full TypeScript interfaces (JackpotData, Calculation, StateInfo, BreakEvenResult, AnnuityResult, GroupResult, OddsInfo, etc.)
|
||||
- `frontend/lib/api.ts` — Typed Axios client with all API endpoint functions
|
||||
- `frontend/lib/format.ts` — `formatCurrency`, `formatCurrencyFull`, `formatPercent`, `formatNumber`
|
||||
- `frontend/lib/theme.ts` — Dark MUI theme (primary: `#4fc3f7`, background: `#0a1929`)
|
||||
|
||||
### Components
|
||||
- `frontend/components/ThemeRegistry.tsx` — MUI ThemeProvider wrapper with CssBaseline
|
||||
- `frontend/components/NavBar.tsx` — Sticky app bar with navigation links
|
||||
|
||||
### Pages (7 routes)
|
||||
|
||||
| Route | File | Description |
|
||||
|-------|------|-------------|
|
||||
| `/` | `app/page.tsx` | Home — jackpot cards grid (4 lotteries) + tool cards grid (6 tools) |
|
||||
| `/calculator` | `app/calculator/page.tsx` | Investment calculator — jackpot input, lottery type, state selector with tax rates, invest % slider, annual return slider, cycles, results summary, 90-day cycle table |
|
||||
| `/compare` | `app/compare/page.tsx` | Side-by-side comparison — state selector, 4 lottery cards with jackpot, odds, after-tax take-home, daily/annual income |
|
||||
| `/breakeven` | `app/breakeven/page.tsx` | Break-even analysis — lottery/state selectors, required jackpot, odds, probability, take-home fraction, expected value |
|
||||
| `/annuity` | `app/annuity/page.tsx` | Annuity calculator — jackpot, type, years, annual increase slider, summary cards, year-by-year payment schedule table |
|
||||
| `/group` | `app/group/page.tsx` | Group play — member count, custom share weights, per-member breakdown table (share %, jackpot share, after-tax, daily/annual income) |
|
||||
| `/odds` | `app/odds/page.tsx` | Probability display — odds, percentage, ticket cost, log-scale relative bar, "50% chance" ticket count |
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Docker & Infrastructure
|
||||
|
||||
### Docker Images Built
|
||||
| Image | Size | Description |
|
||||
|-------|------|-------------|
|
||||
| `lottery-tracker-backend` | 2.28 GB | Python 3.13-slim + Playwright Chromium + Gunicorn |
|
||||
| `lottery-tracker-frontend` | 285 MB | Node.js 20-alpine + Next.js standalone |
|
||||
|
||||
### Docker Fixes Applied
|
||||
1. **Removed `playwright install-deps chromium`** from Dockerfile.backend — system deps already installed manually; the auto-installer fails on newer Debian due to renamed font packages (`ttf-unifont` → `fonts-unifont`)
|
||||
2. **Generated `package-lock.json`** — required by `npm ci` in frontend Dockerfile
|
||||
3. **Created `frontend/public/`** directory with `manifest.json` — Dockerfile COPY step requires it
|
||||
4. **Added `.venv/` to `.dockerignore`** — was inflating build context
|
||||
5. **Removed `version: '3.8'`** warning — obsolete in modern Docker Compose
|
||||
6. **Removed email-scheduler service** from `docker-compose.yml`
|
||||
7. **Switched healthcheck** from `curl` to `python -c "import urllib.request; ..."`
|
||||
8. **Backend CMD** changed to gunicorn (2 workers, 120s timeout)
|
||||
|
||||
### MUI Grid Fix
|
||||
All 7 frontend pages used `<Grid size={{ xs: 12, sm: 6 }}>` syntax (Grid2 API), but imported `Grid` from `@mui/material` (legacy Grid v1). Fixed by changing imports to `Grid2 as Grid` in all pages.
|
||||
|
||||
### Running Containers
|
||||
| Container | Status | Port Mapping |
|
||||
|-----------|--------|-------------|
|
||||
| `lottery-backend` | Up (healthy) | `0.0.0.0:5000 → 5000` |
|
||||
| `lottery-frontend` | Up | `0.0.0.0:3003 → 3000` |
|
||||
|
||||
### Access URLs
|
||||
- **Frontend**: http://localhost:3003
|
||||
- **Backend API**: http://localhost:5000/api/health
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: Documentation & Config
|
||||
|
||||
### Updated Files
|
||||
- **`.gitignore`** — added `.next/`, `*.xlsx`, `*.html`, `ssl/` certs, coverage outputs
|
||||
- **`AGENTS.md`** — filled in repo facts (Python 3.13/Flask + Next.js 15/MUI 6, pytest, ruff, docker compose)
|
||||
- **`DOCKER_README.md`** — rewritten: removed email references, removed hardcoded password, added `.env.example` workflow, config table, production deployment guide
|
||||
- **`DOCKER_QUICKSTART.md`** — rewritten: removed email service, updated container descriptions, simplified quick start
|
||||
|
||||
---
|
||||
|
||||
## Verification
|
||||
|
||||
- **64/64 tests passing** (`pytest -q`)
|
||||
- **ruff lint clean** (`ruff check .` — all checks passed)
|
||||
- **Docker build successful** — both images built
|
||||
- **Containers running** — backend healthy, frontend serving
|
||||
|
||||
---
|
||||
|
||||
## Architecture Summary
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────┐
|
||||
│ nginx (prod) │
|
||||
│ Rate limiting + SSL │
|
||||
├─────────────────┬───────────────────────────────┤
|
||||
│ Frontend │ Backend │
|
||||
│ Next.js 15 │ Flask 3.1 │
|
||||
│ MUI 6 │ Gunicorn │
|
||||
│ TypeScript │ Python 3.13 │
|
||||
│ Port 3000 │ Port 5000 │
|
||||
│ │ │
|
||||
│ 7 pages │ 11 API endpoints │
|
||||
│ Dark theme │ 4 lottery scrapers │
|
||||
│ Axios client │ TTL cache (6h) │
|
||||
│ │ 51 state tax rates │
|
||||
│ │ Playwright (Canadian) │
|
||||
└─────────────────┴───────────────────────────────┘
|
||||
```
|
||||
|
||||
### Tech Stack
|
||||
- **Backend**: Python 3.13, Flask 3.1, Gunicorn, BeautifulSoup, Playwright
|
||||
- **Frontend**: Next.js 15, TypeScript, Material-UI 6, Recharts, Axios
|
||||
- **Testing**: pytest (64 tests), ruff (lint)
|
||||
- **Docker**: Multi-container (backend + frontend + nginx for prod)
|
||||
- **Config**: Environment variables via `.env` + `python-dotenv`
|
||||
Reference in New Issue
Block a user