Stabilize beta release with warning cleanup and edge-case fixes

This commit is contained in:
Trey t
2026-02-22 13:18:14 -06:00
parent fddea81e36
commit ec2bbb4764
55 changed files with 712 additions and 315 deletions

View File

@@ -58,7 +58,8 @@ enum RouteFilters {
var cityDays: [String: Set<Date>] = [:]
for stop in option.stops {
let city = stop.city
let city = normalizedCityKey(stop.city)
guard !city.isEmpty else { continue }
let day = calendar.startOfDay(for: stop.arrivalDate)
cityDays[city, default: []].insert(day)
}
@@ -83,18 +84,34 @@ enum RouteFilters {
for option in options {
var cityDays: [String: Set<Date>] = [:]
var displayNames: [String: String] = [:]
for stop in option.stops {
let normalized = normalizedCityKey(stop.city)
guard !normalized.isEmpty else { continue }
if displayNames[normalized] == nil {
displayNames[normalized] = stop.city
}
let day = calendar.startOfDay(for: stop.arrivalDate)
cityDays[stop.city, default: []].insert(day)
cityDays[normalized, default: []].insert(day)
}
for (city, days) in cityDays where days.count > 1 {
violatingCities.insert(city)
for (normalized, days) in cityDays where days.count > 1 {
violatingCities.insert(displayNames[normalized] ?? normalized)
}
}
return Array(violatingCities).sorted()
}
private static func normalizedCityKey(_ city: String) -> String {
let cityPart = city.split(separator: ",", maxSplits: 1).first.map(String.init) ?? city
return cityPart
.lowercased()
.replacingOccurrences(of: ".", with: "")
.split(whereSeparator: \.isWhitespace)
.joined(separator: " ")
}
// MARK: - Trip List Filters
/// Filters trips by sport.
@@ -133,8 +150,11 @@ enum RouteFilters {
/// - Uses calendar start-of-day for comparison
static func filterByDateRange(_ trips: [Trip], start: Date, end: Date) -> [Trip] {
let calendar = Calendar.current
let rangeStart = calendar.startOfDay(for: start)
let rangeEnd = calendar.startOfDay(for: end)
// Be tolerant of inverted inputs from UI/state restores by normalizing bounds.
let normalizedStart = min(start, end)
let normalizedEnd = max(start, end)
let rangeStart = calendar.startOfDay(for: normalizedStart)
let rangeEnd = calendar.startOfDay(for: normalizedEnd)
return trips.filter { trip in
let tripStart = calendar.startOfDay(for: trip.startDate)

View File

@@ -270,7 +270,7 @@ final class ScenarioAPlanner: ScenarioPlanner {
travelSegments: itinerary.travelSegments,
totalDrivingHours: itinerary.totalDrivingHours,
totalDistanceMiles: itinerary.totalDistanceMiles,
geographicRationale: "\(stops.count) games: \(cities)"
geographicRationale: "\(routeGames.count) games: \(cities)"
)
itineraryOptions.append(option)
}

View File

@@ -298,16 +298,9 @@ final class ScenarioBPlanner: ScenarioPlanner {
to: lastGameDate
).day ?? 0
// If selected games span more days than trip duration, can't fit
// If selected games span more days than trip duration, no valid window exists.
if gameSpanDays >= duration {
// Just return one window that exactly covers the games
let start = firstGameDate
let end = Calendar.current.date(
byAdding: .day,
value: gameSpanDays + 1,
to: start
) ?? lastGameDate
return [DateInterval(start: start, end: end)]
return []
}
// Generate sliding windows