Files
Sportstime/SportsTime/Planning/Engine/ScenarioPlanner.swift
Trey t 1703ca5b0f refactor: change domain model IDs from UUID to String canonical IDs
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>
2026-01-12 09:24:33 -06:00

68 lines
2.4 KiB
Swift

//
// ScenarioPlanner.swift
// SportsTime
//
// Protocol for scenario-based trip planning.
//
import Foundation
/// Protocol that all scenario planners must implement.
/// Each scenario (A, B, C) has its own isolated implementation.
protocol ScenarioPlanner {
/// Plan itineraries for this scenario.
/// - Parameter request: The planning request with all inputs
/// - Returns: Success with ranked itineraries, or explicit failure
func plan(request: PlanningRequest) -> ItineraryResult
}
/// Factory for creating the appropriate scenario planner
enum ScenarioPlannerFactory {
/// Creates the appropriate planner based on the request inputs
static func planner(for request: PlanningRequest) -> ScenarioPlanner {
print("🔍 ScenarioPlannerFactory: Selecting planner...")
print(" - followTeamId: \(request.preferences.followTeamId ?? "nil")")
print(" - selectedGames.count: \(request.selectedGames.count)")
print(" - startLocation: \(request.startLocation?.name ?? "nil")")
print(" - endLocation: \(request.endLocation?.name ?? "nil")")
// Scenario D: User wants to follow a specific team
if request.preferences.followTeamId != nil {
print("🔍 ScenarioPlannerFactory: → ScenarioDPlanner (follow team)")
return ScenarioDPlanner()
}
// Scenario B: User selected specific games
if !request.selectedGames.isEmpty {
print("🔍 ScenarioPlannerFactory: → ScenarioBPlanner (selected games)")
return ScenarioBPlanner()
}
// Scenario C: User specified start and end locations
if request.startLocation != nil && request.endLocation != nil {
print("🔍 ScenarioPlannerFactory: → ScenarioCPlanner (start/end locations)")
return ScenarioCPlanner()
}
// Scenario A: Date range only (default)
print("🔍 ScenarioPlannerFactory: → ScenarioAPlanner (default/date range)")
return ScenarioAPlanner()
}
/// Classifies which scenario applies to this request
static func classify(_ request: PlanningRequest) -> PlanningScenario {
if request.preferences.followTeamId != nil {
return .scenarioD
}
if !request.selectedGames.isEmpty {
return .scenarioB
}
if request.startLocation != nil && request.endLocation != nil {
return .scenarioC
}
return .scenarioA
}
}