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:
Trey t
2026-01-12 09:24:33 -06:00
parent 4b2cacaeba
commit 1703ca5b0f
53 changed files with 642 additions and 727 deletions

View File

@@ -32,7 +32,7 @@ struct ScenarioCPlannerTests {
/// Creates a stadium at a known location
private func makeStadium(
id: UUID = UUID(),
id: String = "stadium_test_\(UUID().uuidString)",
city: String,
state: String = "ST",
lat: Double,
@@ -53,10 +53,10 @@ struct ScenarioCPlannerTests {
/// 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 {
@@ -91,8 +91,8 @@ struct ScenarioCPlannerTests {
startDate: Date,
endDate: Date,
allGames: [Game],
stadiums: [UUID: Stadium],
teams: [UUID: Team] = [:],
stadiums: [String: Stadium],
teams: [String: Team] = [:],
mustStopLocations: [LocationInput] = [],
allowRepeatCities: Bool = true,
numberOfDrivers: Int = 1,
@@ -127,8 +127,8 @@ struct ScenarioCPlannerTests {
func test_departReturn_SameCity_ReturnsRoundTrip() {
// Setup: Start and end in Chicago
// Create stadiums in Chicago and a nearby city (Milwaukee) for games along the route
let chicagoId = UUID()
let milwaukeeId = UUID()
let chicagoId = "stadium_chicago_\(UUID().uuidString)"
let milwaukeeId = "stadium_milwaukee_\(UUID().uuidString)"
let chicago = makeStadium(id: chicagoId, city: "Chicago", lat: 41.8781, lon: -87.6298)
let milwaukee = makeStadium(id: milwaukeeId, city: "Milwaukee", lat: 43.0389, lon: -87.9065)
@@ -169,10 +169,10 @@ struct ScenarioCPlannerTests {
@Test("6.2 - Different cities creates one-way route")
func test_departReturn_DifferentCities_ReturnsOneWayRoute() {
// Setup: Boston to Washington DC corridor (East Coast)
let bostonId = UUID()
let nycId = UUID()
let phillyId = UUID()
let dcId = UUID()
let bostonId = "stadium_boston_\(UUID().uuidString)"
let nycId = "stadium_nyc_\(UUID().uuidString)"
let phillyId = "stadium_philly_\(UUID().uuidString)"
let dcId = "stadium_dc_\(UUID().uuidString)"
// East Coast corridor from north to south
let boston = makeStadium(id: bostonId, city: "Boston", state: "MA", lat: 42.3601, lon: -71.0589)
@@ -220,10 +220,10 @@ struct ScenarioCPlannerTests {
func test_departReturn_GamesAlongCorridor_IncludesNearbyGames() {
// Setup: Chicago to St. Louis corridor
// Include games that are "along the way" (directional)
let chicagoId = UUID()
let springfieldId = UUID()
let stLouisId = UUID()
let milwaukeeId = UUID() // This is NOT along the route (north of Chicago)
let chicagoId = "stadium_chicago_\(UUID().uuidString)"
let springfieldId = "stadium_springfield_\(UUID().uuidString)"
let stLouisId = "stadium_stlouis_\(UUID().uuidString)"
let milwaukeeId = "stadium_milwaukee_\(UUID().uuidString)" // This is NOT along the route (north of Chicago)
// Chicago to St. Louis is ~300 miles south
let chicago = makeStadium(id: chicagoId, city: "Chicago", lat: 41.8781, lon: -87.6298)
@@ -280,9 +280,9 @@ struct ScenarioCPlannerTests {
@Test("6.4 - No games along route returns failure")
func test_departReturn_NoGamesAlongRoute_ThrowsError() {
// Setup: Start/end cities have no games
let chicagoId = UUID()
let stLouisId = UUID()
let seattleId = UUID() // Games here, but not along Chicago-St. Louis route
let chicagoId = "stadium_chicago_\(UUID().uuidString)"
let stLouisId = "stadium_stlouis_\(UUID().uuidString)"
let seattleId = "stadium_seattle_\(UUID().uuidString)" // Games here, but not along Chicago-St. Louis route
let chicago = makeStadium(id: chicagoId, city: "Chicago", lat: 41.8781, lon: -87.6298)
let stLouis = makeStadium(id: stLouisId, city: "St. Louis", lat: 38.6270, lon: -90.1994)
@@ -325,7 +325,7 @@ struct ScenarioCPlannerTests {
@Test("6.5 - Invalid city (no stadiums) returns failure")
func test_departReturn_InvalidCity_ThrowsError() {
// Setup: Start location is a city with no stadium
let chicagoId = UUID()
let chicagoId = "stadium_chicago_\(UUID().uuidString)"
let chicago = makeStadium(id: chicagoId, city: "Chicago", lat: 41.8781, lon: -87.6298)
let stadiums = [chicagoId: chicago]
@@ -357,10 +357,10 @@ struct ScenarioCPlannerTests {
func test_departReturn_ExtremeDistance_RespectsConstraints() {
// Setup: NYC to LA route (~2,800 miles)
// With 8 hours/day at 60 mph = 480 miles/day, this takes ~6 days just driving
let nycId = UUID()
let laId = UUID()
let chicagoId = UUID() // Along the route
let denverID = UUID() // Along the route
let nycId = "stadium_nyc_\(UUID().uuidString)"
let laId = "stadium_la_\(UUID().uuidString)"
let chicagoId = "stadium_chicago_\(UUID().uuidString)" // Along the route
let denverID = "stadium_denver_\(UUID().uuidString)" // Along the route
let nyc = makeStadium(id: nycId, city: "New York", lat: 40.7128, lon: -73.9352)
let la = makeStadium(id: laId, city: "Los Angeles", lat: 34.0522, lon: -118.2437)
@@ -426,9 +426,9 @@ struct ScenarioCPlannerTests {
@Test("6.7 - Must-stop location is included in route")
func test_departReturn_WithMustStopLocation_IncludesStop() {
// Setup: Boston to DC with must-stop in Philadelphia
let bostonId = UUID()
let phillyId = UUID()
let dcId = UUID()
let bostonId = "stadium_boston_\(UUID().uuidString)"
let phillyId = "stadium_philly_\(UUID().uuidString)"
let dcId = "stadium_dc_\(UUID().uuidString)"
let boston = makeStadium(id: bostonId, city: "Boston", lat: 42.3601, lon: -71.0589)
let philly = makeStadium(id: phillyId, city: "Philadelphia", lat: 39.9526, lon: -75.1652)
@@ -476,8 +476,8 @@ struct ScenarioCPlannerTests {
@Test("6.8 - Must-stop with no nearby games is still included")
func test_departReturn_MustStopNoNearbyGames_IncludesStopAnyway() {
// Setup: Boston to DC with must-stop in a city without games
let bostonId = UUID()
let dcId = UUID()
let bostonId = "stadium_boston_\(UUID().uuidString)"
let dcId = "stadium_dc_\(UUID().uuidString)"
let boston = makeStadium(id: bostonId, city: "Boston", lat: 42.3601, lon: -71.0589)
let dc = makeStadium(id: dcId, city: "Washington", lat: 38.9072, lon: -77.0369)
@@ -528,10 +528,10 @@ struct ScenarioCPlannerTests {
@Test("6.9 - Multiple must-stops are all included")
func test_departReturn_MultipleMustStops_AllIncluded() {
// Setup: Boston to DC with must-stops in NYC and Philadelphia
let bostonId = UUID()
let nycId = UUID()
let phillyId = UUID()
let dcId = UUID()
let bostonId = "stadium_boston_\(UUID().uuidString)"
let nycId = "stadium_nyc_\(UUID().uuidString)"
let phillyId = "stadium_philly_\(UUID().uuidString)"
let dcId = "stadium_dc_\(UUID().uuidString)"
let boston = makeStadium(id: bostonId, city: "Boston", lat: 42.3601, lon: -71.0589)
let nyc = makeStadium(id: nycId, city: "New York", lat: 40.7128, lon: -73.9352)
@@ -588,10 +588,10 @@ struct ScenarioCPlannerTests {
func test_departReturn_MustStopConflictsWithRoute_FindsCompromise() {
// Setup: Boston to DC with must-stop that's slightly off the optimal route
// Cleveland is west of the Boston-DC corridor but could be included with detour
let bostonId = UUID()
let dcId = UUID()
let clevelandId = UUID()
let pittsburghId = UUID()
let bostonId = "stadium_boston_\(UUID().uuidString)"
let dcId = "stadium_dc_\(UUID().uuidString)"
let clevelandId = "stadium_cleveland_\(UUID().uuidString)"
let pittsburghId = "stadium_pittsburgh_\(UUID().uuidString)"
let boston = makeStadium(id: bostonId, city: "Boston", lat: 42.3601, lon: -71.0589)
let dc = makeStadium(id: dcId, city: "Washington", lat: 38.9072, lon: -77.0369)