Skip to content

Commit

Permalink
initial commit calibration assistant
Browse files Browse the repository at this point in the history
This commit introduces a calibration assistant function to xdripswift.
When the user clicks calibrate, the previous x minutes of BG data is analysed (delta change, std deviation and current BG level), weightings are applied to the deviations calculated from the programmed limits and a result is output. Based upon this result to user is allowed to calibrate normally or they are asked to consider waiting, or they are told directly to not calibrate.
A debug option is in developer settings to show the calculations in the UIAlert to allow troubleshooting.
The results and recommendation are also logged to the trace file.
The user can enable a visual assistant that will change the calibration icon colour (every time a new BG is processed) to indicate if it is a good time to calibrate or not.
EN and ES translations are included
  • Loading branch information
paulplant committed Feb 2, 2023
1 parent 178d800 commit e9662d0
Show file tree
Hide file tree
Showing 13 changed files with 532 additions and 23 deletions.
6 changes: 5 additions & 1 deletion xdrip.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
470CE1FC246802EB00D5CB74 /* BluetoothPeripheralsView.strings in Resources */ = {isa = PBXBuildFile; fileRef = 470CE1FE246802EB00D5CB74 /* BluetoothPeripheralsView.strings */; };
470F021326DD515300C5D626 /* SettingsViewSensorCountdownSettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 470F021226DD515300C5D626 /* SettingsViewSensorCountdownSettingsViewModel.swift */; };
47150A4027F6211C00DB2994 /* SettingsViewTreatmentsSettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47150A3F27F6211C00DB2994 /* SettingsViewTreatmentsSettingsViewModel.swift */; };
472196EB2868BC5C007B2908 /* ConstantsCalibrationAssistant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472196EA2868BC5C007B2908 /* ConstantsCalibrationAssistant.swift */; };
4749EB9B25B36E010072DF8B /* LibreNFC.strings in Resources */ = {isa = PBXBuildFile; fileRef = 4749EB9D25B36E010072DF8B /* LibreNFC.strings */; };
47503382247420A200D2260B /* BluetoothPeripheralView.strings in Resources */ = {isa = PBXBuildFile; fileRef = 47503384247420A200D2260B /* BluetoothPeripheralView.strings */; };
4752B400263570DA0081D551 /* ConstantsStatistics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4752B3FF263570DA0081D551 /* ConstantsStatistics.swift */; };
Expand Down Expand Up @@ -711,6 +712,7 @@
470CE1FF246802F400D5CB74 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/BluetoothPeripheralsView.strings; sourceTree = "<group>"; };
470F021226DD515300C5D626 /* SettingsViewSensorCountdownSettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewSensorCountdownSettingsViewModel.swift; sourceTree = "<group>"; };
47150A3F27F6211C00DB2994 /* SettingsViewTreatmentsSettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewTreatmentsSettingsViewModel.swift; sourceTree = "<group>"; };
472196EA2868BC5C007B2908 /* ConstantsCalibrationAssistant.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConstantsCalibrationAssistant.swift; sourceTree = "<group>"; };
4749EB9C25B36E010072DF8B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/LibreNFC.strings; sourceTree = "<group>"; };
47503383247420A200D2260B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/BluetoothPeripheralView.strings; sourceTree = "<group>"; };
4752B3FF263570DA0081D551 /* ConstantsStatistics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConstantsStatistics.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2760,6 +2762,7 @@
F8AF36142455C6F700B5977B /* ConstantsTrace.swift */,
F8E3A2AA23DA520B00E5E98A /* ConstantsWatch.swift */,
4752B3FF263570DA0081D551 /* ConstantsStatistics.swift */,
472196EA2868BC5C007B2908 /* ConstantsCalibrationAssistant.swift */,
);
name = Constants;
path = xdrip/Constants;
Expand Down Expand Up @@ -3760,6 +3763,7 @@
F85FB769255DE14600D1C39E /* ConstantsLibreSmoothing.swift in Sources */,
F8F1671B272B3E4F001AA3D8 /* DexcomBackfillStream.swift in Sources */,
F8DF766023E38FC100063910 /* BLEPeripheral+CoreDataClass.swift in Sources */,
472196EB2868BC5C007B2908 /* ConstantsCalibrationAssistant.swift in Sources */,
F80ED2EE236F68F90005C035 /* SettingsViewM5StackWiFiSettingsViewModel.swift in Sources */,
F8FDD6CB2553385000625B49 /* Array.swift in Sources */,
F8A389C823203E3E0010F405 /* ConstantsM5Stack.swift in Sources */,
Expand Down Expand Up @@ -4879,7 +4883,7 @@
CODE_SIGN_ENTITLEMENTS = "$(XDRIP_ENTITLEMENTS_DEBUG)";
CODE_SIGN_IDENTITY = "$(XDRIP_CODE_SIGN_IDENTITY_DEBUG)";
CODE_SIGN_STYLE = "$(XDRIP_CODE_SIGN_STYLE)";
DEVELOPMENT_TEAM = "$(XDRIP_DEVELOPMENT_TEAM)";
DEVELOPMENT_TEAM = 92C77A2942;
INFOPLIST_FILE = "$(SRCROOT)/xdrip/Supporting Files/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
Expand Down
72 changes: 72 additions & 0 deletions xdrip/Constants/ConstantsCalibrationAssistant.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
//
// ConstantsCalibrationAssistant.swift
// xdrip
//
// Created by Paul Plant on 26/6/22.
// Copyright © 2022 Johan Degraeve. All rights reserved.
//

