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:
@@ -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]] = []
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user