13 KiB
13 KiB
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
- Define app scope and features
- Choose tech stack
- Design database schema
- Design fetch system
- Define data sources and API endpoints
- Create CLAUDE.md
✅ Phase 1 — Database Setup
- Create
lottosight/project folder structure - Write
db/database.py— SQLite init, create all tables - Write
db/models.py— CRUD: insert draw, get draws, check duplicate, insert prediction, insert fetch log - Seed default game configs (Powerball, Mega Millions)
- Write
requirements.txt - Test DB creation and seed on fresh run
- Write
tests/conftest.py— shared tmp_db fixture - Write
tests/test_database.py— 8 tests for database.py (47/47 pass) - Write
tests/test_models.py— 39 tests for models.py (47/47 pass) - Write
.gitea/workflows/ci.yml— CI on every push (syntax check + pytest)
✅ Phase 2 — Fetch System
- Write
core/fetcher.pyfetch_powerball_ny()— NY Open Data APIfetch_megamillions_ny()— NY Open Data APIfetch_megamillions_tx()— Texas Lottery CSVfetch_all()— calls all 3, aggregates results- Duplicate detection logic
- Return added/skipped counts per source
- Write
ui/statusbar.py— bottom status bar widget - Wire auto-fetch on app launch (background thread)
- Wire 24hr scheduled fetch (APScheduler)
- Write
main.py— app window, toolbar with manual fetch button - Wire manual fetch button →
fetch_all()→ update status bar - Test: fresh DB → fetch → verify records inserted (67/67 pass)
- Test: second fetch → verify duplicates skipped, counts correct
- Test: cross-source dedup (same date, different source → skipped)
✅ Phase 3 — History Browser
- Write
ui/history.py- Treeview table with columns: Game, Date, Numbers, Bonus, Mult., Source
- Filter by game (dropdown)
- Search by date range (From / To entries)
- Sort by column headers (▲/▼ indicators, numeric sort for bonus/multiplier)
- Row count display
- Connect history screen to DB reads via
get_draws_with_game() - Auto-refresh after fetch completes
- 13 tests (80/80 total passing)
✅ Phase 4 — Analysis Engine + Charts
- Write
core/analyzer.pyfrequency_analysis(game_id, last_n)gap_analysis(game_id)positional_frequency(game_id)pair_analysis(game_id)odd_even_ratio(game_id)sum_range_analysis(game_id)delta_analysis(game_id)
- Write
ui/analysis.py- Frequency bar chart (Matplotlib + FigureCanvasTkAgg)
- Positional frequency heatmap (imshow, YlOrRd colormap)
- Gap chart (color-coded: blue=recent, red=due)
- Game dropdown + frequency window selector
- NavigationToolbar on each tab for zoom/pan
- 26 tests for all 7 analysis functions (106/106 total passing)
✅ Phase 5 — Prediction Engine
- Write
core/predictor.pyhot_numbers(game_id, last_n=100)— top-frequency + most-frequent bonusdue_numbers(game_id)— highest gap numbers from poolweighted_random(game_id)— numpy weighted choice (min weight 1 for unseen)monte_carlo(game_id, simulations=10000)— tally-based selectionpositional_pick(game_id)— per-position best with dedup- All strategies: random fallback on empty DB
- Write
ui/predictor_ui.py- Game + strategy + ticket count dropdowns
- Generate button (disables during generation)
- Treeview results: #, zero-padded numbers, bonus
- Save to DB (insert_prediction per ticket) + Clear
- Strategy description label
- 18 tests — all 5 strategies × validity + empty DB + edge cases (124/124 total)
🔲 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
.specfile - 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
$limitand$offsetparams 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