Commit Graph

36 Commits

Author SHA1 Message Date
Trey t
63fb06c41a fix: update pipeline imports to use sport modules
After Phase 1 refactoring moved scraper functions to sport-specific
modules (nba.py, mlb.py, etc.), these pipeline scripts still imported
from scrape_schedules.py.

- run_pipeline.py: import from core.py and sport modules
- validate_data.py: import from core.py and sport modules
- run_canonicalization_pipeline.py: import from core.py and sport modules

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 10:52:13 -06:00
Trey t
d9f446bccb docs(07-01): create Scripts/README.md with pipeline documentation
- Overview and quick start commands
- ASCII architecture diagram showing data flow
- Module reference table for all Python scripts
- Sport modules table with stadium counts
- Data files and alias file documentation
- Pipeline commands for scraping, canonicalization, CloudKit

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 10:42:47 -06:00
Trey t
9d2dbf61dd feat(06-01): add orphan listing and completeness metrics
Add --list-orphans flag with orphan detection by record type,
data completeness metrics (coordinates, capacity, team/stadium refs),
health score calculation (0-100), and actionable recommendations.
Includes JSON export and menu option 17.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 10:34:39 -06:00
Trey t
9f0edc4228 feat(06-01): add comprehensive validation command
Add --validate flag with local validation, CloudKit relationship
checking, and sync status comparison. Includes JSON export via
--output flag and menu option 16 for interactive mode.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 10:31:52 -06:00
Trey t
5a08659837 feat(05-02): add individual record management commands
Add commands for managing individual CloudKit records:
- --get TYPE ID: Retrieve and display single record
- --list TYPE [--count]: List all recordNames for a type
- --update-record TYPE ID FIELD=VALUE: Update fields with conflict handling
- --delete-record TYPE ID [--force]: Delete with confirmation

Features:
- Type validation against VALID_RECORD_TYPES
- Triple lookup fallback: direct -> deterministic UUID -> canonicalId query
- Automatic type parsing for numeric field values
- Conflict detection with automatic forceReplace retry
- Deletion confirmation (skip with --force)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 10:17:40 -06:00
Trey t
5763db4a61 feat(05-02): add sync verification with --verify flag
- Add --verify flag for quick verification (counts + 5-record spot-check)
- Add --verify-deep flag for full field-by-field comparison
- Add verify_sync() function to compare CloudKit vs local data
- Add lookup() method to CloudKit class for record lookups
- Add menu options 14-15 for verify sync quick/deep
2026-01-10 10:13:08 -06:00
Trey t
d9a6aa4fe4 feat(05-01): add differential sync with smart-sync flag
- sync_diff() for differential uploads
- update operation with recordChangeTag conflict handling
- --smart-sync and --delete-orphans flags
- Menu options 12-13 for smart sync

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 10:08:04 -06:00
Trey t
0c74495ee5 feat(05-01): add change detection with diff reporting
- query_all() method with pagination
- compute_diff() returns new/updated/unchanged/deleted
- --diff flag shows report without importing

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 10:05:29 -06:00
Trey t
b6286119d7 feat(04-01): run game canonicalization pipeline
Generate canonical games with team/stadium links for 5760 games across
NBA, MLB, NHL, NFL, and MLS.

Added missing team aliases:
- NFL WSH -> team_nfl_was (Washington Commanders)
- MLS NY -> team_mls_nyrb (NY Red Bulls)
- MLS ATX -> team_mls_aus (Austin FC)

Remaining 8 warnings are expected NFL playoff placeholders (TBD/AFC/NFC).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 09:55:53 -06:00
Trey t
81f620defe feat(03-02): add NWSL to canonicalization pipeline
- Import NWSL_TEAMS from nwsl module
- Add NWSL_DIVISIONS dict (single league structure, no divisions)
- Add NWSL to sport_mappings for team canonicalization
- Add NWSL team abbreviation aliases (ANG, GOTHAM, NCC, BAY, etc.)
- Add NWSL stadium aliases (CPKC Stadium, SeatGeek Stadium, WakeMed, etc.)

Total teams: 180 (13 NWSL teams added)
Final breakdown: NBA(30) + MLB(30) + NHL(32) + NFL(32) + MLS(30) + WNBA(13) + NWSL(13)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 09:43:18 -06:00
Trey t
285bc075d7 feat(03-02): add WNBA to canonicalization pipeline
- Import WNBA_TEAMS from wnba module
- Add WNBA_DIVISIONS dict (single league structure, no divisions)
- Add WNBA to sport_mappings for team canonicalization
- Update arena_key to use 'arena' for WNBA (like NBA/NHL)
- Add WNBA team abbreviation aliases (LV, LAS, NYL, PHX, etc.)
- Add WNBA stadium aliases (Michelob Ultra Arena, Gateway Center, etc.)

