ソースを参照

More outlining; rough structure for determine and helpers WIP

Deniz Cengiz 11 ヶ月 前
コミット
a90160d34b

+ 76 - 21
Trio/Sources/APS/OpenAPSSwift/DetermineBasal/DetermineBasalGenerator.swift

@@ -1,24 +1,20 @@
 import Foundation
 
-struct DeterminationRequest {
-    let glucose:        [BloodGlucose]
-    let pumpHistory:    [PumpHistoryEvent]
-    let carbTreatments: [MealInput]
-    let currentTemp:    TempBasal
-    let preferences:    Preferences
-    let custom:         TrioCustomOrefVariables
-    let date:           Date
+struct DeterminationInputs {
+    let profile: Profile
+    let currentTemp: TempBasal
+    let iobData: IobResult
+    let autosensData: Autosens
+    let mealData: ComputedCarbs?
+    let reservoirData: Reservoir
+    let currentTime: Date
 }
 
-protocol SMBProvider {
-    func isSMBEnabled(
-        glucose: BloodGlucose,
-        profile: Profile,
-        autosens: Autosens,
-        date: Date
-    ) -> Bool
-    
-    // TODO: handle oref JS's enable_smb() logic
+protocol OverrideHandler {
+    func overrideProfileParameters(profile: Profile, override: Override?) throws -> Profile
+
+    // TODO: handle mutation of profile parameters that the user can alter using Overrides
+    /// This could also possibly be handled via an extension of our existing `ProfileGenerator` (?)
 }
 
 struct DeterminationGenerator {
@@ -26,14 +22,40 @@ struct DeterminationGenerator {
     let iobGenerator: IobGenerator
     let autosensGenerator: AutosensGenerator
     let mealProcessor: MealTotal
-    let smbProvider: SMBProvider
+
+    // override data can just be fetched from the DB
+    // handling via overrideManager ?
 
     func generate(
-        request _: DeterminationRequest
+        request _: DeterminationInputs
     ) throws -> Determination? {
-        
         // FIXME: implement... (return type will not be Optional; just to shut up the compiler)
-        
+
+        // trio-oref signature:
+//        function determine_basal(glucose_status, currenttemp, iob_data, profile, autosens_data, meal_data, tempBasalFunctions, microBolusAllowed, reservoir_data, currentTime, pumphistory, preferences, basalprofile, trio_custom_variables, middleWare) {
+
+        // openaps/oref0 signature:
+//        function determine_basal(glucose_status, currenttemp, iob_data, profile, autosens_data, meal_data, tempBasalFunctions, microBolusAllowed, reservoir_data, currentTime) {
+
+        /// We also need a call to glucose-get-last here (JS passes object `glucoseStatus`) → could be a simple function in GlucoseStorage
+        /// We also need the tempBasal helpers (JS passes object `tempBasalFunctions` with functions)
+        /// `tempBasalFunctions.getMaxSafeBasal` should be a helper function in or extension of`TrioSettings.swift`
+        /// `tempBasalFunctions.setTempBasal` is a helper function utilizing pass by value of `rT` ("requested Temp") and adjusting `rT.duration` and `rT.rate`… can be an extension / helper fn of `DeterminationGenerator` itself
+        /// TLDR; we could omit the 2 parameters `glucoseStatus` and `tempBasalFunctions`
+
+        /// OTHER PARAMS:
+        ///
+        /// JS oref has `reservoir_data`; we have that on file via `loadFileFromStorageAsync(name: Monitor.reservoir)`
+        /// NOT NEEDED: `pumphistory` → we no longer calculate TDD in determine
+        /// NOT NEEDED: `preferences`, only used for dynamic ISF → pull this out
+        /// NOT NEEDED: `basalprofile`, was used for TDD calc as well → remove
+        /// NOT NEEDED: `trio_custom_variables` was used for (1) override handling, (2) SMB enabling → we should handle (1) in service of its own, and (2) already outlined via SMBProvider
+        /// `microBolusAllowed` is currently HARD-CODED (!) to `true`… we always allow microbolusing and only handle this via the various SMB settings → remove ?
+
+        /// All input params can EITHER be passed directly, OR…
+        /// we handle it via an encapsulated struct (I chose DeterminationInputs
+        // TODO: Do we want store algorithm input *and* output?
+
         /// Current determine basal (if we ignore forecasting logic; already modularized) does:
         /// 1. Validate CGM → cancel if needed
         /// 2. Override basal → log
@@ -45,6 +67,39 @@ struct DeterminationGenerator {
         /// 8. Compute carbsReq → we could move this to MEAL
         /// 9. Decide temp basal → we could do a tempBasalGenerator ?
         
+
+        // TODO: how to handle output?
+        // TODO: how to handle logging?
+        
         nil
     }
 }
+
+extension DeterminationGenerator {
+    func calculateExpectedDelta(
+        targetGlucose: Decimal,
+        eventualGlucose: Decimal,
+        glucoseImpact: Decimal
+    ) -> Decimal {
+        // JS expects glucose to rise/fall at rate of glucose impact
+        // adjusted by the rate at which glucose would need to rise/fall
+        // to move eventual glucose to target over a 2 hr window
+        // TODO: expects that glucose can only be available in 5min chunks. do we need to change this handling?
+        
+        let fiveMinuteBlocks = (2 * 60) / 5
+        let delta = targetGlucose - eventualGlucose
+        return glucoseImpact + Decimal(Int(delta) / fiveMinuteBlocks).rounded(toPlaces: 1)
+
+    }
+    
+    func isSMBEnabled(
+        glucose _: BloodGlucose,
+        profile _: Profile,
+        autosens _: Autosens,
+        date _: Date
+    ) -> Bool {
+        // TODO: handle oref JS's enable_smb() logic
+
+        true
+    }
+}