Explorar el Código

Add option for stale glucose values

polscm32 hace 1 año
padre
commit
67ef895848

+ 26 - 2
Trio/Sources/APS/CGM/GlucoseSimulatorSource.swift

@@ -120,6 +120,7 @@ class OscillatingGenerator: BloodGlucoseGenerator {
         static let amplitude: Double = 45.0
         static let period: Double = 10800.0 // 3 hours in seconds
         static let noiseAmplitude: Double = 5.0
+        static let produceStaleValues: Bool = false
     }
 
     /// UserDefaults keys for storing simulator parameters
@@ -128,6 +129,7 @@ class OscillatingGenerator: BloodGlucoseGenerator {
         static let amplitude = "GlucoseSimulator_Amplitude"
         static let period = "GlucoseSimulator_Period"
         static let noiseAmplitude = "GlucoseSimulator_NoiseAmplitude"
+        static let produceStaleValues = "GlucoseSimulator_ProduceStaleValues"
     }
 
     /// Amplitude of the oscillation (±45 mg/dL to create range from ~80 to ~170)
@@ -162,15 +164,26 @@ class OscillatingGenerator: BloodGlucoseGenerator {
         set { UserDefaults.standard.set(newValue, forKey: UserDefaultsKeys.noiseAmplitude) }
     }
 
+    /// Whether to produce stale (unchanging) glucose values
+    var produceStaleValues: Bool {
+        get { UserDefaults.standard.bool(forKey: UserDefaultsKeys.produceStaleValues) }
+        set { UserDefaults.standard.set(newValue, forKey: UserDefaultsKeys.produceStaleValues) }
+    }
+
     /// Start date for the simulation
     private let startup = Date()
 
+    /// Last generated glucose value for stale mode
+    private var lastGeneratedGlucose: Int?
+
     /// Reset all parameters to default values
     func resetToDefaults() {
         centerValue = Defaults.centerValue
         amplitude = Defaults.amplitude
         period = Defaults.period
         noiseAmplitude = Defaults.noiseAmplitude
+        produceStaleValues = Defaults.produceStaleValues
+        lastGeneratedGlucose = nil
     }
 
     /// Generates blood glucose values between the specified dates at the given interval