import Foundation

/// constants used by the calibration assistant
enum ConstantsCalibrationAssistant {

/// the number of minutes of readings that we should use for the calibration assistant calculations
static let minutesToUseForCalculations: Double = 20

// Delta
/// the value over which we will consider that the delta change is significant to display as a concern to the user
static let deltaResultLimit: Double = 90

/// the weighting that will be applied to the delta change value to push the result up
static let deltaMultiplier: Double = 30


// Standard Deviation
/// the value over which we will consider that the variation in change is significant to display as a concern to the user
static let stdDeviationResultLimit: Double = 60

/// the weighting that will be applied to the standard deviation value to push the result up
static let stdDeviationMultiplier: Double = 50


// Very high BG levels
/// the upper higher BG level at which the user should never calibrate. A bigger multiplier will be used for values over this amount
static let higherBgUpperLimit: Double = 160

/// the weighting that will be applied to very high BG values to push the result up
static let higherBgUpperMultiplier: Double = 15


// Higher BG levels
/// the higher BG level at which the user should be careful when calibrating. A smaller multiplier will be applied to values over this amount
static let higherBgRecommendedLimit: Double = 130

/// the weighting that will be applied to moderately high BG values to push the result up
static let higherBgRecommendedMultiplier: Double = 10


// Lower BG levels
/// the lower BG level at which the user should be careful when calibrating. A smaller multiplier will be applied to values below this amount
static let lowerBgRecommendedLimit: Double = 90

/// the weight that will be applied to moderately low BG values to push the result up
static let lowerBgRecommendedMultiplier: Double = 10


// Very low BG levels
/// the lower BG level at which the user should never calibrate. A bigger multiplier will be used for values under this amount
static let lowerBgLowerLimit: Double = 75

/// the weighting that will be applied to very low BG values to push the result up
static let lowerBgLowerMultiplier: Double = 15


// Limits
/// the limit below which the calibration result will be considered as OK
static let okToCalibrateLimit: Double = 130

/// the limit below which (and above okToCalibrateLimit) when the calibration result will be considered as "Not Ideal" and the user will be warned to be careful and calibrate later
static let notIdealToCalibrateLimit: Double = 200

}
26 changes: 26 additions & 0 deletions xdrip/Extensions/UserDefaults.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ extension UserDefaults {
case miniChartHoursToShow = "miniChartHoursToShow"
/// should the screen/chart be allowed to rotate?
case allowScreenRotation = "allowScreenRotation"
/// should the calibration assistant be enabled?
case showVisualCalibrationAssistant = "showVisualCalibrationAssistant"
/// should the clock view be shown when the screen is locked?
case showClockWhenScreenIsLocked = "showClockWhenScreenIsLocked"
/// show the objectives and make them display on the graph? Or just hide it all because it's too complicated to waste time with?
Expand Down Expand Up @@ -341,6 +343,9 @@ extension UserDefaults {

case loopDelayValueInMinutes = "loopDelayValueInMinutes"

/// Default value is false. If true then the calibration assistant will show the results to the user
case showCalibrationAssistantResults = "showCalibrationAssistantResults"

/// used for Libre data parsing - only for Libre 1 or Libre 2 read via transmitter, ie full NFC block
case previousRawLibreValues = "previousRawLibreValues"

Expand Down Expand Up @@ -852,6 +857,17 @@ extension UserDefaults {
}
}

/// should the calibration assistant be enabled?
@objc dynamic var showVisualCalibrationAssistant: Bool {
// default value for bool in userdefaults is false, as default we want the calibration assistant to be enabled
get {
return !bool(forKey: Key.showVisualCalibrationAssistant.rawValue)
}
set {
set(!newValue, forKey: Key.showVisualCalibrationAssistant.rawValue)
}
}


// MARK: Treatments Settings

Expand Down Expand Up @@ -1724,6 +1740,16 @@ extension UserDefaults {
set(newValue, forKey: Key.suppressLoopShare.rawValue)
}
}

