test(09-03): add travel corridor game inclusion tests

Added 5 TDD tests for Feature 1 (travel corridor game inclusion):
- Direct route with games along path includes all corridor games
- Game slightly off corridor within tolerance included
- Game far from corridor excluded
- Multiple games mixed filters correctly (excludes south/beyond-end games)
- No games along corridor returns empty route or failure

Tests validate that Scenario C planning correctly:
- Includes games within ~50-100 miles of direct travel corridor
- Excludes games in wrong direction (south when traveling north)
- Excludes games beyond the destination city

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-01-10 15:28:19 -06:00
parent ceb001885e
commit 31d1163953

View File

@@ -2020,4 +2020,257 @@ struct ScenarioCPlannerTests {
Issue.record("Expected success")
}
}
// MARK: - Feature 1: Travel Corridor Game Inclusion Tests
@Test("Direct route with games along path includes all corridor games")
func corridor_DirectRouteWithGamesAlongPath_IncludesAllGames() {
let planner = ScenarioCPlanner()
// Create stadiums: LA San Jose SF (direct north on I-5/101)
let la = makeStadium(name: "Dodger Stadium", city: "Los Angeles", state: "CA",
latitude: 34.0739, longitude: -118.2400)
let sj = makeStadium(name: "SAP Center", city: "San Jose", state: "CA",
latitude: 37.3326, longitude: -121.9010) // Midpoint between LA and SF
let sf = sfStadium
// Games along the path
let laGame = makeGame(stadiumId: la.id, date: date("2026-06-05 19:00"))
let sjGame = makeGame(stadiumId: sj.id, date: date("2026-06-06 19:00"))
let sfGame = makeGame(stadiumId: sf.id, date: date("2026-06-07 19:00"))
let startLoc = LocationInput(
name: "Los Angeles",
coordinate: CLLocationCoordinate2D(latitude: la.latitude, longitude: la.longitude)
)
let endLoc = LocationInput(
name: "San Francisco",
coordinate: CLLocationCoordinate2D(latitude: sf.latitude, longitude: sf.longitude)
)
let request = makeRequest(
games: [laGame, sjGame, sfGame],
stadiums: [la.id: la, sj.id: sj, sf.id: sf],
startLocation: startLoc,
endLocation: endLoc,
startDate: date("2026-06-01 00:00"),
endDate: date("2026-06-30 23:59")
)
let result = planner.plan(request: request)
if case .success(let options) = result {
#expect(!options.isEmpty, "Should return at least one route")
// Best option should include all 3 games (LA SJ SF)
let topOption = options.first!
let gameIds = topOption.stops.flatMap { $0.games }
#expect(gameIds.contains(laGame.id), "Should include LA game")
#expect(gameIds.contains(sjGame.id), "Should include San Jose game (midpoint)")
#expect(gameIds.contains(sfGame.id), "Should include SF game")
} else {
Issue.record("Expected success with games along direct corridor")
}
}
@Test("Game slightly off corridor within tolerance included")
func corridor_GameSlightlyOffCorridor_IncludedWithinTolerance() {
let planner = ScenarioCPlanner()
// LA SF is north on I-5
// Sacramento is ~20 miles east of I-5, should be within corridor tolerance
let la = laStadium
let sacramento = makeStadium(name: "Golden 1 Center", city: "Sacramento", state: "CA",
latitude: 38.5802, longitude: -121.4996) // Slightly east of direct path
let sf = sfStadium
let laGame = makeGame(stadiumId: la.id, date: date("2026-06-05 19:00"))
let sacGame = makeGame(stadiumId: sacramento.id, date: date("2026-06-06 19:00"))
let sfGame = makeGame(stadiumId: sf.id, date: date("2026-06-07 19:00"))
let startLoc = LocationInput(
name: "Los Angeles",
coordinate: CLLocationCoordinate2D(latitude: la.latitude, longitude: la.longitude)
)
let endLoc = LocationInput(
name: "San Francisco",
coordinate: CLLocationCoordinate2D(latitude: sf.latitude, longitude: sf.longitude)
)
let request = makeRequest(
games: [laGame, sacGame, sfGame],
stadiums: [la.id: la, sacramento.id: sacramento, sf.id: sf],
startLocation: startLoc,
endLocation: endLoc,
startDate: date("2026-06-01 00:00"),
endDate: date("2026-06-30 23:59")
)
let result = planner.plan(request: request)
if case .success(let options) = result {
#expect(!options.isEmpty)
// Sacramento should be included (within corridor tolerance)
let allGameIds = options.flatMap { $0.stops.flatMap { $0.games } }
#expect(allGameIds.contains(sacGame.id), "Sacramento should be included (within ~50mi corridor tolerance)")
} else {
Issue.record("Expected success with slightly off-corridor game")
}
}
@Test("Game far from corridor excluded")
func corridor_GameFarFromCorridor_Excluded() {
let planner = ScenarioCPlanner()
// LA SF is north-bound
// Phoenix is ~300 miles east, far from corridor
let la = laStadium
let phoenix = makeStadium(name: "Chase Field", city: "Phoenix", state: "AZ",
latitude: 33.4452, longitude: -112.0667) // Far east of LASF path
let sf = sfStadium
let laGame = makeGame(stadiumId: la.id, date: date("2026-06-05 19:00"))
let phoenixGame = makeGame(stadiumId: phoenix.id, date: date("2026-06-06 19:00"))
let sfGame = makeGame(stadiumId: sf.id, date: date("2026-06-07 19:00"))
let startLoc = LocationInput(
name: "Los Angeles",
coordinate: CLLocationCoordinate2D(latitude: la.latitude, longitude: la.longitude)
)
let endLoc = LocationInput(
name: "San Francisco",
coordinate: CLLocationCoordinate2D(latitude: sf.latitude, longitude: sf.longitude)
)
let request = makeRequest(
games: [laGame, phoenixGame, sfGame],
stadiums: [la.id: la, phoenix.id: phoenix, sf.id: sf],
startLocation: startLoc,
endLocation: endLoc,
startDate: date("2026-06-01 00:00"),
endDate: date("2026-06-30 23:59")
)
let result = planner.plan(request: request)
if case .success(let options) = result {
#expect(!options.isEmpty)
// Phoenix should be excluded (too far from LASF corridor)
let allGameIds = options.flatMap { $0.stops.flatMap { $0.games } }
#expect(!allGameIds.contains(phoenixGame.id), "Phoenix should be excluded (300mi east, far from corridor)")
} else {
Issue.record("Expected success but with Phoenix excluded")
}
}
@Test("Multiple games some on corridor some off filters correctly")
func corridor_MultipleGamesMixed_FiltersCorrectly() {
let planner = ScenarioCPlanner()
// LA Portland route
let la = laStadium
let sd = sdStadium // South of LA - wrong direction
let sf = sfStadium // On path north
let seattle = makeStadium(name: "T-Mobile Park", city: "Seattle", state: "WA",
latitude: 47.5914, longitude: -122.3325) // Beyond Portland
let portland = makeStadium(name: "Providence Park", city: "Portland", state: "OR",
latitude: 45.5212, longitude: -122.6917)
let laGame = makeGame(stadiumId: la.id, date: date("2026-06-05 19:00"))
let sdGame = makeGame(stadiumId: sd.id, date: date("2026-06-06 19:00")) // Should exclude (south)
let sfGame = makeGame(stadiumId: sf.id, date: date("2026-06-07 19:00")) // Should include (on path)
let seattleGame = makeGame(stadiumId: seattle.id, date: date("2026-06-08 19:00")) // Should exclude (beyond end)
let startLoc = LocationInput(
name: "Los Angeles",
coordinate: CLLocationCoordinate2D(latitude: la.latitude, longitude: la.longitude)
)
let endLoc = LocationInput(
name: "Portland",
coordinate: CLLocationCoordinate2D(latitude: portland.latitude, longitude: portland.longitude)
)
let request = makeRequest(
games: [laGame, sdGame, sfGame, seattleGame],
stadiums: [la.id: la, sd.id: sd, sf.id: sf, seattle.id: seattle, portland.id: portland],
startLocation: startLoc,
endLocation: endLoc,
startDate: date("2026-06-01 00:00"),
endDate: date("2026-06-30 23:59")
)
let result = planner.plan(request: request)
if case .success(let options) = result {
#expect(!options.isEmpty)
let allGameIds = options.flatMap { $0.stops.flatMap { $0.games } }
// Should include games on corridor
#expect(allGameIds.contains(laGame.id), "LA should be included (start)")
#expect(allGameIds.contains(sfGame.id), "SF should be included (on path north)")
// Should exclude off-corridor games
#expect(!allGameIds.contains(sdGame.id), "San Diego should be excluded (south, wrong direction)")
#expect(!allGameIds.contains(seattleGame.id), "Seattle should be excluded (beyond end point)")
} else {
Issue.record("Expected success with selective corridor filtering")
}
}
@Test("No games along corridor returns empty route or failure")
func corridor_NoGamesAlongCorridor_ReturnsEmptyOrFailure() {
let planner = ScenarioCPlanner()
// LA Seattle route (I-5 corridor)
let la = laStadium
let seattle = makeStadium(name: "T-Mobile Park", city: "Seattle", state: "WA",
latitude: 47.5914, longitude: -122.3325)
// Games far from corridor
let phoenix = makeStadium(name: "Chase Field", city: "Phoenix", state: "AZ",
latitude: 33.4452, longitude: -112.0667) // East
let denver = makeStadium(name: "Coors Field", city: "Denver", state: "CO",
latitude: 39.7559, longitude: -104.9942) // Far east
let phoenixGame = makeGame(stadiumId: phoenix.id, date: date("2026-06-05 19:00"))
let denverGame = makeGame(stadiumId: denver.id, date: date("2026-06-06 19:00"))
let startLoc = LocationInput(
name: "Los Angeles",
coordinate: CLLocationCoordinate2D(latitude: la.latitude, longitude: la.longitude)
)
let endLoc = LocationInput(
name: "Seattle",
coordinate: CLLocationCoordinate2D(latitude: seattle.latitude, longitude: seattle.longitude)
)
let request = makeRequest(
games: [phoenixGame, denverGame],
stadiums: [la.id: la, seattle.id: seattle, phoenix.id: phoenix, denver.id: denver],
startLocation: startLoc,
endLocation: endLoc,
startDate: date("2026-06-01 00:00"),
endDate: date("2026-06-30 23:59")
)
let result = planner.plan(request: request)
// Should either fail (.noGamesInRange or .noValidRoutes) OR return route with no games
switch result {
case .failure(let failure):
// Expected: no games in corridor
#expect(failure.reason == .noValidRoutes || failure.reason == .noGamesInRange,
"Should fail with noValidRoutes or noGamesInRange")
case .success(let options):
// If success, route should have only start/end waypoints, no games
if let topOption = options.first {
let gameCount = topOption.stops.flatMap { $0.games }.count
#expect(gameCount == 0, "Route should have no games if all games are off-corridor")
}
}
}
}