Просмотр исходного кода

Add validation guards for FPU settings to avoid out-of-range issues post migration 0.2.5 to 0.5.0

Deniz Cengiz 1 год назад
Родитель
Сommit
c155ba7398

+ 15 - 10
Trio/Sources/APS/Storage/CarbsStorage.swift

@@ -27,6 +27,8 @@ final class BaseCarbsStorage: CarbsStorage, Injectable {
 
     private let updateSubject = PassthroughSubject<Void, Never>()
 
+    private let settingsProvider = PickerSettingsProvider.shared
+
     var updatePublisher: AnyPublisher<Void, Never> {
         updateSubject.eraseToAnyPublisher()
     }
@@ -111,7 +113,7 @@ final class BaseCarbsStorage: CarbsStorage, Injectable {
 
      - Returns: The computed duration in hours.
      */
-    private func calculateComputedDuration(fpus: Decimal, timeCap: Int) -> Int {
+    private func calculateComputedDuration(fpus: Decimal, timeCap: Decimal) -> Decimal {
         switch fpus {
         case ..<2:
             return 3
@@ -145,22 +147,25 @@ final class BaseCarbsStorage: CarbsStorage, Injectable {
         createdAt: Date,
         actualDate: Date?
     ) -> ([CarbsEntry], Decimal) {
-        let interval = settings.settings.minuteInterval
-        let timeCap = settings.settings.timeCap
-        let adjustment = settings.settings.individualAdjustmentFactor
-        let delay = settings.settings.delay
+        let interval = min(settings.settings.minuteInterval, settingsProvider.settings.minuteInterval.max)
+        let timeCap = min(settings.settings.timeCap, settingsProvider.settings.timeCap.max)
+        let adjustment = min(
+            settings.settings.individualAdjustmentFactor,
+            settingsProvider.settings.individualAdjustmentFactor.max
+        )
+        let delay = min(settings.settings.delay, settingsProvider.settings.delay.max)
 
         let kcal = protein * 4 + fat * 9
         let carbEquivalents = (kcal / 10) * adjustment
         let fpus = carbEquivalents / 10
         var computedDuration = calculateComputedDuration(fpus: fpus, timeCap: timeCap)
 
-        var carbEquivalentSize: Decimal = carbEquivalents / Decimal(computedDuration)
-        carbEquivalentSize /= Decimal(60 / interval)
+        var carbEquivalentSize: Decimal = carbEquivalents / computedDuration
+        carbEquivalentSize /= Decimal(60) / interval
 
         if carbEquivalentSize < 1.0 {
             carbEquivalentSize = 1.0
-            computedDuration = Int(carbEquivalents / carbEquivalentSize)
+            computedDuration = min(carbEquivalents / carbEquivalentSize, timeCap)
         }
 
         let roundedEquivalent: Double = round(Double(carbEquivalentSize * 10)) / 10
@@ -173,8 +178,8 @@ final class BaseCarbsStorage: CarbsStorage, Injectable {
         var firstIndex = true
 
         while carbEquivalents > 0, numberOfEquivalents > 0 {
-            useDate = firstIndex ? useDate.addingTimeInterval(delay.minutes.timeInterval) : useDate
-                .addingTimeInterval(interval.minutes.timeInterval)
+            useDate = firstIndex ? useDate.addingTimeInterval(TimeInterval(delay)) : useDate
+                .addingTimeInterval(TimeInterval(interval))
             firstIndex = false
 
             let eachCarbEntry = CarbsEntry(

+ 6 - 6
Trio/Sources/Models/TrioSettings.swift

@@ -42,9 +42,9 @@ struct TrioSettings: JSON, Equatable {
     var showCarbsRequiredBadge: Bool = true
     var useFPUconversion: Bool = true
     var individualAdjustmentFactor: Decimal = 0.5
-    var timeCap: Int = 8
-    var minuteInterval: Int = 30
-    var delay: Int = 60
+    var timeCap: Decimal = 8
+    var minuteInterval: Decimal = 30
+    var delay: Decimal = 60
     var useAppleHealth: Bool = false
     var smoothGlucose: Bool = false
     var eA1cDisplayUnit: EstimatedA1cDisplayUnit = .percent
@@ -167,15 +167,15 @@ extension TrioSettings: Decodable {
             settings.overrideFactor = overrideFactor
         }
 
-        if let timeCap = try? container.decode(Int.self, forKey: .timeCap) {
+        if let timeCap = try? container.decode(Decimal.self, forKey: .timeCap) {
             settings.timeCap = timeCap
         }
 
-        if let minuteInterval = try? container.decode(Int.self, forKey: .minuteInterval) {
+        if let minuteInterval = try? container.decode(Decimal.self, forKey: .minuteInterval) {
             settings.minuteInterval = minuteInterval
         }
 
-        if let delay = try? container.decode(Int.self, forKey: .delay) {
+        if let delay = try? container.decode(Decimal.self, forKey: .delay) {
             settings.delay = delay
         }
 

+ 13 - 24
Trio/Sources/Modules/MealSettings/MealSettingsStateModel.swift

@@ -16,36 +16,25 @@ extension MealSettings {
         override func subscribe() {
             units = settingsManager.settings.units
 
-            subscribeSetting(\.useFPUconversion, on: $useFPUconversion) { useFPUconversion = $0 }
             subscribeSetting(\.maxCarbs, on: $maxCarbs) { maxCarbs = $0 }
             subscribeSetting(\.maxFat, on: $maxFat) { maxFat = $0 }
             subscribeSetting(\.maxProtein, on: $maxProtein) { maxProtein = $0 }
 
-            subscribeSetting(\.timeCap, on: $timeCap.map(Int.init), initial: {
-                timeCap = Decimal($0)
-            }, map: {
-                $0
-            })
-
             subscribePreferencesSetting(\.maxMealAbsorptionTime, on: $maxMealAbsorptionTime) { maxMealAbsorptionTime = $0 }
 
-            subscribeSetting(\.minuteInterval, on: $minuteInterval.map(Int.init), initial: {
-                minuteInterval = Decimal($0)
-            }, map: {
-                $0
-            })
-
-            subscribeSetting(\.delay, on: $delay.map(Int.init), initial: {
-                delay = Decimal($0)
-            }, map: {
-                $0
-            })
-
-            subscribeSetting(\.individualAdjustmentFactor, on: $individualAdjustmentFactor, initial: {
-                individualAdjustmentFactor = $0
-            }, map: {
-                $0
-            })
+            subscribeSetting(\.useFPUconversion, on: $useFPUconversion) { useFPUconversion = $0 }
+
+            // "Fat and Protein Delay"
+            subscribeSetting(\.delay, on: $delay) { delay = $0 }
+
+            // "Maximum Duration"
+            subscribeSetting(\.timeCap, on: $timeCap) { timeCap = $0 }
+
+            // "Spread Interval"
+            subscribeSetting(\.minuteInterval, on: $minuteInterval) { minuteInterval = $0 }
+
+            // "Fat and Protein Percentage"
+            subscribeSetting(\.individualAdjustmentFactor, on: $individualAdjustmentFactor) { individualAdjustmentFactor = $0 }
         }
     }
 }