import Charts import Foundation import SwiftUI struct ChartTempTarget: Hashable { let amount: Decimal let start: Date let end: Date } extension MainChartView { func drawTempTargets() -> some ChartContent { ForEach(chartTempTargets, id: \.self) { target in let targetLimited = min(max(target.amount, 0), upperLimit) RuleMark( xStart: .value("Start", target.start), xEnd: .value("End", target.end), y: .value("Value", targetLimited) ) .foregroundStyle(Color.purple.opacity(0.75)).lineStyle(.init(lineWidth: 8)) } } // Calculations for temp target bar mark func calculateTempTargets() async { // Perform calculations off the main thread let calculatedTTs = await Task.detached { () -> [ChartTempTarget] in var groupedPackages: [[TempTarget]] = [] var currentPackage: [TempTarget] = [] var calculatedTTs: [ChartTempTarget] = [] for target in await tempTargets { if target.duration > 0 { if !currentPackage.isEmpty { groupedPackages.append(currentPackage) currentPackage = [] } currentPackage.append(target) } else if let lastNonZeroTempTarget = currentPackage.last(where: { $0.duration > 0 }) { // Ensure this cancel target is within the valid time range if target.createdAt >= lastNonZeroTempTarget.createdAt, target.createdAt <= lastNonZeroTempTarget.createdAt .addingTimeInterval(TimeInterval(lastNonZeroTempTarget.duration * 60)) { currentPackage.append(target) } } } // Append the last group, if any if !currentPackage.isEmpty { groupedPackages.append(currentPackage) } for package in groupedPackages { guard let firstNonZeroTarget = package.first(where: { $0.duration > 0 }) else { continue } var end = firstNonZeroTarget.createdAt.addingTimeInterval(TimeInterval(firstNonZeroTarget.duration * 60)) let earliestCancelTarget = package.filter({ $0.duration == 0 }).min(by: { $0.createdAt < $1.createdAt }) if let earliestCancelTarget = earliestCancelTarget { end = min(earliestCancelTarget.createdAt, end) } if let targetTop = firstNonZeroTarget.targetTop { let adjustedTarget = await units == .mgdL ? targetTop : targetTop.asMmolL calculatedTTs .append(ChartTempTarget(amount: adjustedTarget, start: firstNonZeroTarget.createdAt, end: end)) } } return calculatedTTs }.value // Update chartTempTargets on the main thread await MainActor.run { self.chartTempTargets = calculatedTTs } } }