|
8 | 8 | import Foundation |
9 | 9 |
|
10 | 10 | class FitnessCalculator { |
| 11 | + enum Pace: Int { |
| 12 | + case verySlowWalk = 0 |
| 13 | + case slowWalk = 1 |
| 14 | + case avgWalk = 2 |
| 15 | + case briskWalk = 3 |
| 16 | + case jog = 4 |
| 17 | + case run = 5 |
| 18 | + case fastRun = 6 |
| 19 | + case veryFastRun = 7 |
| 20 | + |
| 21 | + var metValue: Double { |
| 22 | + switch self { |
| 23 | + case .verySlowWalk: return 2.0 |
| 24 | + case .slowWalk: return 2.8 |
| 25 | + case .avgWalk: return 3.5 |
| 26 | + case .briskWalk: return 4.3 |
| 27 | + case .jog: return 7.0 |
| 28 | + case .run: return 9.8 |
| 29 | + case .fastRun: return 11.0 |
| 30 | + case .veryFastRun: return 13.0 |
| 31 | + } |
| 32 | + } |
| 33 | + |
| 34 | + var milesPerHour: Double { |
| 35 | + switch self { |
| 36 | + case .verySlowWalk: return 1.0 |
| 37 | + case .slowWalk: return 2.0 |
| 38 | + case .avgWalk: return 3.0 |
| 39 | + case .briskWalk: return 4.0 |
| 40 | + case .jog: return 5.0 |
| 41 | + case .run: return 6.0 |
| 42 | + case .fastRun: return 7.5 |
| 43 | + case .veryFastRun: return 10.0 |
| 44 | + } |
| 45 | + } |
| 46 | + } |
| 47 | + |
11 | 48 | let personalizationController = PersonalizationController.shared |
12 | 49 | let bleManager = BLEManager.shared |
13 | 50 |
|
14 | | - func calculateDistance(steps: Int) -> Double { |
15 | | - let avgStrideRatio = 0.413 |
16 | | - let height = personalizationController.calculatedHeight |
17 | | - let strideLength = height * avgStrideRatio * (personalizationController.gender == .male ? 1.0 : 0.9) |
18 | | - |
| 51 | + func calculateDistance(steps: Int, pace: FitnessCalculator.Pace = .avgWalk) -> Double { |
| 52 | + let avgStrideRatio = personalizationController.gender == .male ? 0.415 : 0.413 |
| 53 | + let calculatedHeight = personalizationController.calculatedHeight |
| 54 | + let height = personalizationController.units == .metric ? (calculatedHeight / 2.54) : (calculatedHeight) // Convert to inches |
| 55 | + let baseStrideLength = height * avgStrideRatio |
| 56 | + |
| 57 | + // Adjust stride length based on pace |
| 58 | + let strideMultiplier: Double = { |
| 59 | + switch pace { |
| 60 | + case .verySlowWalk: return 0.85 |
| 61 | + case .slowWalk: return 0.95 |
| 62 | + case .avgWalk: return 1.0 |
| 63 | + case .briskWalk: return 1.1 |
| 64 | + case .jog: return 1.25 |
| 65 | + case .run: return 1.4 |
| 66 | + case .fastRun: return 1.55 |
| 67 | + case .veryFastRun: return 1.7 |
| 68 | + } |
| 69 | + }() |
| 70 | + |
| 71 | + let strideLength = baseStrideLength * strideMultiplier |
19 | 72 | var distance = strideLength * Double(steps) |
20 | 73 |
|
21 | | - // Unit conversion |
22 | 74 | if personalizationController.units == .imperial { |
23 | | - distance /= (100.0 * 1609.34) |
| 75 | + distance /= 63360 // Convert inches to miles |
24 | 76 | } else { |
25 | | - distance /= 100000 |
| 77 | + distance /= 39370 // Convert inches to kilometers |
26 | 78 | } |
27 | | - |
| 79 | + |
28 | 80 | return distance |
29 | 81 | } |
30 | 82 |
|
31 | | - func calculateCaloriesBurned(steps: Int) -> Double { |
32 | | - return 0.0 |
| 83 | + func stepsPerMinute(steps: Int, pace: FitnessCalculator.Pace = .avgWalk) -> Int { |
| 84 | + // TODO: update for metric |
| 85 | + let distance = calculateDistance(steps: steps, pace: pace) |
| 86 | + let timeMinutes = (distance / pace.milesPerHour) * 60.0 |
| 87 | + |
| 88 | + let spm = Double(steps) / timeMinutes |
| 89 | + return Int(ceil(spm)) |
| 90 | + } |
| 91 | + |
| 92 | + func calculateCaloriesBurned(steps: Int, pace: FitnessCalculator.Pace = .avgWalk) -> Int { |
| 93 | + // TODO: support custom duration |
| 94 | + let spm = stepsPerMinute(steps: steps, pace: pace) |
| 95 | + let weight = personalizationController.calculatedWeight |
| 96 | + let calculatedWeight = personalizationController.units == .metric ? weight : (weight * 0.453592) |
| 97 | + let durationInHours = Double(steps) / Double(spm) / 60.0 |
| 98 | + |
| 99 | + let caloriesBurned = Int(ceil(pace.metValue * calculatedWeight * durationInHours)) |
| 100 | + return caloriesBurned |
33 | 101 | } |
34 | 102 | } |
0 commit comments