Total teams: 167 (13 WNBA teams added)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 09:41:59 -06:00
Trey t
b6a913df1d feat(03-02): add MLS to canonicalization pipeline
- Import MLS_TEAMS from mls module
- Add MLS_DIVISIONS dict (Eastern/Western conferences)
- Add MLS to sport_mappings for team canonicalization
- Add MLS team abbreviation aliases (LA, NYC, RBNY, etc.)
- Add MLS stadium historical aliases (BMO, PayPal Park, Shell Energy, etc.)

Total teams: 154 (30 MLS teams added)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 09:40:39 -06:00
Trey t
90c9cef0bd feat(03-01): add NFL stadium historical aliases
Add NFL entries to HISTORICAL_STADIUM_ALIASES dict:
- Caesars Superdome (Mercedes-Benz, Louisiana Superdome)
- Paycor Stadium (Paul Brown Stadium)
- Empower Field at Mile High (Broncos Stadium, Sports Authority, Invesco, Mile High)
- Acrisure Stadium (Heinz Field)
- EverBank Stadium (TIAA Bank, Alltel, Jacksonville Municipal)
- Northwest Stadium (FedExField, Jack Kent Cooke)
- Hard Rock Stadium (Sun Life, Land Shark, Dolphin, Pro Player, Joe Robbie)
- Highmark Stadium (Bills Stadium, New Era, Ralph Wilson, Rich Stadium)
- GEHA Field at Arrowhead Stadium (Arrowhead Stadium)
- AT&T Stadium (Cowboys Stadium)
- Lumen Field (CenturyLink, Qwest, Seahawks Stadium)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 09:36:11 -06:00
Trey t
41496b6bea feat(03-01): add NFL team abbreviation aliases
Add NFL entries to TEAM_ABBREV_ALIASES dict:
- Historical relocations: OAK→LV, SD→LAC, STL→LAR
- Common 3-letter variations: JAC, GNB, KAN, NWE, NOR, TAM, SFO
- Direct match for WAS included for completeness

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 09:35:21 -06:00
Trey t
d4d0d95c54 feat(03-01): add NFL to team canonicalization
Add NFL support to canonicalize_teams.py:
- Import NFL_TEAMS from scrape_schedules
- Add NFL_DIVISIONS dict with all 32 teams mapped to conference/division
- Include NFL in sport_mappings for canonicalization
- Add NFL_DIVISIONS to division_map lookup

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 09:34:49 -06:00
Trey t
5307fdf6a4 feat(02.1-03): integrate NWSL module with scrape_schedules.py
Update scrape_schedules.py to import NWSL stadium functionality from nwsl.py:
- Add import for NWSL_TEAMS, get_nwsl_team_abbrev, scrape_nwsl_stadiums
- Remove inline NWSL_TEAMS dict (now imported from nwsl.py)
- Remove stub scrape_nwsl_stadiums function (now using module implementation)
- Update docstrings and comments to reflect module structure

Stadium scraping now uses modules for all secondary sports:
- MLS: 30 stadiums from mls.py
- WNBA: 13 arenas from wnba.py
- NWSL: 13 stadiums from nwsl.py

Only CBB remains inline (350+ D1 teams requires separate scoped phase).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 01:06:14 -06:00
Trey t
75e2498382 feat(02.1-03): create NWSL sport module with hardcoded stadiums
Create nwsl.py following the established sport module pattern:
- 13 NWSL teams matching current 2025 season roster
- All 13 stadiums with complete data (capacity, year_opened, coordinates)
- Cross-referenced MLS coordinates for shared stadiums (10 shared with MLS)
- 3 NWSL-specific stadiums: SeatGeek Stadium, CPKC Stadium, WakeMed Soccer Park

