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

Create dailyStat.JSON.

Version. DaílyStats

New names. Daily Stats. TIR works.

New variable names etc
Jon B.M 3 лет назад
Родитель
Сommit
541195d9d5

+ 1 - 1
Config.xcconfig

@@ -1,5 +1,5 @@
 APP_DISPLAY_NAME = FreeAPS X
-APP_VERSION = 0.2.8
+APP_VERSION = 0.2.9
 APP_BUILD_NUMBER = 1
 DEVELOPER_TEAM = ##TEAM_ID##
 BUNDLE_IDENTIFIER = ru.artpancreas.$(DEVELOPMENT_TEAM).FreeAPS

+ 4 - 0
FreeAPS.xcodeproj/project.pbxproj

@@ -18,6 +18,7 @@
 		19795118275953E50044850D /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 198377D4266BFFF6004DE65E /* Localizable.strings */; };
 		198377D2266BFFF6004DE65E /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 198377D4266BFFF6004DE65E /* Localizable.strings */; };
 		199561C1275E61A50077B976 /* HealthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 199561C0275E61A50077B976 /* HealthKit.framework */; };
+		19B0EF2128F6D66200069496 /* DailyStats.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B0EF2028F6D66200069496 /* DailyStats.swift */; };
 		19F79FA9283AE7E000646323 /* TDD.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19F79FA8283AE7E000646323 /* TDD.swift */; };
 		1BBB001DAD60F3B8CEA4B1C7 /* ISFEditorStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 505E09DC17A0C3D0AF4B66FE /* ISFEditorStateModel.swift */; };
 		1D845DF2E3324130E1D95E67 /* DataTableProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60744C3E9BB3652895C908CC /* DataTableProvider.swift */; };
@@ -456,6 +457,7 @@
 		199561C0275E61A50077B976 /* HealthKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = HealthKit.framework; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS8.0.sdk/System/Library/Frameworks/HealthKit.framework; sourceTree = DEVELOPER_DIR; };
 		199732B4271B72DD00129A3F /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/Localizable.strings"; sourceTree = "<group>"; };
 		199732B5271B9EE900129A3F /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Localizable.strings"; sourceTree = "<group>"; };
+		19B0EF2028F6D66200069496 /* DailyStats.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DailyStats.swift; sourceTree = "<group>"; };
 		19C166682756EFBD00ED12E3 /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/InfoPlist.strings; sourceTree = "<group>"; };
 		19C166692756EFBD00ED12E3 /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/Localizable.strings; sourceTree = "<group>"; };
 		19F79FA8283AE7E000646323 /* TDD.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TDD.swift; sourceTree = "<group>"; };
@@ -1327,6 +1329,7 @@
 				19F79FA8283AE7E000646323 /* TDD.swift */,
 				1935363F28496F7D001E0B16 /* TDD_averages.swift */,
 				CE82E02628E869DF00473A9C /* AlertEntry.swift */,
+				19B0EF2028F6D66200069496 /* DailyStats.swift */,
 			);
 			path = Models;
 			sourceTree = "<group>";
@@ -2168,6 +2171,7 @@
 				3811DE3025C9D49500A708ED /* HomeStateModel.swift in Sources */,
 				38BF021725E7CBBC00579895 /* PumpManagerExtensions.swift in Sources */,
 				38F3B2EF25ED8E2A005C48AA /* TempTargetsStorage.swift in Sources */,
+				19B0EF2128F6D66200069496 /* DailyStats.swift in Sources */,
 				3811DF1025CAAAE200A708ED /* APSManager.swift in Sources */,
 				3870FF4725EC187A0088248F /* BloodGlucose.swift in Sources */,
 				38A0364225ED069400FCBB52 /* TempBasal.swift in Sources */,

+ 180 - 61
FreeAPS/Sources/APS/APSManager.swift

