Remove debug prints and fix build warnings

- Remove all print statements from planning engine, data providers, and PDF generation
- Fix deprecated CLGeocoder usage with MKLocalSearch for iOS 26
- Fix Swift 6 actor isolation by converting PDFGenerator/ExportService to @MainActor
- Add @retroactive to CLLocationCoordinate2D protocol conformances
- Fix unused variable warnings in GameDAGRouter and scenario planners
- Remove unreachable catch blocks in SettingsViewModel

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-01-08 13:25:27 -06:00
parent fbb5ae683e
commit 045fcd9c07
20 changed files with 188 additions and 303 deletions

View File

@@ -92,8 +92,6 @@ enum GameDAGRouter {
guard !sortedDays.isEmpty else { return [] }
print("[GameDAGRouter] \(games.count) games across \(sortedDays.count) days")
print("[GameDAGRouter] Games per day: \(sortedDays.map { buckets[$0]?.count ?? 0 })")
// Step 3: Initialize beam with first day's games
var beam: [[Game]] = []
@@ -113,10 +111,9 @@ enum GameDAGRouter {
}
}
print("[GameDAGRouter] Initial beam size: \(beam.count)")
// Step 4: Expand beam day by day
for (index, dayIndex) in sortedDays.dropFirst().enumerated() {
for (_, dayIndex) in sortedDays.dropFirst().enumerated() {
let todaysGames = buckets[dayIndex] ?? []
var nextBeam: [[Game]] = []
@@ -131,14 +128,11 @@ enum GameDAGRouter {
continue
}
var addedAny = false
// Try adding each of today's games
for candidate in todaysGames {
if canTransition(from: lastGame, to: candidate, stadiums: stadiums, constraints: constraints) {
let newPath = path + [candidate]
nextBeam.append(newPath)
addedAny = true
}
}
@@ -148,7 +142,6 @@ enum GameDAGRouter {
// Dominance pruning + beam truncation
beam = pruneAndTruncate(nextBeam, beamWidth: beamWidth, stadiums: stadiums)
print("[GameDAGRouter] Day \(dayIndex): nextBeam=\(nextBeam.count), after prune=\(beam.count), max games=\(beam.map { $0.count }.max() ?? 0)")
}
// Step 5: Filter routes that contain all anchors
@@ -160,15 +153,7 @@ enum GameDAGRouter {
// Step 6: Ensure geographic diversity in results
// Group routes by their primary region (city with most games)
// Then pick the best route from each region
let diverseRoutes = selectDiverseRoutes(routesWithAnchors, stadiums: stadiums, maxCount: maxOptions)
print("[GameDAGRouter] Found \(routesWithAnchors.count) routes with anchors, returning \(diverseRoutes.count) diverse routes")
for (i, route) in diverseRoutes.prefix(5).enumerated() {
let cities = route.compactMap { stadiums[$0.stadiumId]?.city }.joined(separator: "")
print("[GameDAGRouter] Route \(i+1): \(route.count) games - \(cities)")
}
return diverseRoutes
return selectDiverseRoutes(routesWithAnchors, stadiums: stadiums, maxCount: maxOptions)
}
/// Compatibility wrapper that matches GeographicRouteExplorer's interface.
@@ -320,7 +305,6 @@ enum GameDAGRouter {
return score1 > score2
}
print("[GameDAGRouter] Found \(sortedRegions.count) distinct regions: \(sortedRegions.prefix(10).joined(separator: ", "))")
// Pick routes round-robin from each region to ensure diversity
var selectedRoutes: [[Game]] = []

View File

@@ -76,14 +76,12 @@ enum ItineraryBuilder {
to: toStop,
constraints: constraints
) else {
print("\(logPrefix) Failed to estimate travel: \(fromStop.city) -> \(toStop.city)")
return nil
}
// Run optional validator (e.g., arrival time check for Scenario B)
if let validator = segmentValidator {
if !validator(segment, fromStop, toStop) {
print("\(logPrefix) Segment validation failed: \(fromStop.city) -> \(toStop.city)")
return nil
}
}
@@ -97,7 +95,6 @@ enum ItineraryBuilder {
// Verify invariant: segments = stops - 1
//
guard travelSegments.count == stops.count - 1 else {
print("\(logPrefix) Invariant violated: \(travelSegments.count) segments for \(stops.count) stops")
return nil
}
@@ -147,9 +144,8 @@ enum ItineraryBuilder {
searchRadiusMiles: 5.0,
intervalMiles: 100.0
)
print("[ItineraryBuilder] Found \(evChargers.count) EV chargers: \(segment.fromLocation.name) -> \(segment.toLocation.name)")
} catch {
print("[ItineraryBuilder] EV charger search failed: \(error.localizedDescription)")
// EV charger search failed - continue without chargers
}
}
@@ -167,7 +163,7 @@ enum ItineraryBuilder {
enrichedSegments.append(enrichedSegment)
} catch {
print("[ItineraryBuilder] Route calculation failed, keeping original: \(error.localizedDescription)")
// Route calculation failed - keep original segment
enrichedSegments.append(segment)
}
}
@@ -252,7 +248,6 @@ enum ItineraryBuilder {
// Get coordinates
guard let fromCoord = fromStop.coordinate,
let toCoord = toStop.coordinate else {
print("\(logPrefix) Missing coordinates: \(fromStop.city) -> \(toStop.city)")
// Fall back to estimate
guard let segment = TravelEstimator.estimate(
from: fromStop,
@@ -283,9 +278,7 @@ enum ItineraryBuilder {
searchRadiusMiles: 5.0,
intervalMiles: 100.0
)
print("\(logPrefix) Found \(evChargers.count) EV chargers: \(fromStop.city) -> \(toStop.city)")
} catch {
print("\(logPrefix) EV charger search failed: \(error.localizedDescription)")
// Continue without chargers - not a critical failure
}
}
@@ -302,7 +295,6 @@ enum ItineraryBuilder {
// Run optional validator
if let validator = segmentValidator {
if !validator(segment, fromStop, toStop) {
print("\(logPrefix) Segment validation failed: \(fromStop.city) -> \(toStop.city)")
return nil
}
}
@@ -312,7 +304,6 @@ enum ItineraryBuilder {
totalDistance += segment.estimatedDistanceMiles
} catch {
print("\(logPrefix) Route calculation failed, using estimate: \(error.localizedDescription)")
// Fall back to estimate
guard let segment = TravelEstimator.estimate(
from: fromStop,
@@ -329,7 +320,6 @@ enum ItineraryBuilder {
// Verify invariant
guard travelSegments.count == stops.count - 1 else {
print("\(logPrefix) Invariant violated: \(travelSegments.count) segments for \(stops.count) stops")
return nil
}
@@ -366,7 +356,6 @@ enum ItineraryBuilder {
let deadline = gameStart.addingTimeInterval(-bufferSeconds)
if earliestArrival > deadline {
print("[ItineraryBuilder] Cannot arrive in time: earliest arrival \(earliestArrival) > deadline \(deadline)")
return false
}
return true

View File

@@ -68,9 +68,6 @@ final class ScenarioAPlanner: ScenarioPlanner {
.filter { dateRange.contains($0.startTime) }
.sorted { $0.startTime < $1.startTime }
print("[ScenarioA] Found \(gamesInRange.count) games in date range")
print("[ScenarioA] Stadiums available: \(request.stadiums.count)")
// No games? Nothing to plan.
if gamesInRange.isEmpty {
return .failure(
@@ -100,11 +97,6 @@ final class ScenarioAPlanner: ScenarioPlanner {
stopBuilder: buildStops
)
print("[ScenarioA] GameDAGRouter returned \(validRoutes.count) routes")
if !validRoutes.isEmpty {
print("[ScenarioA] Route sizes: \(validRoutes.map { $0.count })")
}
if validRoutes.isEmpty {
return .failure(
PlanningFailure(
@@ -136,23 +128,16 @@ final class ScenarioAPlanner: ScenarioPlanner {
// Build stops for this route
let stops = buildStops(from: routeGames, stadiums: request.stadiums)
guard !stops.isEmpty else {
print("[ScenarioA] Route \(index + 1) produced no stops, skipping")
routesFailed += 1
continue
}
// Log stop details
let stopCities = stops.map { "\($0.city) (coord: \($0.coordinate != nil))" }
print("[ScenarioA] Route \(index + 1): \(stops.count) stops - \(stopCities.joined(separator: ""))")
// Calculate travel segments using shared ItineraryBuilder
guard let itinerary = ItineraryBuilder.build(
stops: stops,
constraints: request.drivingConstraints,
logPrefix: "[ScenarioA]"
constraints: request.drivingConstraints
) else {
// This route fails driving constraints, skip it
print("[ScenarioA] Route \(index + 1) failed driving constraints, skipping")
routesFailed += 1
continue
}
@@ -176,8 +161,6 @@ final class ScenarioAPlanner: ScenarioPlanner {
// If no routes passed all constraints, fail.
// Otherwise, return all valid options for the user to choose from.
//
print("[ScenarioA] Routes attempted: \(routesAttempted), failed: \(routesFailed), succeeded: \(itineraryOptions.count)")
if itineraryOptions.isEmpty {
return .failure(
PlanningFailure(
@@ -201,7 +184,6 @@ final class ScenarioAPlanner: ScenarioPlanner {
limit: request.preferences.maxTripOptions
)
print("[ScenarioA] Returning \(rankedOptions.count) itinerary options (leisure: \(leisureLevel.rawValue))")
return .success(rankedOptions)
}

View File

@@ -168,7 +168,6 @@ final class ScenarioBPlanner: ScenarioPlanner {
limit: request.preferences.maxTripOptions
)
print("[ScenarioB] Returning \(rankedOptions.count) itinerary options (leisure: \(leisureLevel.rawValue))")
return .success(Array(rankedOptions))
}
@@ -249,13 +248,7 @@ final class ScenarioBPlanner: ScenarioPlanner {
// Last window: first selected game is on first day of window
// Window start = firstGameDate
// Window end = start + duration days
let lastWindowStart = firstGameDate
let lastWindowEnd = Calendar.current.date(
byAdding: .day,
value: duration,
to: lastWindowStart
)!
// Slide from first window to last window
var currentStart = firstWindowStart
@@ -277,7 +270,6 @@ final class ScenarioBPlanner: ScenarioPlanner {
)!
}
print("[ScenarioB] Generated \(dateRanges.count) sliding windows for \(duration)-day trip")
return dateRanges
}

View File

@@ -175,8 +175,6 @@ final class ScenarioCPlanner: ScenarioPlanner {
stadiums: request.stadiums
)
print("[ScenarioC] Found \(directionalStadiums.count) directional stadiums from \(startLocation.name) to \(endLocation.name)")
//
// Step 5: For each date range, explore routes
//
@@ -267,7 +265,6 @@ final class ScenarioCPlanner: ScenarioPlanner {
limit: request.preferences.maxTripOptions
)
print("[ScenarioC] Returning \(rankedOptions.count) itinerary options (leisure: \(leisureLevel.rawValue))")
return .success(Array(rankedOptions))
}
@@ -318,7 +315,6 @@ final class ScenarioCPlanner: ScenarioPlanner {
let detourDistance = toStadium + fromStadium
// Also check that stadium is making progress (closer to end than start is)
let distanceFromStart = distanceBetween(start, stadiumCoord)
let distanceToEnd = distanceBetween(stadiumCoord, end)
// Stadium should be within the "cone" from start to end
@@ -408,7 +404,6 @@ final class ScenarioCPlanner: ScenarioPlanner {
}
}
print("[ScenarioC] Generated \(dateRanges.count) date ranges for \(daySpan)-day trip")
return dateRanges
}
@@ -561,7 +556,6 @@ final class ScenarioCPlanner: ScenarioPlanner {
// Allow increases up to tolerance percentage
let allowedIncrease = prev * forwardProgressTolerance
if currentDistance > prev + allowedIncrease {
print("[ScenarioC] Backtracking: \(stop.city) increases distance to end (\(Int(currentDistance))mi vs \(Int(prev))mi)")
return false
}
}

View File

@@ -19,23 +19,9 @@ final class TripPlanningEngine {
func planItineraries(request: PlanningRequest) -> ItineraryResult {
// Detect scenario and get the appropriate planner
let scenario = ScenarioPlannerFactory.classify(request)
let planner = ScenarioPlannerFactory.planner(for: request)
print("[TripPlanningEngine] Detected scenario: \(scenario)")
print("[TripPlanningEngine] Using planner: \(type(of: planner))")
// Delegate to the scenario planner
let result = planner.plan(request: request)
// Log result
switch result {
case .success(let options):
print("[TripPlanningEngine] Success: \(options.count) itinerary options")
case .failure(let failure):
print("[TripPlanningEngine] Failure: \(failure.reason)")
}
return result
return planner.plan(request: request)
}
}