- Add PlanningTips data model with 105 tips across 7 categories
- Wire random tips into HomeView (3 tips per session)
- Add TripOptionsGrouper for grouping by city/game count and mileage
- Update TripOptionsView with sectioned display when sorting
- Recommended and Best Efficiency remain flat lists
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Enable zoom/pan on progress map with reset button
- Add visit count badges to stadium chips
- Create GamesHistoryView with year grouping and sport filters
- Create StadiumVisitHistoryView for viewing all visits to a stadium
- Add VisitListCard and GamesHistoryRow components
- Add "See All" navigation from Recent Visits to Games History
- Add tests for map interactions, visit lists, and games history
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace progressive reveal with single fade-in of all steps
- Add canPlanTrip validation requiring all fields before planning
- Disable Plan Trip button until all selections are made
- Simplify ViewModel by removing step-by-step visibility logic
- Update tests for new validation-based approach
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Reorder wizard steps: dates before sports (enables availability check)
- Add contentShape(Rectangle()) for full tap targets on all cards
- Fix route preference showing preselected value
- Fix sport cards having inconsistent heights
- Speed up step reveal animation (0.3s → 0.15s)
- Add debounced scroll delay to avoid interrupting selection
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add allRichGames method to DataProvider
- Update TripCreationViewModel.loadGamesForBrowsing to use allGames (removes 90-day limit)
- Update MockCloudKitService sync methods to use new delta sync signatures
- Update MockAppDataProvider with renamed methods and new allGames/allRichGames
- Fix all callers: ScheduleViewModel, TripCreationViewModel, SuggestedTripsGenerator, GameMatcher
- Update CLAUDE.md documentation with new method names
This completes the delta sync implementation:
- CloudKit sync now uses modificationDate for proper delta sync
- First sync fetches ALL data, subsequent syncs only fetch modified records
- "By Games" mode now shows all available games (not just 90 days)
- All data types (stadiums, teams, games) use consistent delta sync pattern
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This refactor fixes the achievement system by using stable canonical string
IDs (e.g., "stadium_mlb_fenway_park") instead of random UUIDs. This ensures
stadium mappings for achievements are consistent across app launches and
CloudKit sync operations.
Changes:
- Stadium, Team, Game: id property changed from UUID to String
- Trip, TripStop, TripPreferences: updated to use String IDs for games/stadiums
- CKModels: removed UUID parsing, use canonical IDs directly
- AchievementEngine: now matches against canonical stadium IDs
- All test files updated to use String IDs instead of UUID()
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The Green Monster (Fenway) and Ivy League (Wrigley) achievements
weren't working because:
1. Symbolic IDs use lowercase sport (stadium_mlb_bos)
2. Sport enum uses uppercase raw values (MLB)
3. Visits store stadium UUIDs, not symbolic IDs
Added resolveSymbolicStadiumId() helper that:
- Uppercases the sport string before Sport(rawValue:)
- Looks up team by abbreviation and sport
- Returns the team's stadiumId as UUID string
Also fixed:
- getStadiumIdsForLeague returns UUID strings (not symbolic IDs)
- AchievementProgress.isEarned computed from progress OR stored record
- getStadiumIdsForDivision queries CanonicalTeam properly
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Lock all maps to North America (no pan/zoom) in ProgressMapView and TripDetailView
- Sort saved trips by most cities (stops count)
- Filter cross-country trips to top 2 by stops on home screen
- Use LocationSearchSheet for Follow Team home location (consistent with must-stop)
- Initialize DateRangePicker to show selected dates on appear
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds a new planning mode that lets users follow a team's schedule
(home + away games) and builds multi-city routes accordingly.
Key changes:
- New ScenarioDPlanner with team filtering and route generation
- Team picker UI with sport grouping and search
- Fix TravelEstimator 5-day limit (was 2-day) for cross-country routes
- Fix DateInterval end boundary to include games on last day
- Comprehensive test suite covering edge cases:
- Multi-city routes with adequate/insufficient time
- Optimal game selection per city for feasibility
- 5-day driving segment limits
- Multiple driver scenarios
Enables trips like Houston → Chicago → Anaheim following the Astros.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement comprehensive test infrastructure and all 124 tests across 11 phases:
- Phase 0: Test infrastructure (fixtures, mocks, helpers)
- Phases 1-10: Core planning engine tests (previously implemented)
- Phase 11: Edge case omnibus (11 new tests)
- Data edge cases: nil stadiums, malformed dates, invalid coordinates
- Boundary conditions: driving limits, radius boundaries
- Time zone cases: cross-timezone games, DST transitions
Reorganize test structure under Planning/ directory with proper organization.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Added 7 TDD tests for Feature 2 (geographic efficiency / anti-backtracking):
- Route must start at specified start city
- Route must end at specified end city
- Intermediate games in wrong order rejected or reordered
- Multiple route options - least backtracking preferred
- Minor backtracking within tolerance is acceptable
- Excessive backtracking beyond destination rejected
- Correct directional classification for north-to-south route
All tests pass - existing ScenarioCPlanner implementation already
validates monotonic progress and prevents excessive backtracking.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added 5 TDD tests for Feature 1 (travel corridor game inclusion):
- Direct route with games along path includes all corridor games
- Game slightly off corridor within tolerance included
- Game far from corridor excluded
- Multiple games mixed filters correctly (excludes south/beyond-end games)
- No games along corridor returns empty route or failure
Tests validate that Scenario C planning correctly:
- Includes games within ~50-100 miles of direct travel corridor
- Excludes games in wrong direction (south when traveling north)
- Excludes games beyond the destination city
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Tests same-day games in close cities (both included - FAILING)
- Tests same-day games in distant cities (only one per route - PASSING)
- Tests same-day games on opposite coasts (only one per route - PASSING)
- Tests three same-day games (picks feasible combinations - FAILING)
2 of 4 tests failing - need to implement feasible same-day game logic.
- Tests game at range start in different timezone (included)
- Tests game before range start in different timezone (excluded)
- Tests game at range end in different timezone (included)
- Tests game after range end in different timezone (excluded)
All tests pass - DateInterval.contains() correctly handles timezone boundaries.
Added 6 diversity tests to validate multi-dimensional route variety.
All tests pass, proving selectDiverseRoutes() produces varied results.
Tests validate:
- Game count diversity (2-3 games to 5+ games)
- City count diversity (2-3 cities to 4+ cities)
- Mileage diversity (short <500mi, medium 500-1000mi, long 1000+mi)
- Duration diversity (2-3 days to 5+ days)
- Bucket coverage (≥3 different game count buckets)
- No duplicate routes (unique game combinations)
Helper generateDiverseDataset() creates 50 games across 20 stadiums
over 14 days for realistic diversity testing.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added 4 performance tests with 1K, 5K, 10K games to validate DAG
algorithm scalability. Tests currently failing (RED phase).
Tests:
- 1K games: <2s expected
- 5K games: <10s expected
- 10K games: <30s expected
- 10K games: memory stability
Helper generateLargeDataset() creates realistic test data with
distributed stadiums and games across time spans.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add 7 canTransition boundary tests:
- Same stadium same day 4 hours apart is feasible
- Different stadium 1000 miles apart same day is infeasible
- Different stadium 380 miles apart 2 days apart is feasible
- Different stadium 100 miles apart 4 hours available is feasible
- Different stadium 100 miles apart 1 hour available is infeasible
- Game end buffer (3 hour) validation
- Arrival buffer (1 hour) validation
Also removes broken DayCardTests that referenced types removed in
previous refactor (DayCard, DayConflictInfo).
Total: 17 GameDAGRouter edge case tests all passing.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add 10 TDD tests for GameDAGRouter covering:
- Empty games array returns empty routes
- Single game returns single-game route
- Single game with non-matching anchor returns empty
- Two chronological feasible games returns combined route
- Two games too far apart same day returns separate routes
- Two games reverse chronological returns separate routes
- Three games with only feasible pairs returns valid combinations
- Anchor filtering excludes routes missing anchors
- Repeat cities OFF excludes same city twice
- Repeat cities ON allows same city twice
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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>
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>
- Replace O(2^n) GeographicRouteExplorer with O(n) GameDAGRouter using DAG + beam search
- Add geographic diversity to route selection (returns routes from distinct regions)
- Add trip options selector UI (TripOptionsView, TripOptionCard) to choose between routes
- Simplify itinerary display: separate games and travel segments by date
- Remove complex ItineraryDay bundling, query games/travel directly per day
- Update ScenarioA/B/C planners to use GameDAGRouter
- Add new test suites for planners and travel estimator
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- 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>