Files
workouts/Shared/Model/Enums.swift
T
rzen 2c1e4759ae Add machine comfort settings and tighten the document schemas
Machine-based exercises now carry ordered name/value comfort settings
(seat height, back-rest position, ...) on both ExerciseDocument and, as a
plan-time snapshot, WorkoutLogDocument — the optional array doubles as the
machine flag. Editable from the exercise editor's new Machine section and
from the workout row's settings sheet, whose mid-workout edits write back
to the originating split (workout saved first, so seed clone-on-edit
repointing can't clobber the log edit).

Schema tightening rides the same rev: splits bump to v2 (weight-reminder
fields and the unused exercise category removed), workouts to v3 (the
derived `completed` flag removed; status is the single source). Starter
seeds regenerated at v2 with unchanged ULIDs; SwiftData cache schema
bumped to rebuild. SCHEMA.md documents the shapes.

Claude-Session: https://claude.ai/code/session_01LEoff8bXGBS83tK1c55Mf7
2026-07-06 16:29:44 -04:00

118 lines
3.5 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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)" }
}