Module exports:
- NWSL_TEAMS dict
- get_nwsl_team_abbrev() function
- scrape_nwsl_stadiums_hardcoded() function
- scrape_nwsl_stadiums() function with fallback system
- NWSL_STADIUM_SOURCES configuration

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 01:04:15 -06:00
Trey t
f141136bb4 feat(02.1-02): integrate WNBA module with scrape_schedules.py
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 00:59:53 -06:00
Trey t
5a51dab59f feat(02.1-02): create WNBA sport module with 13 hardcoded arenas
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 00:59:02 -06:00
Trey t
8f1803b10d feat(02.1-01): integrate MLS module with scrape_schedules.py
- Import MLS_TEAMS, get_mls_team_abbrev, scrape_mls_stadiums from mls.py
- Remove inline MLS_TEAMS dict (now imported from module)
- Remove inline MLS stadium scraper functions (now in mls.py)
- Update TODO comments to reflect MLS extraction complete

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 00:52:17 -06:00
Trey t
addc9b37f7 feat(02.1-01): create MLS sport module with 30 hardcoded stadiums
Add complete MLS stadium data following established sport module pattern:
- 30 MLS stadiums with capacity (soccer configuration) and year_opened
- MLS_TEAMS dict with all 30 teams
- get_mls_team_abbrev() function for team abbreviation lookup
- scrape_mls_stadiums_hardcoded() as primary source
- scrape_mls_stadiums_gavinr() as fallback source
- MLS_STADIUM_SOURCES configuration for fallback system

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 00:50:56 -06:00
Trey t
c2da6a7770 feat(02-02): regenerate stadium data with canonicalization pipeline
- Ran scrape_schedules.py --stadiums-update
- Ran canonicalize_stadiums.py for canonical IDs
- Core sports: MLB:30, NBA:30, NHL:32, NFL:30 (122 total)
- MLS stadiums also included from comprehensive scrape (30)
- Stadium aliases generated for historical name mappings

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 00:37:09 -06:00
Trey t
90bdf1608c feat(02-01): add year_opened to all 122 hardcoded stadiums
Added year_opened field to stadium data across all 4 sport modules:
- MLB: 30 ballparks (1912-2023)
- NBA: 30 arenas (1968-2024)
- NHL: 32 arenas (1968-2021)
- NFL: 30 stadiums (1924-2020)

Updated Stadium object creation in all modules to pass year_opened.
Stadium dataclass already supported the field.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 00:31:45 -06:00
Trey t
b93205e7fb feat(01-03): refactor scrape_schedules.py to orchestrator
Transform monolithic 3359-line script into thin 733-line orchestrator:

- Import core utilities from core.py (Game, Stadium, fallback system)
- Import MLB/NBA/NHL/NFL scrapers from dedicated sport modules
- Core sports now use module convenience functions (scrape_{sport}_games)
- Non-core sports (WNBA, MLS, NWSL, CBB) remain inline with TODO markers
- CLI unchanged: --sport, --season, --stadiums-only, --stadiums-update
- 78% reduction in orchestrator size (3359 -> 733 lines)

Phase 1: Script Architecture complete - all 4 core sports modularized.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 00:18:09 -06:00
Trey t
a6c9230335 feat(01-03): create nfl.py sport module
Extract NFL scrapers from monolithic scrape_schedules.py into dedicated
sport module following established pattern from nba.py/nhl.py:

- NFL_TEAMS: 32 teams with stadiums
- Game scrapers: ESPN API, Pro-Football-Reference, CBS Sports
- Stadium scrapers: ScoreBot, GeoJSON gist, hardcoded fallback
- NFL_GAME_SOURCES and NFL_STADIUM_SOURCES configurations
- get_nfl_season_string() for cross-calendar-year format (2025-26)
- scrape_nfl_games() convenience function with fallback

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 00:14:42 -06:00
Trey t
c229fa73fd feat(01-02): create nhl.py sport module
NHL team mappings, Hockey-Reference/NHL API/ESPN scrapers, stadium data with coordinates.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 00:07:38 -06:00
Trey t
70acfb7bc6 feat(01-02): create nba.py sport module
NBA team mappings, Basketball-Reference/ESPN/CBS scrapers, stadium data with coordinates.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 00:07:37 -06:00
Trey t
cdf4c775ff feat(01-01): create mlb.py sport module
- MLB_TEAMS dictionary with all 30 teams
- Game scrapers: Baseball-Reference, MLB Stats API, ESPN
- Stadium scrapers: MLBScoreBot, GeoJSON, hardcoded fallback
- MLB_GAME_SOURCES and MLB_STADIUM_SOURCES configurations
- scrape_mlb_games() convenience function

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 23:59:04 -06:00
Trey t
edbb5dbbda feat(01-01): create core.py shared module
- Rate limiting utilities (REQUEST_DELAY, rate_limit, fetch_page)
- Data classes (Game, Stadium)
- Multi-source fallback system (ScraperSource, scrape_with_fallback)
- Stadium fallback system (StadiumScraperSource, scrape_stadiums_with_fallback)
- ID generation (assign_stable_ids)
- Export utilities (export_to_json, validate_games)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 23:58:55 -06:00
Trey t
8790d2ad73 Remove CFB/NASCAR/PGA and streamline to 8 supported sports
- Remove College Football, NASCAR, and PGA from scraper and app
- Clean all data files (stadiums, games, pipeline reports)
- Update Sport.swift enum and all UI components
- Add sportstime.py CLI tool for pipeline management
- Add DATA_SCRAPING.md documentation
- Add WNBA/MLS/NWSL implementation documentation
- Scraper now supports: NBA, MLB, NHL, NFL, WNBA, MLS, NWSL, CBB

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 23:22:13 -06:00
Trey t
f5e509a9ae Add region-based filtering and route length diversity
- Add RegionMapSelector UI for geographic trip filtering (East/Central/West)
- Add RouteFilters module for allowRepeatCities preference
- Improve GameDAGRouter to preserve route length diversity
  - Routes now grouped by city count before scoring
  - Ensures 2-city trips appear alongside longer trips
  - Increased beam width and max options for better coverage
