Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cartfile.resolved
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
github "LoopKit/Amplitude-iOS" "2137d5fd44bf630ed33e1e72d7af6d8f8612f270"
github "LoopKit/CGMBLEKit" "ea1267791c66e884f1013fffd36faf4555cc6eaf"
github "LoopKit/G4ShareSpy" "fed5a389e3e47e3a1953878dd21852aa5f44b360"
github "LoopKit/LoopKit" "c6e9f9200deec9a401ab1725e888451b17dee98a"
github "LoopKit/LoopKit" "643026a2adbb1011f195c8d9bb5a16cd9fb576e4"
github "LoopKit/dexcom-share-client-swift" "b0419edf55c7f389b36cb47dd5c376bbd3d03d69"
github "i-schuetz/SwiftCharts" "0.6.2"
github "ps2/rileylink_ios" "8418b57c1983bdefaec7ccb456c86d5efacf40e7"
20 changes: 4 additions & 16 deletions Common/Extensions/GlucoseRangeSchedule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,6 @@ extension GlucoseRangeSchedule {
return activeOverride?.context
}

var activeOverrideQuantityRange: Range<HKQuantity>? {
guard let activeOverride = activeOverride else {
return nil
}

let lowerBound = HKQuantity(unit: unit, doubleValue: activeOverride.value.minValue)
let upperBound = HKQuantity(unit: unit, doubleValue: activeOverride.value.maxValue)
return lowerBound..<upperBound
}