@@ -184,8 +197,19 @@ class OscillatingGenerator: BloodGlucoseGenerator {
         var currentDate = startDate
 
         while currentDate <= finishDate {
-            let glucose = generate(date: currentDate)
-            let direction = calculateDirection(at: currentDate)
+            let glucose: Int
+            let direction: BloodGlucose.Direction
+
+            if produceStaleValues, lastGeneratedGlucose != nil {
+                // In stale mode, use the last generated glucose value
+                glucose = lastGeneratedGlucose!
+                direction = .flat
+            } else {
+                // Generate a new glucose value
+                glucose = generate(date: currentDate)
+                direction = calculateDirection(at: currentDate)
+                lastGeneratedGlucose = glucose
+            }
 
             // Create BloodGlucose with the correct constructor
             let bloodGlucose = BloodGlucose(

+ 6 - 0
Trio/Sources/Localizations/Main/Localizable.xcstrings

@@ -124156,6 +124156,9 @@
     "Processing…" : {
 
     },
+    "Produce Stale Values" : {
+
+    },
     "profile" : {
       "localizations" : {
         "ar" : {
@@ -176987,6 +176990,9 @@
         }
       }
     },
+    "When stale values are enabled, the simulator will repeatedly output the last generated glucose value." : {
+
+    },
     "When Suspend Zeros IOB is enabled, any active temporary basal rates during a pump suspension are reset, with new 0 U/hr temporary basal rates added to counteract those done during suspension." : {
       "localizations" : {
         "ar" : {

+ 49 - 31
Trio/Sources/Modules/CGMSettings/View/CustomCGMOptionsView.swift

@@ -20,6 +20,7 @@ extension CGMSettings {
         @State private var amplitude: Double = UserDefaults.standard.double(forKey: "GlucoseSimulator_Amplitude")
         @State private var period: Double = UserDefaults.standard.double(forKey: "GlucoseSimulator_Period")
         @State private var noiseAmplitude: Double = UserDefaults.standard.double(forKey: "GlucoseSimulator_NoiseAmplitude")
+        @State private var produceStaleValues: Bool = UserDefaults.standard.bool(forKey: "GlucoseSimulator_ProduceStaleValues")
 
         // Initialize state variables with defaults if needed
         private func initializeSimulatorSettings() {
@@ -35,6 +36,7 @@ extension CGMSettings {
             if noiseAmplitude == 0 {
                 noiseAmplitude = OscillatingGenerator.Defaults.noiseAmplitude
             }
+            // produceStaleValues is already initialized as false by default
         }
 
         // Save simulator settings to UserDefaults
@@ -43,6 +45,7 @@ extension CGMSettings {
             UserDefaults.standard.set(amplitude, forKey: "GlucoseSimulator_Amplitude")
             UserDefaults.standard.set(period, forKey: "GlucoseSimulator_Period")
             UserDefaults.standard.set(noiseAmplitude, forKey: "GlucoseSimulator_NoiseAmplitude")
+            UserDefaults.standard.set(produceStaleValues, forKey: "GlucoseSimulator_ProduceStaleValues")
         }
 
         var body: some View {
@@ -227,43 +230,57 @@ extension CGMSettings {
                     .font(.headline)
                     .padding(.top, 8)
 
-                VStack(alignment: .leading, spacing: 8) {
-                    Text("Center Value: \(Int(centerValue)) mg/dL")
-                    Text("The average glucose level around which values will oscillate.")
-                        .font(.caption)
-                        .foregroundColor(.secondary)
-                    Slider(value: $centerValue, in: 80 ... 200, step: 1)
-                        .accentColor(.accentColor)
+                Toggle(isOn: $produceStaleValues) {
+                    VStack(alignment: .leading) {
+                        Text("Produce Stale Values")
+                    }
                 }
+                .padding(.vertical, 4)
 
-                VStack(alignment: .leading, spacing: 8) {
-                    Text("Amplitude: ±\(Int(amplitude)) mg/dL")
-                    Text("Range: \(Int(centerValue - amplitude))–\(Int(centerValue + amplitude)) mg/dL")
-                        .font(.caption)
-                        .foregroundColor(.secondary)
-                    Text("The maximum deviation from the center value. Higher values create wider swings.")
-                        .font(.caption)
-                        .foregroundColor(.secondary)
-                    Slider(value: $amplitude, in: 10 ... 100, step: 5)
-                        .accentColor(.accentColor)
-                }
+                if !produceStaleValues {
+                    VStack(alignment: .leading, spacing: 8) {
+                        Text("Center Value: \(Int(centerValue)) mg/dL")
+                        Text("The average glucose level around which values will oscillate.")
+                            .font(.caption)
+                            .foregroundColor(.secondary)
+                        Slider(value: $centerValue, in: 80 ... 200, step: 1)
+                            .accentColor(.accentColor)
+                    }
 
-                VStack(alignment: .leading, spacing: 8) {
-                    Text("Period: \(Int(period / 3600)) hours")
-                    Text("The time it takes to complete one full cycle from high to low and back to high.")
-                        .font(.caption)
-                        .foregroundColor(.secondary)
-                    Slider(value: $period, in: 3600 ... 21600, step: 1800)
-                        .accentColor(.accentColor)
-                }
+                    VStack(alignment: .leading, spacing: 8) {
+                        Text("Amplitude: ±\(Int(amplitude)) mg/dL")
+                        Text("Range: \(Int(centerValue - amplitude))–\(Int(centerValue + amplitude)) mg/dL")
+                            .font(.subheadline)
+                            .foregroundColor(.secondary)
+                        Text("The maximum deviation from the center value. Higher values create wider swings.")
+                            .font(.caption)
+                            .foregroundColor(.secondary)
+                        Slider(value: $amplitude, in: 10 ... 100, step: 5)
+                            .accentColor(.accentColor)
+                    }
+
+                    VStack(alignment: .leading, spacing: 8) {
+                        Text("Period: \(Int(period / 3600)) hours")
+                        Text("The time it takes to complete one full cycle from high to low and back to high.")
+                            .font(.caption)
+                            .foregroundColor(.secondary)
+                        Slider(value: $period, in: 3600 ... 21600, step: 1800)
+                            .accentColor(.accentColor)
+                    }
 
-                VStack(alignment: .leading, spacing: 8) {
-                    Text("Noise: ±\(Int(noiseAmplitude)) mg/dL")
-                    Text("Random variation added to each reading to simulate real-world sensor noise.")
+                    VStack(alignment: .leading, spacing: 8) {
+                        Text("Noise: ±\(Int(noiseAmplitude)) mg/dL")
+                        Text("Random variation added to each reading to simulate real-world sensor noise.")
+                            .font(.caption)
+                            .foregroundColor(.secondary)
+                        Slider(value: $noiseAmplitude, in: 0 ... 20, step: 1)
+                            .accentColor(.accentColor)
+                    }
+                } else {
+                    Text("When stale values are enabled, the simulator will repeatedly output the last generated glucose value.")
                         .font(.caption)
                         .foregroundColor(.secondary)
-                    Slider(value: $noiseAmplitude, in: 0 ... 20, step: 1)
-                        .accentColor(.accentColor)
+                        .padding(.vertical, 8)
                 }
 
                 Button("Reset to Defaults") {
@@ -271,6 +288,7 @@ extension CGMSettings {
                     amplitude = OscillatingGenerator.Defaults.amplitude
                     period = OscillatingGenerator.Defaults.period
                     noiseAmplitude = OscillatingGenerator.Defaults.noiseAmplitude
+                    produceStaleValues = OscillatingGenerator.Defaults.produceStaleValues
                     saveSimulatorSettings()
                 }
                 .buttonStyle(.bordered)