feat: improve planning engine travel handling, itinerary reordering, and scenario planners
Add TravelInfo initializers and city normalization helpers to fix repeat city-pair disambiguation. Improve drag-and-drop reordering with segment index tracking and source-row-aware zone calculation. Enhance all five scenario planners with better next-day departure handling and travel segment placement. Add comprehensive tests across all planners. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -295,12 +295,42 @@ final class ScenarioCPlanner: ScenarioPlanner {
|
||||
cityName: String,
|
||||
stadiums: [String: Stadium]
|
||||
) -> [Stadium] {
|
||||
let normalizedCity = cityName.lowercased().trimmingCharacters(in: .whitespaces)
|
||||
let normalizedCity = normalizeCityName(cityName)
|
||||
return stadiums.values.filter { stadium in
|
||||
stadium.city.lowercased().trimmingCharacters(in: .whitespaces) == normalizedCity
|
||||
let normalizedStadiumCity = normalizeCityName(stadium.city)
|
||||
if normalizedStadiumCity == normalizedCity { return true }
|
||||
return normalizedStadiumCity.contains(normalizedCity) || normalizedCity.contains(normalizedStadiumCity)
|
||||
}
|
||||
}
|
||||
|
||||
/// Normalizes city labels for resilient user-input matching.
|
||||
private func normalizeCityName(_ raw: String) -> String {
|
||||
// Keep the city component before state suffixes like "City, ST".
|
||||
let cityPart = raw.split(separator: ",", maxSplits: 1).first.map(String.init) ?? raw
|
||||
var normalized = cityPart
|
||||
.lowercased()
|
||||
.replacingOccurrences(of: ".", with: "")
|
||||
.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
|
||||
let aliases: [String: String] = [
|
||||
"nyc": "new york",
|
||||
"new york city": "new york",
|
||||
"la": "los angeles",
|
||||
"sf": "san francisco",
|
||||
"dc": "washington",
|
||||
"washington dc": "washington"
|
||||
]
|
||||
|
||||
if let aliased = aliases[normalized] {
|
||||
normalized = aliased
|
||||
}
|
||||
|
||||
// Collapse repeated spaces after punctuation/alias normalization.
|
||||
return normalized
|
||||
.split(whereSeparator: \.isWhitespace)
|
||||
.joined(separator: " ")
|
||||
}
|
||||
|
||||
/// Finds stadiums that make forward progress from start to end.
|
||||
///
|
||||
/// A stadium is "directional" if visiting it doesn't significantly increase
|
||||
|
||||
Reference in New Issue
Block a user