- Add TripOptionsView filters (max cities slider, pace filter)
- Remove TravelStyle section from trip creation (replaced by region selector)
- Clean up debug logging from DataProvider and ScenarioAPlanner

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 15:18:37 -06:00
Trey t
7efcea7bd4 Add canonical ID pipeline and fix UUID consistency for CloudKit sync
- Add local canonicalization pipeline (stadiums, teams, games) that generates
  deterministic canonical IDs before CloudKit upload
- Fix CanonicalSyncService to use deterministic UUIDs from canonical IDs
  instead of random UUIDs from CloudKit records
- Add SyncStadium/SyncTeam/SyncGame types to CloudKitService that preserve
  canonical ID relationships during sync
- Add canonical ID field keys to CKModels for reading from CloudKit records
- Bundle canonical JSON files (stadiums_canonical, teams_canonical,
  games_canonical, stadium_aliases) for consistent bootstrap data
- Update BootstrapService to prefer canonical format files over legacy format

This ensures all entities use consistent deterministic UUIDs derived from
their canonical IDs, preventing duplicate records when syncing CloudKit
data with bootstrapped local data.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 10:30:09 -06:00
Trey t
1ee47df53e Add StadiumAlias CloudKit sync and offline-first data architecture
- Add CKStadiumAlias model for CloudKit record mapping
- Add fetchStadiumAliases/fetchStadiumAliasChanges to CloudKitService
- Add syncStadiumAliases to CanonicalSyncService for delta sync
- Add subscribeToStadiumAliasUpdates for push notifications
- Update cloudkit_import.py with --stadium-aliases-only option

Data Architecture Updates:
- Remove obsolete provider files (CanonicalDataProvider, CloudKitDataProvider, StubDataProvider)
- AppDataProvider now reads exclusively from SwiftData
- Add background CloudKit sync on app startup (non-blocking)
- Document data architecture in CLAUDE.md

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 22:20:07 -06:00
Trey t
92d808caf5 Add Stadium Progress system and themed loading spinners
Stadium Progress & Achievements:
- Add StadiumVisit and Achievement SwiftData models
- Create Progress tab with interactive map view
- Implement photo-based visit import with GPS/date matching
- Add achievement badges (count-based, regional, journey)
- Create shareable progress cards for social media
- Add canonical data infrastructure (stadium identities, team aliases)
- Implement score resolution from free APIs (MLB, NBA, NHL stats)

UI Improvements:
- Add ThemedSpinner and ThemedSpinnerCompact components
- Replace all ProgressView() with themed spinners throughout app
- Fix sport selection state not persisting when navigating away

Bug Fixes:
- Fix Coast to Coast trips showing only 1 city (validation issue)
- Fix stadium progress showing 0/0 (filtering issue)
- Remove "Stadium Quest" title from progress view

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 20:20:03 -06:00
Trey t
4184af60b5 Refactor travel segments and simplify trip options
Travel segment architecture:
- Remove departureTime/arrivalTime from TravelSegment (location-based, not date-based)
- Fix travel sections appearing after destination instead of between cities
- Fix missing travel segments when revisiting same city (consecutive grouping)
- Remove unwanted rest day at end of trip

Planning engine fixes:
- All three planners now group only consecutive games at same stadium
- Visiting A → B → A creates 3 stops with proper travel between

UI simplification:
- Remove redundant sort options (mostDriving/leastDriving, mostCities/leastCities)
- Remove unused "Find Other Sports Along Route" toggle (was dead code)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 19:39:53 -06:00
Trey t
9088b46563 Initial commit: SportsTime trip planning app
- Three-scenario planning engine (A: date range, B: selected games, C: directional routes)
- GeographicRouteExplorer with anchor game support for route exploration
- Shared ItineraryBuilder for travel segment calculation
- TravelEstimator for driving time/distance estimation
- SwiftUI views for trip creation and detail display
- CloudKit integration for schedule data
- Python scraping scripts for sports schedules

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 00:46:40 -06:00