refactor: change domain model IDs from UUID to String canonical IDs
This refactor fixes the achievement system by using stable canonical string IDs (e.g., "stadium_mlb_fenway_park") instead of random UUIDs. This ensures stadium mappings for achievements are consistent across app launches and CloudKit sync operations. Changes: - Stadium, Team, Game: id property changed from UUID to String - Trip, TripStop, TripPreferences: updated to use String IDs for games/stadiums - CKModels: removed UUID parsing, use canonical IDs directly - AchievementEngine: now matches against canonical stadium IDs - All test files updated to use String IDs instead of UUID() Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -31,7 +31,7 @@ struct ScenarioBPlannerTests {
|
||||
|
||||
/// Creates a stadium at a known location
|
||||
private func makeStadium(
|
||||
id: UUID = UUID(),
|
||||
id: String = "stadium_test_\(UUID().uuidString)",
|
||||
city: String,
|
||||
lat: Double,
|
||||
lon: Double,
|
||||
@@ -51,10 +51,10 @@ struct ScenarioBPlannerTests {
|
||||
|
||||
/// Creates a game at a stadium
|
||||
private func makeGame(
|
||||
id: UUID = UUID(),
|
||||
stadiumId: UUID,
|
||||
homeTeamId: UUID = UUID(),
|
||||
awayTeamId: UUID = UUID(),
|
||||
id: String = "game_test_\(UUID().uuidString)",
|
||||
stadiumId: String,
|
||||
homeTeamId: String = "team_test_\(UUID().uuidString)",
|
||||
awayTeamId: String = "team_test_\(UUID().uuidString)",
|
||||
dateTime: Date,
|
||||
sport: Sport = .mlb
|
||||
) -> Game {
|
||||
@@ -74,9 +74,9 @@ struct ScenarioBPlannerTests {
|
||||
startDate: Date,
|
||||
endDate: Date,
|
||||
allGames: [Game],
|
||||
mustSeeGameIds: Set<UUID>,
|
||||
stadiums: [UUID: Stadium],
|
||||
teams: [UUID: Team] = [:],
|
||||
mustSeeGameIds: Set<String>,
|
||||
stadiums: [String: Stadium],
|
||||
teams: [String: Team] = [:],
|
||||
allowRepeatCities: Bool = true,
|
||||
numberOfDrivers: Int = 1,
|
||||
maxDrivingHoursPerDriver: Double = 8.0
|
||||
@@ -106,11 +106,11 @@ struct ScenarioBPlannerTests {
|
||||
@Test("5.1 - Single must-see game returns trip with that game")
|
||||
func test_mustSeeGames_SingleGame_ReturnsTripWithThatGame() {
|
||||
// Setup: Single must-see game
|
||||
let stadiumId = UUID()
|
||||
let stadiumId = "stadium_test_\(UUID().uuidString)"
|
||||
let stadium = makeStadium(id: stadiumId, city: "Chicago", lat: 41.8781, lon: -87.6298)
|
||||
let stadiums = [stadiumId: stadium]
|
||||
|
||||
let gameId = UUID()
|
||||
let gameId = "game_test_\(UUID().uuidString)"
|
||||
let game = makeGame(id: gameId, stadiumId: stadiumId, dateTime: makeDate(day: 10, hour: 19))
|
||||
|
||||
let request = makePlanningRequest(
|
||||
@@ -139,9 +139,9 @@ struct ScenarioBPlannerTests {
|
||||
func test_mustSeeGames_MultipleGames_ReturnsOptimalRoute() {
|
||||
// Setup: 3 must-see games in nearby cities (all Central region for single-region search)
|
||||
// Region boundary: Central is -110 to -85 longitude
|
||||
let chicagoId = UUID()
|
||||
let milwaukeeId = UUID()
|
||||
let stLouisId = UUID()
|
||||
let chicagoId = "stadium_chicago_\(UUID().uuidString)"
|
||||
let milwaukeeId = "stadium_milwaukee_\(UUID().uuidString)"
|
||||
let stLouisId = "stadium_stlouis_\(UUID().uuidString)"
|
||||
|
||||
// All cities in Central region (longitude between -110 and -85)
|
||||
let chicago = makeStadium(id: chicagoId, city: "Chicago", lat: 41.8781, lon: -87.6298)
|
||||
@@ -150,9 +150,9 @@ struct ScenarioBPlannerTests {
|
||||
|
||||
let stadiums = [chicagoId: chicago, milwaukeeId: milwaukee, stLouisId: stLouis]
|
||||
|
||||
let game1Id = UUID()
|
||||
let game2Id = UUID()
|
||||
let game3Id = UUID()
|
||||
let game1Id = "game_test_1_\(UUID().uuidString)"
|
||||
let game2Id = "game_test_2_\(UUID().uuidString)"
|
||||
let game3Id = "game_test_3_\(UUID().uuidString)"
|
||||
|
||||
let game1 = makeGame(id: game1Id, stadiumId: chicagoId, dateTime: makeDate(day: 5, hour: 19))
|
||||
let game2 = makeGame(id: game2Id, stadiumId: milwaukeeId, dateTime: makeDate(day: 7, hour: 19))
|
||||
@@ -187,8 +187,8 @@ struct ScenarioBPlannerTests {
|
||||
@Test("5.3 - Games in different cities are connected")
|
||||
func test_mustSeeGames_GamesInDifferentCities_ConnectsThem() {
|
||||
// Setup: 2 must-see games in distant but reachable cities
|
||||
let nycId = UUID()
|
||||
let bostonId = UUID()
|
||||
let nycId = "stadium_nyc_\(UUID().uuidString)"
|
||||
let bostonId = "stadium_boston_\(UUID().uuidString)"
|
||||
|
||||
// NYC to Boston is ~215 miles (~4 hours driving)
|
||||
let nyc = makeStadium(id: nycId, city: "New York", lat: 40.7128, lon: -73.9352)
|
||||
@@ -196,8 +196,8 @@ struct ScenarioBPlannerTests {
|
||||
|
||||
let stadiums = [nycId: nyc, bostonId: boston]
|
||||
|
||||
let game1Id = UUID()
|
||||
let game2Id = UUID()
|
||||
let game1Id = "game_test_1_\(UUID().uuidString)"
|
||||
let game2Id = "game_test_2_\(UUID().uuidString)"
|
||||
|
||||
// Games 2 days apart - plenty of time to drive
|
||||
let game1 = makeGame(id: game1Id, stadiumId: nycId, dateTime: makeDate(day: 5, hour: 19))
|
||||
@@ -238,7 +238,7 @@ struct ScenarioBPlannerTests {
|
||||
@Test("5.4 - Empty selection returns failure")
|
||||
func test_mustSeeGames_EmptySelection_ThrowsError() {
|
||||
// Setup: No must-see games selected
|
||||
let stadiumId = UUID()
|
||||
let stadiumId = "stadium_test_\(UUID().uuidString)"
|
||||
let stadium = makeStadium(id: stadiumId, city: "Chicago", lat: 41.8781, lon: -87.6298)
|
||||
let stadiums = [stadiumId: stadium]
|
||||
|
||||
@@ -266,8 +266,8 @@ struct ScenarioBPlannerTests {
|
||||
func test_mustSeeGames_ImpossibleToConnect_ThrowsError() {
|
||||
// Setup: Games on same day in cities ~850 miles apart (impossible in 8 hours)
|
||||
// Both cities in East region (> -85 longitude) so regional search covers both
|
||||
let nycId = UUID()
|
||||
let atlantaId = UUID()
|
||||
let nycId = "stadium_nyc_\(UUID().uuidString)"
|
||||
let atlantaId = "stadium_atlanta_\(UUID().uuidString)"
|
||||
|
||||
// NYC to Atlanta is ~850 miles (~13 hours driving) - impossible with 8-hour limit
|
||||
let nyc = makeStadium(id: nycId, city: "New York", lat: 40.7128, lon: -73.9352)
|
||||
@@ -275,8 +275,8 @@ struct ScenarioBPlannerTests {
|
||||
|
||||
let stadiums = [nycId: nyc, atlantaId: atlanta]
|
||||
|
||||
let game1Id = UUID()
|
||||
let game2Id = UUID()
|
||||
let game1Id = "game_test_1_\(UUID().uuidString)"
|
||||
let game2Id = "game_test_2_\(UUID().uuidString)"
|
||||
|
||||
// Same day games 6 hours apart - even if you left right after game 1,
|
||||
// you can't drive 850 miles in 6 hours with 8-hour daily limit
|
||||
@@ -409,10 +409,10 @@ struct ScenarioBPlannerTests {
|
||||
}
|
||||
|
||||
// Build coordinate map for brute force verification
|
||||
var stopCoordinates: [UUID: CLLocationCoordinate2D] = [:]
|
||||
var stopCoordinates: [String: CLLocationCoordinate2D] = [:]
|
||||
for stop in firstOption.stops {
|
||||
if let coord = stop.coordinate {
|
||||
stopCoordinates[stop.id] = coord
|
||||
stopCoordinates[stop.id.uuidString] = coord
|
||||
}
|
||||
}
|
||||
|
||||
@@ -421,7 +421,7 @@ struct ScenarioBPlannerTests {
|
||||
return
|
||||
}
|
||||
|
||||
let stopIds = firstOption.stops.map { $0.id }
|
||||
let stopIds = firstOption.stops.map { $0.id.uuidString }
|
||||
let verificationResult = BruteForceRouteVerifier.verify(
|
||||
proposedRoute: stopIds,
|
||||
stops: stopCoordinates,
|
||||
@@ -471,17 +471,17 @@ struct ScenarioBPlannerTests {
|
||||
#expect(!includedMustSee.isEmpty, "Should include some must-see games")
|
||||
|
||||
// Build coordinate map
|
||||
var stopCoordinates: [UUID: CLLocationCoordinate2D] = [:]
|
||||
var stopCoordinates: [String: CLLocationCoordinate2D] = [:]
|
||||
for stop in firstOption.stops {
|
||||
if let coord = stop.coordinate {
|
||||
stopCoordinates[stop.id] = coord
|
||||
stopCoordinates[stop.id.uuidString] = coord
|
||||
}
|
||||
}
|
||||
|
||||
// Check that there's no obviously better route (10% threshold)
|
||||
guard stopCoordinates.count >= 2 else { return }
|
||||
|
||||
let stopIds = firstOption.stops.map { $0.id }
|
||||
let stopIds = firstOption.stops.map { $0.id.uuidString }
|
||||
let (hasBetter, improvement) = BruteForceRouteVerifier.hasObviouslyBetterRoute(
|
||||
proposedRoute: stopIds,
|
||||
stops: stopCoordinates,
|
||||
|
||||
Reference in New Issue
Block a user