/// if true, then the calibration assistant will show all calculations and values. Set to false by default
var showCalibrationAssistantResults: Bool {
get {
return bool(forKey: Key.showCalibrationAssistantResults.rawValue)
}
set {
set(newValue, forKey: Key.showCalibrationAssistantResults.rawValue)
}
}

/// used for Libre data parsing - for processing in LibreDataParser which is only in case of reading with NFC (ie bubble etc)
var previousRawLibreValues: [Double] {
Expand Down
10 changes: 5 additions & 5 deletions xdrip/Storyboards/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
Expand Up @@ -397,32 +397,32 @@
<constraint firstAttribute="height" constant="50" id="2xB-Gd-4Tz"/>
</constraints>
<items>
<barButtonItem title="Snooze" image="moon.zzz" catalog="system" id="f3E-Tt-LBV">
<barButtonItem title="Snooze" image="moon.zzz" catalog="system" style="plain" id="f3E-Tt-LBV">
<connections>
<action selector="preSnoozeToolbarButtonAction:" destination="9pv-A4-QxB" id="IDv-ho-TZ2"/>
<segue destination="NvR-Zh-2Zn" kind="show" identifier="RootViewToSnoozeView" id="VtQ-ZG-btn"/>
</connections>
</barButtonItem>
<barButtonItem style="plain" systemItem="flexibleSpace" id="uM8-jT-s3T"/>
<barButtonItem title="Sensor" image="ellipsis.circle" catalog="system" id="ZIM-Wf-bUy">
<barButtonItem title="Sensor" image="ellipsis.circle" catalog="system" style="plain" id="ZIM-Wf-bUy">
<connections>
<action selector="sensorToolbarButtonAction:" destination="9pv-A4-QxB" id="2vd-6L-ifa"/>
</connections>
</barButtonItem>
<barButtonItem style="plain" systemItem="flexibleSpace" id="to4-9c-pNT"/>
<barButtonItem title="Calibrate" image="scope" catalog="system" id="u4d-bZ-Kw8">
<barButtonItem title="Calibrate" image="scope" catalog="system" style="plain" id="u4d-bZ-Kw8">
<connections>
<action selector="calibrateToolbarButtonAction:" destination="9pv-A4-QxB" id="qNA-1R-UK5"/>
</connections>
</barButtonItem>
<barButtonItem style="plain" systemItem="flexibleSpace" id="SlH-A4-F18"/>
<barButtonItem title="Lock" image="lock" catalog="system" id="wfX-50-2w6">
<barButtonItem title="Lock" image="lock" catalog="system" style="plain" id="wfX-50-2w6">
<connections>
<action selector="screenLockToolbarButtonAction:" destination="9pv-A4-QxB" id="L14-hJ-4a9"/>
</connections>
</barButtonItem>
<barButtonItem style="plain" systemItem="flexibleSpace" id="a6G-aW-JeE"/>
<barButtonItem title="Help" image="questionmark.circle" catalog="system" id="DuN-xR-xYB">
<barButtonItem title="Help" image="questionmark.circle" catalog="system" style="plain" id="DuN-xR-xYB">
<connections>
<action selector="helpToolbarButtonAction:" destination="9pv-A4-QxB" id="DGg-9c-TqQ"/>
</connections>
Expand Down
14 changes: 14 additions & 0 deletions xdrip/Storyboards/en.lproj/CalibrationRequest.strings
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,17 @@
"calibration_title" = "Calibration";
"calibration_notification_title" = "Calibration";
"calibration_notification_body" = "Click the Notification to Calibrate";

// Calibration Assistant strings
"calibrateButtonTitle" = "Calibrate";
"calibrateAnywayButtonTitle" = "Calibrate Anyway!";
"okToCalibrate" = "Conditions are OK to calibrate";
"waitToCalibrate" = "You may calibrate, but it would be better to wait";
"doNotCalibrate" = "You should not calibrate now. Wait for a better time";
"bgValuesRising" = "BG values have been rising";
"bgValuesDropping" = "BG values have been dropping";
"bgValuesNotStable" = "BG values are not stable enough";
"bgValueTooHigh" = "Current BG value is too high";
"bgValuesSlightlyHigh" = "Current BG value is slightly high";
"bgValueTooLow" = "Current BG value is too low";
"bgValuesSlightlyLow" = "Current BG value is slightly low";
2 changes: 2 additions & 0 deletions xdrip/Storyboards/en.lproj/SettingsViews.strings
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"settingsviews_IntervalMessage" = "Minimum interval between two notifications (mins)";
"settingsviews_allowScreenRotation" = "Allow Chart Rotation?";
"settingsviews_showMiniChart" = "Show the Mini-Chart?";
"settingsviews_showVisualCalibrationAssistant" = "Show Calibration Assistant?";
"settingsviews_showClockWhenScreenIsLocked" = "Show Clock when Locked?";
"settingsviews_urgentHighValue" = "Urgent High Value:";
"settingsviews_highValue" = "High Value:";
Expand Down Expand Up @@ -132,3 +133,4 @@
"expanatoryTextSelectTime" = "As of what time should the value apply";
"expanatoryTextSelectValue" = "Delay in minutes, applied to readings shared with Loop";
"warningLoopDelayAlreadyExists" = "There is already a loopDelay for this time.";
"showCalibrationAssistantResults" = "Calibration Assistant Debug";
14 changes: 14 additions & 0 deletions xdrip/Storyboards/es.lproj/CalibrationRequest.strings
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,17 @@
"calibration_title" = "Calibración";
"calibration_notification_title" = "Calibración";
"calibration_notification_body" = "Haz click en la notificación para calibrar";

// Calibration Assistant strings
"calibrateButtonTitle" = "Calibrar";
"calibrateAnywayButtonTitle" = "¡Calibrar Igualmente!";
"okToCalibrate" = "Las condiciones son aptas para calibrar";
"waitToCalibrate" = "Se puede calibrar ahora, pero sería mejor esperar";
"doNotCalibrate" = "No se debe calibrar ahora mismo";
"bgValuesRising" = "Los valores de glucosa han estado subiendo";
"bgValuesDropping" = "Los valores de glucosa han estado bajando";
"bgValuesNotStable" = "Los valores de glucosa son poco estables";
"bgValueTooHigh" = "La glucosa actual es demasiado alto";
"bgValuesSlightlyHigh" = "La glucosa actual es ligeramente alto";
"bgValueTooLow" = "La glucosa actual es demasiado bajo";
"bgValuesSlightlyLow" = "La glucosa actual es ligeramente bajo";
3 changes: 3 additions & 0 deletions xdrip/Storyboards/es.lproj/SettingsViews.strings
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,6 @@
"settingsviews_housekeeperRetentionPeriod" = "Periodo de Retención (días):";
"settingsviews_housekeeperExportAllData" = "Exportar Todo";
"settingsviews_housekeeperRetentionPeriodMessage" = "¿Durante cuántos días debemos guardar los datos? (Min 90, Max 365)\n\n(Recomendado: 90 días)";

"settingsviews_showVisualCalibrationAssistant" = "Asistente de Calibración?";
"showCalibrationAssistantResults" = "Calibration Assistant Debug";
49 changes: 49 additions & 0 deletions xdrip/Texts/TextsCalibration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,55 @@ enum Texts_Calibrations {
return NSLocalizedString("enter_calibration_value", tableName: filename, bundle: Bundle.main, value: "Enter Calibration Value", comment: "When calibration alert goess off, user clicks the notification, app opens, dialog pops up, this is the text in the dialog")
}()

static let calibrateButtonTitle:String = {
return NSLocalizedString("calibrateButtonTitle", tableName: filename, bundle: Bundle.main, value: "Calibrate", comment: "the calibrate button title")
}()

static let calibrateAnywayButtonTitle:String = {
return NSLocalizedString("calibrateAnywayButtonTitle", tableName: filename, bundle: Bundle.main, value: "Calibrate Anyway!", comment: "the calibrate anyway button title")
}()

static let okToCalibrate:String = {
return NSLocalizedString("okToCalibrate", tableName: filename, bundle: Bundle.main, value: "Conditions are OK to calibrate", comment: "a message to inform that the BG values are OK to calibrate")
}()

static let waitToCalibrate:String = {
return NSLocalizedString("waitToCalibrate", tableName: filename, bundle: Bundle.main, value: "You may calibrate, but it would be better to wait", comment: "a message to inform that the user whould wait before calibrate")
}()

static let doNotCalibrate:String = {
return NSLocalizedString("doNotCalibrate", tableName: filename, bundle: Bundle.main, value: "You should not calibrate now. Wait for a better time", comment: "a message to inform that the user should not calibrate")
}()

static let bgValuesRising:String = {
return NSLocalizedString("bgValuesRising", tableName: filename, bundle: Bundle.main, value: "BG values have been rising", comment: "a message to inform that the BG values have been rising too much to calibrate")
}()

static let bgValuesDropping:String = {
return NSLocalizedString("bgValuesDropping", tableName: filename, bundle: Bundle.main, value: "BG values have been dropping", comment: "a message to inform that the BG values have been dropping too much to calibrate")
}()

static let bgValuesNotStable:String = {
return NSLocalizedString("bgValuesNotStable", tableName: filename, bundle: Bundle.main, value: "BG values are not stable enough", comment: "a message to inform that the BG values are not stable enough to calibrate")
}()

static let bgValueTooHigh:String = {
return NSLocalizedString("bgValueTooHigh", tableName: filename, bundle: Bundle.main, value: "Current BG value is too high", comment: "a message to inform that the current BG value is too high to calibrate")
}()

static let bgValuesSlightlyHigh:String = {
return NSLocalizedString("bgValuesSlightlyHigh", tableName: filename, bundle: Bundle.main, value: "Current BG value is slightly high", comment: "a message to inform that the current BG value is slightly high to calibrate")
}()

static let bgValueTooLow:String = {
return NSLocalizedString("bgValueTooLow", tableName: filename, bundle: Bundle.main, value: "Current BG value is too low", comment: "a message to inform that the current BG value is too low to calibrate")
}()

static let bgValuesSlightlyLow:String = {
return NSLocalizedString("bgValuesSlightlyLow", tableName: filename, bundle: Bundle.main, value: "Current BG value is slightly low", comment: "a message to inform that the current BG value is slightly low to calibrate")
}()


}


Loading

0 comments on commit e9662d0

Please sign in to comment.