فهرست منبع

Further rework processing logic, remove nested loop WIP

Deniz Cengiz 1 سال پیش
والد
کامیت
d0ed79a229

+ 88 - 41
FreeAPS/Sources/Modules/Home/View/Chart/ChartElements/GlucoseTargetsView.swift

@@ -4,7 +4,6 @@ import SwiftUI
 
 
 struct GlucoseTargetsView: ChartContent {
 struct GlucoseTargetsView: ChartContent {
     let startMarker: Date
     let startMarker: Date
-    let endMarker: Date
     let units: GlucoseUnits
     let units: GlucoseUnits
     let bgTargets: BGTargets
     let bgTargets: BGTargets
 
 
@@ -24,42 +23,7 @@ struct GlucoseTargetsView: ChartContent {
      */
      */
     private func drawGlucoseTargets() -> some ChartContent {
     private func drawGlucoseTargets() -> some ChartContent {
         // Array to store target profiles for visualization
         // Array to store target profiles for visualization
-        var targetProfiles: [TargetProfile] = []
-        let targets = bgTargets.targets
-
-        // Generate profiles for today and tomorrow, because otherwise the targets would be cut off at midnight
-        // TODO: maybe theres a better solution than introducing a second for loop?
-        let days = [0, 1]
-
-        for dayOffset in days {
-            // Calculate base date for current day offset
-            // it should be the start of the day of the startMarker
-            let baseDate = Calendar.current.startOfDay(for: startMarker)
-                .addingTimeInterval(TimeInterval(dayOffset * 24 * 60 * 60))
-
-            for (index, target) in targets.enumerated() {
-                // Calculate start time by adding target offset
-                let startTime = baseDate.addingTimeInterval(TimeInterval(target.offset * 60))
-
-                // Calculate end time - either next target or end of day
-                let endTime: Date = {
-                    if index + 1 < targets.count {
-                        return baseDate.addingTimeInterval(TimeInterval(targets[index + 1].offset * 60))
-                    } else {
-                        return baseDate.addingTimeInterval(24 * 60 * 60)
-                    }
-                }()
-
-                // append target profile to array
-                targetProfiles.append(
-                    TargetProfile(
-                        value: units == .mgdL ? target.low : target.low.asMmolL,
-                        startTime: startTime.timeIntervalSinceReferenceDate,
-                        endTime: endTime.timeIntervalSinceReferenceDate
-                    )
-                )
-            }
-        }
+        let targetProfiles: [TargetProfile] = processFetchedTargets(bgTargets)
 
 
         // Draw target lines for each profile
         // Draw target lines for each profile
         return ForEach(targetProfiles, id: \.self) { profile in
         return ForEach(targetProfiles, id: \.self) { profile in
@@ -67,16 +31,99 @@ struct GlucoseTargetsView: ChartContent {
                 x: .value("Time", Date(timeIntervalSinceReferenceDate: profile.startTime)),
                 x: .value("Time", Date(timeIntervalSinceReferenceDate: profile.startTime)),
                 y: .value("Target", profile.value)
                 y: .value("Target", profile.value)
             )
             )
-            .lineStyle(.init(lineWidth: 0.5))
-            .foregroundStyle(Color.green.opacity(0.8))
+            .lineStyle(.init(lineWidth: 1))
+            .foregroundStyle(Color.green.gradient)
 
 
             LineMark(
             LineMark(
                 x: .value("Time", Date(timeIntervalSinceReferenceDate: profile.endTime)),
                 x: .value("Time", Date(timeIntervalSinceReferenceDate: profile.endTime)),
                 y: .value("Target", profile.value)
                 y: .value("Target", profile.value)
             )
             )
-            .lineStyle(.init(lineWidth: 0.5))
-            .foregroundStyle(Color.green.opacity(0.8))
+            .lineStyle(.init(lineWidth: 1))
+            .foregroundStyle(Color.green.gradient)
+        }
+    }
+
+    /**
+     Processes raw glucose target data into a list of target profiles for visualization.
+
+     - Parameter rawTargets: The raw glucose target data containing offset and glucose values.
+     - Returns: An array of `TargetProfile` objects, each representing a glucose target range for today and tomorrow.
+
+     The function:
+     - Converts glucose targets into profiles covering two consecutive days (today and tomorrow).
+     - Calculates start and end times for each target based on the offsets provided.
+     - Handles conversions between mg/dL and mmol/L as per user settings.
+     - Ensures targets span across midnight to avoid data cutoff.
+
+     Example:
+     For a target at offset 0 (midnight) with low glucose value 70 mg/dL, the function generates two profiles:
+     - One for today from midnight to the next target offset or end of the day.
+     - Another for tomorrow covering the same time range.
+     */
+    private func processFetchedTargets(_ rawTargets: BGTargets) -> [TargetProfile] {
+        var targetProfiles: [TargetProfile] = []
+
+        // Ensure there are targets to process
+        guard !rawTargets.targets.isEmpty else {
+            print("Warning: No targets to process in rawTargets.")
+            return []
+        }
+
+        let targets = rawTargets.targets
+
+        // Base date is the start of the day for the startMarker
+        let baseDate = Calendar.current.startOfDay(for: startMarker)
+
+        // Process each target twice: once for today and once for tomorrow
+        for index in 0 ..< (targets.count * 2) {
+            // Calculate the day offset (0 for today, 1 for tomorrow)
+            let dayOffset = index / targets.count
+            let targetIndex = index % targets.count
+
+            // Validate target index to ensure safety
+            guard targetIndex < targets.count else {
+                print("Error: Invalid target index \(targetIndex).")
+                continue
+            }
+
+            // Fetch the target for the current iteration
+            let target = targets[targetIndex]
+
+            // Calculate the time offset for the current day
+            let dayTimeOffset = TimeInterval(dayOffset * 24 * 60 * 60)
+
+            // Calculate the start time for the current target
+            let startTime = baseDate
+                .addingTimeInterval(dayTimeOffset)
+                .addingTimeInterval(TimeInterval(target.offset * 60))
+
+            // Calculate the end time for the current target
+            let endTime: Date = {
+                if targetIndex + 1 < targets.count {
+                    // End time is the start time of the next target within the same day
+                    return baseDate
+                        .addingTimeInterval(dayTimeOffset)
+                        .addingTimeInterval(TimeInterval(targets[targetIndex + 1].offset * 60))
+                } else {
+                    // End time is the end of the day (midnight of the next day)
+                    return baseDate.addingTimeInterval(dayTimeOffset + 24 * 60 * 60)
+                }
+            }()
+
+            // Convert glucose value based on user unit preference (mg/dL or mmol/L)
+            let targetValue = units == .mgdL ? target.low : target.low.asMmolL
+
+            // Append the processed target profile to the list
+            targetProfiles.append(
+                TargetProfile(
+                    value: targetValue,
+                    startTime: startTime.timeIntervalSinceReferenceDate,
+                    endTime: endTime.timeIntervalSinceReferenceDate
+                )
+            )
         }
         }
+
+        return targetProfiles
     }
     }
 }
 }
 
 

+ 0 - 2
FreeAPS/Sources/Modules/Home/View/Chart/MainChartView.swift

@@ -139,9 +139,7 @@ extension MainChartView {
 
 
                 GlucoseTargetsView(
                 GlucoseTargetsView(
                     startMarker: startMarker,
                     startMarker: startMarker,
-                    endMarker: endMarker,
                     units: state.units,
                     units: state.units,
-
                     bgTargets: state.bgTargets
                     bgTargets: state.bgTargets
                 )
                 )