test(08-01): canTransition boundary tests and cleanup
Add 7 canTransition boundary tests: - Same stadium same day 4 hours apart is feasible - Different stadium 1000 miles apart same day is infeasible - Different stadium 380 miles apart 2 days apart is feasible - Different stadium 100 miles apart 4 hours available is feasible - Different stadium 100 miles apart 1 hour available is infeasible - Game end buffer (3 hour) validation - Arrival buffer (1 hour) validation Also removes broken DayCardTests that referenced types removed in previous refactor (DayCard, DayConflictInfo). Total: 17 GameDAGRouter edge case tests all passing. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -342,4 +342,196 @@ struct GameDAGRouterTests {
|
||||
|
||||
#expect(routeWithBoth != nil, "With repeat cities ON, should allow both LA games")
|
||||
}
|
||||
|
||||
// MARK: - canTransition Boundary Tests (via findRoutes behavior)
|
||||
|
||||
@Test("Same stadium same day 4 hours apart is feasible")
|
||||
func findRoutes_SameStadium_SameDay_4HoursApart_Feasible() {
|
||||
let stadium = losAngelesStadium
|
||||
|
||||
// Same stadium, 4 hours apart - should be feasible
|
||||
let game1 = makeGame(stadiumId: stadium.id, startTime: date("2026-06-15 14:00"))
|
||||
let game2 = makeGame(stadiumId: stadium.id, startTime: date("2026-06-15 20:00"))
|
||||
|
||||
let result = GameDAGRouter.findRoutes(
|
||||
games: [game1, game2],
|
||||
stadiums: [stadium.id: stadium],
|
||||
constraints: .default
|
||||
)
|
||||
|
||||
// Should have a route with both games (same stadium is always feasible)
|
||||
let routeWithBoth = result.first { route in
|
||||
route.count == 2 &&
|
||||
route.contains { $0.id == game1.id } &&
|
||||
route.contains { $0.id == game2.id }
|
||||
}
|
||||
|
||||
#expect(routeWithBoth != nil, "Same stadium transition should be feasible")
|
||||
}
|
||||
|
||||
@Test("Different stadium 1000 miles apart same day is infeasible")
|
||||
func findRoutes_DifferentStadium_1000Miles_SameDay_Infeasible() {
|
||||
// LA to Chicago is ~1750 miles, way too far for same day
|
||||
let la = losAngelesStadium
|
||||
let chicago = chicagoStadium
|
||||
|
||||
// Same day, 6 hours apart - impossible to drive 1750 miles
|
||||
let game1 = makeGame(stadiumId: la.id, startTime: date("2026-06-15 13:00"))
|
||||
let game2 = makeGame(stadiumId: chicago.id, startTime: date("2026-06-15 20:00"))
|
||||
|
||||
let result = GameDAGRouter.findRoutes(
|
||||
games: [game1, game2],
|
||||
stadiums: [la.id: la, chicago.id: chicago],
|
||||
constraints: .default
|
||||
)
|
||||
|
||||
// Should NOT have a combined route (too far for same day)
|
||||
let routeWithBoth = result.first { route in
|
||||
route.count == 2 &&
|
||||
route.contains { $0.id == game1.id } &&
|
||||
route.contains { $0.id == game2.id }
|
||||
}
|
||||
|
||||
#expect(routeWithBoth == nil, "1750 miles same day should be infeasible")
|
||||
}
|
||||
|
||||
@Test("Different stadium 1000 miles apart 2 days apart is feasible")
|
||||
func findRoutes_DifferentStadium_1000Miles_2DaysApart_Feasible() {
|
||||
// LA to Chicago is ~1750 miles, but 2 days gives 16 hours driving (at 60mph = 960 miles max)
|
||||
// Actually need more time - let's use 3 days for 1750 miles at 60mph = ~29 hours
|
||||
// 3 days * 8 hours/day = 24 hours driving - still not enough
|
||||
// Use LA to SF (~380 miles) which is doable in 1-2 days
|
||||
let la = losAngelesStadium
|
||||
let sf = sanFranciscoStadium
|
||||
|
||||
// 2 days apart - 380 miles * 1.3 = 494 miles, at 60mph = 8.2 hours
|
||||
// 2 days * 8 hours = 16 hours available - feasible
|
||||
let game1 = makeGame(stadiumId: la.id, startTime: date("2026-06-15 19:00"))
|
||||
let game2 = makeGame(stadiumId: sf.id, startTime: date("2026-06-17 19:00"))
|
||||
|
||||
let result = GameDAGRouter.findRoutes(
|
||||
games: [game1, game2],
|
||||
stadiums: [la.id: la, sf.id: sf],
|
||||
constraints: .default
|
||||
)
|
||||
|
||||
let routeWithBoth = result.first { route in
|
||||
route.count == 2 &&
|
||||
route.contains { $0.id == game1.id } &&
|
||||
route.contains { $0.id == game2.id }
|
||||
}
|
||||
|
||||
#expect(routeWithBoth != nil, "380 miles with 2 days should be feasible")
|
||||
}
|
||||
|
||||
@Test("Different stadium 100 miles apart 4 hours available is feasible")
|
||||
func findRoutes_DifferentStadium_100Miles_4HoursAvailable_Feasible() {
|
||||
// Create stadiums ~100 miles apart (roughly LA to San Diego distance)
|
||||
let la = losAngelesStadium
|
||||
let sanDiego = makeStadium(city: "San Diego", lat: 32.7076, lon: -117.1569)
|
||||
|
||||
// LA to San Diego is ~120 miles * 1.3 = 156 road miles, at 60mph = 2.6 hours
|
||||
// Game 1 at 14:00, ends ~17:00 (3hr buffer), departure 17:00
|
||||
// Game 2 at 21:00, must arrive by 20:00 (1hr buffer)
|
||||
// Available: 3 hours - just enough for 2.6 hour drive
|
||||
let game1 = makeGame(stadiumId: la.id, startTime: date("2026-06-15 14:00"))
|
||||
let game2 = makeGame(stadiumId: sanDiego.id, startTime: date("2026-06-15 21:00"))
|
||||
|
||||
let result = GameDAGRouter.findRoutes(
|
||||
games: [game1, game2],
|
||||
stadiums: [la.id: la, sanDiego.id: sanDiego],
|
||||
constraints: .default
|
||||
)
|
||||
|
||||
let routeWithBoth = result.first { route in
|
||||
route.count == 2 &&
|
||||
route.contains { $0.id == game1.id } &&
|
||||
route.contains { $0.id == game2.id }
|
||||
}
|
||||
|
||||
#expect(routeWithBoth != nil, "~120 miles with 4 hours available should be feasible")
|
||||
}
|
||||
|
||||
@Test("Different stadium 100 miles apart 1 hour available is infeasible")
|
||||
func findRoutes_DifferentStadium_100Miles_1HourAvailable_Infeasible() {
|
||||
let la = losAngelesStadium
|
||||
let sanDiego = makeStadium(city: "San Diego", lat: 32.7076, lon: -117.1569)
|
||||
|
||||
// Game 1 at 14:00, ends ~17:00 (3hr buffer)
|
||||
// Game 2 at 18:00, must arrive by 17:00 (1hr buffer)
|
||||
// Available: 0 hours - not enough for any driving
|
||||
let game1 = makeGame(stadiumId: la.id, startTime: date("2026-06-15 14:00"))
|
||||
let game2 = makeGame(stadiumId: sanDiego.id, startTime: date("2026-06-15 18:00"))
|
||||
|
||||
let result = GameDAGRouter.findRoutes(
|
||||
games: [game1, game2],
|
||||
stadiums: [la.id: la, sanDiego.id: sanDiego],
|
||||
constraints: .default
|
||||
)
|
||||
|
||||
// Should NOT have a combined route (not enough time)
|
||||
let routeWithBoth = result.first { route in
|
||||
route.count == 2 &&
|
||||
route.contains { $0.id == game1.id } &&
|
||||
route.contains { $0.id == game2.id }
|
||||
}
|
||||
|
||||
#expect(routeWithBoth == nil, "~120 miles with no available time should be infeasible")
|
||||
}
|
||||
|
||||
@Test("Game end buffer - 3 hour buffer after game end before departure")
|
||||
func findRoutes_GameEndBuffer_3Hours() {
|
||||
let la = losAngelesStadium
|
||||
let sanDiego = makeStadium(city: "San Diego", lat: 32.7076, lon: -117.1569)
|
||||
|
||||
// Game 1 at 14:00, ends + 3hr buffer = departure 17:00
|
||||
// LA to SD: ~113 miles * 1.3 = 147 road miles, at 60mph = 2.45 hours
|
||||
// Game 2 at 19:30 - arrival deadline 18:30 (1hr buffer)
|
||||
// Available: 1.5 hours (17:00 to 18:30) - clearly infeasible for 2.45 hour drive
|
||||
let game1 = makeGame(stadiumId: la.id, startTime: date("2026-06-15 14:00"))
|
||||
let game2 = makeGame(stadiumId: sanDiego.id, startTime: date("2026-06-15 19:30"))
|
||||
|
||||
let result = GameDAGRouter.findRoutes(
|
||||
games: [game1, game2],
|
||||
stadiums: [la.id: la, sanDiego.id: sanDiego],
|
||||
constraints: .default
|
||||
)
|
||||
|
||||
// With 3hr game end buffer: depart 17:00, arrive by 18:30 = 1.5 hours
|
||||
// Need 2.45 hours driving - clearly infeasible
|
||||
let routeWithBoth = result.first { route in
|
||||
route.count == 2 &&
|
||||
route.contains { $0.id == game1.id } &&
|
||||
route.contains { $0.id == game2.id }
|
||||
}
|
||||
|
||||
#expect(routeWithBoth == nil, "Only 1.5 hours available for 2.45 hour drive should be infeasible")
|
||||
}
|
||||
|
||||
@Test("Arrival buffer - 1 hour buffer before next game start")
|
||||
func findRoutes_ArrivalBuffer_1Hour() {
|
||||
let la = losAngelesStadium
|
||||
let sanDiego = makeStadium(city: "San Diego", lat: 32.7076, lon: -117.1569)
|
||||
|
||||
// Game 1 at 14:00, ends + 3hr buffer = depart 17:00
|
||||
// Need ~2.6 hours driving
|
||||
// Game 2 at 22:00 - arrival deadline 21:00
|
||||
// Available: 4 hours (17:00 to 21:00) - feasible
|
||||
let game1 = makeGame(stadiumId: la.id, startTime: date("2026-06-15 14:00"))
|
||||
let game2 = makeGame(stadiumId: sanDiego.id, startTime: date("2026-06-15 22:00"))
|
||||
|
||||
let result = GameDAGRouter.findRoutes(
|
||||
games: [game1, game2],
|
||||
stadiums: [la.id: la, sanDiego.id: sanDiego],
|
||||
constraints: .default
|
||||
)
|
||||
|
||||
let routeWithBoth = result.first { route in
|
||||
route.count == 2 &&
|
||||
route.contains { $0.id == game1.id } &&
|
||||
route.contains { $0.id == game2.id }
|
||||
}
|
||||
|
||||
#expect(routeWithBoth != nil, "4 hours available (with 1hr arrival buffer) should be feasible")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user