- 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>
329 lines
16 KiB
Markdown
329 lines
16 KiB
Markdown
# 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
|
|
1. **Initial Model**: Pre-trained on synthetic trip data
|
|
2. **On-Device Learning**: Core ML updatable model
|
|
3. **Features**: Trip duration, sports mix, driving hours, scenic detours, game density
|
|
|
|
### Model Integration
|
|
```swift
|
|
// 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
|