- 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>
16 KiB
16 KiB
Sport Travel Planner - Architecture Document
1. High-Level Architecture
┌─────────────────────────────────────────────────────────────────────────────┐
│ PRESENTATION LAYER │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ HomeView │ │ TripView │ │ScheduleView│ │ SettingsView│ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │ │
│ ┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐ │
│ │HomeViewModel│ │TripViewModel│ │ScheduleVM │ │ SettingsVM │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ DOMAIN LAYER │
│ ┌─────────────────────┐ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ TripPlanner │ │ RouteOptimizer │ │ ScheduleMatcher │ │
│ │ (Orchestrator) │ │ (Algorithm) │ │ (Game Finder) │ │
│ └──────────┬──────────┘ └──────────┬──────────┘ └──────────┬──────────┘ │
│ │ │ │ │
│ ┌──────────▼────────────────────────▼────────────────────────▼──────────┐ │
│ │ TripPlanningEngine │ │
│ │ • Constraint Solver • Route Graph • Scoring (CoreML) │ │
│ └───────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ DATA LAYER │
│ ┌─────────────────────┐ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ TripRepository │ │ ScheduleRepository │ │ StadiumRepository │ │
│ │ (SwiftData) │ │ (CloudKit) │ │ (CloudKit) │ │
│ └─────────────────────┘ └─────────────────────┘ └─────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────┐│
│ │ CloudKit Sync Manager ││
│ │ • Public Database (Schedules, Stadiums) ││
│ │ • Shared Database (Collaborative Trips - Phase 2) ││
│ └─────────────────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────────────────┘
2. Project Structure
SportsTime/
├── Core/
│ ├── Models/
│ │ ├── Domain/ # Pure Swift domain models
│ │ │ ├── Sport.swift
│ │ │ ├── Team.swift
│ │ │ ├── Game.swift
│ │ │ ├── Stadium.swift
│ │ │ ├── Trip.swift
│ │ │ ├── TripStop.swift
│ │ │ ├── TravelSegment.swift
│ │ │ └── TripPreferences.swift
│ │ ├── CloudKit/ # CKRecord-backed models
│ │ │ ├── CKGame.swift
│ │ │ ├── CKStadium.swift
│ │ │ └── CKTeam.swift
│ │ └── Local/ # SwiftData models
│ │ ├── SavedTrip.swift
│ │ ├── UserPreferences.swift
│ │ └── CachedSchedule.swift
│ ├── Services/
│ │ ├── CloudKitService.swift
│ │ ├── LocationService.swift
│ │ ├── DistanceMatrixService.swift
│ │ └── ExportService.swift
│ ├── Utilities/
│ │ └── DateFormatter+Extensions.swift
│ └── Extensions/
│ └── CLLocation+Extensions.swift
├── Features/
│ ├── Home/
│ │ ├── Views/
│ │ │ └── HomeView.swift
│ │ └── ViewModels/
│ │ └── HomeViewModel.swift
│ ├── Trip/
│ │ ├── Views/
│ │ │ ├── TripCreationView.swift
│ │ │ ├── TripDetailView.swift
│ │ │ ├── TripStopCard.swift
│ │ │ └── TripPreferencesForm.swift
│ │ └── ViewModels/
│ │ ├── TripCreationViewModel.swift
│ │ └── TripDetailViewModel.swift
│ ├── Schedule/
│ │ ├── Views/
│ │ │ ├── ScheduleListView.swift
│ │ │ └── GameCard.swift
│ │ └── ViewModels/
│ │ └── ScheduleViewModel.swift
│ └── Settings/
│ ├── Views/
│ │ └── SettingsView.swift
│ └── ViewModels/
│ └── SettingsViewModel.swift
├── Planning/
│ ├── Engine/
│ │ ├── TripPlanningEngine.swift
│ │ ├── RouteOptimizer.swift
│ │ ├── ScheduleMatcher.swift
│ │ └── ConstraintSolver.swift
│ ├── Scoring/
│ │ ├── TripScorer.swift
│ │ └── RoutePreferenceModel.mlmodel
│ └── Models/
│ ├── PlanningRequest.swift
│ ├── PlanningResult.swift
│ └── RouteGraph.swift
├── Export/
│ ├── PDFGenerator.swift
│ ├── TripShareManager.swift
│ └── Templates/
│ └── TripPDFTemplate.swift
└── Resources/
└── Assets.xcassets
3. Data Flow
Trip Creation Flow
User Input → TripCreationViewModel → PlanningRequest
│
▼
TripPlanningEngine
│
┌──────────────────────┼──────────────────────┐
▼ ▼ ▼
ScheduleMatcher RouteOptimizer ConstraintSolver
│ │ │
└──────────────────────┼──────────────────────┘
▼
TripScorer (CoreML)
│
▼
PlanningResult → Trip
│
▼
TripDetailView (Display)
│
▼
SavedTrip (SwiftData persist)
4. CloudKit Schema
Public Database Records
| Record Type | Fields |
|---|---|
Team |
id, name, abbreviation, sport, city, stadiumRef |
Stadium |
id, name, city, state, latitude, longitude, capacity, teamRefs |
Game |
id, homeTeamRef, awayTeamRef, stadiumRef, dateTime, sport, season |
Sport |
id, name, seasonStart, seasonEnd, iconName |
Relationships
- Team → Stadium (reference)
- Game → Team (home, away references)
- Game → Stadium (reference)
5. Trip Planning Algorithm
Step 1: Input Parsing
Parse user preferences into PlanningRequest:
- Start/End locations (geocoded)
- Date range
- Must-see games (locked stops)
- Travel mode (drive/fly)
- Constraints (max hours/day, EV, lodging type)
Step 2: Game Discovery
FOR each sport in selected sports:
Query games within date range
Filter by geographic relevance (within reasonable detour)
Include must-see games regardless of detour
Score games by:
- Team popularity
- Rivalry factor
- Venue uniqueness
Step 3: Route Graph Construction
Build weighted graph:
Nodes = [Start, Stadiums with games, End]
Edges = Travel segments with:
- Distance
- Drive time (or flight availability)
- Scenic score (if scenic preference)
- EV charging availability
Step 4: Constraint Solving
Apply hard constraints:
- Must-see games are mandatory nodes
- Max stops OR max duration
- Game times must be reachable
Apply soft constraints (scored):
- Leisure level (rest days)
- Driving hours per day
- Scenic preference
Step 5: Route Optimization
IF stops < 8:
Use exact TSP solution (branch and bound)
ELSE:
Use nearest-neighbor heuristic + 2-opt improvement
Respect temporal constraints (game dates)
Step 6: Itinerary Generation
FOR each day in trip:
Assign:
- Travel segments
- Game attendance
- Lodging location
- Rest periods (based on leisure level)
- EV charging stops (if applicable)
Step 7: Scoring & Ranking
Score final itinerary:
- Game quality score
- Route efficiency score
- Fatigue score (inverse)
- User preference alignment
Return top 3 alternatives if possible
6. CoreML Strategy
On-Device Models
| Model | Purpose | Input | Output |
|---|---|---|---|
RoutePreferenceModel |
Score route alternatives | Route features vector | Preference score 0-1 |
LeisureBalancer |
Optimize rest distribution | Trip features | Rest day placement |
PersonalizationModel |
Learn user preferences | Historical trips | Preference weights |
Training Approach
- Initial Model: Pre-trained on synthetic trip data
- On-Device Learning: Core ML updatable model
- Features: Trip duration, sports mix, driving hours, scenic detours, game density
Model Integration
// Scoring a route option
let scorer = try RoutePreferenceModel()
let input = RoutePreferenceModelInput(
totalDistance: route.distance,
gameCount: route.games.count,
scenicScore: route.scenicRating,
avgDriveHours: route.averageDailyDrive,
leisureRatio: route.restDays / route.totalDays
)
let score = try scorer.prediction(input: input).preferenceScore
7. SwiftUI Screen Flow
┌─────────────────┐
│ Launch/Splash │
└────────┬────────┘
▼
┌─────────────────┐
│ HomeView │◄──────────────────────────────────┐
│ - Saved Trips │ │
│ - Quick Start │ │
│ - Schedule │ │
└────────┬────────┘ │
│ │
▼ │
┌─────────────────┐ ┌─────────────────┐ │
│TripCreationView │────►│ GamePickerSheet │ │
│ - Preferences │ │ (Must-See Games)│ │
│ - Locations │ └─────────────────┘ │
│ - Constraints │ │
└────────┬────────┘ │
│ "Plan Trip" │
▼ │
┌─────────────────┐ │
│ PlanningView │ │
│ (Loading State) │ │
└────────┬────────┘ │
▼ │
┌─────────────────┐ ┌─────────────────┐ │
│ TripDetailView │────►│ ExportSheet │ │
│ - Day-by-Day │ │ - PDF │ │
│ - Map View │ │ - Share │ │
│ - Games List │ │ - Email │ │
│ - Save Trip │ └─────────────────┘ │
└────────┬────────┘ │
│ Save │
▼ │
┌─────────────────┐ │
│ SavedTripsView │───────────────────────────────────┘
└─────────────────┘
8. Key Dependencies
- SwiftData: Local persistence for trips and preferences
- CloudKit: Shared schedules and stadium data
- MapKit: Route visualization and distance calculations
- CoreML: On-device trip scoring and personalization
- PDFKit: Trip export functionality
- CoreLocation: User location and geocoding