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

@@ -20,7 +20,7 @@ struct BruteForceRouteVerifier {
let isOptimal: Bool
let proposedRouteDistance: Double
let optimalRouteDistance: Double
let optimalRoute: [UUID]?
let optimalRoute: [String]?
let improvement: Double? // Percentage improvement if not optimal
let permutationsChecked: Int
@@ -39,8 +39,8 @@ struct BruteForceRouteVerifier {
/// - tolerance: Percentage tolerance for "near-optimal" (default 0 = must be exactly optimal)
/// - Returns: Verification result
static func verify(
proposedRoute: [UUID],
stops: [UUID: CLLocationCoordinate2D],
proposedRoute: [String],
stops: [String: CLLocationCoordinate2D],
tolerance: Double = 0
) -> VerificationResult {
guard proposedRoute.count <= TestConstants.bruteForceMaxStops else {
@@ -64,7 +64,7 @@ struct BruteForceRouteVerifier {
// Find optimal route by checking all permutations
let allPermutations = permutations(of: proposedRoute)
var optimalDistance = Double.infinity
var optimalRoute: [UUID] = []
var optimalRoute: [String] = []
for permutation in allPermutations {
let distance = calculateRouteDistance(permutation, stops: stops)
@@ -102,10 +102,10 @@ struct BruteForceRouteVerifier {
/// Verify a route is optimal with a fixed start and end point
static func verifyWithFixedEndpoints(
proposedRoute: [UUID],
stops: [UUID: CLLocationCoordinate2D],
startId: UUID,
endId: UUID,
proposedRoute: [String],
stops: [String: CLLocationCoordinate2D],
startId: String,
endId: String,
tolerance: Double = 0
) -> VerificationResult {
guard proposedRoute.first == startId && proposedRoute.last == endId else {
@@ -132,7 +132,7 @@ struct BruteForceRouteVerifier {
// Generate all permutations of intermediate stops
let allPermutations = permutations(of: Array(intermediateStops))
var optimalDistance = Double.infinity
var optimalRoute: [UUID] = []
var optimalRoute: [String] = []
for permutation in allPermutations {
var fullRoute = [startId]
@@ -172,8 +172,8 @@ struct BruteForceRouteVerifier {
/// Check if there's an obviously better route (significantly shorter)
static func hasObviouslyBetterRoute(
proposedRoute: [UUID],
stops: [UUID: CLLocationCoordinate2D],
proposedRoute: [String],
stops: [String: CLLocationCoordinate2D],
threshold: Double = 0.1 // 10% improvement threshold
) -> (hasBetter: Bool, improvement: Double?) {
let result = verify(proposedRoute: proposedRoute, stops: stops, tolerance: threshold)
@@ -184,8 +184,8 @@ struct BruteForceRouteVerifier {
/// Calculate total route distance using haversine formula
static func calculateRouteDistance(
_ route: [UUID],
stops: [UUID: CLLocationCoordinate2D]
_ route: [String],
stops: [String: CLLocationCoordinate2D]
) -> Double {
guard route.count >= 2 else { return 0 }
@@ -263,15 +263,15 @@ struct BruteForceRouteVerifier {
extension BruteForceRouteVerifier {
/// Verify a trip's route is optimal
static func verifyTrip(_ trip: Trip) -> VerificationResult {
var stops: [UUID: CLLocationCoordinate2D] = [:]
var stops: [String: CLLocationCoordinate2D] = [:]
for stop in trip.stops {
if let coord = stop.coordinate {
stops[stop.id] = coord
stops[stop.id.uuidString] = coord
}
}
let routeIds = trip.stops.map { $0.id }
let routeIds = trip.stops.map { $0.id.uuidString }
return verify(proposedRoute: routeIds, stops: stops)
}