Redesign trip option cards and fix various UI/planning issues
TripOptionCard improvements: - Replace horizontal route with vertical layout (start → end with arrow) - Remove rank badges (1, 2, 3, etc.) - Split stats into two rows: cities/miles and sports with game counts - Clear selection when navigating back from detail view Settings cleanup: - Remove unused settings (preferred game time, playoff games, notifications) - Convert remaining settings to sliders Planning fixes: - Fix multi-day driving calculation in canTransition - Remove over-restrictive trip rejection in TravelEstimator - Clear games cache when sport selection changes UI polish: - RoutePreviewStrip shows all cities (abbreviated) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -220,7 +220,7 @@ enum GameDAGRouter {
|
||||
///
|
||||
/// Requirements:
|
||||
/// 1. B starts after A (time moves forward)
|
||||
/// 2. Driving time is within daily limit
|
||||
/// 2. We have enough days between games to complete the drive
|
||||
/// 3. We can arrive at B before B starts
|
||||
///
|
||||
private static func canTransition(
|
||||
@@ -238,9 +238,8 @@ enum GameDAGRouter {
|
||||
// Get stadiums
|
||||
guard let fromStadium = stadiums[from.stadiumId],
|
||||
let toStadium = stadiums[to.stadiumId] else {
|
||||
// Missing stadium info - use generous fallback
|
||||
// Assume 300 miles at 60 mph = 5 hours, which is usually feasible
|
||||
return true
|
||||
// Missing stadium info - can't calculate distance, reject to be safe
|
||||
return false
|
||||
}
|
||||
|
||||
let fromCoord = fromStadium.coordinate
|
||||
@@ -254,16 +253,36 @@ enum GameDAGRouter {
|
||||
|
||||
let drivingHours = distanceMiles / 60.0 // Average 60 mph
|
||||
|
||||
// Must be within daily limit
|
||||
guard drivingHours <= constraints.maxDailyDrivingHours else { return false }
|
||||
|
||||
// Calculate if we can arrive in time
|
||||
// Calculate available driving time between games
|
||||
// After game A ends (+ buffer), how much time until game B starts (- buffer)?
|
||||
let departureTime = from.startTime.addingTimeInterval(gameEndBufferHours * 3600)
|
||||
let arrivalTime = departureTime.addingTimeInterval(drivingHours * 3600)
|
||||
let deadline = to.startTime.addingTimeInterval(-3600) // 1 hour buffer before game
|
||||
let availableSeconds = deadline.timeIntervalSince(departureTime)
|
||||
let availableHours = availableSeconds / 3600.0
|
||||
|
||||
// Must arrive before game starts (with 1 hour buffer)
|
||||
let deadline = to.startTime.addingTimeInterval(-3600)
|
||||
guard arrivalTime <= deadline else { return false }
|
||||
// Calculate how many driving days we have
|
||||
// Each day can have maxDailyDrivingHours of driving
|
||||
let calendar = Calendar.current
|
||||
let fromDay = calendar.startOfDay(for: from.startTime)
|
||||
let toDay = calendar.startOfDay(for: to.startTime)
|
||||
let daysBetween = calendar.dateComponents([.day], from: fromDay, to: toDay).day ?? 0
|
||||
|
||||
// Available driving hours = days between * max per day
|
||||
// (If games are same day, daysBetween = 0, but we might still have hours available)
|
||||
let maxDrivingHoursAvailable: Double
|
||||
if daysBetween == 0 {
|
||||
// Same day - only have hours between games
|
||||
maxDrivingHoursAvailable = max(0, availableHours)
|
||||
} else {
|
||||
// Multi-day - can drive each day
|
||||
maxDrivingHoursAvailable = Double(daysBetween) * constraints.maxDailyDrivingHours
|
||||
}
|
||||
|
||||
// Check if we have enough driving time
|
||||
guard drivingHours <= maxDrivingHoursAvailable else { return false }
|
||||
|
||||
// Also verify we can arrive before game starts (sanity check)
|
||||
guard availableHours >= drivingHours else { return false }
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user