Add region-based filtering and route length diversity

- Add RegionMapSelector UI for geographic trip filtering (East/Central/West)
- Add RouteFilters module for allowRepeatCities preference
- Improve GameDAGRouter to preserve route length diversity
  - Routes now grouped by city count before scoring
  - Ensures 2-city trips appear alongside longer trips
  - Increased beam width and max options for better coverage
- Add TripOptionsView filters (max cities slider, pace filter)
- Remove TravelStyle section from trip creation (replaced by region selector)
- Clean up debug logging from DataProvider and ScenarioAPlanner

🤖 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-09 15:18:37 -06:00
parent 3e778473e6
commit f5e509a9ae
20 changed files with 952 additions and 3245 deletions

View File

@@ -86,6 +86,10 @@ final class TripCreationViewModel {
var numberOfDrivers: Int = 1
var maxDrivingHoursPerDriver: Double = 8
// Travel Preferences
var allowRepeatCities: Bool = true
var selectedRegions: Set<Region> = [.east, .central, .west]
// MARK: - Dependencies
private let planningEngine = TripPlanningEngine()
@@ -273,10 +277,6 @@ final class TripCreationViewModel {
await loadScheduleData()
}
// Read max trip options from settings (default 10)
let savedMaxOptions = UserDefaults.standard.integer(forKey: "maxTripOptions")
let maxTripOptions = savedMaxOptions > 0 ? min(20, savedMaxOptions) : 10
// Build preferences
let preferences = TripPreferences(
planningMode: planningMode,
@@ -297,7 +297,8 @@ final class TripCreationViewModel {
lodgingType: lodgingType,
numberOfDrivers: numberOfDrivers,
maxDrivingHoursPerDriver: maxDrivingHoursPerDriver,
maxTripOptions: maxTripOptions
allowRepeatCities: allowRepeatCities,
selectedRegions: selectedRegions
)
// Build planning request
@@ -451,6 +452,17 @@ final class TripCreationViewModel {
availableGames = []
isLoadingGames = false
currentPreferences = nil
allowRepeatCities = true
selectedRegions = [.east, .central, .west]
}
/// Toggles region selection. Any combination is allowed.
func toggleRegion(_ region: Region) {
if selectedRegions.contains(region) {
selectedRegions.remove(region)
} else {
selectedRegions.insert(region)
}
}
/// Select a specific itinerary option and navigate to its detail
@@ -465,9 +477,6 @@ final class TripCreationViewModel {
/// Convert an itinerary option to a Trip (public for use by TripOptionsView)
func convertOptionToTrip(_ option: ItineraryOption) -> Trip {
let savedMaxOptions = UserDefaults.standard.integer(forKey: "maxTripOptions")
let maxOptions = savedMaxOptions > 0 ? min(20, savedMaxOptions) : 10
let preferences = currentPreferences ?? TripPreferences(
planningMode: planningMode,
startLocation: nil,
@@ -487,7 +496,8 @@ final class TripCreationViewModel {
lodgingType: lodgingType,
numberOfDrivers: numberOfDrivers,
maxDrivingHoursPerDriver: maxDrivingHoursPerDriver,
maxTripOptions: maxOptions
allowRepeatCities: allowRepeatCities,
selectedRegions: selectedRegions
)
return convertToTrip(option: option, preferences: preferences)
}