336 lines
13 KiB
Markdown
336 lines
13 KiB
Markdown
# LottoSight — Project Documentation
|
||
|
||
## App Overview
|
||
|
||
**Name:** LottoSight
|
||
**Type:** Desktop Application
|
||
**Framework:** Python + Tkinter
|
||
**Database:** SQLite (local, zero-config)
|
||
**Purpose:** Analyze historical lottery drawing data and predict next winning numbers using multiple statistical strategies.
|
||
|
||
---
|
||
|
||
## Tech Stack
|
||
|
||
| Component | Technology |
|
||
|---------------|-----------------------------------|
|
||
| UI | Tkinter + ttk |
|
||
| Charts | Matplotlib (embedded in Tkinter) |
|
||
| Database | SQLite via sqlite3 |
|
||
| Data Fetch | requests + BeautifulSoup |
|
||
| Analysis | collections, statistics, numpy |
|
||
| Scheduler | APScheduler |
|
||
| Export | openpyxl |
|
||
| Packaging | PyInstaller |
|
||
|
||
---
|
||
|
||
## Supported Games
|
||
|
||
| Game | Main Balls | Pool | Bonus Ball | Pool |
|
||
|---------------|------------|-------|------------|-------|
|
||
| Powerball | 5 | 1–69 | 1 | 1–26 |
|
||
| Mega Millions | 5 | 1–70 | 1 | 1–25 |
|
||
| Custom | config | config| optional | config|
|
||
|
||
---
|
||
|
||
## Data Sources
|
||
|
||
| Source | Game | Coverage | Method |
|
||
|-------------------------|---------------|------------------|--------------|
|
||
| NY Open Data API | Powerball | 2010–present | REST API |
|
||
| NY Open Data API | Mega Millions | 2002–present | REST API |
|
||
| Texas Lottery CSV | Mega Millions | 2003–present | CSV download |
|
||
|
||
### API Endpoints
|
||
- **Powerball (NY):** `https://data.ny.gov/resource/d6yy-54nr.json`
|
||
- **Mega Millions (NY):** `https://data.ny.gov/resource/5xaw-6ayf.json`
|
||
- **Mega Millions (TX):** `https://www.texaslottery.com/export/sites/lottery/Games/Mega_Millions/Winning_Numbers/download.html`
|
||
|
||
---
|
||
|
||
## File Structure
|
||
|
||
```
|
||
lottosight/
|
||
├── main.py # Entry point, app window, toolbar
|
||
├── db/
|
||
│ ├── database.py # SQLite setup, schema, migrations
|
||
│ └── models.py # CRUD operations, duplicate check
|
||
├── core/
|
||
│ ├── analyzer.py # All analysis logic
|
||
│ ├── predictor.py # Prediction strategies (5 total)
|
||
│ └── fetcher.py # Fetch logic — auto + manual, all 3 sources
|
||
├── ui/
|
||
│ ├── dashboard.py # Home/summary screen
|
||
│ ├── history.py # Draw history browser
|
||
│ ├── analysis.py # Charts and stats screen
|
||
│ ├── predictor_ui.py # Prediction generator screen
|
||
│ ├── settings.py # Settings screen + manual fetch button
|
||
│ └── statusbar.py # Bottom status bar component
|
||
├── assets/
|
||
│ └── icon.png
|
||
├── exports/ # Excel/CSV exports output folder
|
||
├── requirements.txt
|
||
└── CLAUDE.md # This file
|
||
```
|
||
|
||
---
|
||
|
||
## Database Schema
|
||
|
||
### Table: `games`
|
||
| Column | Type | Description |
|
||
|--------------|---------|------------------------------------|
|
||
| id | INTEGER | Primary key |
|
||
| name | TEXT | Game name (e.g. Powerball) |
|
||
| main_count | INTEGER | Number of main balls |
|
||
| main_max | INTEGER | Max value for main balls |
|
||
| bonus_count | INTEGER | Number of bonus balls (0 if none) |
|
||
| bonus_max | INTEGER | Max value for bonus ball |
|
||
| active | INTEGER | 1 = active, 0 = disabled |
|
||
|
||
### Table: `draws`
|
||
| Column | Type | Description |
|
||
|--------------|---------|------------------------------------|
|
||
| id | INTEGER | Primary key |
|
||
| game_id | INTEGER | Foreign key → games.id |
|
||
| draw_date | TEXT | ISO date string (YYYY-MM-DD) |
|
||
| numbers | TEXT | Comma-separated main numbers |
|
||
| bonus | TEXT | Bonus ball number(s) |
|
||
| multiplier | TEXT | Power Play / Megaplier (nullable) |
|
||
| source | TEXT | Data source identifier |
|
||
| created_at | TEXT | Record insert timestamp |
|
||
|
||
### Table: `predictions`
|
||
| Column | Type | Description |
|
||
|--------------|---------|------------------------------------|
|
||
| id | INTEGER | Primary key |
|
||
| game_id | INTEGER | Foreign key → games.id |
|
||
| strategy | TEXT | Strategy name used |
|
||
| numbers | TEXT | Predicted main numbers |
|
||
| bonus | TEXT | Predicted bonus number |
|
||
| created_at | TEXT | Prediction timestamp |
|
||
|
||
### Table: `fetch_log`
|
||
| Column | Type | Description |
|
||
|--------------|---------|------------------------------------|
|
||
| id | INTEGER | Primary key |
|
||
| source | TEXT | Source name |
|
||
| fetched_at | TEXT | Timestamp of fetch |
|
||
| added | INTEGER | New records inserted |
|
||
| skipped | INTEGER | Duplicate records skipped |
|
||
| status | TEXT | success / error |
|
||
| message | TEXT | Error message or notes |
|
||
|
||
---
|
||
|
||
## Fetch System
|
||
|
||
### Auto-Fetch
|
||
- Triggers on **app launch** (background thread)
|
||
- Repeats every **24 hours** via APScheduler
|
||
- Runs in background — does not block UI
|
||
|
||
### Manual Fetch
|
||
- Button in **Toolbar** (always visible, all screens)
|
||
- Button in **Settings screen**
|
||
- Shows "Fetching…" state while running
|
||
|
||
### Duplicate Handling
|
||
- Compare incoming records by `draw_date` + `game_id`
|
||
- Skip if already exists in DB
|
||
- Report result in **status bar**: `X added, Y skipped`
|
||
|
||
### Status Bar Format
|
||
```
|
||
Last fetch: Powerball — 3 added, 2 skipped | Mega Millions — 5 added, 0 skipped | 2026-05-23 08:42 AM
|
||
```
|
||
|
||
---
|
||
|
||
## Analysis Features
|
||
|
||
| Feature | Description |
|
||
|-----------------------|------------------------------------------------------|
|
||
| Frequency analysis | Hot/cold numbers by total draw count |
|
||
| Gap/skip analysis | How many draws since each number last appeared |
|
||
| Positional frequency | Which numbers appear most in each draw position |
|
||
| Pair/triplet patterns | Number combinations that appear together often |
|
||
| Odd/even ratio | Ratio of odd vs even numbers per draw |
|
||
| Sum range analysis | Distribution of total sums across all draws |
|
||
| Delta patterns | Differences between consecutive numbers in a draw |
|
||
|
||
---
|
||
|
||
## Prediction Strategies
|
||
|
||
| # | Strategy | Description |
|
||
|---|--------------------|-----------------------------------------------------------|
|
||
| 1 | Hot Numbers | Top N most frequent numbers in last X draws |
|
||
| 2 | Due Numbers | Numbers overdue based on expected frequency gap |
|
||
| 3 | Weighted Random | numpy random choice weighted by historical frequency |
|
||
| 4 | Monte Carlo | 10,000 simulations, pick most common result |
|
||
| 5 | Positional | Most frequent number per draw position |
|
||
|
||
---
|
||
|
||
## UI Screens
|
||
|
||
| Screen | Description |
|
||
|--------------|----------------------------------------------------------|
|
||
| Dashboard | Summary stats, last draw result, quick actions |
|
||
| History | Searchable/sortable draw history table |
|
||
| Analysis | Charts — frequency bar, heatmap, gap chart |
|
||
| Predictor | Pick strategy → generate ticket numbers |
|
||
| Settings | Game config, data sources, fetch interval, manual fetch |
|
||
|
||
---
|
||
|
||
## Logging
|
||
|
||
All actions are logged to console and optionally to a log file:
|
||
- `[FETCH]` — auto/manual fetch events
|
||
- `[DB]` — insert, skip, error events
|
||
- `[PREDICT]` — prediction generated
|
||
- `[EXPORT]` — export actions
|
||
- `[ERROR]` — any exception with traceback
|
||
|
||
---
|
||
|
||
## Build Phases & To-Do
|
||
|
||
### ✅ Phase 0 — Planning
|
||
- [x] Define app scope and features
|
||
- [x] Choose tech stack
|
||
- [x] Design database schema
|
||
- [x] Design fetch system
|
||
- [x] Define data sources and API endpoints
|
||
- [x] Create CLAUDE.md
|
||
|
||
---
|
||
|
||
### ✅ Phase 1 — Database Setup
|
||
- [x] Create `lottosight/` project folder structure
|
||
- [x] Write `db/database.py` — SQLite init, create all tables
|
||
- [x] Write `db/models.py` — CRUD: insert draw, get draws, check duplicate, insert prediction, insert fetch log
|
||
- [x] Seed default game configs (Powerball, Mega Millions)
|
||
- [x] Write `requirements.txt`
|
||
- [x] Test DB creation and seed on fresh run
|
||
- [x] Write `tests/conftest.py` — shared tmp_db fixture
|
||
- [x] Write `tests/test_database.py` — 8 tests for database.py (47/47 pass)
|
||
- [x] Write `tests/test_models.py` — 39 tests for models.py (47/47 pass)
|
||
- [x] Write `.gitea/workflows/ci.yml` — CI on every push (syntax check + pytest)
|
||
|
||
---
|
||
|
||
### ✅ Phase 2 — Fetch System
|
||
- [x] Write `core/fetcher.py`
|
||
- [x] `fetch_powerball_ny()` — NY Open Data API
|
||
- [x] `fetch_megamillions_ny()` — NY Open Data API
|
||
- [x] `fetch_megamillions_tx()` — Texas Lottery CSV
|
||
- [x] `fetch_all()` — calls all 3, aggregates results
|
||
- [x] Duplicate detection logic
|
||
- [x] Return added/skipped counts per source
|
||
- [x] Write `ui/statusbar.py` — bottom status bar widget
|
||
- [x] Wire auto-fetch on app launch (background thread)
|
||
- [x] Wire 24hr scheduled fetch (APScheduler)
|
||
- [x] Write `main.py` — app window, toolbar with manual fetch button
|
||
- [x] Wire manual fetch button → `fetch_all()` → update status bar
|
||
- [x] Test: fresh DB → fetch → verify records inserted (67/67 pass)
|
||
- [x] Test: second fetch → verify duplicates skipped, counts correct
|
||
- [x] Test: cross-source dedup (same date, different source → skipped)
|
||
|
||
---
|
||
|
||
### ✅ Phase 3 — History Browser
|
||
- [x] Write `ui/history.py`
|
||
- [x] Treeview table with columns: Game, Date, Numbers, Bonus, Mult., Source
|
||
- [x] Filter by game (dropdown)
|
||
- [x] Search by date range (From / To entries)
|
||
- [x] Sort by column headers (▲/▼ indicators, numeric sort for bonus/multiplier)
|
||
- [x] Row count display
|
||
- [x] Connect history screen to DB reads via `get_draws_with_game()`
|
||
- [x] Auto-refresh after fetch completes
|
||
- [x] 13 tests (80/80 total passing)
|
||
|
||
---
|
||
|
||
### ✅ Phase 4 — Analysis Engine + Charts
|
||
- [x] Write `core/analyzer.py`
|
||
- [x] `frequency_analysis(game_id, last_n)`
|
||
- [x] `gap_analysis(game_id)`
|
||
- [x] `positional_frequency(game_id)`
|
||
- [x] `pair_analysis(game_id)`
|
||
- [x] `odd_even_ratio(game_id)`
|
||
- [x] `sum_range_analysis(game_id)`
|
||
- [x] `delta_analysis(game_id)`
|
||
- [x] Write `ui/analysis.py`
|
||
- [x] Frequency bar chart (Matplotlib + FigureCanvasTkAgg)
|
||
- [x] Positional frequency heatmap (imshow, YlOrRd colormap)
|
||
- [x] Gap chart (color-coded: blue=recent, red=due)
|
||
- [x] Game dropdown + frequency window selector
|
||
- [x] NavigationToolbar on each tab for zoom/pan
|
||
- [x] 26 tests for all 7 analysis functions (106/106 total passing)
|
||
|
||
---
|
||
|
||
### 🔲 Phase 5 — Prediction Engine
|
||
- [ ] Write `core/predictor.py`
|
||
- [ ] `hot_numbers(game_id, last_n)`
|
||
- [ ] `due_numbers(game_id)`
|
||
- [ ] `weighted_random(game_id)`
|
||
- [ ] `monte_carlo(game_id, simulations=10000)`
|
||
- [ ] `positional_pick(game_id)`
|
||
- [ ] Write `ui/predictor_ui.py`
|
||
- [ ] Strategy selector dropdown
|
||
- [ ] Number of tickets input
|
||
- [ ] Generate button
|
||
- [ ] Results display (generated tickets)
|
||
- [ ] Save prediction to DB
|
||
- [ ] Test all 5 strategies produce valid number sets
|
||
|
||
---
|
||
|
||
### 🔲 Phase 6 — Settings Screen
|
||
- [ ] Write `ui/settings.py`
|
||
- [ ] Game enable/disable toggles
|
||
- [ ] Fetch interval display (24hrs, read-only for now)
|
||
- [ ] Manual fetch button (same as toolbar)
|
||
- [ ] Last fetch timestamp per source
|
||
- [ ] DB stats (total records per game)
|
||
- [ ] Wire settings to DB config reads/writes
|
||
|
||
---
|
||
|
||
### 🔲 Phase 7 — Export + Polish
|
||
- [ ] Add export to Excel (`openpyxl`) for:
|
||
- [ ] Draw history
|
||
- [ ] Predictions
|
||
- [ ] Frequency analysis
|
||
- [ ] Add export to CSV
|
||
- [ ] Add `assets/icon.png`
|
||
- [ ] App title bar + icon
|
||
- [ ] Window min-size + resizable layout
|
||
- [ ] Error handling — network down, API timeout, bad CSV
|
||
|
||
---
|
||
|
||
### 🔲 Phase 8 — Packaging
|
||
- [ ] Write PyInstaller `.spec` file
|
||
- [ ] Test build on target OS (Windows / Mac / Linux)
|
||
- [ ] Bundle SQLite DB, assets, exports folder
|
||
- [ ] Test packaged app fresh install (no Python required)
|
||
|
||
---
|
||
|
||
## Notes
|
||
|
||
- SQLite DB file stored at: `lottosight/data/lottosight.db`
|
||
- Exports land in: `lottosight/exports/`
|
||
- All fetch operations run in **background threads** to keep UI responsive
|
||
- NY Open Data API supports `$limit` and `$offset` params for pagination
|
||
- Texas Lottery CSV requires parsing — columns vary, needs header detection
|
||
- Powerball matrix changed Oct 7, 2015 (5/69+1/26) — pre-2015 data has different pool sizes, flag in DB or filter
|