@@ -641,79 +641,198 @@ final class BaseAPSManager: APSManager, Injectable {
 
             storage.save(enacted, as: OpenAPS.Enact.enacted)
 
-            // Add to tdd.json:
-            //
-            let preferences = settingsManager.preferences
-            let currentTDD = enacted.tdd ?? 0
-            let file = OpenAPS.Monitor.tdd
-            let tdd = TDD(
-                TDD: currentTDD,
-                timestamp: Date(),
-                id: UUID().uuidString
-            )
-            var uniqEvents: [TDD] = []
-            storage.transaction { storage in
-                storage.append(tdd, to: file, uniqBy: \.id)
-                uniqEvents = storage.retrieve(file, as: [TDD].self)?
-                    .filter { $0.timestamp.addingTimeInterval(14.days.timeInterval) > Date() }
-                    .sorted { $0.timestamp > $1.timestamp } ?? []
-
-                var total: Decimal = 0
-                var indeces: Decimal = 0
-
-                for uniqEvent in uniqEvents {
-                    if uniqEvent.TDD > 0 {
-                        total += uniqEvent.TDD
-                        indeces += 1
-                    }
-                }
-
-                let entriesPast2hours = storage.retrieve(file, as: [TDD].self)?
-                    .filter { $0.timestamp.addingTimeInterval(2.hours.timeInterval) > Date() }
-                    .sorted { $0.timestamp > $1.timestamp } ?? []
+            // Create a tdd.json
+            tdd(enacted_: enacted)
 
-                var totalAmount: Decimal = 0
-                var nrOfIndeces: Decimal = 0
+            // Create a dailyStats.json
+            dailyStats()
 
-                for entry in entriesPast2hours {
-                    if entry.TDD > 0 {
-                        totalAmount += entry.TDD
-                        nrOfIndeces += 1
-                    }
+            debug(.apsManager, "Suggestion enacted. Received: \(received)")
+            DispatchQueue.main.async {
+                self.broadcaster.notify(EnactedSuggestionObserver.self, on: .main) {
+                    $0.enactedSuggestionDidUpdate(enacted)
                 }
+            }
+            nightscout.uploadStatus()
+        }
+    }
 
-                if indeces == 0 {
-                    indeces = 1
+    func tdd(enacted_: Suggestion) {
+        // Add to tdd.json:
+        let preferences = settingsManager.preferences
+        let currentTDD = enacted_.tdd ?? 0
+        let file = OpenAPS.Monitor.tdd
+        let tdd = TDD(
+            TDD: currentTDD,
+            timestamp: Date(),
+            id: UUID().uuidString
+        )
+        var uniqEvents: [TDD] = []
+        storage.transaction { storage in
+            storage.append(tdd, to: file, uniqBy: \.id)
+            uniqEvents = storage.retrieve(file, as: [TDD].self)?
+                .filter { $0.timestamp.addingTimeInterval(14.days.timeInterval) > Date() }
+                .sorted { $0.timestamp > $1.timestamp } ?? []
+            var total: Decimal = 0
+            var indeces: Decimal = 0
+            for uniqEvent in uniqEvents {
+                if uniqEvent.TDD > 0 {
+                    total += uniqEvent.TDD
+                    indeces += 1
                 }
-
-                if nrOfIndeces == 0 {
-                    nrOfIndeces = 1
+            }
+            let entriesPast2hours = storage.retrieve(file, as: [TDD].self)?
+                .filter { $0.timestamp.addingTimeInterval(2.hours.timeInterval) > Date() }
+                .sorted { $0.timestamp > $1.timestamp } ?? []
+            var totalAmount: Decimal = 0
+            var nrOfIndeces: Decimal = 0
+            for entry in entriesPast2hours {
+                if entry.TDD > 0 {
+                    totalAmount += entry.TDD
+                    nrOfIndeces += 1
                 }
+            }
+            if indeces == 0 {
+                indeces = 1
+            }
+            if nrOfIndeces == 0 {
+                nrOfIndeces = 1
+            }
+            let average14 = total / indeces
+            let average2hours = totalAmount / nrOfIndeces
+            let weight = preferences.weightPercentage
+            let weighted_average = weight * average2hours + (1 - weight) * average14
+            let averages = TDD_averages(
+                average_total_data: average14,
+                weightedAverage: weighted_average,
+                past2hoursAverage: average2hours,
+                date: Date()
+            )
+            storage.save(averages, as: OpenAPS.Monitor.tdd_averages)
+            storage.save(Array(uniqEvents), as: file)
+        }
+    }
 
-                let average14 = total / indeces
-                let average2hours = totalAmount / nrOfIndeces
-                let weight = preferences.weightPercentage
-                let weighted_average = weight * average2hours + (1 - weight) * average14
+    func dailyStats() {
+        // Add to dailyStats.JSON
+        let preferences = settingsManager.preferences
+        let glucose = storage.retrieve(OpenAPS.Monitor.glucose, as: [BloodGlucose].self)
+        let carbs = storage.retrieve(OpenAPS.Monitor.carbHistory, as: [CarbsEntry].self)
+        let tdds = storage.retrieve(OpenAPS.Monitor.tdd, as: [TDD].self)
+        let currentTDD = tdds?[0].TDD
+        var bg: Decimal = 0
+        var nr_bgs: Decimal = 0
 
-                let averages = TDD_averages(
-                    average_total_data: average14,
-                    weightedAverage: weighted_average,
-                    past2hoursAverage: average2hours,
-                    date: Date()
-                )
-                storage.save(averages, as: OpenAPS.Monitor.tdd_averages)
-                storage.save(Array(uniqEvents), as: file)
+        for entry in glucose! {
+            if entry.glucose! > 0 {
+                bg += Decimal(entry.glucose!)
+                nr_bgs += 1
             }
-            // End of tdd.json
+        }
 
-            debug(.apsManager, "Suggestion enacted. Received: \(received)")
-            DispatchQueue.main.async {
-                self.broadcaster.notify(EnactedSuggestionObserver.self, on: .main) {
-                    $0.enactedSuggestionDidUpdate(enacted)
-                }
+        var carbTotal: Decimal = 0
+
+        for each in carbs! {
+            if each.carbs != 0 {
+                carbTotal += each.carbs
             }
-            nightscout.uploadStatus()
         }
+
+        var bgAvg = bg / nr_bgs
+        // Round to two decimals
+        bgAvg = Decimal(round(Double(bgAvg * 100)) / 100)
+
+        var algo_ = "oref0"
+        if preferences.enableChris, preferences.useNewFormula {
+            algo_ = "Dynamic ISF, Logarithmic Formula"
+        } else if !preferences.useNewFormula, preferences.enableChris {
+            algo_ = "Dynamic ISF, Original Formula"
+        }
+
+        let af = preferences.adjustmentFactor
+        let insulin_type = preferences.curve
+
+        var buildDate: Date {
+            if let infoPath = Bundle.main.path(forResource: "Info", ofType: "plist"),
+               let infoAttr = try? FileManager.default.attributesOfItem(atPath: infoPath),
+               let infoDate = infoAttr[.modificationDate] as? Date
+            {
+                return infoDate
+            }
+            return Date()
+        }
+
+        let nsObject: AnyObject? = Bundle.main.infoDictionary!["CFBundleShortVersionString"] as AnyObject
+        let version = nsObject as! String
+        let pump_ = pumpManager?.localizedTitle ?? ""
+        let cgm = settingsManager.settings.cgm
+        let file = OpenAPS.Monitor.dailyStats
+        let date_ = Date()
+
+        let dailystat = DailyStats(
+            date: date_,
+            Pump: pump_,
+            CGM: cgm.rawValue,
+            TIR_Percentage: Decimal(tir().tir),
+            Hypoglucemias_Percentage: Decimal(tir().hypos),
+            Hyperglucemias_Percentage: Decimal(tir().hypers),
+            BG_daily_Average: bgAvg,
+            TDD: currentTDD ?? 0,
+            Carbs_24h: carbTotal,
+            Algorithm: algo_,
+            AdjustmentFactor: af,
+            insulinType: insulin_type.rawValue,
+            FAX_Build_Version: version,
+            FAX_Build_Date: buildDate,
+            id: UUID().uuidString
+        )
+
+        // If empty daily_stats.json, create a first entry
+        if file.rawJSON.algo == nil {
+            storage.save(dailystat, as: file)
+        } else {
+            var items: [DailyStats] = []
+
+            storage.transaction { storage in
+                storage.append(dailystat, to: file, uniqBy: \.id)
+                items = storage.retrieve(file, as: [DailyStats].self)?
+                    .filter { $0.date.addingTimeInterval(-1435.minutes.timeInterval) < Date() }
+                    .sorted { $0.date > $1.date } ?? []
+                storage.save(Array(items), as: file)
+            }
+        }
+    }
+
+    func tir() -> (hypos: Double, hypers: Double, tir: Double) {
+        let glucose = storage.retrieve(OpenAPS.Monitor.glucose, as: [BloodGlucose].self)
+        let length_ = glucose!.count
+        let endIndex = length_ - 1
+        let fullTime = glucose![0].date - glucose![endIndex].date
+        var timeInHypo = 0.0
+        var timeInHyper = 0.0
+        var i = 0
+
+        repeat {
+            let currentTime = glucose![i].date
+            var x = i
+            while x < endIndex {
+                x += 1
+                if x < endIndex {
+                    if glucose![x].glucose! < 80 {
+                        timeInHypo += Double(currentTime - glucose![x].date)
+                    } else if glucose![x].glucose! > 200 {
+                        timeInHyper += Double(currentTime - glucose![x].date)
+                    } else { break }
+                }
+            }
+            i += 1
+        } while i <= endIndex
+
+        let hypos = (timeInHypo / Double(fullTime)) * 100
+        let hypers = (timeInHyper / Double(fullTime)) * 100
+        let tir = 100 - (round(hypos) + round(hypers))
+
+        return (round(hypos), round(hypers), round(tir))
     }
 
     private func processError(_ error: Error) {

+ 1 - 0
FreeAPS/Sources/APS/OpenAPS/Constants.swift

@@ -57,6 +57,7 @@ extension OpenAPS {
         static let tdd = "monitor/tdd.json"
         static let tdd_averages = "monitor/tdd_averages.json"
         static let alertHistory = "monitor/alerthistory.json"
+        static let dailyStats = "monitor/daily_stats.json"
     }
 
     enum Enact {

+ 73 - 0
FreeAPS/Sources/Models/DailyStats.swift

@@ -0,0 +1,73 @@
+import Foundation
+
+struct DailyStats: JSON, Equatable {
+    var date: Date
+    var Pump: String
+    var CGM: String
+    var TIR_Percentage: Decimal
+    var Hypoglucemias_Percentage: Decimal
+    var Hyperglucemias_Percentage: Decimal
+    var BG_daily_Average: Decimal
+    var TDD: Decimal
+    var Carbs_24h: Decimal
+    var Algorithm: String
+    var AdjustmentFactor: Decimal
+    var insulinType: String
+    var FAX_Build_Version: String
+    var FAX_Build_Date: Date
+    var id: String
+
+    init(
+        date: Date,
+        Pump: String,
+        CGM: String,
+        TIR_Percentage: Decimal,
+        Hypoglucemias_Percentage: Decimal,
+        Hyperglucemias_Percentage: Decimal,
+        BG_daily_Average: Decimal,
+        TDD: Decimal,
+        Carbs_24h: Decimal,
+        Algorithm: String,
+        AdjustmentFactor: Decimal,
+        insulinType: String,
+        FAX_Build_Version: String,
+        FAX_Build_Date: Date,
+        id: String
+    ) {
+        self.date = date
+        self.Pump = Pump
+        self.CGM = CGM
+        self.TIR_Percentage = TIR_Percentage
+        self.Hypoglucemias_Percentage = Hypoglucemias_Percentage
+        self.Hyperglucemias_Percentage = Hyperglucemias_Percentage
+        self.BG_daily_Average = BG_daily_Average
+        self.TDD = TDD
+        self.Carbs_24h = Carbs_24h
+        self.Algorithm = Algorithm
+        self.AdjustmentFactor = AdjustmentFactor
+        self.insulinType = insulinType
+        self.FAX_Build_Version = FAX_Build_Version
+        self.FAX_Build_Date = FAX_Build_Date
+        self.id = id
+    }
+}
+
+extension DailyStats {
+    private enum CodingKeys: String, CodingKey {
+        case date
+        case Pump
+        case CGM
+        case TIR_Percentage
+        case Hypoglucemias_Percentage
+        case Hyperglucemias_Percentage
+        case BG_daily_Average
+        case TDD
+        case Carbs_24h
+        case Algorithm
+        case AdjustmentFactor
+        case insulinType
+        case FAX_Build_Version
+        case FAX_Build_Date
+        case id
+    }
+}

+ 2 - 0
FreeAPS/Sources/Modules/Settings/View/SettingsRootView.swift

@@ -114,6 +114,8 @@ extension Settings {
                                 .navigationLink(to: .configEditor(file: OpenAPS.Monitor.tdd), from: self)
                             Text("TDD Averages")
                                 .navigationLink(to: .configEditor(file: OpenAPS.Monitor.tdd_averages), from: self)
+                            Text("Daily Statistics")
+                                .navigationLink(to: .configEditor(file: OpenAPS.Monitor.dailyStats), from: self)
                             Text("Edit settings json")
                                 .navigationLink(to: .configEditor(file: OpenAPS.FreeAPS.settings), from: self)
                         }