import Foundation /// Completion state of a workout or an individual exercise log. Persisted as its /// raw string in both the JSON documents and the SwiftData cache. enum WorkoutStatus: String, CaseIterable, Codable, Sendable { case notStarted case inProgress case completed case skipped var displayName: String { switch self { case .notStarted: "Not Started" case .inProgress: "In Progress" case .completed: "Completed" case .skipped: "Skipped" } } var name: String { displayName } } /// How an exercise's effort is measured. Persisted as its raw `Int` value. enum LoadType: Int, CaseIterable, Codable, Sendable { case none = 0 case weight = 1 case duration = 2 var name: String { switch self { case .none: "None" case .weight: "Weight" case .duration: "Duration" } } } /// The kind of training a split represents — used to tag the Apple Health workout /// so it lands in the right category (and credits the rings correctly), and to pick /// a MET value when the phone has to estimate calories without watch sensor data. /// Persisted as its raw `Int` on `SplitDocument`; the `HKWorkoutActivityType` /// mapping lives in `Shared/HealthKit/HealthKitMapping.swift` to keep this enum /// HealthKit-free. enum WorkoutActivityType: Int, CaseIterable, Codable, Sendable { case traditionalStrength = 0 // default case functionalStrength = 1 case hiit = 2 case coreTraining = 3 case cardio = 4 case cycling = 5 var displayName: String { switch self { case .traditionalStrength: "Strength Training" case .functionalStrength: "Functional Strength" case .hiit: "HIIT" case .coreTraining: "Core Training" case .cardio: "Cardio" case .cycling: "Cycling" } } var systemImage: String { switch self { case .traditionalStrength: "dumbbell.fill" case .functionalStrength: "figure.strengthtraining.functional" case .hiit: "figure.highintensity.intervaltraining" case .coreTraining: "figure.core.training" case .cardio: "figure.run" case .cycling: "figure.outdoor.cycle" } } /// Metabolic-equivalent value used only for the phone-side calorie estimate /// (`kcal ≈ MET × bodyweightKg × hours`) when no watch metrics are available. var met: Double { switch self { case .traditionalStrength: 5.0 case .functionalStrength: 4.0 case .hiit: 8.0 case .coreTraining: 4.0 case .cardio: 7.0 case .cycling: 7.5 } } } /// Where a workout's health metrics came from: real watch sensors, or a phone-side /// estimate written when no watch session ran. Persisted in `WorkoutMetrics`. enum MetricSource: String, Codable, Sendable { case watch case phoneEstimate } /// Display unit for weights. The stored weight values are plain integers and are /// never rewritten when this changes — switching only relabels what's shown. enum WeightUnit: String, CaseIterable, Codable, Sendable { case lb case kg var displayName: String { switch self { case .lb: "Pounds (lb)" case .kg: "Kilograms (kg)" } } var abbreviation: String { switch self { case .lb: "lb" case .kg: "kg" } } /// Render a stored weight value with the current unit's label, e.g. "135 lb". func format(_ value: Int) -> String { "\(value) \(abbreviation)" } }