var configuredOverrideContexts: [GlucoseRangeSchedule.Override.Context] {
var contexts: [GlucoseRangeSchedule.Override.Context] = []
for (context, range) in overrideRanges where !range.isZero {
Expand All @@ -53,15 +43,13 @@ extension GlucoseRangeSchedule {

return contexts
}

func minQuantity(at date: Date) -> HKQuantity {
return HKQuantity(unit: unit, doubleValue: value(at: date).minValue)
}
}


extension DoubleRange {
var averageValue: Double {
extension Range where Bound == HKQuantity {
func averageValue(for unit: HKUnit) -> Double {
let minValue = lowerBound.doubleValue(for: unit)
let maxValue = upperBound.doubleValue(for: unit)
return (maxValue + minValue) / 2
}
}
29 changes: 13 additions & 16 deletions Loop/Managers/DoseMath.swift
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ extension Collection where Element == GlucoseValue {
let targetValue = targetGlucoseValue(
percentEffectDuration: time / model.effectDuration,
minValue: suspendThresholdValue,
maxValue: correctionRange.value(at: prediction.startDate).averageValue
maxValue: correctionRange.quantityRange(at: prediction.startDate).averageValue(for: unit)
)

// Compute the dose required to bring this prediction to target:
Expand Down Expand Up @@ -287,40 +287,37 @@ extension Collection where Element == GlucoseValue {
}

// Choose either the minimum glucose or eventual glocse as the correction delta
let minGlucoseTargets = correctionRange.value(at: min.startDate)
let eventualGlucoseTargets = correctionRange.value(at: eventual.startDate)

let minGlucoseValue = min.quantity.doubleValue(for: unit)
let eventualGlucoseValue = eventual.quantity.doubleValue(for: unit)
let minGlucoseTargets = correctionRange.quantityRange(at: min.startDate)
let eventualGlucoseTargets = correctionRange.quantityRange(at: eventual.startDate)

// Treat the mininum glucose when both are below range
if minGlucoseValue < minGlucoseTargets.minValue &&
eventual.quantity.doubleValue(for: unit) < eventualGlucoseTargets.minValue
if min.quantity < minGlucoseTargets.lowerBound &&
eventual.quantity < eventualGlucoseTargets.lowerBound
{
let time = min.startDate.timeIntervalSince(date)
// For time = 0, assume a small amount effected. This will result in large (negative) unit recommendation rather than no recommendation at all.
let percentEffected = Swift.max(.ulpOfOne, 1 - model.percentEffectRemaining(at: time))

guard let units = insulinCorrectionUnits(
fromValue: minGlucoseValue,
toValue: minGlucoseTargets.averageValue,
fromValue: min.quantity.doubleValue(for: unit),
toValue: minGlucoseTargets.averageValue(for: unit),
effectedSensitivity: sensitivityValue * percentEffected
) else {
return nil
}

return .entirelyBelowRange(
correcting: min,
minTarget: HKQuantity(unit: unit, doubleValue: minGlucoseTargets.minValue),
minTarget: minGlucoseTargets.lowerBound,
units: units
)
} else if eventualGlucoseValue > eventualGlucoseTargets.maxValue,
} else if eventual.quantity > eventualGlucoseTargets.upperBound,
let minCorrectionUnits = minCorrectionUnits, let correctingGlucose = correctingGlucose
{
return .aboveRange(
min: min,
correcting: correctingGlucose,
minTarget: HKQuantity(unit: unit, doubleValue: eventualGlucoseTargets.minValue),
minTarget: eventualGlucoseTargets.lowerBound,
units: minCorrectionUnits
)
} else {
Expand Down Expand Up @@ -361,7 +358,7 @@ extension Collection where Element == GlucoseValue {
let correction = self.insulinCorrection(
to: correctionRange,
at: date,
suspendThreshold: suspendThreshold ?? correctionRange.minQuantity(at: date),
suspendThreshold: suspendThreshold ?? correctionRange.quantityRange(at: date).lowerBound,
sensitivity: sensitivity.quantity(at: date),
model: model
)
Expand Down Expand Up @@ -416,7 +413,7 @@ extension Collection where Element == GlucoseValue {
guard let correction = self.insulinCorrection(
to: correctionRange,
at: date,
suspendThreshold: suspendThreshold ?? correctionRange.minQuantity(at: date),
suspendThreshold: suspendThreshold ?? correctionRange.quantityRange(at: date).lowerBound,
sensitivity: sensitivity.quantity(at: date),
model: model
) else {
Expand All @@ -432,7 +429,7 @@ extension Collection where Element == GlucoseValue {
// Handle the "current BG below target" notice here
// TODO: Don't assume in the future that the first item in the array is current BG
if case .predictedGlucoseBelowTarget? = bolus.notice,
let first = first, first.quantity < correctionRange.minQuantity(at: first.startDate)
let first = first, first.quantity < correctionRange.quantityRange(at: first.startDate).lowerBound
{
bolus.notice = .currentGlucoseBelowTarget(glucose: first)
}
Expand Down
24 changes: 15 additions & 9 deletions LoopUI/Extensions/ChartPoint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import SwiftCharts


extension ChartPoint {
static func pointsForGlucoseRangeSchedule(_ glucoseRangeSchedule: GlucoseRangeSchedule, xAxisValues: [ChartAxisValue]) -> [ChartPoint] {
let targetRanges = glucoseRangeSchedule.between(
static func pointsForGlucoseRangeSchedule(_ glucoseRangeSchedule: GlucoseRangeSchedule, unit: HKUnit, xAxisValues: [ChartAxisValue]) -> [ChartPoint] {
let targetRanges = glucoseRangeSchedule.quantityBetween(
start: ChartAxisValueDate.dateFromScalar(xAxisValues.first!.scalar),
end: ChartAxisValueDate.dateFromScalar(xAxisValues.last!.scalar)
)
Expand All @@ -38,7 +38,7 @@ extension ChartPoint {
endDate = ChartAxisValueDate(date: targetRanges[index + 1].startDate, formatter: dateFormatter)
}

let value = range.value.rangeWithMinimumIncremement(glucoseRangeSchedule.unit.chartableIncrement)
let value = range.value.doubleRangeWithMinimumIncrement(in: unit)
let minValue = ChartAxisValueDouble(value.minValue)
let maxValue = ChartAxisValueDouble(value.maxValue)

Expand All @@ -56,8 +56,12 @@ extension ChartPoint {
return maxPoints + minPoints.reversed()
}

static func pointsForGlucoseRangeScheduleOverride(_ override: GlucoseRangeSchedule.Override, unit: HKUnit, xAxisValues: [ChartAxisValue], extendEndDateToChart: Bool = false) -> [ChartPoint] {
let range = override.value.rangeWithMinimumIncremement(unit.chartableIncrement)
static func pointsForGlucoseRangeScheduleOverride(_ glucoseRangeSchedule: GlucoseRangeSchedule, unit: HKUnit, xAxisValues: [ChartAxisValue], extendEndDateToChart: Bool = false) -> [ChartPoint] {
guard let override = glucoseRangeSchedule.override else {
return []
}

let range = override.quantityRange.doubleRangeWithMinimumIncrement(in: unit)
let startDate = Date()
let endDate = override.end

Expand Down Expand Up @@ -96,10 +100,12 @@ extension ChartPoint: TimelineValue {
}


private extension DoubleRange {
func rangeWithMinimumIncremement(_ increment: Double) -> DoubleRange {
var minValue = self.minValue
var maxValue = self.maxValue
private extension Range where Bound == HKQuantity {
func doubleRangeWithMinimumIncrement(in unit: HKUnit) -> DoubleRange {
let increment = unit.chartableIncrement

var minValue = self.lowerBound.doubleValue(for: unit)
var maxValue = self.upperBound.doubleValue(for: unit)

if (maxValue - minValue) < .ulpOfOne {
minValue -= increment
Expand Down
13 changes: 3 additions & 10 deletions LoopUI/Managers/StatusChartsManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -952,16 +952,9 @@ public final class StatusChartsManager {
let xAxisValues = xAxisValues, xAxisValues.count > 1,
let schedule = targetGlucoseSchedule
{
targetGlucosePoints = ChartPoint.pointsForGlucoseRangeSchedule(schedule, xAxisValues: xAxisValues)

if let override = schedule.override {
targetOverridePoints = ChartPoint.pointsForGlucoseRangeScheduleOverride(override, unit: schedule.unit, xAxisValues: xAxisValues, extendEndDateToChart: true)

targetOverrideDurationPoints = ChartPoint.pointsForGlucoseRangeScheduleOverride(override, unit: schedule.unit, xAxisValues: xAxisValues)
} else {
targetOverridePoints = []
targetOverrideDurationPoints = []
}
targetGlucosePoints = ChartPoint.pointsForGlucoseRangeSchedule(schedule, unit: glucoseUnit, xAxisValues: xAxisValues)
targetOverridePoints = ChartPoint.pointsForGlucoseRangeScheduleOverride(schedule, unit: glucoseUnit, xAxisValues: xAxisValues, extendEndDateToChart: true)
targetOverrideDurationPoints = ChartPoint.pointsForGlucoseRangeScheduleOverride(schedule, unit: glucoseUnit, xAxisValues: xAxisValues)
}
}
}
2 changes: 1 addition & 1 deletion WatchApp Extension/Models/GlucoseChartData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ struct GlucoseChartData {
max = Swift.max(max, correction.value.upperBound.doubleValue(for: unit))
}

if let override = correctionRange?.activeOverrideQuantityRange {
if let override = correctionRange?.activeOverride?.quantityRange {
min = Swift.min(min, override.lowerBound.doubleValue(for: unit))
max = Swift.max(max, override.upperBound.doubleValue(for: unit))
}
Expand Down
2 changes: 1 addition & 1 deletion WatchApp Extension/Scenes/GlucoseChartScene.swift
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ class GlucoseChartScene: SKScene {
inactiveNodes.removeValue(forKey: range.chartHashValue)

if range.end < spannedInterval.end {
let extendedRange = GlucoseRangeSchedule.Override(context: range.context, start: range.start, end: spannedInterval.end, value: range.value)
let extendedRange = GlucoseRangeSchedule.Override(context: range.context, start: range.start, end: spannedInterval.end, unit: range.unit, value: range.value)
let (sprite2, created) = getSprite(forHash: extendedRange.chartHashValue)
sprite2.color = UIColor.glucose.withAlphaComponent(0.25)
sprite2.zPosition = NodePlane.overrideRanges.zPosition
Expand Down
4 changes: 2 additions & 2 deletions WatchApp Extension/Scenes/GlucoseChartValueHashable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,10 @@ extension AbsoluteScheduleValue: GlucoseChartValueHashable where T == Range<HKQu

extension GlucoseRangeSchedule.Override: GlucoseChartValueHashable {
var min: Double {
return value.minValue
return quantityRange.lowerBound.doubleValue(for: .milligramsPerDeciliter)
}

var max: Double {
return value.maxValue
return quantityRange.upperBound.doubleValue(for: .milligramsPerDeciliter)
}
}