From 69edd7c64068b40f336617d7a80642a6a4463582 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20B=20M=C3=A5rtensson?= <53905247+Jon-b-m@users.noreply.github.com> Date: Fri, 26 May 2023 10:56:51 +0200 Subject: [PATCH 01/45] Release 2.0.0 (#78) * Profiles. Save profiles as presets. Use Button from Home View to stop/open profile settings. Overrride settings deleted from settings. Open with profiles button instead. * Bug fixes * Deleted some unnecessary CoreData saving code. * Localization fixes and translations from iAPS Crowdin translators (Thank you all Crowdin translators!). --- Config.xcconfig | 2 +- .../Core_Data.xcdatamodel/contents | 33 +- .../CGMBLEKit/de.lproj/Localizable.strings | 1 - .../CGMBLEKit/es.lproj/Localizable.strings | 1 - .../CGMBLEKit/fr.lproj/Localizable.strings | 1 - .../CGMBLEKit/it.lproj/Localizable.strings | 13 +- .../CGMBLEKit/nb.lproj/Localizable.strings | 1 - .../CGMBLEKit/nl.lproj/Localizable.strings | 1 - .../CGMBLEKit/pl.lproj/Localizable.strings | 1 - .../CGMBLEKit/ru.lproj/Localizable.strings | 1 - .../zh-Hans.lproj/Localizable.strings | 1 - .../CGMBLEKitUI/da.lproj/Localizable.strings | 12 - .../da.lproj/TransmitterManagerSetup.strings | 7 - .../CGMBLEKitUI/de.lproj/Localizable.strings | 12 - .../de.lproj/TransmitterManagerSetup.strings | 13 +- .../CGMBLEKitUI/es.lproj/Localizable.strings | 12 - .../es.lproj/TransmitterManagerSetup.strings | 13 +- .../CGMBLEKitUI/fr.lproj/Localizable.strings | 12 - .../fr.lproj/TransmitterManagerSetup.strings | 7 - .../CGMBLEKitUI/he.lproj/Localizable.strings | 11 +- .../he.lproj/TransmitterManagerSetup.strings | 13 +- .../CGMBLEKitUI/it.lproj/Localizable.strings | 22 +- .../it.lproj/TransmitterManagerSetup.strings | 17 +- .../CGMBLEKitUI/nb.lproj/Localizable.strings | 12 - .../nb.lproj/TransmitterManagerSetup.strings | 13 +- .../CGMBLEKitUI/nl.lproj/Localizable.strings | 12 - .../nl.lproj/TransmitterManagerSetup.strings | 7 - .../CGMBLEKitUI/pl.lproj/Localizable.strings | 12 - .../pl.lproj/TransmitterManagerSetup.strings | 13 +- .../TransmitterManagerSetup.strings | 6 + .../CGMBLEKitUI/ru.lproj/Localizable.strings | 12 - .../ru.lproj/TransmitterManagerSetup.strings | 13 - .../CGMBLEKitUI/sv.lproj/Localizable.strings | 7 - .../sv.lproj/TransmitterManagerSetup.strings | 9 +- .../CGMBLEKitUI/tr.lproj/Localizable.strings | 12 - .../tr.lproj/TransmitterManagerSetup.strings | 7 - .../TransmitterManagerSetup.strings | 13 +- .../G7SensorKit/it.lproj/Localizable.strings | 66 ++-- .../G7SensorKit/nb.lproj/Localizable.strings | 34 +- .../Resources/it.lproj/Localizable.strings | 24 +- .../Resources/nb.lproj/Localizable.strings | 4 +- .../Resources/uk.lproj/Localizable.strings | 28 +- .../Resources/ar.lproj/Localizable.strings | 199 +++++++++++ .../Resources/ca.lproj/Localizable.strings | 221 ++++++++++++- .../Resources/da.lproj/Localizable.strings | 7 +- .../Resources/de.lproj/Localizable.strings | 5 +- .../Resources/en.lproj/Localizable.strings | 221 ++++++++++++- .../Resources/es.lproj/Localizable.strings | 7 +- .../Resources/fi.lproj/Localizable.strings | 64 ++++ .../Resources/fr.lproj/Localizable.strings | 7 +- .../Resources/he.lproj/Localizable.strings | 58 ++++ .../Resources/it.lproj/Localizable.strings | 7 +- .../Resources/nb.lproj/Localizable.strings | 5 +- .../Resources/nl.lproj/Localizable.strings | 7 - .../Resources/pl.lproj/Localizable.strings | 7 - .../Resources/pt-BR.lproj/Localizable.strings | 73 +++++ .../Resources/pt-PT.lproj/Localizable.strings | 221 ++++++++++++- .../Resources/ru.lproj/Localizable.strings | 7 +- .../Resources/sk.lproj/Localizable.strings | 139 ++++++++ .../Resources/sv.lproj/Localizable.strings | 72 +++- .../Resources/tr.lproj/Localizable.strings | 7 +- .../Resources/uk.lproj/Localizable.strings | 221 ++++++++++++- .../zh-Hans.lproj/Localizable.strings | 112 +++++++ .../it.lproj/Localizable.strings | 142 ++++---- .../Resources/it.lproj/Localizable.strings | 2 +- .../Resources/uk.lproj/Localizable.strings | 58 ++-- .../Resources/it.lproj/Localizable.strings | 4 +- .../Resources/uk.lproj/Localizable.strings | 88 ++--- .../Base.lproj/Localizable.strings | 67 +++- .../ar.lproj/Localizable.strings | 100 ++++++ .../ca.lproj/Localizable.strings | 106 ++++++ .../da.lproj/Localizable.strings | 1 - .../de.lproj/Localizable.strings | 3 +- .../es.lproj/Localizable.strings | 1 - .../fi.lproj/Localizable.strings | 45 +++ .../fr.lproj/Localizable.strings | 3 +- .../he.lproj/Localizable.strings | 13 +- .../it.lproj/Localizable.strings | 5 +- .../nb.lproj/Localizable.strings | 1 - .../nl.lproj/Localizable.strings | 1 - .../pl.lproj/Localizable.strings | 1 - .../pt-BR.lproj/Localizable.strings | 52 +++ .../pt-PT.lproj/Localizable.strings | 106 ++++++ .../sk.lproj/Localizable.strings | 4 +- .../sv.lproj/Localizable.strings | 45 +++ .../tr.lproj/Localizable.strings | 1 - .../uk.lproj/Localizable.strings | 65 ++++ .../zh-Hans.lproj/Localizable.strings | 58 ++++ FreeAPS/Resources/it.lproj/InfoPlist.strings | 4 +- .../javascript/bundle/determine-basal.js | 2 +- FreeAPS/Sources/APS/APSManager.swift | 5 - FreeAPS/Sources/APS/OpenAPS/OpenAPS.swift | 59 ++-- .../Main/de.lproj/Localizable.strings | 36 +- .../Main/en.lproj/Localizable.strings | 6 + .../Main/it.lproj/Localizable.strings | 54 +-- .../Main/nb.lproj/Localizable.strings | 22 +- .../Main/ru.lproj/Localizable.strings | 3 +- .../Main/sv.lproj/Localizable.strings | 35 -- .../Main/uk.lproj/Localizable.strings | 18 +- FreeAPS/Sources/Models/Oref2_variables.swift | 38 ++- .../Modules/AddCarbs/AddCarbsStateModel.swift | 1 - .../Sources/Modules/Home/HomeStateModel.swift | 13 +- .../Modules/Home/View/HomeRootView.swift | 127 ++++++-- .../OverrideProfilesStateModel.swift | 178 +++++++++- .../View/OverrideProfilesRootView.swift | 308 ++++++++++++++---- .../Settings/View/SettingsRootView.swift | 1 - 106 files changed, 3282 insertions(+), 778 deletions(-) create mode 100644 Dependencies/rileylink_ios/RileyLinkKitUI/ca.lproj/Localizable.strings create mode 100644 Dependencies/rileylink_ios/RileyLinkKitUI/pt-PT.lproj/Localizable.strings diff --git a/Config.xcconfig b/Config.xcconfig index 1f335b5d83..7dd19822f4 100644 --- a/Config.xcconfig +++ b/Config.xcconfig @@ -1,5 +1,5 @@ APP_DISPLAY_NAME = iAPS -APP_VERSION = 1.6.5 +APP_VERSION = 2.0.0 APP_BUILD_NUMBER = 1 COPYRIGHT_NOTICE = DEVELOPER_TEAM = ##TEAM_ID## diff --git a/Core_Data.xcdatamodeld/Core_Data.xcdatamodel/contents b/Core_Data.xcdatamodeld/Core_Data.xcdatamodel/contents index 3e3b399581..3be8b8d79b 100644 --- a/Core_Data.xcdatamodeld/Core_Data.xcdatamodel/contents +++ b/Core_Data.xcdatamodeld/Core_Data.xcdatamodel/contents @@ -5,7 +5,6 @@ - @@ -14,7 +13,6 @@ - @@ -27,7 +25,6 @@ - @@ -47,13 +44,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Dependencies/CGMBLEKit/CGMBLEKit/de.lproj/Localizable.strings b/Dependencies/CGMBLEKit/CGMBLEKit/de.lproj/Localizable.strings index 4ca4b9cc22..18e510d3b7 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKit/de.lproj/Localizable.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKit/de.lproj/Localizable.strings @@ -39,4 +39,3 @@ /* Error description */ "Unknown characteristic" = "Unbekannte Charakteristik"; - diff --git a/Dependencies/CGMBLEKit/CGMBLEKit/es.lproj/Localizable.strings b/Dependencies/CGMBLEKit/CGMBLEKit/es.lproj/Localizable.strings index 743c929ed6..ff8a32114c 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKit/es.lproj/Localizable.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKit/es.lproj/Localizable.strings @@ -39,4 +39,3 @@ /* Error description */ "Unknown characteristic" = "Característica desconocida"; - diff --git a/Dependencies/CGMBLEKit/CGMBLEKit/fr.lproj/Localizable.strings b/Dependencies/CGMBLEKit/CGMBLEKit/fr.lproj/Localizable.strings index 284b17ce10..4546ce5819 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKit/fr.lproj/Localizable.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKit/fr.lproj/Localizable.strings @@ -39,4 +39,3 @@ /* Error description */ "Unknown characteristic" = "Caractéristique inconnue"; - diff --git a/Dependencies/CGMBLEKit/CGMBLEKit/it.lproj/Localizable.strings b/Dependencies/CGMBLEKit/CGMBLEKit/it.lproj/Localizable.strings index 9e9621ca7b..ae5c809c0e 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKit/it.lproj/Localizable.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKit/it.lproj/Localizable.strings @@ -17,26 +17,25 @@ "Peripheral command was invalid" = "Il comando della periferica non era valido"; /* Timeout error description */ -"Peripheral did not respond in time" = "La periferica non ha risposto nel tempo limite"; +"Peripheral did not respond in time" = "La periferica non ha risposto entro il tempo limite"; /* Not ready error description */ -"Peripheral isnʼt connected" = "La periferica non e' connessa"; +"Peripheral isnʼt connected" = "La periferica non è connessa"; /* The description of sensor calibration state when sensor calibration is ok. */ -"Sensor calibration is OK" = "La calibrazione del sensore e' valida"; +"Sensor calibration is OK" = "La calibrazione del sensore è valida"; /* The description of sensor calibration state when raw value is unknown. (1: missing data details) */ -"Sensor is in unknown state %1$d" = "Il Sensore e' in un stato%1$d sconosciuto"; +"Sensor is in unknown state %1$d" = "Il Sensore è in un stato %1$d sconosciuto"; /* The description of sensor calibration state when sensor sensor is stopped. */ -"Sensor is stopped" = "Il Sensore e' fermato"; +"Sensor is stopped" = "Il Sensore è fermo"; /* The description of sensor calibration state when sensor sensor is warming up. */ -"Sensor is warming up" = "Il Sensore si sta riscaldando"; +"Sensor is warming up" = "Il sensore è in fase di avvio"; /* The description of sensor calibration state when sensor needs calibration. */ "Sensor needs calibration" = "Il sensore necessita di calibrazione"; /* Error description */ "Unknown characteristic" = "Caratteristica sconosciuta"; - diff --git a/Dependencies/CGMBLEKit/CGMBLEKit/nb.lproj/Localizable.strings b/Dependencies/CGMBLEKit/CGMBLEKit/nb.lproj/Localizable.strings index b5f0c3d371..cadb73a837 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKit/nb.lproj/Localizable.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKit/nb.lproj/Localizable.strings @@ -39,4 +39,3 @@ /* Error description */ "Unknown characteristic" = "Ukjent karakteristikk"; - diff --git a/Dependencies/CGMBLEKit/CGMBLEKit/nl.lproj/Localizable.strings b/Dependencies/CGMBLEKit/CGMBLEKit/nl.lproj/Localizable.strings index 96deda64d5..bfb17befa7 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKit/nl.lproj/Localizable.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKit/nl.lproj/Localizable.strings @@ -39,4 +39,3 @@ /* Error description */ "Unknown characteristic" = "Onbekende eigenschap"; - diff --git a/Dependencies/CGMBLEKit/CGMBLEKit/pl.lproj/Localizable.strings b/Dependencies/CGMBLEKit/CGMBLEKit/pl.lproj/Localizable.strings index 837bc5a80e..f2bc414300 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKit/pl.lproj/Localizable.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKit/pl.lproj/Localizable.strings @@ -39,4 +39,3 @@ /* Error description */ "Unknown characteristic" = "Nieznany błąd"; - diff --git a/Dependencies/CGMBLEKit/CGMBLEKit/ru.lproj/Localizable.strings b/Dependencies/CGMBLEKit/CGMBLEKit/ru.lproj/Localizable.strings index 1a58bbd5b1..ca294360dc 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKit/ru.lproj/Localizable.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKit/ru.lproj/Localizable.strings @@ -39,4 +39,3 @@ /* Error description */ "Unknown characteristic" = "Неизвестная характеристика"; - diff --git a/Dependencies/CGMBLEKit/CGMBLEKit/zh-Hans.lproj/Localizable.strings b/Dependencies/CGMBLEKit/CGMBLEKit/zh-Hans.lproj/Localizable.strings index 34975c241d..c300a5d6ba 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKit/zh-Hans.lproj/Localizable.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKit/zh-Hans.lproj/Localizable.strings @@ -39,4 +39,3 @@ /* Error description */ "Unknown characteristic" = "未知特性"; - diff --git a/Dependencies/CGMBLEKit/CGMBLEKitUI/da.lproj/Localizable.strings b/Dependencies/CGMBLEKit/CGMBLEKitUI/da.lproj/Localizable.strings index 7e04b5af9b..60cb50e5b3 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKitUI/da.lproj/Localizable.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKitUI/da.lproj/Localizable.strings @@ -23,9 +23,6 @@ Title text for the button to remove a CGM from Loop */ /* Section title for latest glucose calibration */ "Latest Calibration" = "Seneste kalibrering"; -/* Section title for latest connection date */ -"Latest Connection" = "Seneste forbindelse"; - /* Section title for latest glucose reading */ "Latest Reading" = "Seneste aflæsning"; @@ -35,15 +32,6 @@ Title text for the button to remove a CGM from Loop */ /* Button title to open CGM app */ "Open App" = "Åben app"; -/* Section title for remote data synchronization */ -"Remote Data Synchronization" = "Synkronisering af fjerndata"; - -/* Title describing past sensor expiration */ -"Sensor Expired" = "Sensor udløbet"; - -/* Title describing sensor expiration */ -"Sensor Expires" = "Sensor udløber"; - /* Title describing sensor session age */ "Session Age" = "Session-alder"; diff --git a/Dependencies/CGMBLEKit/CGMBLEKitUI/da.lproj/TransmitterManagerSetup.strings b/Dependencies/CGMBLEKit/CGMBLEKitUI/da.lproj/TransmitterManagerSetup.strings index 0e451042b4..8c20114319 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKitUI/da.lproj/TransmitterManagerSetup.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKitUI/da.lproj/TransmitterManagerSetup.strings @@ -21,10 +21,3 @@ /* Class = "UITextField"; placeholder = "Enter the 6-digit transmitter ID"; ObjectID = "nKX-TW-GhD"; */ "nKX-TW-GhD.placeholder" = "Indtast det 6-cifrede sender-ID"; - -/* Class = "UITableViewSection"; footerTitle = "The transmitter ID can be found printed on the back of the device, on the side of the box it came in, and from within the settings menus of the receiver and mobile app."; ObjectID = "Qub-6B-0aB"; */ -"Qub-6B-0aB.footerTitle" = "Sender-ID'et kan findes trykt på bagsiden af ​​enheden, på den side af boksen, den kom i, og fra indstillingsmenuerne på modtageren og mobilappen."; - -/* Class = "UITableViewSection"; headerTitle = "Transmitter ID"; ObjectID = "Qub-6B-0aB"; */ -"Qub-6B-0aB.headerTitle" = "Sender ID"; - diff --git a/Dependencies/CGMBLEKit/CGMBLEKitUI/de.lproj/Localizable.strings b/Dependencies/CGMBLEKit/CGMBLEKitUI/de.lproj/Localizable.strings index 2242562b38..d3217ad239 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKitUI/de.lproj/Localizable.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKitUI/de.lproj/Localizable.strings @@ -23,9 +23,6 @@ Title text for the button to remove a CGM from Loop */ /* Section title for latest glucose calibration */ "Latest Calibration" = "Letzte Kalibrierung"; -/* Section title for latest connection date */ -"Latest Connection" = "Letzte Verbindung"; - /* Section title for latest glucose reading */ "Latest Reading" = "Letzter Wert"; @@ -35,15 +32,6 @@ Title text for the button to remove a CGM from Loop */ /* Button title to open CGM app */ "Open App" = "App öffnen"; -/* Section title for remote data synchronization */ -"Remote Data Synchronization" = "Remote Daten Synchronisation"; - -/* Title describing past sensor expiration */ -"Sensor Expired" = "Sensor abgelaufen"; - -/* Title describing sensor expiration */ -"Sensor Expires" = "Sensor-Ablaufzeitpunkt"; - /* Title describing sensor session age */ "Session Age" = "Sitzungsalter"; diff --git a/Dependencies/CGMBLEKit/CGMBLEKitUI/de.lproj/TransmitterManagerSetup.strings b/Dependencies/CGMBLEKit/CGMBLEKitUI/de.lproj/TransmitterManagerSetup.strings index 71c85c81c3..1cd9ff5339 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKitUI/de.lproj/TransmitterManagerSetup.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKitUI/de.lproj/TransmitterManagerSetup.strings @@ -7,6 +7,12 @@ /* Class = "UILabel"; text = "Detail"; ObjectID = "GOT-KQ-cEh"; */ "GOT-KQ-cEh.text" = "Detail"; +/* Class = "UITableViewSection"; footerTitle = "The transmitter ID can be found printed on the back of the device, on the side of the box it came in, and from within the settings menus of the receiver and mobile app."; ObjectID = "Qub-6B-0aB"; */ +"Qub-6B-0aB.footerTitle" = "Die Transmitter-ID befindet sich auf der Rückseite des Transmitters, an der Seite der Verpackung und in den Einstellungsmenüs des Empfängers sowie der Dexcom-App."; + +/* Class = "UITableViewSection"; headerTitle = "Transmitter ID"; ObjectID = "Qub-6B-0aB"; */ +"Qub-6B-0aB.headerTitle" = "Transmitter-ID"; + /* Class = "UITableViewSection"; footerTitle = "Data can be downloaded over the Internet from Share when the transmitter connection fails."; ObjectID = "k1N-Rg-XDy"; */ "k1N-Rg-XDy.footerTitle" = "Daten können über das Internet von Share heruntergeladen werden, wenn die Verbindung zum Transmitter unterbrochen ist."; @@ -15,10 +21,3 @@ /* Class = "UITextField"; placeholder = "Enter the 6-digit transmitter ID"; ObjectID = "nKX-TW-GhD"; */ "nKX-TW-GhD.placeholder" = "Geben Sie die 6-stellige Transmitter-ID ein"; - -/* Class = "UITableViewSection"; footerTitle = "The transmitter ID can be found printed on the back of the device, on the side of the box it came in, and from within the settings menus of the receiver and mobile app."; ObjectID = "Qub-6B-0aB"; */ -"Qub-6B-0aB.footerTitle" = "Die Transmitter-ID befindet sich auf der Rückseite des Transmitters, an der Seite der Verpackung und in den Einstellungsmenüs des Empfängers sowie der Dexcom-App."; - -/* Class = "UITableViewSection"; headerTitle = "Transmitter ID"; ObjectID = "Qub-6B-0aB"; */ -"Qub-6B-0aB.headerTitle" = "Transmitter-ID"; - diff --git a/Dependencies/CGMBLEKit/CGMBLEKitUI/es.lproj/Localizable.strings b/Dependencies/CGMBLEKit/CGMBLEKitUI/es.lproj/Localizable.strings index db45f273fd..e421c72129 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKitUI/es.lproj/Localizable.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKitUI/es.lproj/Localizable.strings @@ -23,9 +23,6 @@ Title text for the button to remove a CGM from Loop */ /* Section title for latest glucose calibration */ "Latest Calibration" = "Calibración más reciente"; -/* Section title for latest connection date */ -"Latest Connection" = "Conexión más reciente"; - /* Section title for latest glucose reading */ "Latest Reading" = "Dato más reciente"; @@ -35,15 +32,6 @@ Title text for the button to remove a CGM from Loop */ /* Button title to open CGM app */ "Open App" = "Abrir App"; -/* Section title for remote data synchronization */ -"Remote Data Synchronization" = "Sincronización remota de datos"; - -/* Title describing past sensor expiration */ -"Sensor Expired" = "Sensor caducado"; - -/* Title describing sensor expiration */ -"Sensor Expires" = "El sensor caduca"; - /* Title describing sensor session age */ "Session Age" = "Tiempo de sesión del sensor"; diff --git a/Dependencies/CGMBLEKit/CGMBLEKitUI/es.lproj/TransmitterManagerSetup.strings b/Dependencies/CGMBLEKit/CGMBLEKitUI/es.lproj/TransmitterManagerSetup.strings index 9d3fb37911..d58d859440 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKitUI/es.lproj/TransmitterManagerSetup.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKitUI/es.lproj/TransmitterManagerSetup.strings @@ -7,6 +7,12 @@ /* Class = "UILabel"; text = "Detail"; ObjectID = "GOT-KQ-cEh"; */ "GOT-KQ-cEh.text" = "Detalle"; +/* Class = "UITableViewSection"; footerTitle = "The transmitter ID can be found printed on the back of the device, on the side of the box it came in, and from within the settings menus of the receiver and mobile app."; ObjectID = "Qub-6B-0aB"; */ +"Qub-6B-0aB.footerTitle" = "La identificación del transmisor puede encontrarse en la parte trasera del dispositivo, en el lateral de la caja en la que venía, o en los menús de ajustes del receptor y la app del teléfono móvil. "; + +/* Class = "UITableViewSection"; headerTitle = "Transmitter ID"; ObjectID = "Qub-6B-0aB"; */ +"Qub-6B-0aB.headerTitle" = "Identificación del transmisor"; + /* Class = "UITableViewSection"; footerTitle = "Data can be downloaded over the Internet from Share when the transmitter connection fails."; ObjectID = "k1N-Rg-XDy"; */ "k1N-Rg-XDy.footerTitle" = "Los datos pueden descargarse, vía internet, desde el Share cuando la conexión del transmisor falla."; @@ -15,10 +21,3 @@ /* Class = "UITextField"; placeholder = "Enter the 6-digit transmitter ID"; ObjectID = "nKX-TW-GhD"; */ "nKX-TW-GhD.placeholder" = "Introduzca la identificación de 6 cifras del transmisor"; - -/* Class = "UITableViewSection"; footerTitle = "The transmitter ID can be found printed on the back of the device, on the side of the box it came in, and from within the settings menus of the receiver and mobile app."; ObjectID = "Qub-6B-0aB"; */ -"Qub-6B-0aB.footerTitle" = "La identificación del transmisor puede encontrarse en la parte trasera del dispositivo, en el lateral de la caja en la que venía, o en los menús de ajustes del receptor y la app del teléfono móvil. "; - -/* Class = "UITableViewSection"; headerTitle = "Transmitter ID"; ObjectID = "Qub-6B-0aB"; */ -"Qub-6B-0aB.headerTitle" = "Identificación del transmisor"; - diff --git a/Dependencies/CGMBLEKit/CGMBLEKitUI/fr.lproj/Localizable.strings b/Dependencies/CGMBLEKit/CGMBLEKitUI/fr.lproj/Localizable.strings index 60eb1694f5..37755d838a 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKitUI/fr.lproj/Localizable.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKitUI/fr.lproj/Localizable.strings @@ -23,9 +23,6 @@ Title text for the button to remove a CGM from Loop */ /* Section title for latest glucose calibration */ "Latest Calibration" = "Dernier étalonnage"; -/* Section title for latest connection date */ -"Latest Connection" = "Dernière connexion"; - /* Section title for latest glucose reading */ "Latest Reading" = "Dernière mesure"; @@ -35,15 +32,6 @@ Title text for the button to remove a CGM from Loop */ /* Button title to open CGM app */ "Open App" = "Ouvrir l’application"; -/* Section title for remote data synchronization */ -"Remote Data Synchronization" = "Synchronisation des données à distance"; - -/* Title describing past sensor expiration */ -"Sensor Expired" = "Capteur expiré"; - -/* Title describing sensor expiration */ -"Sensor Expires" = "Le capteur expire"; - /* Title describing sensor session age */ "Session Age" = "L’âge de la session"; diff --git a/Dependencies/CGMBLEKit/CGMBLEKitUI/fr.lproj/TransmitterManagerSetup.strings b/Dependencies/CGMBLEKit/CGMBLEKitUI/fr.lproj/TransmitterManagerSetup.strings index 120bf97e35..dcb51c6b7f 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKitUI/fr.lproj/TransmitterManagerSetup.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKitUI/fr.lproj/TransmitterManagerSetup.strings @@ -21,10 +21,3 @@ /* Class = "UITextField"; placeholder = "Enter the 6-digit transmitter ID"; ObjectID = "nKX-TW-GhD"; */ "nKX-TW-GhD.placeholder" = "Entrez l’ID du transmetteur, composé de 6 lettres et chiffres"; - -/* Class = "UITableViewSection"; footerTitle = "The transmitter ID can be found printed on the back of the device, on the side of the box it came in, and from within the settings menus of the receiver and mobile app."; ObjectID = "Qub-6B-0aB"; */ -"Qub-6B-0aB.footerTitle" = "L’ID du transmetteur se trouve sur le dos de l’appareil, sur la boîte dans laquelle il est fourni, et depuis les menus de réglages du récepteur et de l’application mobile."; - -/* Class = "UITableViewSection"; headerTitle = "Transmitter ID"; ObjectID = "Qub-6B-0aB"; */ -"Qub-6B-0aB.headerTitle" = "ID du transmetteur"; - diff --git a/Dependencies/CGMBLEKit/CGMBLEKitUI/he.lproj/Localizable.strings b/Dependencies/CGMBLEKit/CGMBLEKitUI/he.lproj/Localizable.strings index 03db033646..1a2dc01239 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKitUI/he.lproj/Localizable.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKitUI/he.lproj/Localizable.strings @@ -23,9 +23,6 @@ Title text for the button to remove a CGM from Loop */ /* Section title for latest glucose calibration */ "Latest Calibration" = "Latest Calibration"; -/* Section title for latest connection date */ -"Latest Connection" = "חיבור אחרון"; - /* Section title for latest glucose reading */ "Latest Reading" = "Latest Reading"; @@ -35,8 +32,8 @@ Title text for the button to remove a CGM from Loop */ /* Button title to open CGM app */ "Open App" = "Open App"; -/* Title describing past sensor expiration */ -"Sensor Expired" = "Sensor Expired"; +/* Title describing sensor session age */ +"Session Age" = "Session Age"; /* Section title for remote data synchronization */ "Remote Data Synchronization" = "Remote Data Synchronization"; @@ -44,8 +41,8 @@ Title text for the button to remove a CGM from Loop */ /* Title describing sensor expiration */ "Sensor Expires" = "Sensor Expires"; -/* Title describing sensor session age */ -"Session Age" = "Session Age"; +/* Title describing past sensor expiration */ +"Sensor Expired" = "Sensor Expired"; /* Title describing CGM calibration and battery state */ "Status" = "Status"; diff --git a/Dependencies/CGMBLEKit/CGMBLEKitUI/he.lproj/TransmitterManagerSetup.strings b/Dependencies/CGMBLEKit/CGMBLEKitUI/he.lproj/TransmitterManagerSetup.strings index 3568d2477f..d35f2a6770 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKitUI/he.lproj/TransmitterManagerSetup.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKitUI/he.lproj/TransmitterManagerSetup.strings @@ -7,6 +7,12 @@ /* Class = "UILabel"; text = "Detail"; ObjectID = "GOT-KQ-cEh"; */ "GOT-KQ-cEh.text" = "Detail"; +/* Class = "UITableViewSection"; footerTitle = "The transmitter ID can be found printed on the back of the device, on the side of the box it came in, and from within the settings menus of the receiver and mobile app."; ObjectID = "Qub-6B-0aB"; */ +"Qub-6B-0aB.footerTitle" = "The transmitter ID can be found printed on the back of the device, on the side of the box it came in, and from within the settings menus of the receiver and mobile app."; + +/* Class = "UITableViewSection"; headerTitle = "Transmitter ID"; ObjectID = "Qub-6B-0aB"; */ +"Qub-6B-0aB.headerTitle" = "Transmitter ID"; + /* Class = "UITableViewSection"; footerTitle = "Data can be downloaded over the Internet from Share when the transmitter connection fails."; ObjectID = "k1N-Rg-XDy"; */ "k1N-Rg-XDy.footerTitle" = "Data can be downloaded over the Internet from Share when the transmitter connection fails."; @@ -15,10 +21,3 @@ /* Class = "UITextField"; placeholder = "Enter the 6-digit transmitter ID"; ObjectID = "nKX-TW-GhD"; */ "nKX-TW-GhD.placeholder" = "Enter the 6-digit transmitter ID"; - -/* Class = "UITableViewSection"; footerTitle = "The transmitter ID can be found printed on the back of the device, on the side of the box it came in, and from within the settings menus of the receiver and mobile app."; ObjectID = "Qub-6B-0aB"; */ -"Qub-6B-0aB.footerTitle" = "The transmitter ID can be found printed on the back of the device, on the side of the box it came in, and from within the settings menus of the receiver and mobile app."; - -/* Class = "UITableViewSection"; headerTitle = "Transmitter ID"; ObjectID = "Qub-6B-0aB"; */ -"Qub-6B-0aB.headerTitle" = "Transmitter ID"; - diff --git a/Dependencies/CGMBLEKit/CGMBLEKitUI/it.lproj/Localizable.strings b/Dependencies/CGMBLEKit/CGMBLEKitUI/it.lproj/Localizable.strings index 6ae470ab45..e4640d4720 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKitUI/it.lproj/Localizable.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKitUI/it.lproj/Localizable.strings @@ -1,5 +1,5 @@ /* Format string for glucose trend per minute. (1: glucose value and unit) */ -"%@/min" = "%@/min"; +"%@/min" = "%@/minuto"; /* Confirmation message for deleting a CGM */ "Are you sure you want to delete this CGM?" = "Sei sicuro di voler eliminare questo CGM?"; @@ -23,9 +23,6 @@ Title text for the button to remove a CGM from Loop */ /* Section title for latest glucose calibration */ "Latest Calibration" = "Ultima calibrazione"; -/* Section title for latest connection date */ -"Latest Connection" = "Ultima connessione"; - /* Section title for latest glucose reading */ "Latest Reading" = "Ultima lettura"; @@ -35,26 +32,17 @@ Title text for the button to remove a CGM from Loop */ /* Button title to open CGM app */ "Open App" = "Apri app"; -/* Section title for remote data synchronization */ -"Remote Data Synchronization" = "Sincronizzazione di dati remoti"; - -/* Title describing past sensor expiration */ -"Sensor Expired" = "Sensore Scaduto"; - -/* Title describing sensor expiration */ -"Sensor Expires" = "Scadenza Sensore"; - /* Title describing sensor session age */ "Session Age" = "Età sessione"; /* Section title for remote data synchronization */ -"Remote Data Synchronization" = "Sincronizzazione di dati remoti"; +"Remote Data Synchronization" = "Sincronizzazione dei dati remoti"; /* Title describing sensor expiration */ -"Sensor Expires" = "Scadenza Sensore"; +"Sensor Expires" = "Scadenza sensore"; /* Title describing past sensor expiration */ -"Sensor Expired" = "Sensore Scaduto"; +"Sensor Expired" = "Sensore scaduto"; /* Title describing CGM calibration and battery state */ "Status" = "Stato"; @@ -69,4 +57,4 @@ Title text for the button to remove a CGM from Loop */ "Trend" = "Tendenza"; /* The title text for the upload glucose switch cell */ -"Upload Readings" = "Carica Letture"; +"Upload Readings" = "Carica letture"; diff --git a/Dependencies/CGMBLEKit/CGMBLEKitUI/it.lproj/TransmitterManagerSetup.strings b/Dependencies/CGMBLEKit/CGMBLEKitUI/it.lproj/TransmitterManagerSetup.strings index 90067533b3..8d0cf342ac 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKitUI/it.lproj/TransmitterManagerSetup.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKitUI/it.lproj/TransmitterManagerSetup.strings @@ -2,23 +2,22 @@ "5oU-vK-JHQ.text" = "Credenziali"; /* Class = "UITableViewController"; title = "Transmitter Setup"; ObjectID = "Dds-49-o7G"; */ -"Dds-49-o7G.title" = "Configurazione"; +"Dds-49-o7G.title" = "Configurazione trasmettitore"; /* Class = "UILabel"; text = "Detail"; ObjectID = "GOT-KQ-cEh"; */ "GOT-KQ-cEh.text" = "Dettaglio"; +/* Class = "UITableViewSection"; footerTitle = "The transmitter ID can be found printed on the back of the device, on the side of the box it came in, and from within the settings menus of the receiver and mobile app."; ObjectID = "Qub-6B-0aB"; */ +"Qub-6B-0aB.footerTitle" = "L'ID del trasmettitore è riportato sul retro del dispositivo, ai lati della confezione di imballaggio e nel menù impostazioni del ricevitore dell’app per dispositivi mobili."; + +/* Class = "UITableViewSection"; headerTitle = "Transmitter ID"; ObjectID = "Qub-6B-0aB"; */ +"Qub-6B-0aB.headerTitle" = "ID trasmettitore"; + /* Class = "UITableViewSection"; footerTitle = "Data can be downloaded over the Internet from Share when the transmitter connection fails."; ObjectID = "k1N-Rg-XDy"; */ -"k1N-Rg-XDy.footerTitle" = "In caso di problemi di connessione del trasmettitore, puoi scaricare i dati da Internet grazie alla funzionalità Condividi."; +"k1N-Rg-XDy.footerTitle" = "In caso di problemi di connessione del trasmettitore, puoi scaricare i dati da Internet grazie alla funzionalità Share."; /* Class = "UITableViewSection"; headerTitle = "Dexcom Share"; ObjectID = "k1N-Rg-XDy"; */ "k1N-Rg-XDy.headerTitle" = "Dexcom Share"; /* Class = "UITextField"; placeholder = "Enter the 6-digit transmitter ID"; ObjectID = "nKX-TW-GhD"; */ "nKX-TW-GhD.placeholder" = "Inserisci ID a 6 cifre del trasmettitore"; - -/* Class = "UITableViewSection"; footerTitle = "The transmitter ID can be found printed on the back of the device, on the side of the box it came in, and from within the settings menus of the receiver and mobile app."; ObjectID = "Qub-6B-0aB"; */ -"Qub-6B-0aB.footerTitle" = "L'ID del trasmettitore è riportato sul retro del dispositivo, ai lati della confezione di imballaggio e nel menù Impostazioni del ricevitore e dell’app per dispositivi mobili."; - -/* Class = "UITableViewSection"; headerTitle = "Transmitter ID"; ObjectID = "Qub-6B-0aB"; */ -"Qub-6B-0aB.headerTitle" = "ID trasmettitore"; - diff --git a/Dependencies/CGMBLEKit/CGMBLEKitUI/nb.lproj/Localizable.strings b/Dependencies/CGMBLEKit/CGMBLEKitUI/nb.lproj/Localizable.strings index 7a1b8d0849..96ca0c89fa 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKitUI/nb.lproj/Localizable.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKitUI/nb.lproj/Localizable.strings @@ -23,9 +23,6 @@ Title text for the button to remove a CGM from Loop */ /* Section title for latest glucose calibration */ "Latest Calibration" = "Siste kalibrering"; -/* Section title for latest connection date */ -"Latest Connection" = "Siste forbindelse"; - /* Section title for latest glucose reading */ "Latest Reading" = "Siste måling"; @@ -35,15 +32,6 @@ Title text for the button to remove a CGM from Loop */ /* Button title to open CGM app */ "Open App" = "Åpne app"; -/* Section title for remote data synchronization */ -"Remote Data Synchronization" = "Synkronisering av eksterne data"; - -/* Title describing past sensor expiration */ -"Sensor Expired" = "Sensor utløpt"; - -/* Title describing sensor expiration */ -"Sensor Expires" = "Sensor utløper"; - /* Title describing sensor session age */ "Session Age" = "Alder på økt"; diff --git a/Dependencies/CGMBLEKit/CGMBLEKitUI/nb.lproj/TransmitterManagerSetup.strings b/Dependencies/CGMBLEKit/CGMBLEKitUI/nb.lproj/TransmitterManagerSetup.strings index b5a02d40b1..16ee365856 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKitUI/nb.lproj/TransmitterManagerSetup.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKitUI/nb.lproj/TransmitterManagerSetup.strings @@ -7,6 +7,12 @@ /* Class = "UILabel"; text = "Detail"; ObjectID = "GOT-KQ-cEh"; */ "GOT-KQ-cEh.text" = "Detalj"; +/* Class = "UITableViewSection"; footerTitle = "The transmitter ID can be found printed on the back of the device, on the side of the box it came in, and from within the settings menus of the receiver and mobile app."; ObjectID = "Qub-6B-0aB"; */ +"Qub-6B-0aB.footerTitle" = "Sender ID finner du på baksiden av senderen, eller på siden av esken den kom i, eller under innstillinger i appen til senderen."; + +/* Class = "UITableViewSection"; headerTitle = "Transmitter ID"; ObjectID = "Qub-6B-0aB"; */ +"Qub-6B-0aB.headerTitle" = "Sender ID"; + /* Class = "UITableViewSection"; footerTitle = "Data can be downloaded over the Internet from Share when the transmitter connection fails."; ObjectID = "k1N-Rg-XDy"; */ "k1N-Rg-XDy.footerTitle" = "Data kan lastes ned over internett fra Share-server om tilkobling til sender ikke fungerer."; @@ -15,10 +21,3 @@ /* Class = "UITextField"; placeholder = "Enter the 6-digit transmitter ID"; ObjectID = "nKX-TW-GhD"; */ "nKX-TW-GhD.placeholder" = "Skriv 6-siffret sender ID"; - -/* Class = "UITableViewSection"; footerTitle = "The transmitter ID can be found printed on the back of the device, on the side of the box it came in, and from within the settings menus of the receiver and mobile app."; ObjectID = "Qub-6B-0aB"; */ -"Qub-6B-0aB.footerTitle" = "Sender ID finner du på baksiden av senderen, eller på siden av esken den kom i, eller under innstillinger i appen til senderen."; - -/* Class = "UITableViewSection"; headerTitle = "Transmitter ID"; ObjectID = "Qub-6B-0aB"; */ -"Qub-6B-0aB.headerTitle" = "Sender ID"; - diff --git a/Dependencies/CGMBLEKit/CGMBLEKitUI/nl.lproj/Localizable.strings b/Dependencies/CGMBLEKit/CGMBLEKitUI/nl.lproj/Localizable.strings index e23d1af5b5..a6e5cd7dcf 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKitUI/nl.lproj/Localizable.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKitUI/nl.lproj/Localizable.strings @@ -23,9 +23,6 @@ Title text for the button to remove a CGM from Loop */ /* Section title for latest glucose calibration */ "Latest Calibration" = "Laatste Kalibratie"; -/* Section title for latest connection date */ -"Latest Connection" = "Laatste Verbinding"; - /* Section title for latest glucose reading */ "Latest Reading" = "Laatste Meting"; @@ -35,15 +32,6 @@ Title text for the button to remove a CGM from Loop */ /* Button title to open CGM app */ "Open App" = "Open App"; -/* Section title for remote data synchronization */ -"Remote Data Synchronization" = "Remote Gegevenssynchronisatie"; - -/* Title describing past sensor expiration */ -"Sensor Expired" = "Sensor Verlopen"; - -/* Title describing sensor expiration */ -"Sensor Expires" = "Sensor Verloopt"; - /* Title describing sensor session age */ "Session Age" = "Sessieduur"; diff --git a/Dependencies/CGMBLEKit/CGMBLEKitUI/nl.lproj/TransmitterManagerSetup.strings b/Dependencies/CGMBLEKit/CGMBLEKitUI/nl.lproj/TransmitterManagerSetup.strings index 511206134b..6250bfce04 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKitUI/nl.lproj/TransmitterManagerSetup.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKitUI/nl.lproj/TransmitterManagerSetup.strings @@ -21,10 +21,3 @@ /* Class = "UITextField"; placeholder = "Enter the 6-digit transmitter ID"; ObjectID = "nKX-TW-GhD"; */ "nKX-TW-GhD.placeholder" = "Vul de 6 cijferige zenderserienummer in"; - -/* Class = "UITableViewSection"; footerTitle = "The transmitter ID can be found printed on the back of the device, on the side of the box it came in, and from within the settings menus of the receiver and mobile app."; ObjectID = "Qub-6B-0aB"; */ -"Qub-6B-0aB.footerTitle" = "De zenderserienummer staat achter op het apparaat, op de zijkant van de verpakking en in het instellingenmenu van de ontvanger en de app."; - -/* Class = "UITableViewSection"; headerTitle = "Transmitter ID"; ObjectID = "Qub-6B-0aB"; */ -"Qub-6B-0aB.headerTitle" = "Zenderserienummer"; - diff --git a/Dependencies/CGMBLEKit/CGMBLEKitUI/pl.lproj/Localizable.strings b/Dependencies/CGMBLEKit/CGMBLEKitUI/pl.lproj/Localizable.strings index e6315ca80a..0cf8c40340 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKitUI/pl.lproj/Localizable.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKitUI/pl.lproj/Localizable.strings @@ -23,9 +23,6 @@ Title text for the button to remove a CGM from Loop */ /* Section title for latest glucose calibration */ "Latest Calibration" = "Ostatnia kalibracja"; -/* Section title for latest connection date */ -"Latest Connection" = "Ostatnie połączenie"; - /* Section title for latest glucose reading */ "Latest Reading" = "Ostatni odczyt"; @@ -35,15 +32,6 @@ Title text for the button to remove a CGM from Loop */ /* Button title to open CGM app */ "Open App" = "Otwórz aplikację"; -/* Section title for remote data synchronization */ -"Remote Data Synchronization" = "Zdalna synchronizacja danych"; - -/* Title describing past sensor expiration */ -"Sensor Expired" = "Sensor wygasł"; - -/* Title describing sensor expiration */ -"Sensor Expires" = "Sensor Wygasa"; - /* Title describing sensor session age */ "Session Age" = "Wiek sesji"; diff --git a/Dependencies/CGMBLEKit/CGMBLEKitUI/pl.lproj/TransmitterManagerSetup.strings b/Dependencies/CGMBLEKit/CGMBLEKitUI/pl.lproj/TransmitterManagerSetup.strings index b60433a135..b5d9b207ae 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKitUI/pl.lproj/TransmitterManagerSetup.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKitUI/pl.lproj/TransmitterManagerSetup.strings @@ -7,6 +7,12 @@ /* Class = "UILabel"; text = "Detail"; ObjectID = "GOT-KQ-cEh"; */ "GOT-KQ-cEh.text" = "Detail"; +/* Class = "UITableViewSection"; footerTitle = "The transmitter ID can be found printed on the back of the device, on the side of the box it came in, and from within the settings menus of the receiver and mobile app."; ObjectID = "Qub-6B-0aB"; */ +"Qub-6B-0aB.footerTitle" = "ID nadajnika jest nadrukowany z tyłu urządzenia, z boku opakowania, w którym go dostarczono oraz jest dostępny w menu ustawień odbiornika i w aplikacji mobilnej."; + +/* Class = "UITableViewSection"; headerTitle = "Transmitter ID"; ObjectID = "Qub-6B-0aB"; */ +"Qub-6B-0aB.headerTitle" = "ID nadajnika"; + /* Class = "UITableViewSection"; footerTitle = "Data can be downloaded over the Internet from Share when the transmitter connection fails."; ObjectID = "k1N-Rg-XDy"; */ "k1N-Rg-XDy.footerTitle" = "Dane można pobrać przez internet z Share, kiedy połączenie nadajnika się nie powiedzie."; @@ -15,10 +21,3 @@ /* Class = "UITextField"; placeholder = "Enter the 6-digit transmitter ID"; ObjectID = "nKX-TW-GhD"; */ "nKX-TW-GhD.placeholder" = "Wprowadź 6-cyfrowy ID nadajnika"; - -/* Class = "UITableViewSection"; footerTitle = "The transmitter ID can be found printed on the back of the device, on the side of the box it came in, and from within the settings menus of the receiver and mobile app."; ObjectID = "Qub-6B-0aB"; */ -"Qub-6B-0aB.footerTitle" = "ID nadajnika jest nadrukowany z tyłu urządzenia, z boku opakowania, w którym go dostarczono oraz jest dostępny w menu ustawień odbiornika i w aplikacji mobilnej."; - -/* Class = "UITableViewSection"; headerTitle = "Transmitter ID"; ObjectID = "Qub-6B-0aB"; */ -"Qub-6B-0aB.headerTitle" = "ID nadajnika"; - diff --git a/Dependencies/CGMBLEKit/CGMBLEKitUI/pt-BR.lproj/TransmitterManagerSetup.strings b/Dependencies/CGMBLEKit/CGMBLEKitUI/pt-BR.lproj/TransmitterManagerSetup.strings index d4c1dc78b8..abc113fad1 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKitUI/pt-BR.lproj/TransmitterManagerSetup.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKitUI/pt-BR.lproj/TransmitterManagerSetup.strings @@ -7,6 +7,12 @@ /* Class = "UILabel"; text = "Detail"; ObjectID = "GOT-KQ-cEh"; */ "GOT-KQ-cEh.text" = "Detail"; +/* Class = "UITableViewSection"; footerTitle = "The transmitter ID can be found printed on the back of the device, on the side of the box it came in, and from within the settings menus of the receiver and mobile app."; ObjectID = "Qub-6B-0aB"; */ +"Qub-6B-0aB.footerTitle" = "O ID do transmissor pode ser encontrado impresso na parte traseira do dispositivo, na parte lateral da caixa em que ele veio e nos menus de configurações do receptor e do aplicativo móvel."; + +/* Class = "UITableViewSection"; headerTitle = "Transmitter ID"; ObjectID = "Qub-6B-0aB"; */ +"Qub-6B-0aB.headerTitle" = "ID do Transmissor"; + /* Class = "UITableViewSection"; footerTitle = "Data can be downloaded over the Internet from Share when the transmitter connection fails."; ObjectID = "k1N-Rg-XDy"; */ "k1N-Rg-XDy.footerTitle" = "Os dados podem ser baixados pela Internet a partir do compartilhamento quando a conexão do transmissor falhar."; diff --git a/Dependencies/CGMBLEKit/CGMBLEKitUI/ru.lproj/Localizable.strings b/Dependencies/CGMBLEKit/CGMBLEKitUI/ru.lproj/Localizable.strings index 22e567ea6e..04528f042b 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKitUI/ru.lproj/Localizable.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKitUI/ru.lproj/Localizable.strings @@ -23,9 +23,6 @@ Title text for the button to remove a CGM from Loop */ /* Section title for latest glucose calibration */ "Latest Calibration" = "Последняя калибровка"; -/* Section title for latest connection date */ -"Latest Connection" = "Последнее подключение"; - /* Section title for latest glucose reading */ "Latest Reading" = "Последние данные"; @@ -35,15 +32,6 @@ Title text for the button to remove a CGM from Loop */ /* Button title to open CGM app */ "Open App" = "Открыть приложение"; -/* Section title for remote data synchronization */ -"Remote Data Synchronization" = "Удаленная синхронизация данных"; - -/* Title describing past sensor expiration */ -"Sensor Expired" = "Сенсор истек"; - -/* Title describing sensor expiration */ -"Sensor Expires" = "Сенсор истекает"; - /* Title describing sensor session age */ "Session Age" = "Сенсор отработал"; diff --git a/Dependencies/CGMBLEKit/CGMBLEKitUI/ru.lproj/TransmitterManagerSetup.strings b/Dependencies/CGMBLEKit/CGMBLEKitUI/ru.lproj/TransmitterManagerSetup.strings index 2e46d1f81e..9bda4bb2c7 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKitUI/ru.lproj/TransmitterManagerSetup.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKitUI/ru.lproj/TransmitterManagerSetup.strings @@ -13,12 +13,6 @@ /* Class = "UITableViewSection"; headerTitle = "Transmitter ID"; ObjectID = "Qub-6B-0aB"; */ "Qub-6B-0aB.headerTitle" = "ID трансмиттера"; -/* Class = "UITableViewSection"; footerTitle = "The transmitter ID can be found printed on the back of the device, on the side of the box it came in, and from within the settings menus of the receiver and mobile app."; ObjectID = "Qub-6B-0aB"; */ -"Qub-6B-0aB.footerTitle" = "Номер трансмиттера находится на обратной стороне устройства, сбоку кпаковочной коробки, в настройках ресивера и мобильного приложения."; - -/* Class = "UITableViewSection"; headerTitle = "Transmitter ID"; ObjectID = "Qub-6B-0aB"; */ -"Qub-6B-0aB.headerTitle" = "ID трансмиттера"; - /* Class = "UITableViewSection"; footerTitle = "Data can be downloaded over the Internet from Share when the transmitter connection fails."; ObjectID = "k1N-Rg-XDy"; */ "k1N-Rg-XDy.footerTitle" = "Данные могут быть загружены с серверов Share если не произойдет соединение трансмиттера."; @@ -27,10 +21,3 @@ /* Class = "UITextField"; placeholder = "Enter the 6-digit transmitter ID"; ObjectID = "nKX-TW-GhD"; */ "nKX-TW-GhD.placeholder" = "Введите шестизначный идентификатор трансмиттера"; - -/* Class = "UITableViewSection"; footerTitle = "The transmitter ID can be found printed on the back of the device, on the side of the box it came in, and from within the settings menus of the receiver and mobile app."; ObjectID = "Qub-6B-0aB"; */ -"Qub-6B-0aB.footerTitle" = "Номер трансмиттера находится на обратной стороне устройства, сбоку кпаковочной коробки, в настройках ресивера и мобильного приложения."; - -/* Class = "UITableViewSection"; headerTitle = "Transmitter ID"; ObjectID = "Qub-6B-0aB"; */ -"Qub-6B-0aB.headerTitle" = "ID трансмиттера"; - diff --git a/Dependencies/CGMBLEKit/CGMBLEKitUI/sv.lproj/Localizable.strings b/Dependencies/CGMBLEKit/CGMBLEKitUI/sv.lproj/Localizable.strings index 6e1f8bbcb9..855400ae0e 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKitUI/sv.lproj/Localizable.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKitUI/sv.lproj/Localizable.strings @@ -23,9 +23,6 @@ Title text for the button to remove a CGM from Loop */ /* Section title for latest glucose calibration */ "Latest Calibration" = "Senaste kalibrering"; -/* Section title for latest connection date */ -"Latest Connection" = "Senaste anslutning"; - /* Section title for latest glucose reading */ "Latest Reading" = "Senaste avläsning"; @@ -35,9 +32,6 @@ Title text for the button to remove a CGM from Loop */ /* Button title to open CGM app */ "Open App" = "Öppna appen"; -/* Section title for remote data synchronization */ -"Remote Data Synchronization" = "Synkronisering av fjärrlagrad data"; - /* Title describing sensor session age */ "Session Age" = "Sessionsålder"; @@ -64,4 +58,3 @@ Title text for the button to remove a CGM from Loop */ /* The title text for the upload glucose switch cell */ "Upload Readings" = "Ladda upp avläsningar"; - diff --git a/Dependencies/CGMBLEKit/CGMBLEKitUI/sv.lproj/TransmitterManagerSetup.strings b/Dependencies/CGMBLEKit/CGMBLEKitUI/sv.lproj/TransmitterManagerSetup.strings index b7608bdc3a..a6c2537b31 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKitUI/sv.lproj/TransmitterManagerSetup.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKitUI/sv.lproj/TransmitterManagerSetup.strings @@ -5,7 +5,7 @@ "Dds-49-o7G.title" = "Sändarinställning"; /* Class = "UILabel"; text = "Detail"; ObjectID = "GOT-KQ-cEh"; */ -"GOT-KQ-cEh.text" = "Detail"; +"GOT-KQ-cEh.text" = "Detalj"; /* Class = "UITableViewSection"; footerTitle = "The transmitter ID can be found printed on the back of the device, on the side of the box it came in, and from within the settings menus of the receiver and mobile app."; ObjectID = "Qub-6B-0aB"; */ "Qub-6B-0aB.footerTitle" = "Sändar-ID kan hittas tryckt på baksidan av enheten, på sidan av lådan den kom in samt från inställningsmenyn för mottagaren och mobilappen."; @@ -21,10 +21,3 @@ /* Class = "UITextField"; placeholder = "Enter the 6-digit transmitter ID"; ObjectID = "nKX-TW-GhD"; */ "nKX-TW-GhD.placeholder" = "Ange 6-siffrigt sändar-ID"; - -/* Class = "UITableViewSection"; footerTitle = "The transmitter ID can be found printed on the back of the device, on the side of the box it came in, and from within the settings menus of the receiver and mobile app."; ObjectID = "Qub-6B-0aB"; */ -"Qub-6B-0aB.footerTitle" = "Sändar-ID kan hittas tryckt på baksidan av enheten, på sidan av lådan den kom in samt från inställningsmenyn för mottagaren och mobilappen."; - -/* Class = "UITableViewSection"; headerTitle = "Transmitter ID"; ObjectID = "Qub-6B-0aB"; */ -"Qub-6B-0aB.headerTitle" = "Sändari-ID"; - diff --git a/Dependencies/CGMBLEKit/CGMBLEKitUI/tr.lproj/Localizable.strings b/Dependencies/CGMBLEKit/CGMBLEKitUI/tr.lproj/Localizable.strings index a8a103f769..e36520bfb6 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKitUI/tr.lproj/Localizable.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKitUI/tr.lproj/Localizable.strings @@ -23,9 +23,6 @@ Title text for the button to remove a CGM from Loop */ /* Section title for latest glucose calibration */ "Latest Calibration" = "Son Kalibrasyon"; -/* Section title for latest connection date */ -"Latest Connection" = "Son Bağlantı"; - /* Section title for latest glucose reading */ "Latest Reading" = "Son Okuma"; @@ -35,15 +32,6 @@ Title text for the button to remove a CGM from Loop */ /* Button title to open CGM app */ "Open App" = "Uygulamayı aç"; -/* Section title for remote data synchronization */ -"Remote Data Synchronization" = "Uzaktan Veri Senkronizasyonu"; - -/* Title describing past sensor expiration */ -"Sensor Expired" = "Sensörün Süresi Doldu"; - -/* Title describing sensor expiration */ -"Sensor Expires" = "Sensörün Süresi Doluyor"; - /* Title describing sensor session age */ "Session Age" = "Sensör Yaşı"; diff --git a/Dependencies/CGMBLEKit/CGMBLEKitUI/tr.lproj/TransmitterManagerSetup.strings b/Dependencies/CGMBLEKit/CGMBLEKitUI/tr.lproj/TransmitterManagerSetup.strings index 09ee87069e..08a70c9fae 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKitUI/tr.lproj/TransmitterManagerSetup.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKitUI/tr.lproj/TransmitterManagerSetup.strings @@ -21,10 +21,3 @@ /* Class = "UITextField"; placeholder = "Enter the 6-digit transmitter ID"; ObjectID = "nKX-TW-GhD"; */ "nKX-TW-GhD.placeholder" = "6 basamaklı verici kimliğini girin"; - -/* Class = "UITableViewSection"; footerTitle = "The transmitter ID can be found printed on the back of the device, on the side of the box it came in, and from within the settings menus of the receiver and mobile app."; ObjectID = "Qub-6B-0aB"; */ -"Qub-6B-0aB.footerTitle" = "Verici kimliğini, cihazın arkasında, geldiği kutunun yan tarafında, alıcının mobil uygulamasının ayarlar menüsünde bulabilirsiniz."; - -/* Class = "UITableViewSection"; headerTitle = "Transmitter ID"; ObjectID = "Qub-6B-0aB"; */ -"Qub-6B-0aB.headerTitle" = "Verici Kimliği"; - diff --git a/Dependencies/CGMBLEKit/CGMBLEKitUI/zh-Hans.lproj/TransmitterManagerSetup.strings b/Dependencies/CGMBLEKit/CGMBLEKitUI/zh-Hans.lproj/TransmitterManagerSetup.strings index 8b9846202c..73e7ebb501 100644 --- a/Dependencies/CGMBLEKit/CGMBLEKitUI/zh-Hans.lproj/TransmitterManagerSetup.strings +++ b/Dependencies/CGMBLEKit/CGMBLEKitUI/zh-Hans.lproj/TransmitterManagerSetup.strings @@ -7,6 +7,12 @@ /* Class = "UILabel"; text = "Detail"; ObjectID = "GOT-KQ-cEh"; */ "GOT-KQ-cEh.text" = "详情"; +/* Class = "UITableViewSection"; footerTitle = "The transmitter ID can be found printed on the back of the device, on the side of the box it came in, and from within the settings menus of the receiver and mobile app."; ObjectID = "Qub-6B-0aB"; */ +"Qub-6B-0aB.footerTitle" = "发射器编号可在发射器包装盒背面找到,或者可在Dexcom Moblie软件及接受器的“setting”-“Transmitter”中找到"; + +/* Class = "UITableViewSection"; headerTitle = "Transmitter ID"; ObjectID = "Qub-6B-0aB"; */ +"Qub-6B-0aB.headerTitle" = "发射器编号"; + /* Class = "UITableViewSection"; footerTitle = "Data can be downloaded over the Internet from Share when the transmitter connection fails."; ObjectID = "k1N-Rg-XDy"; */ "k1N-Rg-XDy.footerTitle" = "当无法连接发射器时,可通过网络从Dexcom远程下载数据"; @@ -15,10 +21,3 @@ /* Class = "UITextField"; placeholder = "Enter the 6-digit transmitter ID"; ObjectID = "nKX-TW-GhD"; */ "nKX-TW-GhD.placeholder" = "请输入6位发射器编号"; - -/* Class = "UITableViewSection"; footerTitle = "The transmitter ID can be found printed on the back of the device, on the side of the box it came in, and from within the settings menus of the receiver and mobile app."; ObjectID = "Qub-6B-0aB"; */ -"Qub-6B-0aB.footerTitle" = "发射器编号可在发射器包装盒背面找到,或者可在Dexcom Moblie软件及接受器的“setting”-“Transmitter”中找到"; - -/* Class = "UITableViewSection"; headerTitle = "Transmitter ID"; ObjectID = "Qub-6B-0aB"; */ -"Qub-6B-0aB.headerTitle" = "发射器编号"; - diff --git a/Dependencies/G7SensorKit/it.lproj/Localizable.strings b/Dependencies/G7SensorKit/it.lproj/Localizable.strings index 91c855caf6..1c57341197 100644 --- a/Dependencies/G7SensorKit/it.lproj/Localizable.strings +++ b/Dependencies/G7SensorKit/it.lproj/Localizable.strings @@ -2,7 +2,7 @@ "Dexcom G7" = "Dexcom G7"; /* Descriptive text on G7StartupView */ -"iAPS can read G7 CGM data, but you must still use the Dexcom G7 App for pairing, calibration, and other sensor management." = "iAPS can read G7 CGM data, but you must still use the Dexcom G7 App for pairing, calibration, and other sensor management."; +"iAPS can read G7 CGM data, but you must still use the Dexcom G7 App for pairing, calibration, and other sensor management." = "iAPS è in grado di leggere i dati CGM di G7, ma è comunque necessario utilizzare l'App Dexcom G7 per l'accoppiamento, la calibrazione e la gestione di altri sensori."; /* Button title for starting setup */ "Continue" = "Continua"; @@ -11,43 +11,43 @@ "Cancel" = "Cancella"; /* Error description for unreliable state */ -"Glucose data is unavailable" = "Glucose data is unavailable"; +"Glucose data is unavailable" = "I dati della glicemia non sono disponibili"; /* The description of sensor algorithm state when sensor is ok. */ -"Sensor is OK" = "Sensor is OK"; +"Sensor is OK" = "Il sensore è OK"; /* The description of sensor algorithm state when sensor is stopped." */ -"Sensor is stopped" = "Sensor is stopped"; +"Sensor is stopped" = "Il sensore è arrestato"; /* The description of sensor algorithm state when sensor is warming up. */ -"Sensor is warming up" = "Sensor is warming up"; +"Sensor is warming up" = "Il sensore è in fase di avvio"; /* The description of sensor algorithm state when sensor is expired. */ -"Sensor expired" = "Sensor expired"; +"Sensor expired" = "Sensore scaduto"; /* The description of sensor algorithm state when sensor failed. */ -"Sensor failed" = "Sensor failed"; +"Sensor failed" = "Sensore fallito"; /* The description of sensor algorithm state when raw value is unknown. (1: missing data details) */ -"Sensor is in unknown state %1$d" = "Sensor is in unknown state %1$d"; +"Sensor is in unknown state %1$d" = "Il Sensore è in un stato %1$d sconosciuto"; /* title for g7 settings row showing sensor start time */ -"Sensor Start" = "Sensor Start"; +"Sensor Start" = "Avvia sensore"; /* title for g7 settings row showing sensor expiration time */ -"Sensor Expiration" = "Sensor Expiration"; +"Sensor Expiration" = "Scadenza Sensore"; /* title for g7 settings row showing sensor grace period end time */ -"Grace Period End" = "Grace Period End"; +"Grace Period End" = "Fine periodo di tolleranza"; /* Field label */ "Glucose" = "Glucosio"; -"Last Reading" = "Last Reading"; +"Last Reading" = "Ultima lettura"; "Time" = "Tempo"; -"Trend" = "Trend"; +"Trend" = "Tendenza"; "Bluetooth" = "Bluetooth"; @@ -55,7 +55,7 @@ "Name" = "Nome"; /* title for g7 settings connection status when scanning */ -"Scanning" = "Scanning"; +"Scanning" = "Lettura"; /* title for g7 settings connection status when connected */ "Connected" = "Collegato"; @@ -64,16 +64,16 @@ "Connecting" = "In collegamento"; /* title for g7 settings row showing sensor last connect time */ -"Last Connect" = "Last Connect"; +"Last Connect" = "Ultima Connessione"; /* Configuration */ "Configuration" = "Impostazioni"; /* title for g7 config settings to upload readings */ -"Upload Readings" = "Upload Readings"; +"Upload Readings" = "Carica Letture"; /* Button */ -"Scan for new sensor" = "Scan for new sensor"; +"Scan for new sensor" = "Scansiona per nuovo sensore"; /* Button label for removing CGM */ "Delete CGM" = "Elimina CGM"; @@ -81,49 +81,49 @@ /* No glucose value representation (3 dashes for mg/dL) */ "– – –" = "– – –"; /* String displayed instead of a glucose value below the CGM range */ -"LOW" = "LOW"; +"LOW" = "BASSO"; /* String displayed instead of a glucose value above the CGM range */ -"HIGH" = "HIGH"; +"HIGH" = "ALTO"; /* Format string for glucose trend per minute. (1: glucose value and unit) */ -"%@/min" = "%@/min"; +"%@/min" = "%@/minuto"; /* G7 Progress bar label when searching for sensor */ -"Searching for sensor" = "Searching for sensor"; +"Searching for sensor" = "Ricerca del sensore in corso"; /* G7 Progress bar label when sensor expired */ -"Sensor expired" = "Sensor expired"; +"Sensor expired" = "Sensore scaduto"; /* G7 Progress bar label when sensor in warmup */ -"Warmup completes" = "Warmup completes"; +"Warmup completes" = "Avvio completato"; /* G7 Progress bar label when sensor in warmup */ -"Warmup completes" = "Warmup completes"; +"Warmup completes" = "Avvio completato"; /* G7 Progress bar label when sensor failed */ -"Sensor failed" = "Sensor failed"; +"Sensor failed" = "Sensore fallito"; /* G7 Progress bar label when sensor lifetime progress showing */ -"Sensor expires" = "Sensor expires"; +"Sensor expires" = "Il sensore scade"; /* G7 Progress bar label when sensor grace period progress showing */ -"Grace period remaining" = "Grace period remaining"; +"Grace period remaining" = "Periodo di tolleranza residuo"; /* G7 Status highlight text for searching for sensor */ -"Searching for\nSensor" = "Searching for\nSensor"; +"Searching for\nSensor" = "Ricerca del sensore \n"; /* G7 Status highlight text for sensor expired */ -"Sensor\nExpired" = "Sensor\nExpired"; +"Sensor\nExpired" = "Sensore \n scaduto"; /* G7 Status highlight text for signal loss */ -"Sensor\nFailed" = "Sensor\nFailed"; +"Sensor\nFailed" = "Sensore \n Fallito"; /* G7 Status highlight text for signal loss */ -"Signal\nLoss" = "Signal\nLoss"; +"Signal\nLoss" = "Perdita segnale \n"; /*G7 Status highlight text for sensor error */ -"Sensor\nIssue" = "Sensor\nIssue"; +"Sensor\nIssue" = "Problema al sensore \n"; /* G7 Status highlight text for sensor warmup */ -"Sensor\nWarmup" = "Sensor\nWarmup"; +"Sensor\nWarmup" = "Riscaldamento sensore \n"; diff --git a/Dependencies/G7SensorKit/nb.lproj/Localizable.strings b/Dependencies/G7SensorKit/nb.lproj/Localizable.strings index 70819bdb70..fd47dece62 100644 --- a/Dependencies/G7SensorKit/nb.lproj/Localizable.strings +++ b/Dependencies/G7SensorKit/nb.lproj/Localizable.strings @@ -2,7 +2,7 @@ "Dexcom G7" = "Dexcom G7"; /* Descriptive text on G7StartupView */ -"iAPS can read G7 CGM data, but you must still use the Dexcom G7 App for pairing, calibration, and other sensor management." = "iAPS can read G7 CGM data, but you must still use the Dexcom G7 App for pairing, calibration, and other sensor management."; +"iAPS can read G7 CGM data, but you must still use the Dexcom G7 App for pairing, calibration, and other sensor management." = "iAPS kan lese data fra Dexcom G7, men du må fremdeles bruke Dexcom G7-appen for å koble til sender, kalibrere og andre innstillinger for sensoren."; /* Button title for starting setup */ "Continue" = "Fortsett"; @@ -38,7 +38,7 @@ "Sensor Expiration" = "Sensor utløper"; /* title for g7 settings row showing sensor grace period end time */ -"Grace Period End" = "Grace Period End"; +"Grace Period End" = "Slutt på utsettelsesperiode"; /* Field label */ "Glucose" = "Blodsukker"; @@ -55,7 +55,7 @@ "Name" = "Navn"; /* title for g7 settings connection status when scanning */ -"Scanning" = "Scanning"; +"Scanning" = "Skanner"; /* title for g7 settings connection status when connected */ "Connected" = "Tilkoblet"; @@ -64,16 +64,16 @@ "Connecting" = "Kobler til"; /* title for g7 settings row showing sensor last connect time */ -"Last Connect" = "Last Connect"; +"Last Connect" = "Siste tilkobling"; /* Configuration */ "Configuration" = "Oppsett"; /* title for g7 config settings to upload readings */ -"Upload Readings" = "Upload Readings"; +"Upload Readings" = "Last opp avlesninger"; /* Button */ -"Scan for new sensor" = "Scan for new sensor"; +"Scan for new sensor" = "Søk etter ny sensor"; /* Button label for removing CGM */ "Delete CGM" = "Slett CGM"; @@ -90,40 +90,40 @@ "%@/min" = "%@/min"; /* G7 Progress bar label when searching for sensor */ -"Searching for sensor" = "Searching for sensor"; +"Searching for sensor" = "Søker etter sensor"; /* G7 Progress bar label when sensor expired */ "Sensor expired" = "Sensoren er utløpt"; /* G7 Progress bar label when sensor in warmup */ -"Warmup completes" = "Warmup completes"; +"Warmup completes" = "Oppvarming fullført"; /* G7 Progress bar label when sensor in warmup */ -"Warmup completes" = "Warmup completes"; +"Warmup completes" = "Oppvarming fullført"; /* G7 Progress bar label when sensor failed */ "Sensor failed" = "Sensoren feilet"; /* G7 Progress bar label when sensor lifetime progress showing */ -"Sensor expires" = "Sensor expires"; +"Sensor expires" = "Sensor utløper"; /* G7 Progress bar label when sensor grace period progress showing */ -"Grace period remaining" = "Grace period remaining"; +"Grace period remaining" = "Utsettelsesperiode som gjenstår"; /* G7 Status highlight text for searching for sensor */ -"Searching for\nSensor" = "Searching for\nSensor"; +"Searching for\nSensor" = "Søker etter\nSensor"; /* G7 Status highlight text for sensor expired */ -"Sensor\nExpired" = "Sensor\nExpired"; +"Sensor\nExpired" = "Sensor\nUtløpt"; /* G7 Status highlight text for signal loss */ -"Sensor\nFailed" = "Sensor\nFailed"; +"Sensor\nFailed" = "Sensor\nFeilet"; /* G7 Status highlight text for signal loss */ -"Signal\nLoss" = "Signal\nLoss"; +"Signal\nLoss" = "Signal\nTapt"; /*G7 Status highlight text for sensor error */ -"Sensor\nIssue" = "Sensor\nIssue"; +"Sensor\nIssue" = "Sensor\nFeil"; /* G7 Status highlight text for sensor warmup */ -"Sensor\nWarmup" = "Sensor\nWarmup"; +"Sensor\nWarmup" = "Sensor\nOppvarming"; diff --git a/Dependencies/MinimedKit/MinimedKit/Resources/it.lproj/Localizable.strings b/Dependencies/MinimedKit/MinimedKit/Resources/it.lproj/Localizable.strings index 9f1219ad45..6146a28477 100644 --- a/Dependencies/MinimedKit/MinimedKit/Resources/it.lproj/Localizable.strings +++ b/Dependencies/MinimedKit/MinimedKit/Resources/it.lproj/Localizable.strings @@ -17,7 +17,7 @@ "Bolus in progress" = "Bolo in corso"; /* Suggestions for diagnosing a command refused pump error */ -"Check that the pump is not suspended or priming, or has a percent temp basal type" = "Verificare che il microinfusore non sia sospeso o che stia riavvolgendo o che abbia un tipo basale impostato su percentuale"; +"Check that the pump is not suspended or priming, or has a percent temp basal type" = "Verificare che il microinfusore non sia sospeso o che sia in caricamento o che abbia impostata una basale in percentuale"; /* Pump error code returned when command refused */ "Command refused" = "Comando negato"; @@ -26,13 +26,13 @@ "Comms with another pump detected" = "Comunicazione con un altro microinfusore rilevata"; /* Error description */ -"Decoding Error" = "Errore di Decodifica"; +"Decoding Error" = "Errore di decodifica"; /* Error description */ -"Device Error" = "Errore del Dispositivo"; +"Device Error" = "Errore del dispositivo"; /* Describing the pump history insulin data source */ -"Event History" = "Storia degli Eventi"; +"Event History" = "Storico degli eventi"; /* Format string for failure reason. (1: The operation being performed) (2: The response data) */ "Invalid response during %1$@: %2$@" = "Risposta non valida per %1$@: %2$@"; @@ -47,10 +47,10 @@ "Max setting exceeded" = "Impostazione massima superata"; /* Pump title (1: model number) */ -"Minimed %@" = "Minimed %@"; +"Minimed %@" = "MiniMed %@"; /* Generic title of the minimed pump manager */ -"Minimed 500/700 Series" = "Minimed serie 500/700"; +"Minimed 500/700 Series" = "MiniMed serie 500/700"; /* Describing the North America pump region */ "North America" = "Nord America"; @@ -59,16 +59,16 @@ "Pump did not respond" = "Il microinfusore non risponde"; /* Error description */ -"Pump Error" = "Errore Mincroinfusore"; +"Pump Error" = "Errore microinfusore"; /* No comment provided by engineer. */ "Pump is suspended" = "Il microinfusore è sospeso"; /* No comment provided by engineer. */ -"Pump responded unexpectedly" = "Il microinfusore ha risposto inaspettatamente"; +"Pump responded unexpectedly" = "Il microinfusore ha risposto in modo inaspettato"; /* The format string describing a pump message. (1: The packet type)(2: The message type)(3: The message address)(4: The message data */ -"PumpMessage(%1$@, %2$@, %3$@, %4$@)" = "PumpMessage(%1$@, %2$@, %3$@, %4$@)"; +"PumpMessage(%1$@, %2$@, %3$@, %4$@)" = "Informazioni pompa(%1$@, %2$@, %3$@, %4$@)"; /* Describing the reservoir insulin data source */ "Reservoir" = "Serbatoio"; @@ -77,13 +77,13 @@ "RileyLink radio tune failed" = "Sintonizzazione radio RileyLink fallita"; /* The format string description of a TempBasalPumpEvent. (1: The rate of the temp basal in minutes) */ -"Temporary Basal: %1$.3f U/hour" = "Basale Temporanea: %1$.3f U/ora"; +"Temporary Basal: %1$.3f U/hour" = "Basale temporanea: %1$.3f U/ora"; /* The format string description of a TempBasalDurationPumpEvent. (1: The duration of the temp basal in minutes) */ -"Temporary Basal: %1$d min" = "Basale Temporanea: %1$d min"; +"Temporary Basal: %1$d min" = "Basale temporanea: %1$d min"; /* The format string description of a TempBasalPumpEvent. (1: The rate of the temp basal in percent) */ -"Temporary Basal: %1$d%%" = "Basale Temporanea: %1$d%%"; +"Temporary Basal: %1$d%%" = "Basale temporanea: %1$d%%"; /* The format string description of an unknown pump error code. (1: The specific error code raw value) */ "Unknown pump error code: %1$@" = "Codice errore microinfusore sconosciuto: %1$@"; diff --git a/Dependencies/MinimedKit/MinimedKit/Resources/nb.lproj/Localizable.strings b/Dependencies/MinimedKit/MinimedKit/Resources/nb.lproj/Localizable.strings index 37263e3a3c..ed5c91dafc 100644 --- a/Dependencies/MinimedKit/MinimedKit/Resources/nb.lproj/Localizable.strings +++ b/Dependencies/MinimedKit/MinimedKit/Resources/nb.lproj/Localizable.strings @@ -38,7 +38,7 @@ "Invalid response during %1$@: %2$@" = "Ugyldig respons ved %1$@: %2$@"; /* Describing the battery chemistry as Lithium */ -"Lithium" = "Lithium"; +"Lithium" = "Litium"; /* Recovery suggestion */ "Make sure your RileyLink is nearby and powered on" = "Pass på at din RileyLink er slått på og er i nærheten"; @@ -95,4 +95,4 @@ "Unknown response during %1$@: %2$@" = "Ukjent respons ved %1$@: %2$@"; /* Describing the worldwide pump region */ -"World-Wide" = "World-Wide"; +"World-Wide" = "Verdensomspennende"; diff --git a/Dependencies/MinimedKit/MinimedKit/Resources/uk.lproj/Localizable.strings b/Dependencies/MinimedKit/MinimedKit/Resources/uk.lproj/Localizable.strings index dbffe8dfa5..7bc86c0040 100644 --- a/Dependencies/MinimedKit/MinimedKit/Resources/uk.lproj/Localizable.strings +++ b/Dependencies/MinimedKit/MinimedKit/Resources/uk.lproj/Localizable.strings @@ -44,7 +44,7 @@ "Make sure your RileyLink is nearby and powered on" = "Впевніться, що RileyLink увімкнений та знаходиться поруч"; /* Pump error code describing max setting exceeded */ -"Max setting exceeded" = "Max setting exceeded"; +"Max setting exceeded" = "Максимальне значення перевищено"; /* Pump title (1: model number) */ "Minimed %@" = "Minimed %@"; @@ -53,46 +53,46 @@ "Minimed 500/700 Series" = "Minimed 500/700 Series"; /* Describing the North America pump region */ -"North America" = "North America"; +"North America" = "Північна Америка"; /* No comment provided by engineer. */ -"Pump did not respond" = "Pump did not respond"; +"Pump did not respond" = "Помпа не відповідає"; /* Error description */ -"Pump Error" = "Pump Error"; +"Pump Error" = "Помилка помпи"; /* No comment provided by engineer. */ -"Pump is suspended" = "Pump is suspended"; +"Pump is suspended" = "Помпу призупинено"; /* No comment provided by engineer. */ -"Pump responded unexpectedly" = "Pump responded unexpectedly"; +"Pump responded unexpectedly" = "Несподіваний відгук помпи"; /* The format string describing a pump message. (1: The packet type)(2: The message type)(3: The message address)(4: The message data */ -"PumpMessage(%1$@, %2$@, %3$@, %4$@)" = "PumpMessage(%1$@, %2$@, %3$@, %4$@)"; +"PumpMessage(%1$@, %2$@, %3$@, %4$@)" = "Повідомлення помпи(%1$@, %2$@, %3$@, %4$@)"; /* Describing the reservoir insulin data source */ "Reservoir" = "Резервуар"; /* Error description */ -"RileyLink radio tune failed" = "RileyLink radio tune failed"; +"RileyLink radio tune failed" = "Налаштування радіозв'язку з RileyLink не вдалося"; /* The format string description of a TempBasalPumpEvent. (1: The rate of the temp basal in minutes) */ -"Temporary Basal: %1$.3f U/hour" = "Temporary Basal: %1$.3f U/hour"; +"Temporary Basal: %1$.3f U/hour" = "Тимчасовий базал: %1$.3f U/год"; /* The format string description of a TempBasalDurationPumpEvent. (1: The duration of the temp basal in minutes) */ -"Temporary Basal: %1$d min" = "Temporary Basal: %1$d min"; +"Temporary Basal: %1$d min" = "Тимчасовий базал: %1$d хв"; /* The format string description of a TempBasalPumpEvent. (1: The rate of the temp basal in percent) */ -"Temporary Basal: %1$d%%" = "Temporary Basal: %1$d%%"; +"Temporary Basal: %1$d%%" = "Тимчасовий базал: %1$d хв%%"; /* The format string description of an unknown pump error code. (1: The specific error code raw value) */ -"Unknown pump error code: %1$@" = "Unknown pump error code: %1$@"; +"Unknown pump error code: %1$@" = "Невідомий код помилки помпи: %1$@"; /* No comment provided by engineer. */ -"Unknown pump model: %@" = "Unknown pump model: %@"; +"Unknown pump model: %@" = "Невідома модель помпи: %@"; /* Format string for an unknown response. (1: The operation being performed) (2: The response data) */ -"Unknown response during %1$@: %2$@" = "Unknown response during %1$@: %2$@"; +"Unknown response during %1$@: %2$@" = "Невідомий відгук %1$@: %2$@"; /* Describing the worldwide pump region */ "World-Wide" = "World-Wide"; diff --git a/Dependencies/MinimedKit/MinimedKitUI/Resources/ar.lproj/Localizable.strings b/Dependencies/MinimedKit/MinimedKitUI/Resources/ar.lproj/Localizable.strings index f64d17aeb0..015607ef1e 100644 --- a/Dependencies/MinimedKit/MinimedKitUI/Resources/ar.lproj/Localizable.strings +++ b/Dependencies/MinimedKit/MinimedKitUI/Resources/ar.lproj/Localizable.strings @@ -1,21 +1,220 @@ +/* Unit format string for an RSSI value in decibles */ +"%@ dB" = "%@ dB"; + +/* Format string for reservoir volume. (1: The localized volume) */ +"%@U" = "%@U"; + +/* The format string for displaying a frequency tune trial. Extra spaces added for emphesis: (1: frequency in MHz)(2: success count)(3: total count)(4: average RSSI) */ +"%1$@ %2$@/%3$@ %4$@" = "%1$@ %2$@/%3$@ %4$@"; + +/* The format string describing number of basal schedule entries: (1: number of entries) */ +"%1$@ basal schedule entries\n" = "%1$@ basal schedule entries\n"; + +/* The format string describing units of insulin remaining: (1: number of units) */ +"%1$@ Units of insulin remaining\n" = "%1$@ Units of insulin remaining\n"; + +/* Accessibility format string for (1: localized volume)(2: time) */ +"%1$@ units remaining at %2$@" = "%1$@ units remaining at %2$@"; + +/* String format for value with units (1: value, 2: separator, 3: units) */ +"%1$@%2$@%3$@" = "%1$@%2$@%3$@"; + +/* Text indicating ongoing pump time synchronization */ +"Adjusting Pump Time..." = "Adjusting Pump Time..."; + +/* Instructions on selecting battery chemistry type */ +"Alkaline and Lithium batteries decay at differing rates. Alkaline tend to have a linear voltage drop over time whereas lithium cell batteries tend to maintain voltage until halfway through their lifespan. Under normal usage in a Non-MySentry compatible Minimed (x22/x15) insulin pump running Loop, Alkaline batteries last approximately 4 to 5 days. Lithium batteries last between 1-2 weeks. This selection will use different battery voltage decay rates for each of the battery chemistry types and alert the user when a battery is approximately 8 to 10 hours from failure." = "Alkaline and Lithium batteries decay at differing rates. Alkaline tend to have a linear voltage drop over time whereas lithium cell batteries tend to maintain voltage until halfway through their lifespan. Under normal usage in a Non-MySentry compatible Minimed (x22/x15) insulin pump running Loop, Alkaline batteries last approximately 4 to 5 days. Lithium batteries last between 1-2 weeks. This selection will use different battery voltage decay rates for each of the battery chemistry types and alert the user when a battery is approximately 8 to 10 hours from failure."; + +/* Text to confirm delete this pump */ +"Are you sure you want to delete this Pump?" = "Are you sure you want to delete this Pump?"; + +/* The format string describing pump battery voltage: (1: battery voltage) */ +"Battery: %1$@ volts\n" = "Battery: %1$@ volts\n"; + +/* The label indicating the best radio frequency */ +"Best Frequency" = "Best Frequency"; + +/* The format string describing pump bolusing state: (1: bolusing) */ +"Bolusing: %1$@\n" = "Bolusing: %1$@\n"; + /* Cancel button title */ "Cancel" = "إلغاء"; +/* Title text for suspend resume button when temp basal canceling */ +"Canceling Temp Basal" = "Canceling Temp Basal"; + +/* Text shown in basal rate space when basal is changing */ +"Changing" = "Changing"; + +/* Progress message for changing pump time. */ +"Changing time…" = "Changing time…"; + +/* Instructions on selecting battery chemistry type */ +"Choose the type of battery you are using in your pump for better alerting about low battery conditions." = "Choose the type of battery you are using in your pump for better alerting about low battery conditions."; + /* The title of the configuration section in MinimedPumpManager settings */ "Configuration" = "المعطيات"; +/* Button title to connect to pump during setup */ +"Connect" = "Connect"; + +/* Text for continue button */ +"Continue" = "Continue"; + +/* Button label for removing Pump + Text to delete pump */ +"Delete Pump" = "Delete Pump"; + +/* Header for devices section of RileyLinkSetupView */ +"Devices" = "Devices"; + +/* Description for option to not use MySentry */ +"Do not use MySentry" = "Do not use MySentry"; + /* The alert title for a resume error */ "Error Resuming" = "خطأ في الاستئناف"; +/* The alert title for a suspend error */ +"Error Suspending" = "Error Suspending"; + +/* The alert title for an error while synching time */ +"Error Syncing Time" = "Error Syncing Time"; + +/* Progress message for fetching pump glucose. */ +"Fetching glucose…" = "Fetching glucose…"; + +/* Progress message for fetching pump history. */ +"Fetching history…" = "Fetching history…"; + +/* Progress message for fetching pump model. */ +"Fetching pump model…" = "Fetching pump model…"; + +/* The title of the cell showing the pump firmware version */ +"Firmware Version" = "Firmware Version"; + +/* Text shown in insulin delivery space when insulin suspended */ +"Insulin\nSuspended" = "Insulin\nSuspended"; + /* Title of insulin delivery section */ "Insulin Delivery" = "توصيل الأنسولين"; +/* Instructions on selecting an insulin data source */ +"Insulin delivery can be determined from the pump by either interpreting the event history or comparing the reservoir volume over time. Reading event history allows for a more accurate status graph and uploading up-to-date treatment data to Nightscout, at the cost of faster pump battery drain and the possibility of a higher radio error rate compared to reading only reservoir volume. If the selected source cannot be used for any reason, the system will attempt to fall back to the other option." = "Insulin delivery can be determined from the pump by either interpreting the event history or comparing the reservoir volume over time. Reading event history allows for a more accurate status graph and uploading up-to-date treatment data to Nightscout, at the cost of faster pump battery drain and the possibility of a higher radio error rate compared to reading only reservoir volume. If the selected source cannot be used for any reason, the system will attempt to fall back to the other option."; + +/* Header for insulin remaining on pod settings screen */ +"Insulin Remaining" = "Insulin Remaining"; + +/* Text for confidence reminders navigation link */ +"Insulin Type" = "Insulintyp"; + +/* Format string fof navigation bar title for MinimedPumpSettingsView (1: model number) */ +"Medtronic %1$@" = "Medtronic %1$@"; + +/* Instructions on selecting setting for MySentry */ +"Medtronic pump models 523, 723, 554, and 754 have a feature called 'MySentry' that periodically broadcasts the reservoir and pump battery levels. Listening for these broadcasts allows Loop to communicate with the pump less frequently, which can increase pump battery life. However, when using this feature the RileyLink stays awake more of the time and uses more of its own battery. Enabling this may lengthen pump battery life, while disabling it may lengthen RileyLink battery life. This setting is ignored for other pump models." = "Medtronic pump models 523, 723, 554, and 754 have a feature called 'MySentry' that periodically broadcasts the reservoir and pump battery levels. Listening for these broadcasts allows Loop to communicate with the pump less frequently, which can increase pump battery life. However, when using this feature the RileyLink stays awake more of the time and uses more of its own battery. Enabling this may lengthen pump battery life, while disabling it may lengthen RileyLink battery life. This setting is ignored for other pump models."; + +/* Value string for MySentry config when MySentry is not being used */ +"No" = "No"; + +/* Message display when no response from tuning pump */ +"No response" = "No response"; + +/* Button text to cancel pump time sync */ +"No, Keep Pump As Is" = "No, Keep Pump As Is"; + +/* Pump find device instruction */ +"On your pump, go to the Find Device screen and select \"Find Device\".\n\nMain Menu >\nUtilities >\nConnect Devices >\nOther Devices >\nOn >\nFind Device" = "On your pump, go to the Find Device screen and select \"Find Device\".\n\nMain Menu >\nUtilities >\nConnect Devices >\nOther Devices >\nOn >\nFind Device"; + +/* navigation title for pump battery type selection + Text for medtronic pump preferred data source */ +"Preferred Data Source" = "Preferred Data Source"; + +/* Text for medtronic pump battery percent remaining */ +"Pump Battery Remaining" = "Pump Battery Remaining"; + +/* navigation title for pump battery type selection + Text for medtronic pump battery type */ +"Pump Battery Type" = "Pump Battery Type"; + +/* The title text for the pump ID config value */ +"Pump ID" = "Pump ID"; + +/* The title of the command to change pump time zone */ +"Pump Time" = "Pump Time"; + +/* Progress message for reading basal schedule */ +"Reading basal schedule…" = "Reading basal schedule…"; + +/* Progress message for reading pump status */ +"Reading pump status…" = "Reading pump status…"; + +/* The title of the cell showing the pump region */ +"Region" = "Region"; + +/* Title text for button to resume insulin delivery */ +"Resume Delivery" = "Resume Delivery"; + +/* Title text for button when insulin delivery is in the process of being resumed */ +"Resuming" = "Resuming"; + /* Button title to retry sentry setup */ "Retry" = "أعد المحاولة"; +/* Title of insulin delivery section */ +"Scheduled Basal" = "Scheduled Basal"; + +/* Title text for insulin type confirmation page */ +"Select the type of insulin that you will be using in this pump." = "Select the type of insulin that you will be using in this pump."; + +/* Progress message for sending button press to pump. */ +"Sending button press…" = "Sending button press…"; + +/* Title text for suspend resume button when temp basal starting */ +"Starting Temp Basal" = "Starting Temp Basal"; + +/* A message indicating a command succeeded */ +"Succeeded" = "Succeeded"; + +/* Title text for button to suspend insulin delivery */ +"Suspend Delivery" = "Suspend Delivery"; + +/* The format string describing pump suspended state: (1: suspended) */ +"Suspended: %1$@\n" = "Suspended: %1$@\n"; + +/* Title text for button when insulin delivery is in the process of being stopped */ +"Suspending" = "Suspending"; + +/* The title of the command to change pump time zone */ +"Sync to Current Time" = "Sync to Current Time"; + +/* Message for pod sync time action sheet */ +"The time on your pump is different from the current time. Do you want to update the time on your pump to the current time?" = "The time on your pump is different from the current time. Do you want to update the time on your pump to the current time?"; + +/* Title for pod sync time action sheet. */ +"Time Change Detected" = "Time Change Detected"; + +/* The label indicating the results of each frequency trial */ +"Trials" = "Trials"; + +/* Progress message for tuning radio */ +"Tuning radio…" = "Tuning radio…"; + /* Units for showing temp basal rate */ "U/hr" = "وحدة لكل ساعة"; +/* Text to indicate battery percentage is unknown */ +"unknown" = "unknown"; + /* Text shown in basal rate space when delivery status is unknown */ "Unknown" = "Unknown"; +/* Description for option to use MySentry + navigation title for pump battery type selection + Text for medtronic pump to use MySentry */ +"Use MySentry" = "Use MySentry"; + +/* Value string for MySentry config when MySentry is being used */ +"Yes" = "Yes"; + +/* Button text to confirm pump time sync */ +"Yes, Sync to Current Time" = "Yes, Sync to Current Time"; diff --git a/Dependencies/MinimedKit/MinimedKitUI/Resources/ca.lproj/Localizable.strings b/Dependencies/MinimedKit/MinimedKitUI/Resources/ca.lproj/Localizable.strings index c94e37366e..ebe3f71382 100644 --- a/Dependencies/MinimedKit/MinimedKitUI/Resources/ca.lproj/Localizable.strings +++ b/Dependencies/MinimedKit/MinimedKitUI/Resources/ca.lproj/Localizable.strings @@ -1 +1,220 @@ -/* Empty */ \ No newline at end of file +/* Unit format string for an RSSI value in decibles */ +"%@ dB" = "%@ dB"; + +/* Format string for reservoir volume. (1: The localized volume) */ +"%@U" = "%@U"; + +/* The format string for displaying a frequency tune trial. Extra spaces added for emphesis: (1: frequency in MHz)(2: success count)(3: total count)(4: average RSSI) */ +"%1$@ %2$@/%3$@ %4$@" = "%1$@ %2$@/%3$@ %4$@"; + +/* The format string describing number of basal schedule entries: (1: number of entries) */ +"%1$@ basal schedule entries\n" = "%1$@ basal schedule entries\n"; + +/* The format string describing units of insulin remaining: (1: number of units) */ +"%1$@ Units of insulin remaining\n" = "%1$@ Units of insulin remaining\n"; + +/* Accessibility format string for (1: localized volume)(2: time) */ +"%1$@ units remaining at %2$@" = "%1$@ units remaining at %2$@"; + +/* String format for value with units (1: value, 2: separator, 3: units) */ +"%1$@%2$@%3$@" = "%1$@%2$@%3$@"; + +/* Text indicating ongoing pump time synchronization */ +"Adjusting Pump Time..." = "Adjusting Pump Time..."; + +/* Instructions on selecting battery chemistry type */ +"Alkaline and Lithium batteries decay at differing rates. Alkaline tend to have a linear voltage drop over time whereas lithium cell batteries tend to maintain voltage until halfway through their lifespan. Under normal usage in a Non-MySentry compatible Minimed (x22/x15) insulin pump running Loop, Alkaline batteries last approximately 4 to 5 days. Lithium batteries last between 1-2 weeks. This selection will use different battery voltage decay rates for each of the battery chemistry types and alert the user when a battery is approximately 8 to 10 hours from failure." = "Alkaline and Lithium batteries decay at differing rates. Alkaline tend to have a linear voltage drop over time whereas lithium cell batteries tend to maintain voltage until halfway through their lifespan. Under normal usage in a Non-MySentry compatible Minimed (x22/x15) insulin pump running Loop, Alkaline batteries last approximately 4 to 5 days. Lithium batteries last between 1-2 weeks. This selection will use different battery voltage decay rates for each of the battery chemistry types and alert the user when a battery is approximately 8 to 10 hours from failure."; + +/* Text to confirm delete this pump */ +"Are you sure you want to delete this Pump?" = "Are you sure you want to delete this Pump?"; + +/* The format string describing pump battery voltage: (1: battery voltage) */ +"Battery: %1$@ volts\n" = "Battery: %1$@ volts\n"; + +/* The label indicating the best radio frequency */ +"Best Frequency" = "Best Frequency"; + +/* The format string describing pump bolusing state: (1: bolusing) */ +"Bolusing: %1$@\n" = "Bolusing: %1$@\n"; + +/* Cancel button title */ +"Cancel" = "Cancel"; + +/* Title text for suspend resume button when temp basal canceling */ +"Canceling Temp Basal" = "Canceling Temp Basal"; + +/* Text shown in basal rate space when basal is changing */ +"Changing" = "Changing"; + +/* Progress message for changing pump time. */ +"Changing time…" = "Changing time…"; + +/* Instructions on selecting battery chemistry type */ +"Choose the type of battery you are using in your pump for better alerting about low battery conditions." = "Choose the type of battery you are using in your pump for better alerting about low battery conditions."; + +/* The title of the configuration section in MinimedPumpManager settings */ +"Configuration" = "Configuration"; + +/* Button title to connect to pump during setup */ +"Connect" = "Connect"; + +/* Text for continue button */ +"Continue" = "Continue"; + +/* Button label for removing Pump + Text to delete pump */ +"Delete Pump" = "Delete Pump"; + +/* Header for devices section of RileyLinkSetupView */ +"Devices" = "Devices"; + +/* Description for option to not use MySentry */ +"Do not use MySentry" = "Do not use MySentry"; + +/* The alert title for a resume error */ +"Error Resuming" = "Error Resuming"; + +/* The alert title for a suspend error */ +"Error Suspending" = "Error Suspending"; + +/* The alert title for an error while synching time */ +"Error Syncing Time" = "Error Syncing Time"; + +/* Progress message for fetching pump glucose. */ +"Fetching glucose…" = "Fetching glucose…"; + +/* Progress message for fetching pump history. */ +"Fetching history…" = "Fetching history…"; + +/* Progress message for fetching pump model. */ +"Fetching pump model…" = "Fetching pump model…"; + +/* The title of the cell showing the pump firmware version */ +"Firmware Version" = "Firmware Version"; + +/* Text shown in insulin delivery space when insulin suspended */ +"Insulin\nSuspended" = "Insulin\nSuspended"; + +/* Title of insulin delivery section */ +"Insulin Delivery" = "Insulin Delivery"; + +/* Instructions on selecting an insulin data source */ +"Insulin delivery can be determined from the pump by either interpreting the event history or comparing the reservoir volume over time. Reading event history allows for a more accurate status graph and uploading up-to-date treatment data to Nightscout, at the cost of faster pump battery drain and the possibility of a higher radio error rate compared to reading only reservoir volume. If the selected source cannot be used for any reason, the system will attempt to fall back to the other option." = "Insulin delivery can be determined from the pump by either interpreting the event history or comparing the reservoir volume over time. Reading event history allows for a more accurate status graph and uploading up-to-date treatment data to Nightscout, at the cost of faster pump battery drain and the possibility of a higher radio error rate compared to reading only reservoir volume. If the selected source cannot be used for any reason, the system will attempt to fall back to the other option."; + +/* Header for insulin remaining on pod settings screen */ +"Insulin Remaining" = "Insulin Remaining"; + +/* Text for confidence reminders navigation link */ +"Insulin Type" = "Insulintyp"; + +/* Format string fof navigation bar title for MinimedPumpSettingsView (1: model number) */ +"Medtronic %1$@" = "Medtronic %1$@"; + +/* Instructions on selecting setting for MySentry */ +"Medtronic pump models 523, 723, 554, and 754 have a feature called 'MySentry' that periodically broadcasts the reservoir and pump battery levels. Listening for these broadcasts allows Loop to communicate with the pump less frequently, which can increase pump battery life. However, when using this feature the RileyLink stays awake more of the time and uses more of its own battery. Enabling this may lengthen pump battery life, while disabling it may lengthen RileyLink battery life. This setting is ignored for other pump models." = "Medtronic pump models 523, 723, 554, and 754 have a feature called 'MySentry' that periodically broadcasts the reservoir and pump battery levels. Listening for these broadcasts allows Loop to communicate with the pump less frequently, which can increase pump battery life. However, when using this feature the RileyLink stays awake more of the time and uses more of its own battery. Enabling this may lengthen pump battery life, while disabling it may lengthen RileyLink battery life. This setting is ignored for other pump models."; + +/* Value string for MySentry config when MySentry is not being used */ +"No" = "No"; + +/* Message display when no response from tuning pump */ +"No response" = "No response"; + +/* Button text to cancel pump time sync */ +"No, Keep Pump As Is" = "No, Keep Pump As Is"; + +/* Pump find device instruction */ +"On your pump, go to the Find Device screen and select \"Find Device\".\n\nMain Menu >\nUtilities >\nConnect Devices >\nOther Devices >\nOn >\nFind Device" = "On your pump, go to the Find Device screen and select \"Find Device\".\n\nMain Menu >\nUtilities >\nConnect Devices >\nOther Devices >\nOn >\nFind Device"; + +/* navigation title for pump battery type selection + Text for medtronic pump preferred data source */ +"Preferred Data Source" = "Preferred Data Source"; + +/* Text for medtronic pump battery percent remaining */ +"Pump Battery Remaining" = "Pump Battery Remaining"; + +/* navigation title for pump battery type selection + Text for medtronic pump battery type */ +"Pump Battery Type" = "Pump Battery Type"; + +/* The title text for the pump ID config value */ +"Pump ID" = "Pump ID"; + +/* The title of the command to change pump time zone */ +"Pump Time" = "Pump Time"; + +/* Progress message for reading basal schedule */ +"Reading basal schedule…" = "Reading basal schedule…"; + +/* Progress message for reading pump status */ +"Reading pump status…" = "Reading pump status…"; + +/* The title of the cell showing the pump region */ +"Region" = "Region"; + +/* Title text for button to resume insulin delivery */ +"Resume Delivery" = "Resume Delivery"; + +/* Title text for button when insulin delivery is in the process of being resumed */ +"Resuming" = "Resuming"; + +/* Button title to retry sentry setup */ +"Retry" = "Retry"; + +/* Title of insulin delivery section */ +"Scheduled Basal" = "Scheduled Basal"; + +/* Title text for insulin type confirmation page */ +"Select the type of insulin that you will be using in this pump." = "Select the type of insulin that you will be using in this pump."; + +/* Progress message for sending button press to pump. */ +"Sending button press…" = "Sending button press…"; + +/* Title text for suspend resume button when temp basal starting */ +"Starting Temp Basal" = "Starting Temp Basal"; + +/* A message indicating a command succeeded */ +"Succeeded" = "Succeeded"; + +/* Title text for button to suspend insulin delivery */ +"Suspend Delivery" = "Suspend Delivery"; + +/* The format string describing pump suspended state: (1: suspended) */ +"Suspended: %1$@\n" = "Suspended: %1$@\n"; + +/* Title text for button when insulin delivery is in the process of being stopped */ +"Suspending" = "Suspending"; + +/* The title of the command to change pump time zone */ +"Sync to Current Time" = "Sync to Current Time"; + +/* Message for pod sync time action sheet */ +"The time on your pump is different from the current time. Do you want to update the time on your pump to the current time?" = "The time on your pump is different from the current time. Do you want to update the time on your pump to the current time?"; + +/* Title for pod sync time action sheet. */ +"Time Change Detected" = "Time Change Detected"; + +/* The label indicating the results of each frequency trial */ +"Trials" = "Trials"; + +/* Progress message for tuning radio */ +"Tuning radio…" = "Tuning radio…"; + +/* Units for showing temp basal rate */ +"U/hr" = "U/hr"; + +/* Text to indicate battery percentage is unknown */ +"unknown" = "unknown"; + +/* Text shown in basal rate space when delivery status is unknown */ +"Unknown" = "Unknown"; + +/* Description for option to use MySentry + navigation title for pump battery type selection + Text for medtronic pump to use MySentry */ +"Use MySentry" = "Use MySentry"; + +/* Value string for MySentry config when MySentry is being used */ +"Yes" = "Yes"; + +/* Button text to confirm pump time sync */ +"Yes, Sync to Current Time" = "Yes, Sync to Current Time"; diff --git a/Dependencies/MinimedKit/MinimedKitUI/Resources/da.lproj/Localizable.strings b/Dependencies/MinimedKit/MinimedKitUI/Resources/da.lproj/Localizable.strings index 799f150349..0be21bd0b1 100644 --- a/Dependencies/MinimedKit/MinimedKitUI/Resources/da.lproj/Localizable.strings +++ b/Dependencies/MinimedKit/MinimedKitUI/Resources/da.lproj/Localizable.strings @@ -129,6 +129,9 @@ Text for medtronic pump preferred data source */ "Preferred Data Source" = "Foretruken data kilde"; +/* Text for medtronic pump battery percent remaining */ +"Pump Battery Remaining" = "Pump Battery Remaining"; + /* navigation title for pump battery type selection Text for medtronic pump battery type */ "Pump Battery Type" = "Pumpe batteritype"; @@ -199,6 +202,9 @@ /* Units for showing temp basal rate */ "U/hr" = "E/t"; +/* Text to indicate battery percentage is unknown */ +"unknown" = "unknown"; + /* Text shown in basal rate space when delivery status is unknown */ "Unknown" = "Ukendt"; @@ -212,4 +218,3 @@ /* Button text to confirm pump time sync */ "Yes, Sync to Current Time" = "Ja, synkroniser til det aktuelle klokkeslæt"; - diff --git a/Dependencies/MinimedKit/MinimedKitUI/Resources/de.lproj/Localizable.strings b/Dependencies/MinimedKit/MinimedKitUI/Resources/de.lproj/Localizable.strings index e56f9f7d62..2be76fc06d 100644 --- a/Dependencies/MinimedKit/MinimedKitUI/Resources/de.lproj/Localizable.strings +++ b/Dependencies/MinimedKit/MinimedKitUI/Resources/de.lproj/Localizable.strings @@ -90,13 +90,13 @@ "Fetching pump model…" = "Pumpenmodell abrufen…"; /* The title of the cell showing the pump firmware version */ -"Firmware Version" = "Firmware Version"; +"Firmware Version" = "Firmware-Version"; /* Text shown in insulin delivery space when insulin suspended */ "Insulin\nSuspended" = "Insulinabgabe\nunterbrochen"; /* Title of insulin delivery section */ -"Insulin Delivery" = "Insulin Delivery"; +"Insulin Delivery" = "Insulinabgabe"; /* Instructions on selecting an insulin data source */ "Insulin delivery can be determined from the pump by either interpreting the event history or comparing the reservoir volume over time. Reading event history allows for a more accurate status graph and uploading up-to-date treatment data to Nightscout, at the cost of faster pump battery drain and the possibility of a higher radio error rate compared to reading only reservoir volume. If the selected source cannot be used for any reason, the system will attempt to fall back to the other option." = "Die Insulinabgabe kann von der Pumpe bestimmt werden, indem entweder die Ereignishistorie interpretiert wird oder das Reservoirvolumen über die Zeit verglichen wird. Das Lesen der Ereignishistorie ermöglicht eine genauere Statusgrafik und das Hochladen aktueller Behandlungsdaten in Nightscout, auf Kosten einer schnelleren Pumpenbatterieentleerung und der Möglichkeit einer höheren Funkfehlerrate im Vergleich zum Lesen des Reservoirvolumens. Wenn das ausgewählte Gerät aus irgendeinem Grund nicht verwendet werden kann, versucht das System, auf die andere Option zurückzugreifen."; @@ -218,4 +218,3 @@ /* Button text to confirm pump time sync */ "Yes, Sync to Current Time" = "Ja, mit aktueller Zeit synchronisieren"; - diff --git a/Dependencies/MinimedKit/MinimedKitUI/Resources/en.lproj/Localizable.strings b/Dependencies/MinimedKit/MinimedKitUI/Resources/en.lproj/Localizable.strings index 710cecca97..ebe3f71382 100644 --- a/Dependencies/MinimedKit/MinimedKitUI/Resources/en.lproj/Localizable.strings +++ b/Dependencies/MinimedKit/MinimedKitUI/Resources/en.lproj/Localizable.strings @@ -1 +1,220 @@ -/* Empty */ +/* Unit format string for an RSSI value in decibles */ +"%@ dB" = "%@ dB"; + +/* Format string for reservoir volume. (1: The localized volume) */ +"%@U" = "%@U"; + +/* The format string for displaying a frequency tune trial. Extra spaces added for emphesis: (1: frequency in MHz)(2: success count)(3: total count)(4: average RSSI) */ +"%1$@ %2$@/%3$@ %4$@" = "%1$@ %2$@/%3$@ %4$@"; + +/* The format string describing number of basal schedule entries: (1: number of entries) */ +"%1$@ basal schedule entries\n" = "%1$@ basal schedule entries\n"; + +/* The format string describing units of insulin remaining: (1: number of units) */ +"%1$@ Units of insulin remaining\n" = "%1$@ Units of insulin remaining\n"; + +/* Accessibility format string for (1: localized volume)(2: time) */ +"%1$@ units remaining at %2$@" = "%1$@ units remaining at %2$@"; + +/* String format for value with units (1: value, 2: separator, 3: units) */ +"%1$@%2$@%3$@" = "%1$@%2$@%3$@"; + +/* Text indicating ongoing pump time synchronization */ +"Adjusting Pump Time..." = "Adjusting Pump Time..."; + +/* Instructions on selecting battery chemistry type */ +"Alkaline and Lithium batteries decay at differing rates. Alkaline tend to have a linear voltage drop over time whereas lithium cell batteries tend to maintain voltage until halfway through their lifespan. Under normal usage in a Non-MySentry compatible Minimed (x22/x15) insulin pump running Loop, Alkaline batteries last approximately 4 to 5 days. Lithium batteries last between 1-2 weeks. This selection will use different battery voltage decay rates for each of the battery chemistry types and alert the user when a battery is approximately 8 to 10 hours from failure." = "Alkaline and Lithium batteries decay at differing rates. Alkaline tend to have a linear voltage drop over time whereas lithium cell batteries tend to maintain voltage until halfway through their lifespan. Under normal usage in a Non-MySentry compatible Minimed (x22/x15) insulin pump running Loop, Alkaline batteries last approximately 4 to 5 days. Lithium batteries last between 1-2 weeks. This selection will use different battery voltage decay rates for each of the battery chemistry types and alert the user when a battery is approximately 8 to 10 hours from failure."; + +/* Text to confirm delete this pump */ +"Are you sure you want to delete this Pump?" = "Are you sure you want to delete this Pump?"; + +/* The format string describing pump battery voltage: (1: battery voltage) */ +"Battery: %1$@ volts\n" = "Battery: %1$@ volts\n"; + +/* The label indicating the best radio frequency */ +"Best Frequency" = "Best Frequency"; + +/* The format string describing pump bolusing state: (1: bolusing) */ +"Bolusing: %1$@\n" = "Bolusing: %1$@\n"; + +/* Cancel button title */ +"Cancel" = "Cancel"; + +/* Title text for suspend resume button when temp basal canceling */ +"Canceling Temp Basal" = "Canceling Temp Basal"; + +/* Text shown in basal rate space when basal is changing */ +"Changing" = "Changing"; + +/* Progress message for changing pump time. */ +"Changing time…" = "Changing time…"; + +/* Instructions on selecting battery chemistry type */ +"Choose the type of battery you are using in your pump for better alerting about low battery conditions." = "Choose the type of battery you are using in your pump for better alerting about low battery conditions."; + +/* The title of the configuration section in MinimedPumpManager settings */ +"Configuration" = "Configuration"; + +/* Button title to connect to pump during setup */ +"Connect" = "Connect"; + +/* Text for continue button */ +"Continue" = "Continue"; + +/* Button label for removing Pump + Text to delete pump */ +"Delete Pump" = "Delete Pump"; + +/* Header for devices section of RileyLinkSetupView */ +"Devices" = "Devices"; + +/* Description for option to not use MySentry */ +"Do not use MySentry" = "Do not use MySentry"; + +/* The alert title for a resume error */ +"Error Resuming" = "Error Resuming"; + +/* The alert title for a suspend error */ +"Error Suspending" = "Error Suspending"; + +/* The alert title for an error while synching time */ +"Error Syncing Time" = "Error Syncing Time"; + +/* Progress message for fetching pump glucose. */ +"Fetching glucose…" = "Fetching glucose…"; + +/* Progress message for fetching pump history. */ +"Fetching history…" = "Fetching history…"; + +/* Progress message for fetching pump model. */ +"Fetching pump model…" = "Fetching pump model…"; + +/* The title of the cell showing the pump firmware version */ +"Firmware Version" = "Firmware Version"; + +/* Text shown in insulin delivery space when insulin suspended */ +"Insulin\nSuspended" = "Insulin\nSuspended"; + +/* Title of insulin delivery section */ +"Insulin Delivery" = "Insulin Delivery"; + +/* Instructions on selecting an insulin data source */ +"Insulin delivery can be determined from the pump by either interpreting the event history or comparing the reservoir volume over time. Reading event history allows for a more accurate status graph and uploading up-to-date treatment data to Nightscout, at the cost of faster pump battery drain and the possibility of a higher radio error rate compared to reading only reservoir volume. If the selected source cannot be used for any reason, the system will attempt to fall back to the other option." = "Insulin delivery can be determined from the pump by either interpreting the event history or comparing the reservoir volume over time. Reading event history allows for a more accurate status graph and uploading up-to-date treatment data to Nightscout, at the cost of faster pump battery drain and the possibility of a higher radio error rate compared to reading only reservoir volume. If the selected source cannot be used for any reason, the system will attempt to fall back to the other option."; + +/* Header for insulin remaining on pod settings screen */ +"Insulin Remaining" = "Insulin Remaining"; + +/* Text for confidence reminders navigation link */ +"Insulin Type" = "Insulintyp"; + +/* Format string fof navigation bar title for MinimedPumpSettingsView (1: model number) */ +"Medtronic %1$@" = "Medtronic %1$@"; + +/* Instructions on selecting setting for MySentry */ +"Medtronic pump models 523, 723, 554, and 754 have a feature called 'MySentry' that periodically broadcasts the reservoir and pump battery levels. Listening for these broadcasts allows Loop to communicate with the pump less frequently, which can increase pump battery life. However, when using this feature the RileyLink stays awake more of the time and uses more of its own battery. Enabling this may lengthen pump battery life, while disabling it may lengthen RileyLink battery life. This setting is ignored for other pump models." = "Medtronic pump models 523, 723, 554, and 754 have a feature called 'MySentry' that periodically broadcasts the reservoir and pump battery levels. Listening for these broadcasts allows Loop to communicate with the pump less frequently, which can increase pump battery life. However, when using this feature the RileyLink stays awake more of the time and uses more of its own battery. Enabling this may lengthen pump battery life, while disabling it may lengthen RileyLink battery life. This setting is ignored for other pump models."; + +/* Value string for MySentry config when MySentry is not being used */ +"No" = "No"; + +/* Message display when no response from tuning pump */ +"No response" = "No response"; + +/* Button text to cancel pump time sync */ +"No, Keep Pump As Is" = "No, Keep Pump As Is"; + +/* Pump find device instruction */ +"On your pump, go to the Find Device screen and select \"Find Device\".\n\nMain Menu >\nUtilities >\nConnect Devices >\nOther Devices >\nOn >\nFind Device" = "On your pump, go to the Find Device screen and select \"Find Device\".\n\nMain Menu >\nUtilities >\nConnect Devices >\nOther Devices >\nOn >\nFind Device"; + +/* navigation title for pump battery type selection + Text for medtronic pump preferred data source */ +"Preferred Data Source" = "Preferred Data Source"; + +/* Text for medtronic pump battery percent remaining */ +"Pump Battery Remaining" = "Pump Battery Remaining"; + +/* navigation title for pump battery type selection + Text for medtronic pump battery type */ +"Pump Battery Type" = "Pump Battery Type"; + +/* The title text for the pump ID config value */ +"Pump ID" = "Pump ID"; + +/* The title of the command to change pump time zone */ +"Pump Time" = "Pump Time"; + +/* Progress message for reading basal schedule */ +"Reading basal schedule…" = "Reading basal schedule…"; + +/* Progress message for reading pump status */ +"Reading pump status…" = "Reading pump status…"; + +/* The title of the cell showing the pump region */ +"Region" = "Region"; + +/* Title text for button to resume insulin delivery */ +"Resume Delivery" = "Resume Delivery"; + +/* Title text for button when insulin delivery is in the process of being resumed */ +"Resuming" = "Resuming"; + +/* Button title to retry sentry setup */ +"Retry" = "Retry"; + +/* Title of insulin delivery section */ +"Scheduled Basal" = "Scheduled Basal"; + +/* Title text for insulin type confirmation page */ +"Select the type of insulin that you will be using in this pump." = "Select the type of insulin that you will be using in this pump."; + +/* Progress message for sending button press to pump. */ +"Sending button press…" = "Sending button press…"; + +/* Title text for suspend resume button when temp basal starting */ +"Starting Temp Basal" = "Starting Temp Basal"; + +/* A message indicating a command succeeded */ +"Succeeded" = "Succeeded"; + +/* Title text for button to suspend insulin delivery */ +"Suspend Delivery" = "Suspend Delivery"; + +/* The format string describing pump suspended state: (1: suspended) */ +"Suspended: %1$@\n" = "Suspended: %1$@\n"; + +/* Title text for button when insulin delivery is in the process of being stopped */ +"Suspending" = "Suspending"; + +/* The title of the command to change pump time zone */ +"Sync to Current Time" = "Sync to Current Time"; + +/* Message for pod sync time action sheet */ +"The time on your pump is different from the current time. Do you want to update the time on your pump to the current time?" = "The time on your pump is different from the current time. Do you want to update the time on your pump to the current time?"; + +/* Title for pod sync time action sheet. */ +"Time Change Detected" = "Time Change Detected"; + +/* The label indicating the results of each frequency trial */ +"Trials" = "Trials"; + +/* Progress message for tuning radio */ +"Tuning radio…" = "Tuning radio…"; + +/* Units for showing temp basal rate */ +"U/hr" = "U/hr"; + +/* Text to indicate battery percentage is unknown */ +"unknown" = "unknown"; + +/* Text shown in basal rate space when delivery status is unknown */ +"Unknown" = "Unknown"; + +/* Description for option to use MySentry + navigation title for pump battery type selection + Text for medtronic pump to use MySentry */ +"Use MySentry" = "Use MySentry"; + +/* Value string for MySentry config when MySentry is being used */ +"Yes" = "Yes"; + +/* Button text to confirm pump time sync */ +"Yes, Sync to Current Time" = "Yes, Sync to Current Time"; diff --git a/Dependencies/MinimedKit/MinimedKitUI/Resources/es.lproj/Localizable.strings b/Dependencies/MinimedKit/MinimedKitUI/Resources/es.lproj/Localizable.strings index 50e16e4d77..67b765f795 100644 --- a/Dependencies/MinimedKit/MinimedKitUI/Resources/es.lproj/Localizable.strings +++ b/Dependencies/MinimedKit/MinimedKitUI/Resources/es.lproj/Localizable.strings @@ -129,6 +129,9 @@ Text for medtronic pump preferred data source */ "Preferred Data Source" = "Fuente de Datos Preferida"; +/* Text for medtronic pump battery percent remaining */ +"Pump Battery Remaining" = "Pump Battery Remaining"; + /* navigation title for pump battery type selection Text for medtronic pump battery type */ "Pump Battery Type" = "Tipo de batería de microinfusora"; @@ -199,6 +202,9 @@ /* Units for showing temp basal rate */ "U/hr" = "U/hra"; +/* Text to indicate battery percentage is unknown */ +"unknown" = "unknown"; + /* Text shown in basal rate space when delivery status is unknown */ "Unknown" = "Desconocido"; @@ -212,4 +218,3 @@ /* Button text to confirm pump time sync */ "Yes, Sync to Current Time" = "Sí, sincronizar con la hora actual"; - diff --git a/Dependencies/MinimedKit/MinimedKitUI/Resources/fi.lproj/Localizable.strings b/Dependencies/MinimedKit/MinimedKitUI/Resources/fi.lproj/Localizable.strings index 29048e9922..408f9ae6db 100644 --- a/Dependencies/MinimedKit/MinimedKitUI/Resources/fi.lproj/Localizable.strings +++ b/Dependencies/MinimedKit/MinimedKitUI/Resources/fi.lproj/Localizable.strings @@ -19,9 +19,15 @@ /* String format for value with units (1: value, 2: separator, 3: units) */ "%1$@%2$@%3$@" = "%1$@%2$@%3$@"; +/* Text indicating ongoing pump time synchronization */ +"Adjusting Pump Time..." = "Adjusting Pump Time..."; + /* Instructions on selecting battery chemistry type */ "Alkaline and Lithium batteries decay at differing rates. Alkaline tend to have a linear voltage drop over time whereas lithium cell batteries tend to maintain voltage until halfway through their lifespan. Under normal usage in a Non-MySentry compatible Minimed (x22/x15) insulin pump running Loop, Alkaline batteries last approximately 4 to 5 days. Lithium batteries last between 1-2 weeks. This selection will use different battery voltage decay rates for each of the battery chemistry types and alert the user when a battery is approximately 8 to 10 hours from failure." = "Alkali- ja litiumparistot tyhjenevät eri nopeudella. Alkaliparistojen varaus vähenee yleensä lineaarisesti ajan kuluessa, kun taas litiumparistot ylläpitävät yleensä varaustaan korkeana kunnes käyttöaika on noin puolessa välissä. Normaalilla käytöllä Minimed (x22/x15) insuliinipumppu toimii Loop-käytössä alkaliparistolla noin 4–5 päivää. Litiumparistot kestävät 1–2 viikkoa. Tämä valinta näyttää pariston varauksen vähenemisnopeuden sen perusteella kumpi paristotyyppi on valittu ja varoittaa käyttäjää, kun pariston käyttöaika on loppumassa noin 8–10 tunnin kuluessa"; +/* Text to confirm delete this pump */ +"Are you sure you want to delete this Pump?" = "Are you sure you want to delete this Pump?"; + /* The format string describing pump battery voltage: (1: battery voltage) */ "Battery: %1$@ volts\n" = "Paristo: %1$@ volttia\n"; @@ -37,9 +43,15 @@ /* Title text for suspend resume button when temp basal canceling */ "Canceling Temp Basal" = "Kumotaan tilapäinen basaali"; +/* Text shown in basal rate space when basal is changing */ +"Changing" = "Changing"; + /* Progress message for changing pump time. */ "Changing time…" = "Muutetaan aikaa…"; +/* Instructions on selecting battery chemistry type */ +"Choose the type of battery you are using in your pump for better alerting about low battery conditions." = "Choose the type of battery you are using in your pump for better alerting about low battery conditions."; + /* The title of the configuration section in MinimedPumpManager settings */ "Configuration" = "Määritykset"; @@ -56,12 +68,18 @@ /* Header for devices section of RileyLinkSetupView */ "Devices" = "Laitteet"; +/* Description for option to not use MySentry */ +"Do not use MySentry" = "Do not use MySentry"; + /* The alert title for a resume error */ "Error Resuming" = "Virhe jatkamisessa"; /* The alert title for a suspend error */ "Error Suspending" = "Virhe pysäytyksessä"; +/* The alert title for an error while synching time */ +"Error Syncing Time" = "Error Syncing Time"; + /* Progress message for fetching pump glucose. */ "Fetching glucose…" = "Haetaan glukoosiarvo…"; @@ -74,18 +92,36 @@ /* The title of the cell showing the pump firmware version */ "Firmware Version" = "Laiteohjelmiston versio"; +/* Text shown in insulin delivery space when insulin suspended */ +"Insulin\nSuspended" = "Insulin\nSuspended"; + /* Title of insulin delivery section */ "Insulin Delivery" = "Insulin Delivery"; /* Instructions on selecting an insulin data source */ "Insulin delivery can be determined from the pump by either interpreting the event history or comparing the reservoir volume over time. Reading event history allows for a more accurate status graph and uploading up-to-date treatment data to Nightscout, at the cost of faster pump battery drain and the possibility of a higher radio error rate compared to reading only reservoir volume. If the selected source cannot be used for any reason, the system will attempt to fall back to the other option." = "Pumpun annostelemat insuliinimäärät on mahdollista määrittää joko tulkitsemalla tapahtumahistoriaa tai arvioimalla pumppusäiliön insuliinimäärää ajan kuluessa. Tapahtumahistorian lukeminen antaa tarkemman kuvan tilanteesta ja mahdollistaa ajantasaisen tiedonsiirron Nightscoutiin, mutta toisaalta tämä kuluttaa pumpun paristoa nopeammin ja lisää radiovirheiden todennäköisyyttä siihen verrattuna, että luettaisiin ainoastaan pumppusäiliössä olevan insuliinin määrää. Jos valittua lähdettä ei voida mistä tahansa syystä käyttää, järjestelmä pyrkii käyttämään toista vaihtoehtoa."; +/* Header for insulin remaining on pod settings screen */ +"Insulin Remaining" = "Insulin Remaining"; + /* Text for confidence reminders navigation link */ "Insulin Type" = "Insuliinityyppi"; +/* Format string fof navigation bar title for MinimedPumpSettingsView (1: model number) */ +"Medtronic %1$@" = "Medtronic %1$@"; + +/* Instructions on selecting setting for MySentry */ +"Medtronic pump models 523, 723, 554, and 754 have a feature called 'MySentry' that periodically broadcasts the reservoir and pump battery levels. Listening for these broadcasts allows Loop to communicate with the pump less frequently, which can increase pump battery life. However, when using this feature the RileyLink stays awake more of the time and uses more of its own battery. Enabling this may lengthen pump battery life, while disabling it may lengthen RileyLink battery life. This setting is ignored for other pump models." = "Medtronic pump models 523, 723, 554, and 754 have a feature called 'MySentry' that periodically broadcasts the reservoir and pump battery levels. Listening for these broadcasts allows Loop to communicate with the pump less frequently, which can increase pump battery life. However, when using this feature the RileyLink stays awake more of the time and uses more of its own battery. Enabling this may lengthen pump battery life, while disabling it may lengthen RileyLink battery life. This setting is ignored for other pump models."; + +/* Value string for MySentry config when MySentry is not being used */ +"No" = "No"; + /* Message display when no response from tuning pump */ "No response" = "Ei vastausta"; +/* Button text to cancel pump time sync */ +"No, Keep Pump As Is" = "No, Keep Pump As Is"; + /* Pump find device instruction */ "On your pump, go to the Find Device screen and select \"Find Device\".\n\nMain Menu >\nUtilities >\nConnect Devices >\nOther Devices >\nOn >\nFind Device" = "Mene pumppusi Etsi laite -näytölle ja valitse \"Etsi laite\".\n\n Päävalikko >\nTyökalut >\nYhdistä laitteet >\nMuut laitteet >\nPäällä >\nEtsi laite"; @@ -93,6 +129,9 @@ Text for medtronic pump preferred data source */ "Preferred Data Source" = "Ensisijainen tietolähde"; +/* Text for medtronic pump battery percent remaining */ +"Pump Battery Remaining" = "Pump Battery Remaining"; + /* navigation title for pump battery type selection Text for medtronic pump battery type */ "Pump Battery Type" = "Pumpun paristotyyppi"; @@ -100,6 +139,9 @@ /* The title text for the pump ID config value */ "Pump ID" = "Pumpun tunniste"; +/* The title of the command to change pump time zone */ +"Pump Time" = "Pump Time"; + /* Progress message for reading basal schedule */ "Reading basal schedule…" = "Luetaan basaaliohjelmaa…"; @@ -142,6 +184,15 @@ /* Title text for button when insulin delivery is in the process of being stopped */ "Suspending" = "Pysäytetään"; +/* The title of the command to change pump time zone */ +"Sync to Current Time" = "Sync to Current Time"; + +/* Message for pod sync time action sheet */ +"The time on your pump is different from the current time. Do you want to update the time on your pump to the current time?" = "The time on your pump is different from the current time. Do you want to update the time on your pump to the current time?"; + +/* Title for pod sync time action sheet. */ +"Time Change Detected" = "Time Change Detected"; + /* The label indicating the results of each frequency trial */ "Trials" = "Yritykset"; @@ -151,6 +202,19 @@ /* Units for showing temp basal rate */ "U/hr" = "U/h"; +/* Text to indicate battery percentage is unknown */ +"unknown" = "unknown"; + /* Text shown in basal rate space when delivery status is unknown */ "Unknown" = "Tuntematon"; +/* Description for option to use MySentry + navigation title for pump battery type selection + Text for medtronic pump to use MySentry */ +"Use MySentry" = "Use MySentry"; + +/* Value string for MySentry config when MySentry is being used */ +"Yes" = "Yes"; + +/* Button text to confirm pump time sync */ +"Yes, Sync to Current Time" = "Yes, Sync to Current Time"; diff --git a/Dependencies/MinimedKit/MinimedKitUI/Resources/fr.lproj/Localizable.strings b/Dependencies/MinimedKit/MinimedKitUI/Resources/fr.lproj/Localizable.strings index cd08c364f5..ce2732f2cd 100644 --- a/Dependencies/MinimedKit/MinimedKitUI/Resources/fr.lproj/Localizable.strings +++ b/Dependencies/MinimedKit/MinimedKitUI/Resources/fr.lproj/Localizable.strings @@ -129,6 +129,9 @@ Text for medtronic pump preferred data source */ "Preferred Data Source" = "Source de données préférée"; +/* Text for medtronic pump battery percent remaining */ +"Pump Battery Remaining" = "Pump Battery Remaining"; + /* navigation title for pump battery type selection Text for medtronic pump battery type */ "Pump Battery Type" = "Type de pile dans la pompe"; @@ -199,6 +202,9 @@ /* Units for showing temp basal rate */ "U/hr" = "U/h"; +/* Text to indicate battery percentage is unknown */ +"unknown" = "unknown"; + /* Text shown in basal rate space when delivery status is unknown */ "Unknown" = "Inconnu"; @@ -212,4 +218,3 @@ /* Button text to confirm pump time sync */ "Yes, Sync to Current Time" = "Oui, synchroniser avec l'heure actuelle"; - diff --git a/Dependencies/MinimedKit/MinimedKitUI/Resources/he.lproj/Localizable.strings b/Dependencies/MinimedKit/MinimedKitUI/Resources/he.lproj/Localizable.strings index cb58684df9..88083e0915 100644 --- a/Dependencies/MinimedKit/MinimedKitUI/Resources/he.lproj/Localizable.strings +++ b/Dependencies/MinimedKit/MinimedKitUI/Resources/he.lproj/Localizable.strings @@ -19,9 +19,15 @@ /* String format for value with units (1: value, 2: separator, 3: units) */ "%1$@%2$@%3$@" = "%1$@%2$@%3$@"; +/* Text indicating ongoing pump time synchronization */ +"Adjusting Pump Time..." = "Adjusting Pump Time..."; + /* Instructions on selecting battery chemistry type */ "Alkaline and Lithium batteries decay at differing rates. Alkaline tend to have a linear voltage drop over time whereas lithium cell batteries tend to maintain voltage until halfway through their lifespan. Under normal usage in a Non-MySentry compatible Minimed (x22/x15) insulin pump running Loop, Alkaline batteries last approximately 4 to 5 days. Lithium batteries last between 1-2 weeks. This selection will use different battery voltage decay rates for each of the battery chemistry types and alert the user when a battery is approximately 8 to 10 hours from failure." = "Alkaline and Lithium batteries decay at differing rates. Alkaline tend to have a linear voltage drop over time whereas lithium cell batteries tend to maintain voltage until halfway through their lifespan. Under normal usage in a Non-MySentry compatible Minimed (x22/x15) insulin pump running Loop, Alkaline batteries last approximately 4 to 5 days. Lithium batteries last between 1-2 weeks. This selection will use different battery voltage decay rates for each of the battery chemistry types and alert the user when a battery is approximately 8 to 10 hours from failure."; +/* Text to confirm delete this pump */ +"Are you sure you want to delete this Pump?" = "Are you sure you want to delete this Pump?"; + /* The format string describing pump battery voltage: (1: battery voltage) */ "Battery: %1$@ volts\n" = "Battery: %1$@ volts\n"; @@ -37,9 +43,15 @@ /* Title text for suspend resume button when temp basal canceling */ "Canceling Temp Basal" = "Canceling Temp Basal"; +/* Text shown in basal rate space when basal is changing */ +"Changing" = "Changing"; + /* Progress message for changing pump time. */ "Changing time…" = "Changing time…"; +/* Instructions on selecting battery chemistry type */ +"Choose the type of battery you are using in your pump for better alerting about low battery conditions." = "Choose the type of battery you are using in your pump for better alerting about low battery conditions."; + /* The title of the configuration section in MinimedPumpManager settings */ "Configuration" = "Configuration"; @@ -56,12 +68,18 @@ /* Header for devices section of RileyLinkSetupView */ "Devices" = "Devices"; +/* Description for option to not use MySentry */ +"Do not use MySentry" = "Do not use MySentry"; + /* The alert title for a resume error */ "Error Resuming" = "Error Resuming"; /* The alert title for a suspend error */ "Error Suspending" = "Error Suspending"; +/* The alert title for an error while synching time */ +"Error Syncing Time" = "Error Syncing Time"; + /* Progress message for fetching pump glucose. */ "Fetching glucose…" = "Fetching glucose…"; @@ -74,15 +92,36 @@ /* The title of the cell showing the pump firmware version */ "Firmware Version" = "Firmware Version"; +/* Text shown in insulin delivery space when insulin suspended */ +"Insulin\nSuspended" = "Insulin\nSuspended"; + /* Title of insulin delivery section */ "Insulin Delivery" = "Insulin Delivery"; /* Instructions on selecting an insulin data source */ "Insulin delivery can be determined from the pump by either interpreting the event history or comparing the reservoir volume over time. Reading event history allows for a more accurate status graph and uploading up-to-date treatment data to Nightscout, at the cost of faster pump battery drain and the possibility of a higher radio error rate compared to reading only reservoir volume. If the selected source cannot be used for any reason, the system will attempt to fall back to the other option." = "Insulin delivery can be determined from the pump by either interpreting the event history or comparing the reservoir volume over time. Reading event history allows for a more accurate status graph and uploading up-to-date treatment data to Nightscout, at the cost of faster pump battery drain and the possibility of a higher radio error rate compared to reading only reservoir volume. If the selected source cannot be used for any reason, the system will attempt to fall back to the other option."; +/* Header for insulin remaining on pod settings screen */ +"Insulin Remaining" = "Insulin Remaining"; + +/* Text for confidence reminders navigation link */ +"Insulin Type" = "Insulintyp"; + +/* Format string fof navigation bar title for MinimedPumpSettingsView (1: model number) */ +"Medtronic %1$@" = "Medtronic %1$@"; + +/* Instructions on selecting setting for MySentry */ +"Medtronic pump models 523, 723, 554, and 754 have a feature called 'MySentry' that periodically broadcasts the reservoir and pump battery levels. Listening for these broadcasts allows Loop to communicate with the pump less frequently, which can increase pump battery life. However, when using this feature the RileyLink stays awake more of the time and uses more of its own battery. Enabling this may lengthen pump battery life, while disabling it may lengthen RileyLink battery life. This setting is ignored for other pump models." = "Medtronic pump models 523, 723, 554, and 754 have a feature called 'MySentry' that periodically broadcasts the reservoir and pump battery levels. Listening for these broadcasts allows Loop to communicate with the pump less frequently, which can increase pump battery life. However, when using this feature the RileyLink stays awake more of the time and uses more of its own battery. Enabling this may lengthen pump battery life, while disabling it may lengthen RileyLink battery life. This setting is ignored for other pump models."; + +/* Value string for MySentry config when MySentry is not being used */ +"No" = "No"; + /* Message display when no response from tuning pump */ "No response" = "No response"; +/* Button text to cancel pump time sync */ +"No, Keep Pump As Is" = "No, Keep Pump As Is"; + /* Pump find device instruction */ "On your pump, go to the Find Device screen and select \"Find Device\".\n\nMain Menu >\nUtilities >\nConnect Devices >\nOther Devices >\nOn >\nFind Device" = "On your pump, go to the Find Device screen and select \"Find Device\".\n\nMain Menu >\nUtilities >\nConnect Devices >\nOther Devices >\nOn >\nFind Device"; @@ -90,6 +129,9 @@ Text for medtronic pump preferred data source */ "Preferred Data Source" = "Preferred Data Source"; +/* Text for medtronic pump battery percent remaining */ +"Pump Battery Remaining" = "Pump Battery Remaining"; + /* navigation title for pump battery type selection Text for medtronic pump battery type */ "Pump Battery Type" = "Pump Battery Type"; @@ -97,6 +139,9 @@ /* The title text for the pump ID config value */ "Pump ID" = "מספר זיהוי המשאבה"; +/* The title of the command to change pump time zone */ +"Pump Time" = "Pump Time"; + /* Progress message for reading basal schedule */ "Reading basal schedule…" = "Reading basal schedule…"; @@ -118,6 +163,9 @@ /* Title of insulin delivery section */ "Scheduled Basal" = "Scheduled Basal"; +/* Title text for insulin type confirmation page */ +"Select the type of insulin that you will be using in this pump." = "Select the type of insulin that you will be using in this pump."; + /* Progress message for sending button press to pump. */ "Sending button press…" = "Sending button press…"; @@ -154,9 +202,19 @@ /* Units for showing temp basal rate */ "U/hr" = "יח׳/שעה"; +/* Text to indicate battery percentage is unknown */ +"unknown" = "unknown"; + /* Text shown in basal rate space when delivery status is unknown */ "Unknown" = "Unknown"; +/* Description for option to use MySentry + navigation title for pump battery type selection + Text for medtronic pump to use MySentry */ +"Use MySentry" = "Use MySentry"; + /* Value string for MySentry config when MySentry is being used */ "Yes" = "כן"; +/* Button text to confirm pump time sync */ +"Yes, Sync to Current Time" = "Yes, Sync to Current Time"; diff --git a/Dependencies/MinimedKit/MinimedKitUI/Resources/it.lproj/Localizable.strings b/Dependencies/MinimedKit/MinimedKitUI/Resources/it.lproj/Localizable.strings index 714afcab93..cb0308c04d 100644 --- a/Dependencies/MinimedKit/MinimedKitUI/Resources/it.lproj/Localizable.strings +++ b/Dependencies/MinimedKit/MinimedKitUI/Resources/it.lproj/Localizable.strings @@ -129,6 +129,9 @@ Text for medtronic pump preferred data source */ "Preferred Data Source" = "Fonte Dati"; +/* Text for medtronic pump battery percent remaining */ +"Pump Battery Remaining" = "Pump Battery Remaining"; + /* navigation title for pump battery type selection Text for medtronic pump battery type */ "Pump Battery Type" = "Tipo Batteria Microinfusore"; @@ -199,6 +202,9 @@ /* Units for showing temp basal rate */ "U/hr" = "U/ora"; +/* Text to indicate battery percentage is unknown */ +"unknown" = "unknown"; + /* Text shown in basal rate space when delivery status is unknown */ "Unknown" = "Sconosciuto"; @@ -212,4 +218,3 @@ /* Button text to confirm pump time sync */ "Yes, Sync to Current Time" = "Sì, sincronizza con l'ora corrente"; - diff --git a/Dependencies/MinimedKit/MinimedKitUI/Resources/nb.lproj/Localizable.strings b/Dependencies/MinimedKit/MinimedKitUI/Resources/nb.lproj/Localizable.strings index d58f988860..27d65bce38 100644 --- a/Dependencies/MinimedKit/MinimedKitUI/Resources/nb.lproj/Localizable.strings +++ b/Dependencies/MinimedKit/MinimedKitUI/Resources/nb.lproj/Localizable.strings @@ -96,7 +96,7 @@ "Insulin\nSuspended" = "Insulintilførsel utsatt"; /* Title of insulin delivery section */ -"Insulin Delivery" = "Insulin Delivery"; +"Insulin Delivery" = "Insulintilførsel"; /* Instructions on selecting an insulin data source */ "Insulin delivery can be determined from the pump by either interpreting the event history or comparing the reservoir volume over time. Reading event history allows for a more accurate status graph and uploading up-to-date treatment data to Nightscout, at the cost of faster pump battery drain and the possibility of a higher radio error rate compared to reading only reservoir volume. If the selected source cannot be used for any reason, the system will attempt to fall back to the other option." = "Insulintilførsel kan hentes fra pumpa, enten ved å tolke hendelsehistorikken, eller ved å sammenligne reservoarvolumet over tid. Ved å lese hendelsehistorikken får man mer nøyaktig statuskurve og kan laste opp oppdaterte hendelser til Nightscout. Ulempen er høyere batteriforbruk i pumpa, og muligheten for større antall feil ved radiokommunikasjon - sammenlignet med å bare lese reservoarvolumet. Hvis den valgte kilden av noen grunn ikke kan brukes, vill systemet prøve den andre måten."; @@ -123,7 +123,7 @@ "No, Keep Pump As Is" = "Nei, behold pumpen som den er"; /* Pump find device instruction */ -"On your pump, go to the Find Device screen and select \"Find Device\".\n\nMain Menu >\nUtilities >\nConnect Devices >\nOther Devices >\nOn >\nFind Device" = "On your pump, go to the Find Device screen and select \"Find Device\".\n\nMain Menu >\nUtilities >\nConnect Devices >\nOther Devices >\nOn >\nFind Device"; +"On your pump, go to the Find Device screen and select \"Find Device\".\n\nMain Menu >\nUtilities >\nConnect Devices >\nOther Devices >\nOn >\nFind Device" = "På pumpen, gå til \"Find Device\"-skjermen og velg \"Find Device\".\n\nMain Menu >\nUtilities >\nConnect Devices >\nOther Devices >\nOn >\nFind Device"; /* navigation title for pump battery type selection Text for medtronic pump preferred data source */ @@ -218,4 +218,3 @@ /* Button text to confirm pump time sync */ "Yes, Sync to Current Time" = "Ja, Synkroniser til gjeldende tid"; - diff --git a/Dependencies/MinimedKit/MinimedKitUI/Resources/nl.lproj/Localizable.strings b/Dependencies/MinimedKit/MinimedKitUI/Resources/nl.lproj/Localizable.strings index a8883ff833..cbb8c38f32 100644 --- a/Dependencies/MinimedKit/MinimedKitUI/Resources/nl.lproj/Localizable.strings +++ b/Dependencies/MinimedKit/MinimedKitUI/Resources/nl.lproj/Localizable.strings @@ -28,9 +28,6 @@ /* Text to confirm delete this pump */ "Are you sure you want to delete this Pump?" = "Weet je zeker dat je deze pomp wilt verwijderen?"; -/* No comment provided by engineer. */ -"Battery Chemistry" = "Batterij Chemie"; - /* The format string describing pump battery voltage: (1: battery voltage) */ "Battery: %1$@ volts\n" = "Batterij: %1$@ volt\n"; @@ -74,9 +71,6 @@ /* Description for option to not use MySentry */ "Do not use MySentry" = "Gebruik MySentry niet"; -/* No comment provided by engineer. */ -"Done" = "Gereed"; - /* The alert title for a resume error */ "Error Resuming" = "Fout Bij Hervatten"; @@ -224,4 +218,3 @@ /* Button text to confirm pump time sync */ "Yes, Sync to Current Time" = "Ja, Synchroniseer met Huidige Tijd"; - diff --git a/Dependencies/MinimedKit/MinimedKitUI/Resources/pl.lproj/Localizable.strings b/Dependencies/MinimedKit/MinimedKitUI/Resources/pl.lproj/Localizable.strings index c7d720a826..ff73fb8dab 100644 --- a/Dependencies/MinimedKit/MinimedKitUI/Resources/pl.lproj/Localizable.strings +++ b/Dependencies/MinimedKit/MinimedKitUI/Resources/pl.lproj/Localizable.strings @@ -28,9 +28,6 @@ /* Text to confirm delete this pump */ "Are you sure you want to delete this Pump?" = "Czy na pewno chcesz usunąć tę pompę?"; -/* No comment provided by engineer. */ -"Battery Chemistry" = "Chemia baterii"; - /* The format string describing pump battery voltage: (1: battery voltage) */ "Battery: %1$@ volts\n" = "Bateria: %1$@ V\n"; @@ -74,9 +71,6 @@ /* Description for option to not use MySentry */ "Do not use MySentry" = "Nie używaj MySentry"; -/* No comment provided by engineer. */ -"Done" = "Gotowe"; - /* The alert title for a resume error */ "Error Resuming" = "Błąd wznawiania"; @@ -224,4 +218,3 @@ /* Button text to confirm pump time sync */ "Yes, Sync to Current Time" = "Tak, zsynchronizuj z bieżącym czasem"; - diff --git a/Dependencies/MinimedKit/MinimedKitUI/Resources/pt-BR.lproj/Localizable.strings b/Dependencies/MinimedKit/MinimedKitUI/Resources/pt-BR.lproj/Localizable.strings index 736ed2c4d5..1d516ab7f7 100644 --- a/Dependencies/MinimedKit/MinimedKitUI/Resources/pt-BR.lproj/Localizable.strings +++ b/Dependencies/MinimedKit/MinimedKitUI/Resources/pt-BR.lproj/Localizable.strings @@ -1,3 +1,6 @@ +/* Unit format string for an RSSI value in decibles */ +"%@ dB" = "%@ dB"; + /* Format string for reservoir volume. (1: The localized volume) */ "%@U" = "%@U"; @@ -16,9 +19,15 @@ /* String format for value with units (1: value, 2: separator, 3: units) */ "%1$@%2$@%3$@" = "%1$@%2$@%3$@"; +/* Text indicating ongoing pump time synchronization */ +"Adjusting Pump Time..." = "Adjusting Pump Time..."; + /* Instructions on selecting battery chemistry type */ "Alkaline and Lithium batteries decay at differing rates. Alkaline tend to have a linear voltage drop over time whereas lithium cell batteries tend to maintain voltage until halfway through their lifespan. Under normal usage in a Non-MySentry compatible Minimed (x22/x15) insulin pump running Loop, Alkaline batteries last approximately 4 to 5 days. Lithium batteries last between 1-2 weeks. This selection will use different battery voltage decay rates for each of the battery chemistry types and alert the user when a battery is approximately 8 to 10 hours from failure." = "Baterias alcalinas e de lítio descarregam de formas diferentes. Baterias alcalinas tendem a perder voltagem linearmente, enquanto baterias de célula de lítio tendem a manter a voltagem até metade de sua vida útil. Em condições normais de uso do Loop em uma bomba Minimed que não utiliza o MySentry (x22/x15), baterias alcalinas devem durar entre 4 e 5 dias. Baterias de lítio duram entre 1 e 2 semanas. Essa seleção vai utilizar diferentes taxas de descarregamento para cada tipo de bateria e alertar o usuário quando a bateria estiver entre 8 e 10 horas de falhar."; +/* Text to confirm delete this pump */ +"Are you sure you want to delete this Pump?" = "Are you sure you want to delete this Pump?"; + /* The format string describing pump battery voltage: (1: battery voltage) */ "Battery: %1$@ volts\n" = "Bateria: %1$@ volts\n"; @@ -34,9 +43,15 @@ /* Title text for suspend resume button when temp basal canceling */ "Canceling Temp Basal" = "Cancelar Basal Temporária"; +/* Text shown in basal rate space when basal is changing */ +"Changing" = "Changing"; + /* Progress message for changing pump time. */ "Changing time…" = "Alterando a hora..."; +/* Instructions on selecting battery chemistry type */ +"Choose the type of battery you are using in your pump for better alerting about low battery conditions." = "Choose the type of battery you are using in your pump for better alerting about low battery conditions."; + /* The title of the configuration section in MinimedPumpManager settings */ "Configuration" = "Configuração"; @@ -53,12 +68,18 @@ /* Header for devices section of RileyLinkSetupView */ "Devices" = "Dispositivos"; +/* Description for option to not use MySentry */ +"Do not use MySentry" = "Do not use MySentry"; + /* The alert title for a resume error */ "Error Resuming" = "Erro ao Retomar"; /* The alert title for a suspend error */ "Error Suspending" = "Erro ao Suspender"; +/* The alert title for an error while synching time */ +"Error Syncing Time" = "Error Syncing Time"; + /* Progress message for fetching pump glucose. */ "Fetching glucose…" = "Buscando glicose…"; @@ -71,15 +92,36 @@ /* The title of the cell showing the pump firmware version */ "Firmware Version" = "Versão do Firmware"; +/* Text shown in insulin delivery space when insulin suspended */ +"Insulin\nSuspended" = "Insulin\nSuspended"; + /* Title of insulin delivery section */ "Insulin Delivery" = "Insulin Delivery"; /* Instructions on selecting an insulin data source */ "Insulin delivery can be determined from the pump by either interpreting the event history or comparing the reservoir volume over time. Reading event history allows for a more accurate status graph and uploading up-to-date treatment data to Nightscout, at the cost of faster pump battery drain and the possibility of a higher radio error rate compared to reading only reservoir volume. If the selected source cannot be used for any reason, the system will attempt to fall back to the other option." = "A quantidade de insulina utilizada pode ser determinada tanto interpretando o histórico de eventos quanto medindo a diferença no volume do reservatório. Ler a partir do histórico de eventos permite um gráfico de estado mais preciso e o envio de dados de tratamento mais atualizados para o Nightscout, mas com um maior gasto de bateria e com uma maior possibilidade de erros de transmissão, quando comparado com a leitura apenas do volume do reservatório. Se a fonte selecionada não puder ser utilizada por algum motivo, o sistema tentará a outra opção."; +/* Header for insulin remaining on pod settings screen */ +"Insulin Remaining" = "Insulin Remaining"; + +/* Text for confidence reminders navigation link */ +"Insulin Type" = "Insulintyp"; + +/* Format string fof navigation bar title for MinimedPumpSettingsView (1: model number) */ +"Medtronic %1$@" = "Medtronic %1$@"; + +/* Instructions on selecting setting for MySentry */ +"Medtronic pump models 523, 723, 554, and 754 have a feature called 'MySentry' that periodically broadcasts the reservoir and pump battery levels. Listening for these broadcasts allows Loop to communicate with the pump less frequently, which can increase pump battery life. However, when using this feature the RileyLink stays awake more of the time and uses more of its own battery. Enabling this may lengthen pump battery life, while disabling it may lengthen RileyLink battery life. This setting is ignored for other pump models." = "Medtronic pump models 523, 723, 554, and 754 have a feature called 'MySentry' that periodically broadcasts the reservoir and pump battery levels. Listening for these broadcasts allows Loop to communicate with the pump less frequently, which can increase pump battery life. However, when using this feature the RileyLink stays awake more of the time and uses more of its own battery. Enabling this may lengthen pump battery life, while disabling it may lengthen RileyLink battery life. This setting is ignored for other pump models."; + +/* Value string for MySentry config when MySentry is not being used */ +"No" = "No"; + /* Message display when no response from tuning pump */ "No response" = "Sem Resposta"; +/* Button text to cancel pump time sync */ +"No, Keep Pump As Is" = "No, Keep Pump As Is"; + /* Pump find device instruction */ "On your pump, go to the Find Device screen and select \"Find Device\".\n\nMain Menu >\nUtilities >\nConnect Devices >\nOther Devices >\nOn >\nFind Device" = "Na sua Bomba, vá para a tela de encontrar dispositivos (Find Device) e selecione \"Encontrar Dispositivo\" (Find Device).\n\nMenu Principal >\nUtilitários (Utilities) >\nConectar Dispositivos (Connect Devices)\nOutros Dispositivos (Other Devices) >\nLigar (On) >\nEncontrar Dispositivo (Find Device)"; @@ -87,6 +129,9 @@ Text for medtronic pump preferred data source */ "Preferred Data Source" = "Fonte de Dados Preferido"; +/* Text for medtronic pump battery percent remaining */ +"Pump Battery Remaining" = "Pump Battery Remaining"; + /* navigation title for pump battery type selection Text for medtronic pump battery type */ "Pump Battery Type" = "Tipo de Bateria da Bomba"; @@ -94,6 +139,9 @@ /* The title text for the pump ID config value */ "Pump ID" = "ID da Bomba"; +/* The title of the command to change pump time zone */ +"Pump Time" = "Pump Time"; + /* Progress message for reading basal schedule */ "Reading basal schedule…" = "Lendo programação de basal…"; @@ -115,6 +163,9 @@ /* Title of insulin delivery section */ "Scheduled Basal" = "Basal Agendado"; +/* Title text for insulin type confirmation page */ +"Select the type of insulin that you will be using in this pump." = "Select the type of insulin that you will be using in this pump."; + /* Progress message for sending button press to pump. */ "Sending button press…" = "Enviando aperto do botão"; @@ -133,6 +184,15 @@ /* Title text for button when insulin delivery is in the process of being stopped */ "Suspending" = "Suspendendo"; +/* The title of the command to change pump time zone */ +"Sync to Current Time" = "Sync to Current Time"; + +/* Message for pod sync time action sheet */ +"The time on your pump is different from the current time. Do you want to update the time on your pump to the current time?" = "The time on your pump is different from the current time. Do you want to update the time on your pump to the current time?"; + +/* Title for pod sync time action sheet. */ +"Time Change Detected" = "Time Change Detected"; + /* The label indicating the results of each frequency trial */ "Trials" = "Tentativas"; @@ -142,6 +202,19 @@ /* Units for showing temp basal rate */ "U/hr" = "U/hr"; +/* Text to indicate battery percentage is unknown */ +"unknown" = "unknown"; + /* Text shown in basal rate space when delivery status is unknown */ "Unknown" = "Desconhecido"; +/* Description for option to use MySentry + navigation title for pump battery type selection + Text for medtronic pump to use MySentry */ +"Use MySentry" = "Use MySentry"; + +/* Value string for MySentry config when MySentry is being used */ +"Yes" = "Yes"; + +/* Button text to confirm pump time sync */ +"Yes, Sync to Current Time" = "Yes, Sync to Current Time"; diff --git a/Dependencies/MinimedKit/MinimedKitUI/Resources/pt-PT.lproj/Localizable.strings b/Dependencies/MinimedKit/MinimedKitUI/Resources/pt-PT.lproj/Localizable.strings index c94e37366e..82d828f7f3 100644 --- a/Dependencies/MinimedKit/MinimedKitUI/Resources/pt-PT.lproj/Localizable.strings +++ b/Dependencies/MinimedKit/MinimedKitUI/Resources/pt-PT.lproj/Localizable.strings @@ -1 +1,220 @@ -/* Empty */ \ No newline at end of file +/* Unit format string for an RSSI value in decibles */ +"%@ dB" = "%@ dB"; + +/* Format string for reservoir volume. (1: The localized volume) */ +"%@U" = "%@U"; + +/* The format string for displaying a frequency tune trial. Extra spaces added for emphesis: (1: frequency in MHz)(2: success count)(3: total count)(4: average RSSI) */ +"%1$@ %2$@/%3$@ %4$@" = "%1$@ %2$@/%3$@ %4$@"; + +/* The format string describing number of basal schedule entries: (1: number of entries) */ +"%1$@ basal schedule entries\n" = "%1$@ basal schedule entries\n"; + +/* The format string describing units of insulin remaining: (1: number of units) */ +"%1$@ Units of insulin remaining\n" = "%1$@ Units of insulin remaining\n"; + +/* Accessibility format string for (1: localized volume)(2: time) */ +"%1$@ units remaining at %2$@" = "%1$@ units remaining at %2$@"; + +/* String format for value with units (1: value, 2: separator, 3: units) */ +"%1$@%2$@%3$@" = "%1$@%2$@%3$@"; + +/* Text indicating ongoing pump time synchronization */ +"Adjusting Pump Time..." = "Adjusting Pump Time..."; + +/* Instructions on selecting battery chemistry type */ +"Alkaline and Lithium batteries decay at differing rates. Alkaline tend to have a linear voltage drop over time whereas lithium cell batteries tend to maintain voltage until halfway through their lifespan. Under normal usage in a Non-MySentry compatible Minimed (x22/x15) insulin pump running Loop, Alkaline batteries last approximately 4 to 5 days. Lithium batteries last between 1-2 weeks. This selection will use different battery voltage decay rates for each of the battery chemistry types and alert the user when a battery is approximately 8 to 10 hours from failure." = "Alkaline and Lithium batteries decay at differing rates. Alkaline tend to have a linear voltage drop over time whereas lithium cell batteries tend to maintain voltage until halfway through their lifespan. Under normal usage in a Non-MySentry compatible Minimed (x22/x15) insulin pump running Loop, Alkaline batteries last approximately 4 to 5 days. Lithium batteries last between 1-2 weeks. This selection will use different battery voltage decay rates for each of the battery chemistry types and alert the user when a battery is approximately 8 to 10 hours from failure."; + +/* Text to confirm delete this pump */ +"Are you sure you want to delete this Pump?" = "Are you sure you want to delete this Pump?"; + +/* The format string describing pump battery voltage: (1: battery voltage) */ +"Battery: %1$@ volts\n" = "Battery: %1$@ volts\n"; + +/* The label indicating the best radio frequency */ +"Best Frequency" = "Best Frequency"; + +/* The format string describing pump bolusing state: (1: bolusing) */ +"Bolusing: %1$@\n" = "Bolusing: %1$@\n"; + +/* Cancel button title */ +"Cancel" = "Cancelar"; + +/* Title text for suspend resume button when temp basal canceling */ +"Canceling Temp Basal" = "Canceling Temp Basal"; + +/* Text shown in basal rate space when basal is changing */ +"Changing" = "Changing"; + +/* Progress message for changing pump time. */ +"Changing time…" = "Changing time…"; + +/* Instructions on selecting battery chemistry type */ +"Choose the type of battery you are using in your pump for better alerting about low battery conditions." = "Choose the type of battery you are using in your pump for better alerting about low battery conditions."; + +/* The title of the configuration section in MinimedPumpManager settings */ +"Configuration" = "Ajustes"; + +/* Button title to connect to pump during setup */ +"Connect" = "Conectar"; + +/* Text for continue button */ +"Continue" = "Continue"; + +/* Button label for removing Pump + Text to delete pump */ +"Delete Pump" = "Delete Pump"; + +/* Header for devices section of RileyLinkSetupView */ +"Devices" = "Dispositivos"; + +/* Description for option to not use MySentry */ +"Do not use MySentry" = "Do not use MySentry"; + +/* The alert title for a resume error */ +"Error Resuming" = "Error Resuming"; + +/* The alert title for a suspend error */ +"Error Suspending" = "Error Suspending"; + +/* The alert title for an error while synching time */ +"Error Syncing Time" = "Error Syncing Time"; + +/* Progress message for fetching pump glucose. */ +"Fetching glucose…" = "Fetching glucose…"; + +/* Progress message for fetching pump history. */ +"Fetching history…" = "Fetching history…"; + +/* Progress message for fetching pump model. */ +"Fetching pump model…" = "Fetching pump model…"; + +/* The title of the cell showing the pump firmware version */ +"Firmware Version" = "Firmware Version"; + +/* Text shown in insulin delivery space when insulin suspended */ +"Insulin\nSuspended" = "Insulin\nSuspended"; + +/* Title of insulin delivery section */ +"Insulin Delivery" = "Insulin Delivery"; + +/* Instructions on selecting an insulin data source */ +"Insulin delivery can be determined from the pump by either interpreting the event history or comparing the reservoir volume over time. Reading event history allows for a more accurate status graph and uploading up-to-date treatment data to Nightscout, at the cost of faster pump battery drain and the possibility of a higher radio error rate compared to reading only reservoir volume. If the selected source cannot be used for any reason, the system will attempt to fall back to the other option." = "Insulin delivery can be determined from the pump by either interpreting the event history or comparing the reservoir volume over time. Reading event history allows for a more accurate status graph and uploading up-to-date treatment data to Nightscout, at the cost of faster pump battery drain and the possibility of a higher radio error rate compared to reading only reservoir volume. If the selected source cannot be used for any reason, the system will attempt to fall back to the other option."; + +/* Header for insulin remaining on pod settings screen */ +"Insulin Remaining" = "Insulin Remaining"; + +/* Text for confidence reminders navigation link */ +"Insulin Type" = "Insulintyp"; + +/* Format string fof navigation bar title for MinimedPumpSettingsView (1: model number) */ +"Medtronic %1$@" = "Medtronic %1$@"; + +/* Instructions on selecting setting for MySentry */ +"Medtronic pump models 523, 723, 554, and 754 have a feature called 'MySentry' that periodically broadcasts the reservoir and pump battery levels. Listening for these broadcasts allows Loop to communicate with the pump less frequently, which can increase pump battery life. However, when using this feature the RileyLink stays awake more of the time and uses more of its own battery. Enabling this may lengthen pump battery life, while disabling it may lengthen RileyLink battery life. This setting is ignored for other pump models." = "Medtronic pump models 523, 723, 554, and 754 have a feature called 'MySentry' that periodically broadcasts the reservoir and pump battery levels. Listening for these broadcasts allows Loop to communicate with the pump less frequently, which can increase pump battery life. However, when using this feature the RileyLink stays awake more of the time and uses more of its own battery. Enabling this may lengthen pump battery life, while disabling it may lengthen RileyLink battery life. This setting is ignored for other pump models."; + +/* Value string for MySentry config when MySentry is not being used */ +"No" = "No"; + +/* Message display when no response from tuning pump */ +"No response" = "No response"; + +/* Button text to cancel pump time sync */ +"No, Keep Pump As Is" = "No, Keep Pump As Is"; + +/* Pump find device instruction */ +"On your pump, go to the Find Device screen and select \"Find Device\".\n\nMain Menu >\nUtilities >\nConnect Devices >\nOther Devices >\nOn >\nFind Device" = "On your pump, go to the Find Device screen and select \"Find Device\".\n\nMain Menu >\nUtilities >\nConnect Devices >\nOther Devices >\nOn >\nFind Device"; + +/* navigation title for pump battery type selection + Text for medtronic pump preferred data source */ +"Preferred Data Source" = "Preferred Data Source"; + +/* Text for medtronic pump battery percent remaining */ +"Pump Battery Remaining" = "Pump Battery Remaining"; + +/* navigation title for pump battery type selection + Text for medtronic pump battery type */ +"Pump Battery Type" = "Pump Battery Type"; + +/* The title text for the pump ID config value */ +"Pump ID" = "Pump ID"; + +/* The title of the command to change pump time zone */ +"Pump Time" = "Pump Time"; + +/* Progress message for reading basal schedule */ +"Reading basal schedule…" = "Reading basal schedule…"; + +/* Progress message for reading pump status */ +"Reading pump status…" = "Reading pump status…"; + +/* The title of the cell showing the pump region */ +"Region" = "Region"; + +/* Title text for button to resume insulin delivery */ +"Resume Delivery" = "Resume Delivery"; + +/* Title text for button when insulin delivery is in the process of being resumed */ +"Resuming" = "Resuming"; + +/* Button title to retry sentry setup */ +"Retry" = "Retry"; + +/* Title of insulin delivery section */ +"Scheduled Basal" = "Scheduled Basal"; + +/* Title text for insulin type confirmation page */ +"Select the type of insulin that you will be using in this pump." = "Select the type of insulin that you will be using in this pump."; + +/* Progress message for sending button press to pump. */ +"Sending button press…" = "Sending button press…"; + +/* Title text for suspend resume button when temp basal starting */ +"Starting Temp Basal" = "Starting Temp Basal"; + +/* A message indicating a command succeeded */ +"Succeeded" = "Succeeded"; + +/* Title text for button to suspend insulin delivery */ +"Suspend Delivery" = "Suspend Delivery"; + +/* The format string describing pump suspended state: (1: suspended) */ +"Suspended: %1$@\n" = "Suspended: %1$@\n"; + +/* Title text for button when insulin delivery is in the process of being stopped */ +"Suspending" = "Suspending"; + +/* The title of the command to change pump time zone */ +"Sync to Current Time" = "Sync to Current Time"; + +/* Message for pod sync time action sheet */ +"The time on your pump is different from the current time. Do you want to update the time on your pump to the current time?" = "The time on your pump is different from the current time. Do you want to update the time on your pump to the current time?"; + +/* Title for pod sync time action sheet. */ +"Time Change Detected" = "Time Change Detected"; + +/* The label indicating the results of each frequency trial */ +"Trials" = "Trials"; + +/* Progress message for tuning radio */ +"Tuning radio…" = "Tuning radio…"; + +/* Units for showing temp basal rate */ +"U/hr" = "U/hr"; + +/* Text to indicate battery percentage is unknown */ +"unknown" = "unknown"; + +/* Text shown in basal rate space when delivery status is unknown */ +"Unknown" = "Unknown"; + +/* Description for option to use MySentry + navigation title for pump battery type selection + Text for medtronic pump to use MySentry */ +"Use MySentry" = "Use MySentry"; + +/* Value string for MySentry config when MySentry is being used */ +"Yes" = "Yes"; + +/* Button text to confirm pump time sync */ +"Yes, Sync to Current Time" = "Yes, Sync to Current Time"; diff --git a/Dependencies/MinimedKit/MinimedKitUI/Resources/ru.lproj/Localizable.strings b/Dependencies/MinimedKit/MinimedKitUI/Resources/ru.lproj/Localizable.strings index 2b2c381572..4cdea525ae 100644 --- a/Dependencies/MinimedKit/MinimedKitUI/Resources/ru.lproj/Localizable.strings +++ b/Dependencies/MinimedKit/MinimedKitUI/Resources/ru.lproj/Localizable.strings @@ -90,13 +90,13 @@ "Fetching pump model…" = "Получаю модель помпы…"; /* The title of the cell showing the pump firmware version */ -"Firmware Version" = "Firmware Version"; +"Firmware Version" = "Версия прошивки"; /* Text shown in insulin delivery space when insulin suspended */ "Insulin\nSuspended" = "Подача инсулина остановлена"; /* Title of insulin delivery section */ -"Insulin Delivery" = "Insulin Delivery"; +"Insulin Delivery" = "Подача инсулина"; /* Instructions on selecting an insulin data source */ "Insulin delivery can be determined from the pump by either interpreting the event history or comparing the reservoir volume over time. Reading event history allows for a more accurate status graph and uploading up-to-date treatment data to Nightscout, at the cost of faster pump battery drain and the possibility of a higher radio error rate compared to reading only reservoir volume. If the selected source cannot be used for any reason, the system will attempt to fall back to the other option." = "Подача инсулина может определяться с помпы путем интерпретации истории событий или сравнением изменения объемов резервуара за прошедшее время. Чтение истории событий позволяет вычертить более точный график состояния и загрузить в Nightscout актуальные данные лечения/назначений (за счет более быстрого истощения батареи помпы и более высокого процента ошибок радиосвязи) по сравнению со считыванием данных только об объеме резервуара."; @@ -200,7 +200,7 @@ "Tuning radio…" = "Настраивается радиочастота…"; /* Units for showing temp basal rate */ -"U/hr" = "U/hr"; +"U/hr" = "Ед/ч"; /* Text to indicate battery percentage is unknown */ "unknown" = "Неизвестно"; @@ -218,4 +218,3 @@ /* Button text to confirm pump time sync */ "Yes, Sync to Current Time" = "Да, синхронизировать с текущим временем"; - diff --git a/Dependencies/MinimedKit/MinimedKitUI/Resources/sk.lproj/Localizable.strings b/Dependencies/MinimedKit/MinimedKitUI/Resources/sk.lproj/Localizable.strings index 763492a979..c5d259d505 100644 --- a/Dependencies/MinimedKit/MinimedKitUI/Resources/sk.lproj/Localizable.strings +++ b/Dependencies/MinimedKit/MinimedKitUI/Resources/sk.lproj/Localizable.strings @@ -4,15 +4,48 @@ /* Format string for reservoir volume. (1: The localized volume) */ "%@U" = "%@ j"; +/* The format string for displaying a frequency tune trial. Extra spaces added for emphesis: (1: frequency in MHz)(2: success count)(3: total count)(4: average RSSI) */ +"%1$@ %2$@/%3$@ %4$@" = "%1$@ %2$@/%3$@ %4$@"; + +/* The format string describing number of basal schedule entries: (1: number of entries) */ +"%1$@ basal schedule entries\n" = "%1$@ basal schedule entries\n"; + +/* The format string describing units of insulin remaining: (1: number of units) */ +"%1$@ Units of insulin remaining\n" = "%1$@ Units of insulin remaining\n"; + /* Accessibility format string for (1: localized volume)(2: time) */ "%1$@ units remaining at %2$@" = "%1$@ jednotiek zostávajúcich na %2$@"; /* String format for value with units (1: value, 2: separator, 3: units) */ "%1$@%2$@%3$@" = "%1$@ %2$@ %3$@"; +/* Text indicating ongoing pump time synchronization */ +"Adjusting Pump Time..." = "Adjusting Pump Time..."; + +/* Instructions on selecting battery chemistry type */ +"Alkaline and Lithium batteries decay at differing rates. Alkaline tend to have a linear voltage drop over time whereas lithium cell batteries tend to maintain voltage until halfway through their lifespan. Under normal usage in a Non-MySentry compatible Minimed (x22/x15) insulin pump running Loop, Alkaline batteries last approximately 4 to 5 days. Lithium batteries last between 1-2 weeks. This selection will use different battery voltage decay rates for each of the battery chemistry types and alert the user when a battery is approximately 8 to 10 hours from failure." = "Alkaline and Lithium batteries decay at differing rates. Alkaline tend to have a linear voltage drop over time whereas lithium cell batteries tend to maintain voltage until halfway through their lifespan. Under normal usage in a Non-MySentry compatible Minimed (x22/x15) insulin pump running Loop, Alkaline batteries last approximately 4 to 5 days. Lithium batteries last between 1-2 weeks. This selection will use different battery voltage decay rates for each of the battery chemistry types and alert the user when a battery is approximately 8 to 10 hours from failure."; + +/* Text to confirm delete this pump */ +"Are you sure you want to delete this Pump?" = "Are you sure you want to delete this Pump?"; + +/* The format string describing pump battery voltage: (1: battery voltage) */ +"Battery: %1$@ volts\n" = "Battery: %1$@ volts\n"; + +/* The label indicating the best radio frequency */ +"Best Frequency" = "Best Frequency"; + +/* The format string describing pump bolusing state: (1: bolusing) */ +"Bolusing: %1$@\n" = "Bolusing: %1$@\n"; + /* Cancel button title */ "Cancel" = "Zrušiť"; +/* Title text for suspend resume button when temp basal canceling */ +"Canceling Temp Basal" = "Canceling Temp Basal"; + +/* Text shown in basal rate space when basal is changing */ +"Changing" = "Changing"; + /* Progress message for changing pump time. */ "Changing time…" = "Mení sa čas…"; @@ -22,18 +55,46 @@ /* The title of the configuration section in MinimedPumpManager settings */ "Configuration" = "Konfigurácia"; +/* Button title to connect to pump during setup */ +"Connect" = "Connect"; + /* Text for continue button */ "Continue" = "Pokračovať"; +/* Button label for removing Pump + Text to delete pump */ +"Delete Pump" = "Delete Pump"; + /* Header for devices section of RileyLinkSetupView */ "Devices" = "Zariadenia"; +/* Description for option to not use MySentry */ +"Do not use MySentry" = "Do not use MySentry"; + /* The alert title for a resume error */ "Error Resuming" = "Chyba pri obnovení"; /* The alert title for a suspend error */ "Error Suspending" = "Chyba pri pozastavení"; +/* The alert title for an error while synching time */ +"Error Syncing Time" = "Error Syncing Time"; + +/* Progress message for fetching pump glucose. */ +"Fetching glucose…" = "Fetching glucose…"; + +/* Progress message for fetching pump history. */ +"Fetching history…" = "Fetching history…"; + +/* Progress message for fetching pump model. */ +"Fetching pump model…" = "Fetching pump model…"; + +/* The title of the cell showing the pump firmware version */ +"Firmware Version" = "Firmware Version"; + +/* Text shown in insulin delivery space when insulin suspended */ +"Insulin\nSuspended" = "Insulin\nSuspended"; + /* Title of insulin delivery section */ "Insulin Delivery" = "Podávanie inzulínu"; @@ -46,18 +107,56 @@ /* Text for confidence reminders navigation link */ "Insulin Type" = "Typ inzulínu"; +/* Format string fof navigation bar title for MinimedPumpSettingsView (1: model number) */ +"Medtronic %1$@" = "Medtronic %1$@"; + /* Instructions on selecting setting for MySentry */ "Medtronic pump models 523, 723, 554, and 754 have a feature called 'MySentry' that periodically broadcasts the reservoir and pump battery levels. Listening for these broadcasts allows Loop to communicate with the pump less frequently, which can increase pump battery life. However, when using this feature the RileyLink stays awake more of the time and uses more of its own battery. Enabling this may lengthen pump battery life, while disabling it may lengthen RileyLink battery life. This setting is ignored for other pump models." = "Modely pumpy Medtronic 523, 723, 554 a 754 majú funkciu s názvom „MySentry“, ktorá pravidelne vysiela úroveň nabitia batérie zásobníka a pumpy. Počúvanie týchto vysielaní umožňuje Loopu komunikovať s pumpou menej často, čo môže predĺžiť výdrž batérie pumpy. Pri používaní tejto funkcie však RileyLink zostáva viac času v bdelom stave a využíva viac vlastnej batérie. Povolenie môže predĺžiť životnosť batérie pumpy, zatiaľ čo jej vypnutie môže predĺžiť životnosť batérie RileyLink. Toto nastavenie sa pri iných modeloch čerpadiel ignoruje."; /* Value string for MySentry config when MySentry is not being used */ "No" = "Nie"; +/* Message display when no response from tuning pump */ +"No response" = "No response"; + +/* Button text to cancel pump time sync */ +"No, Keep Pump As Is" = "No, Keep Pump As Is"; + /* Pump find device instruction */ "On your pump, go to the Find Device screen and select \"Find Device\".\n\nMain Menu >\nUtilities >\nConnect Devices >\nOther Devices >\nOn >\nFind Device" = "Na pumpe prejdite na obrazovku Nájsť zariadenie a vyberte možnosť „Nájsť zariadenie“. \n\n Hlavné menu >\n Pomôcky >\n Pripojiť zariadenia >\n Iné zariadenia >\n Zapnuté >\n Nájsť zariadenie"; +/* navigation title for pump battery type selection + Text for medtronic pump preferred data source */ +"Preferred Data Source" = "Preferred Data Source"; + +/* Text for medtronic pump battery percent remaining */ +"Pump Battery Remaining" = "Pump Battery Remaining"; + +/* navigation title for pump battery type selection + Text for medtronic pump battery type */ +"Pump Battery Type" = "Pump Battery Type"; + /* The title text for the pump ID config value */ "Pump ID" = "ID pumpy"; +/* The title of the command to change pump time zone */ +"Pump Time" = "Pump Time"; + +/* Progress message for reading basal schedule */ +"Reading basal schedule…" = "Reading basal schedule…"; + +/* Progress message for reading pump status */ +"Reading pump status…" = "Reading pump status…"; + +/* The title of the cell showing the pump region */ +"Region" = "Region"; + +/* Title text for button to resume insulin delivery */ +"Resume Delivery" = "Resume Delivery"; + +/* Title text for button when insulin delivery is in the process of being resumed */ +"Resuming" = "Resuming"; + /* Button title to retry sentry setup */ "Retry" = "Skúsiť znova"; @@ -67,15 +166,55 @@ /* Title text for insulin type confirmation page */ "Select the type of insulin that you will be using in this pump." = "Vyberte typ inzulínu, ktorý budete v tejto pumpe používať."; +/* Progress message for sending button press to pump. */ +"Sending button press…" = "Sending button press…"; + +/* Title text for suspend resume button when temp basal starting */ +"Starting Temp Basal" = "Starting Temp Basal"; + /* A message indicating a command succeeded */ "Succeeded" = "Úspešné"; +/* Title text for button to suspend insulin delivery */ +"Suspend Delivery" = "Suspend Delivery"; + +/* The format string describing pump suspended state: (1: suspended) */ +"Suspended: %1$@\n" = "Suspended: %1$@\n"; + +/* Title text for button when insulin delivery is in the process of being stopped */ +"Suspending" = "Suspending"; + +/* The title of the command to change pump time zone */ +"Sync to Current Time" = "Sync to Current Time"; + +/* Message for pod sync time action sheet */ +"The time on your pump is different from the current time. Do you want to update the time on your pump to the current time?" = "The time on your pump is different from the current time. Do you want to update the time on your pump to the current time?"; + /* Title for pod sync time action sheet. */ "Time Change Detected" = "Zistila sa zmena času"; +/* The label indicating the results of each frequency trial */ +"Trials" = "Trials"; + +/* Progress message for tuning radio */ +"Tuning radio…" = "Tuning radio…"; + +/* Units for showing temp basal rate */ +"U/hr" = "U/hr"; + +/* Text to indicate battery percentage is unknown */ +"unknown" = "unknown"; + /* Text shown in basal rate space when delivery status is unknown */ "Unknown" = "Neznáme"; +/* Description for option to use MySentry + navigation title for pump battery type selection + Text for medtronic pump to use MySentry */ +"Use MySentry" = "Use MySentry"; + /* Value string for MySentry config when MySentry is being used */ "Yes" = "Áno"; +/* Button text to confirm pump time sync */ +"Yes, Sync to Current Time" = "Yes, Sync to Current Time"; diff --git a/Dependencies/MinimedKit/MinimedKitUI/Resources/sv.lproj/Localizable.strings b/Dependencies/MinimedKit/MinimedKitUI/Resources/sv.lproj/Localizable.strings index 7e11bde55e..af766fea30 100644 --- a/Dependencies/MinimedKit/MinimedKitUI/Resources/sv.lproj/Localizable.strings +++ b/Dependencies/MinimedKit/MinimedKitUI/Resources/sv.lproj/Localizable.strings @@ -19,8 +19,14 @@ /* String format for value with units (1: value, 2: separator, 3: units) */ "%1$@%2$@%3$@" = "%1$@%2$@%3$@"; +/* Text indicating ongoing pump time synchronization */ +"Adjusting Pump Time..." = "Justerar pumptid..."; + /* Instructions on selecting battery chemistry type */ -"Alkaline and Lithium batteries decay at differing rates. Alkaline tend to have a linear voltage drop over time whereas lithium cell batteries tend to maintain voltage until halfway through their lifespan. Under normal usage in a Non-MySentry compatible Minimed (x22/x15) insulin pump running Loop, Alkaline batteries last approximately 4 to 5 days. Lithium batteries last between 1-2 weeks. This selection will use different battery voltage decay rates for each of the battery chemistry types and alert the user when a battery is approximately 8 to 10 hours from failure." = "Alkaline and Lithium batteries decay at differing rates. Alkaline tend to have a linear voltage drop over time whereas lithium cell batteries tend to maintain voltage until halfway through their lifespan. Under normal usage in a Non-MySentry compatible Minimed (x22/x15) insulin pump running Loop, Alkaline batteries last approximately 4 to 5 days. Lithium batteries last between 1-2 weeks. This selection will use different battery voltage decay rates for each of the battery chemistry types and alert the user when a battery is approximately 8 to 10 hours from failure."; +"Alkaline and Lithium batteries decay at differing rates. Alkaline tend to have a linear voltage drop over time whereas lithium cell batteries tend to maintain voltage until halfway through their lifespan. Under normal usage in a Non-MySentry compatible Minimed (x22/x15) insulin pump running Loop, Alkaline batteries last approximately 4 to 5 days. Lithium batteries last between 1-2 weeks. This selection will use different battery voltage decay rates for each of the battery chemistry types and alert the user when a battery is approximately 8 to 10 hours from failure." = "Alkaliska och litiumbatterier tappar spänning med olika hastighet. Alkaliska tenderar att ha ett linjärt spänningsfall över tiden, medan litiumcellsbatterier tenderar att behålla spänning fram till halva deras livslängd. Under normal användning, i en icke-MySentry-kompatibel Minimed (x22/x15) insulinpump som kör Loop, varar alkaliska batterier cirka 4 till 5 dagar. Litiumbatterier håller mellan 1-2 veckor. Detta val kommer att använda olika spänningsfall beroende på batterityp och varna användaren när ett batteri har cirka 8 till 10 timmar kvar av sin livslängd."; + +/* Text to confirm delete this pump */ +"Are you sure you want to delete this Pump?" = "Säkert att du vill ta bort dennar pump?"; /* The format string describing pump battery voltage: (1: battery voltage) */ "Battery: %1$@ volts\n" = "Batteri: %1$@ volt\n"; @@ -37,9 +43,15 @@ /* Title text for suspend resume button when temp basal canceling */ "Canceling Temp Basal" = "Avbryt temporär basal"; +/* Text shown in basal rate space when basal is changing */ +"Changing" = "Byter"; + /* Progress message for changing pump time. */ "Changing time…" = "Ändra tid…"; +/* Instructions on selecting battery chemistry type */ +"Choose the type of battery you are using in your pump for better alerting about low battery conditions." = "Välj vilken typ av batteri du använder i din pump."; + /* The title of the configuration section in MinimedPumpManager settings */ "Configuration" = "Konfiguration"; @@ -56,12 +68,18 @@ /* Header for devices section of RileyLinkSetupView */ "Devices" = "Enheter"; +/* Description for option to not use MySentry */ +"Do not use MySentry" = "Använd inte MySentry"; + /* The alert title for a resume error */ "Error Resuming" = "Fel vid återupptagande"; /* The alert title for a suspend error */ "Error Suspending" = "Fel vid försök till paus"; +/* The alert title for an error while synching time */ +"Error Syncing Time" = "Fel vid synkronisering av tid"; + /* Progress message for fetching pump glucose. */ "Fetching glucose…" = "Hämtar glukos…"; @@ -74,25 +92,46 @@ /* The title of the cell showing the pump firmware version */ "Firmware Version" = "Firmware"; +/* Text shown in insulin delivery space when insulin suspended */ +"Insulin\nSuspended" = "Pump\npausad"; + /* Title of insulin delivery section */ -"Insulin Delivery" = "Insulin Delivery"; +"Insulin Delivery" = "Insulintillförsel"; /* Instructions on selecting an insulin data source */ -"Insulin delivery can be determined from the pump by either interpreting the event history or comparing the reservoir volume over time. Reading event history allows for a more accurate status graph and uploading up-to-date treatment data to Nightscout, at the cost of faster pump battery drain and the possibility of a higher radio error rate compared to reading only reservoir volume. If the selected source cannot be used for any reason, the system will attempt to fall back to the other option." = "Insulin delivery can be determined from the pump by either interpreting the event history or comparing the reservoir volume over time. Reading event history allows for a more accurate status graph and uploading up-to-date treatment data to Nightscout, at the cost of faster pump battery drain and the possibility of a higher radio error rate compared to reading only reservoir volume. If the selected source cannot be used for any reason, the system will attempt to fall back to the other option."; +"Insulin delivery can be determined from the pump by either interpreting the event history or comparing the reservoir volume over time. Reading event history allows for a more accurate status graph and uploading up-to-date treatment data to Nightscout, at the cost of faster pump battery drain and the possibility of a higher radio error rate compared to reading only reservoir volume. If the selected source cannot be used for any reason, the system will attempt to fall back to the other option." = "Mängd doserat insulin kan bestämmas antingen genom att tolka händelsehistoriken från pumpen eller genom att jämföra reservoarvolymen över tid. Att läsa av händelsehistoriken tillåter ett mer korrekt status-diagram och mer aktuella behandlingsdata för uppladdning till Nightscout, men laddar ur batteriet snabbare och ökar risken för andel eventuella radiofel jämfört med avläsning av endast reservoarvolym. Om det ena alternativet av någon anledning inte kan användas, försöker systemet med det andra alternativet."; + +/* Header for insulin remaining on pod settings screen */ +"Insulin Remaining" = "Insulin kvar"; /* Text for confidence reminders navigation link */ "Insulin Type" = "Insulintyp"; +/* Format string fof navigation bar title for MinimedPumpSettingsView (1: model number) */ +"Medtronic %1$@" = "Medtronic %1$@"; + +/* Instructions on selecting setting for MySentry */ +"Medtronic pump models 523, 723, 554, and 754 have a feature called 'MySentry' that periodically broadcasts the reservoir and pump battery levels. Listening for these broadcasts allows Loop to communicate with the pump less frequently, which can increase pump battery life. However, when using this feature the RileyLink stays awake more of the time and uses more of its own battery. Enabling this may lengthen pump battery life, while disabling it may lengthen RileyLink battery life. This setting is ignored for other pump models." = "Modellerna 523, 723, 554 och 754 från Medtronic har en funktion som kallas MySentry, som regelbundet övervakar reservoar- och pumpbatterinivåer. Genom att lyssna efter dessa sändningar kan iAPS kommunicera med pumpen mindre ofta, vilket kan öka pumpens batteritid. Men när du använder den här funktionen kommer RileyLink att vara vaken oftare vilket använder mer av sitt eget batteri. Aktivering av detta kan förlänga pumpens batteritid, medan inaktivera det kan förlänga RileyLink-batteriets livslängd. Denna inställning ignoreras för andra pumpmodeller."; + +/* Value string for MySentry config when MySentry is not being used */ +"No" = "Nej"; + /* Message display when no response from tuning pump */ "No response" = "Inget svar"; +/* Button text to cancel pump time sync */ +"No, Keep Pump As Is" = "Nej, behåll pumptid"; + /* Pump find device instruction */ -"On your pump, go to the Find Device screen and select \"Find Device\".\n\nMain Menu >\nUtilities >\nConnect Devices >\nOther Devices >\nOn >\nFind Device" = "On your pump, go to the Find Device screen and select \"Find Device\".\n\nMain Menu >\nUtilities >\nConnect Devices >\nOther Devices >\nOn >\nFind Device"; +"On your pump, go to the Find Device screen and select \"Find Device\".\n\nMain Menu >\nUtilities >\nConnect Devices >\nOther Devices >\nOn >\nFind Device" = "På din pump, gå till skärmen 'Hitta enhet' och välj 'Hitta enhet'.\n\nHuvudmeny >\nTillbehör >\nAnslut enheter >\nAndra enheter >\nPå >\nHitta enhet"; /* navigation title for pump battery type selection Text for medtronic pump preferred data source */ "Preferred Data Source" = "Föredragen datakälla"; +/* Text for medtronic pump battery percent remaining */ +"Pump Battery Remaining" = "Pumpbatteri kvar"; + /* navigation title for pump battery type selection Text for medtronic pump battery type */ "Pump Battery Type" = "Typ av pumpbatteri"; @@ -100,6 +139,9 @@ /* The title text for the pump ID config value */ "Pump ID" = "Pump-ID"; +/* The title of the command to change pump time zone */ +"Pump Time" = "Pumptid"; + /* Progress message for reading basal schedule */ "Reading basal schedule…" = "Läser basalscheman…"; @@ -142,6 +184,15 @@ /* Title text for button when insulin delivery is in the process of being stopped */ "Suspending" = "Pausar"; +/* The title of the command to change pump time zone */ +"Sync to Current Time" = "Synkronisera med aktuell tid"; + +/* Message for pod sync time action sheet */ +"The time on your pump is different from the current time. Do you want to update the time on your pump to the current time?" = "Tiden på din pump skiljer sig från aktuell tid. Vill du uppdatera tiden på din pump till aktuell tid?"; + +/* Title for pod sync time action sheet. */ +"Time Change Detected" = "Tidsändring upptäckt"; + /* The label indicating the results of each frequency trial */ "Trials" = "Försök"; @@ -151,6 +202,19 @@ /* Units for showing temp basal rate */ "U/hr" = "E/timme"; +/* Text to indicate battery percentage is unknown */ +"unknown" = "okänd"; + /* Text shown in basal rate space when delivery status is unknown */ "Unknown" = "Okänd"; +/* Description for option to use MySentry + navigation title for pump battery type selection + Text for medtronic pump to use MySentry */ +"Use MySentry" = "Använd MySentry"; + +/* Value string for MySentry config when MySentry is being used */ +"Yes" = "Ja"; + +/* Button text to confirm pump time sync */ +"Yes, Sync to Current Time" = "Ja, synkronisera med aktuell tid"; diff --git a/Dependencies/MinimedKit/MinimedKitUI/Resources/tr.lproj/Localizable.strings b/Dependencies/MinimedKit/MinimedKitUI/Resources/tr.lproj/Localizable.strings index 009f64f771..59aa23399f 100644 --- a/Dependencies/MinimedKit/MinimedKitUI/Resources/tr.lproj/Localizable.strings +++ b/Dependencies/MinimedKit/MinimedKitUI/Resources/tr.lproj/Localizable.strings @@ -129,6 +129,9 @@ Text for medtronic pump preferred data source */ "Preferred Data Source" = "Tercih Edilen Veri Kaynağı"; +/* Text for medtronic pump battery percent remaining */ +"Pump Battery Remaining" = "Pump Battery Remaining"; + /* navigation title for pump battery type selection Text for medtronic pump battery type */ "Pump Battery Type" = "Pompa Pil Tipi"; @@ -199,6 +202,9 @@ /* Units for showing temp basal rate */ "U/hr" = "Ü/sa"; +/* Text to indicate battery percentage is unknown */ +"unknown" = "unknown"; + /* Text shown in basal rate space when delivery status is unknown */ "Unknown" = "Bilinmeyen"; @@ -212,4 +218,3 @@ /* Button text to confirm pump time sync */ "Yes, Sync to Current Time" = "Evet, Geçerli Saatle Senkronize Et"; - diff --git a/Dependencies/MinimedKit/MinimedKitUI/Resources/uk.lproj/Localizable.strings b/Dependencies/MinimedKit/MinimedKitUI/Resources/uk.lproj/Localizable.strings index c94e37366e..5314910d31 100644 --- a/Dependencies/MinimedKit/MinimedKitUI/Resources/uk.lproj/Localizable.strings +++ b/Dependencies/MinimedKit/MinimedKitUI/Resources/uk.lproj/Localizable.strings @@ -1 +1,220 @@ -/* Empty */ \ No newline at end of file +/* Unit format string for an RSSI value in decibles */ +"%@ dB" = "%@ dB"; + +/* Format string for reservoir volume. (1: The localized volume) */ +"%@U" = "%@U"; + +/* The format string for displaying a frequency tune trial. Extra spaces added for emphesis: (1: frequency in MHz)(2: success count)(3: total count)(4: average RSSI) */ +"%1$@ %2$@/%3$@ %4$@" = "%1$@ %2$@/%3$@ %4$@"; + +/* The format string describing number of basal schedule entries: (1: number of entries) */ +"%1$@ basal schedule entries\n" = "%1$@ basal schedule entries\n"; + +/* The format string describing units of insulin remaining: (1: number of units) */ +"%1$@ Units of insulin remaining\n" = "%1$@ Units of insulin remaining\n"; + +/* Accessibility format string for (1: localized volume)(2: time) */ +"%1$@ units remaining at %2$@" = "%1$@ одиниць залишилося на %2$@"; + +/* String format for value with units (1: value, 2: separator, 3: units) */ +"%1$@%2$@%3$@" = "%1$@%2$@%3$@"; + +/* Text indicating ongoing pump time synchronization */ +"Adjusting Pump Time..." = "Налаштування часу помпи..."; + +/* Instructions on selecting battery chemistry type */ +"Alkaline and Lithium batteries decay at differing rates. Alkaline tend to have a linear voltage drop over time whereas lithium cell batteries tend to maintain voltage until halfway through their lifespan. Under normal usage in a Non-MySentry compatible Minimed (x22/x15) insulin pump running Loop, Alkaline batteries last approximately 4 to 5 days. Lithium batteries last between 1-2 weeks. This selection will use different battery voltage decay rates for each of the battery chemistry types and alert the user when a battery is approximately 8 to 10 hours from failure." = "Alkaline and Lithium batteries decay at differing rates. Alkaline tend to have a linear voltage drop over time whereas lithium cell batteries tend to maintain voltage until halfway through their lifespan. Under normal usage in a Non-MySentry compatible Minimed (x22/x15) insulin pump running Loop, Alkaline batteries last approximately 4 to 5 days. Lithium batteries last between 1-2 weeks. This selection will use different battery voltage decay rates for each of the battery chemistry types and alert the user when a battery is approximately 8 to 10 hours from failure."; + +/* Text to confirm delete this pump */ +"Are you sure you want to delete this Pump?" = "Are you sure you want to delete this Pump?"; + +/* The format string describing pump battery voltage: (1: battery voltage) */ +"Battery: %1$@ volts\n" = "Battery: %1$@ volts\n"; + +/* The label indicating the best radio frequency */ +"Best Frequency" = "Best Frequency"; + +/* The format string describing pump bolusing state: (1: bolusing) */ +"Bolusing: %1$@\n" = "Bolusing: %1$@\n"; + +/* Cancel button title */ +"Cancel" = "Відмінити"; + +/* Title text for suspend resume button when temp basal canceling */ +"Canceling Temp Basal" = "Canceling Temp Basal"; + +/* Text shown in basal rate space when basal is changing */ +"Changing" = "Changing"; + +/* Progress message for changing pump time. */ +"Changing time…" = "Зміна часу…"; + +/* Instructions on selecting battery chemistry type */ +"Choose the type of battery you are using in your pump for better alerting about low battery conditions." = "Choose the type of battery you are using in your pump for better alerting about low battery conditions."; + +/* The title of the configuration section in MinimedPumpManager settings */ +"Configuration" = "Налаштування"; + +/* Button title to connect to pump during setup */ +"Connect" = "Підключити"; + +/* Text for continue button */ +"Continue" = "Продовжити"; + +/* Button label for removing Pump + Text to delete pump */ +"Delete Pump" = "Delete Pump"; + +/* Header for devices section of RileyLinkSetupView */ +"Devices" = "Пристрої"; + +/* Description for option to not use MySentry */ +"Do not use MySentry" = "Do not use MySentry"; + +/* The alert title for a resume error */ +"Error Resuming" = "Помилка при відновленні"; + +/* The alert title for a suspend error */ +"Error Suspending" = "Помилка призупинення"; + +/* The alert title for an error while synching time */ +"Error Syncing Time" = "Error Syncing Time"; + +/* Progress message for fetching pump glucose. */ +"Fetching glucose…" = "Fetching glucose…"; + +/* Progress message for fetching pump history. */ +"Fetching history…" = "Fetching history…"; + +/* Progress message for fetching pump model. */ +"Fetching pump model…" = "Fetching pump model…"; + +/* The title of the cell showing the pump firmware version */ +"Firmware Version" = "Версія прошивки"; + +/* Text shown in insulin delivery space when insulin suspended */ +"Insulin\nSuspended" = "Інсулін\nПризупинено"; + +/* Title of insulin delivery section */ +"Insulin Delivery" = "Доставка інсуліну"; + +/* Instructions on selecting an insulin data source */ +"Insulin delivery can be determined from the pump by either interpreting the event history or comparing the reservoir volume over time. Reading event history allows for a more accurate status graph and uploading up-to-date treatment data to Nightscout, at the cost of faster pump battery drain and the possibility of a higher radio error rate compared to reading only reservoir volume. If the selected source cannot be used for any reason, the system will attempt to fall back to the other option." = "Insulin delivery can be determined from the pump by either interpreting the event history or comparing the reservoir volume over time. Reading event history allows for a more accurate status graph and uploading up-to-date treatment data to Nightscout, at the cost of faster pump battery drain and the possibility of a higher radio error rate compared to reading only reservoir volume. If the selected source cannot be used for any reason, the system will attempt to fall back to the other option."; + +/* Header for insulin remaining on pod settings screen */ +"Insulin Remaining" = "Залишок інсуліну"; + +/* Text for confidence reminders navigation link */ +"Insulin Type" = "Insulintyp"; + +/* Format string fof navigation bar title for MinimedPumpSettingsView (1: model number) */ +"Medtronic %1$@" = "Medtronic %1$@"; + +/* Instructions on selecting setting for MySentry */ +"Medtronic pump models 523, 723, 554, and 754 have a feature called 'MySentry' that periodically broadcasts the reservoir and pump battery levels. Listening for these broadcasts allows Loop to communicate with the pump less frequently, which can increase pump battery life. However, when using this feature the RileyLink stays awake more of the time and uses more of its own battery. Enabling this may lengthen pump battery life, while disabling it may lengthen RileyLink battery life. This setting is ignored for other pump models." = "Medtronic pump models 523, 723, 554, and 754 have a feature called 'MySentry' that periodically broadcasts the reservoir and pump battery levels. Listening for these broadcasts allows Loop to communicate with the pump less frequently, which can increase pump battery life. However, when using this feature the RileyLink stays awake more of the time and uses more of its own battery. Enabling this may lengthen pump battery life, while disabling it may lengthen RileyLink battery life. This setting is ignored for other pump models."; + +/* Value string for MySentry config when MySentry is not being used */ +"No" = "Ні"; + +/* Message display when no response from tuning pump */ +"No response" = "No response"; + +/* Button text to cancel pump time sync */ +"No, Keep Pump As Is" = "Ні, залишити як є"; + +/* Pump find device instruction */ +"On your pump, go to the Find Device screen and select \"Find Device\".\n\nMain Menu >\nUtilities >\nConnect Devices >\nOther Devices >\nOn >\nFind Device" = "On your pump, go to the Find Device screen and select \"Find Device\".\n\nMain Menu >\nUtilities >\nConnect Devices >\nOther Devices >\nOn >\nFind Device"; + +/* navigation title for pump battery type selection + Text for medtronic pump preferred data source */ +"Preferred Data Source" = "Preferred Data Source"; + +/* Text for medtronic pump battery percent remaining */ +"Pump Battery Remaining" = "Pump Battery Remaining"; + +/* navigation title for pump battery type selection + Text for medtronic pump battery type */ +"Pump Battery Type" = "Pump Battery Type"; + +/* The title text for the pump ID config value */ +"Pump ID" = "Pump ID"; + +/* The title of the command to change pump time zone */ +"Pump Time" = "Час помпи"; + +/* Progress message for reading basal schedule */ +"Reading basal schedule…" = "Reading basal schedule…"; + +/* Progress message for reading pump status */ +"Reading pump status…" = "Reading pump status…"; + +/* The title of the cell showing the pump region */ +"Region" = "Region"; + +/* Title text for button to resume insulin delivery */ +"Resume Delivery" = "Resume Delivery"; + +/* Title text for button when insulin delivery is in the process of being resumed */ +"Resuming" = "Resuming"; + +/* Button title to retry sentry setup */ +"Retry" = "Спробувати знову"; + +/* Title of insulin delivery section */ +"Scheduled Basal" = "Запланований базал"; + +/* Title text for insulin type confirmation page */ +"Select the type of insulin that you will be using in this pump." = "Select the type of insulin that you will be using in this pump."; + +/* Progress message for sending button press to pump. */ +"Sending button press…" = "Sending button press…"; + +/* Title text for suspend resume button when temp basal starting */ +"Starting Temp Basal" = "Starting Temp Basal"; + +/* A message indicating a command succeeded */ +"Succeeded" = "Успішно"; + +/* Title text for button to suspend insulin delivery */ +"Suspend Delivery" = "Призупинити доставку"; + +/* The format string describing pump suspended state: (1: suspended) */ +"Suspended: %1$@\n" = "Suspended: %1$@\n"; + +/* Title text for button when insulin delivery is in the process of being stopped */ +"Suspending" = "Suspending"; + +/* The title of the command to change pump time zone */ +"Sync to Current Time" = "Встановити поточний час"; + +/* Message for pod sync time action sheet */ +"The time on your pump is different from the current time. Do you want to update the time on your pump to the current time?" = "Час на вашому насосі відрізняється від поточного часу. Хочете оновити час на насосі до поточного?"; + +/* Title for pod sync time action sheet. */ +"Time Change Detected" = "Виявлено зміну часу"; + +/* The label indicating the results of each frequency trial */ +"Trials" = "Trials"; + +/* Progress message for tuning radio */ +"Tuning radio…" = "Tuning radio…"; + +/* Units for showing temp basal rate */ +"U/hr" = "U/год"; + +/* Text to indicate battery percentage is unknown */ +"unknown" = "unknown"; + +/* Text shown in basal rate space when delivery status is unknown */ +"Unknown" = "Невідомий"; + +/* Description for option to use MySentry + navigation title for pump battery type selection + Text for medtronic pump to use MySentry */ +"Use MySentry" = "Use MySentry"; + +/* Value string for MySentry config when MySentry is being used */ +"Yes" = "Так"; + +/* Button text to confirm pump time sync */ +"Yes, Sync to Current Time" = "Так, синхронізувати з поточним часом"; diff --git a/Dependencies/MinimedKit/MinimedKitUI/Resources/zh-Hans.lproj/Localizable.strings b/Dependencies/MinimedKit/MinimedKitUI/Resources/zh-Hans.lproj/Localizable.strings index dd2dfc4a58..452b995c5e 100644 --- a/Dependencies/MinimedKit/MinimedKitUI/Resources/zh-Hans.lproj/Localizable.strings +++ b/Dependencies/MinimedKit/MinimedKitUI/Resources/zh-Hans.lproj/Localizable.strings @@ -1,3 +1,9 @@ +/* Unit format string for an RSSI value in decibles */ +"%@ dB" = "%@ dB"; + +/* Format string for reservoir volume. (1: The localized volume) */ +"%@U" = "%@U"; + /* The format string for displaying a frequency tune trial. Extra spaces added for emphesis: (1: frequency in MHz)(2: success count)(3: total count)(4: average RSSI) */ "%1$@ %2$@/%3$@ %4$@" = "%1$@ %2$@/%3$@ %4$@"; @@ -7,12 +13,21 @@ /* The format string describing units of insulin remaining: (1: number of units) */ "%1$@ Units of insulin remaining\n" = "胰岛素剩余量 %1$@ U \n"; +/* Accessibility format string for (1: localized volume)(2: time) */ +"%1$@ units remaining at %2$@" = "%1$@ units remaining at %2$@"; + /* String format for value with units (1: value, 2: separator, 3: units) */ "%1$@%2$@%3$@" = "%1$@%2$@%3$@"; +/* Text indicating ongoing pump time synchronization */ +"Adjusting Pump Time..." = "Adjusting Pump Time..."; + /* Instructions on selecting battery chemistry type */ "Alkaline and Lithium batteries decay at differing rates. Alkaline tend to have a linear voltage drop over time whereas lithium cell batteries tend to maintain voltage until halfway through their lifespan. Under normal usage in a Non-MySentry compatible Minimed (x22/x15) insulin pump running Loop, Alkaline batteries last approximately 4 to 5 days. Lithium batteries last between 1-2 weeks. This selection will use different battery voltage decay rates for each of the battery chemistry types and alert the user when a battery is approximately 8 to 10 hours from failure." = "碱性电池和锂电池以不同的速率衰减。随着时间的推移,碱性电池往往具有线性电压降,而锂电池电池则随时间呈线性下降的电压一直保持到其寿命的一半。在非MySentry兼容Minimed(x22 / x15)的胰岛素泵运行Loop时,正常使用情况下,碱性电池可持续大约4至5天,锂电池持续1-2周。此选择将针对每种电池化学类型使用不同的电池电压衰减速率,并在电池电量耗尽前8至10小时前提醒用户。"; +/* Text to confirm delete this pump */ +"Are you sure you want to delete this Pump?" = "Are you sure you want to delete this Pump?"; + /* The format string describing pump battery voltage: (1: battery voltage) */ "Battery: %1$@ volts\n" = "电池:%1$@ V\n"; @@ -25,25 +40,46 @@ /* Cancel button title */ "Cancel" = "取消"; +/* Title text for suspend resume button when temp basal canceling */ +"Canceling Temp Basal" = "Canceling Temp Basal"; + +/* Text shown in basal rate space when basal is changing */ +"Changing" = "Changing"; + /* Progress message for changing pump time. */ "Changing time…" = "正在修改时间…"; +/* Instructions on selecting battery chemistry type */ +"Choose the type of battery you are using in your pump for better alerting about low battery conditions." = "Choose the type of battery you are using in your pump for better alerting about low battery conditions."; + /* The title of the configuration section in MinimedPumpManager settings */ "Configuration" = "配置"; /* Button title to connect to pump during setup */ "Connect" = "连接"; +/* Text for continue button */ +"Continue" = "继续"; + /* Button label for removing Pump Text to delete pump */ "Delete Pump" = "删除泵"; +/* Header for devices section of RileyLinkSetupView */ +"Devices" = "设备"; + +/* Description for option to not use MySentry */ +"Do not use MySentry" = "Do not use MySentry"; + /* The alert title for a resume error */ "Error Resuming" = "无法恢复"; /* The alert title for a suspend error */ "Error Suspending" = "无法暂停"; +/* The alert title for an error while synching time */ +"Error Syncing Time" = "Error Syncing Time"; + /* Progress message for fetching pump glucose. */ "Fetching glucose…" = "正在获取葡萄糖信息…"; @@ -56,12 +92,36 @@ /* The title of the cell showing the pump firmware version */ "Firmware Version" = "Firmware Version"; +/* Text shown in insulin delivery space when insulin suspended */ +"Insulin\nSuspended" = "Insulin\nSuspended"; + +/* Title of insulin delivery section */ +"Insulin Delivery" = "Insulin Delivery"; + /* Instructions on selecting an insulin data source */ "Insulin delivery can be determined from the pump by either interpreting the event history or comparing the reservoir volume over time. Reading event history allows for a more accurate status graph and uploading up-to-date treatment data to Nightscout, at the cost of faster pump battery drain and the possibility of a higher radio error rate compared to reading only reservoir volume. If the selected source cannot be used for any reason, the system will attempt to fall back to the other option." = "可以通过解释事件历史记录或比较随时间推移的储存容量来确定胰岛素输注总量。阅读事件历史记录可以获得更精确的胰岛素输注量并将最新的数据上传到Nightscout,但该方式会造成更快的电池消耗以及可能造成Rileylink通信失败概率增大。如果选中的方式无法正常工作,系统将自动尝试运行另一个方案。"; +/* Header for insulin remaining on pod settings screen */ +"Insulin Remaining" = "Insulin Remaining"; + +/* Text for confidence reminders navigation link */ +"Insulin Type" = "Insulintyp"; + +/* Format string fof navigation bar title for MinimedPumpSettingsView (1: model number) */ +"Medtronic %1$@" = "Medtronic %1$@"; + +/* Instructions on selecting setting for MySentry */ +"Medtronic pump models 523, 723, 554, and 754 have a feature called 'MySentry' that periodically broadcasts the reservoir and pump battery levels. Listening for these broadcasts allows Loop to communicate with the pump less frequently, which can increase pump battery life. However, when using this feature the RileyLink stays awake more of the time and uses more of its own battery. Enabling this may lengthen pump battery life, while disabling it may lengthen RileyLink battery life. This setting is ignored for other pump models." = "Medtronic pump models 523, 723, 554, and 754 have a feature called 'MySentry' that periodically broadcasts the reservoir and pump battery levels. Listening for these broadcasts allows Loop to communicate with the pump less frequently, which can increase pump battery life. However, when using this feature the RileyLink stays awake more of the time and uses more of its own battery. Enabling this may lengthen pump battery life, while disabling it may lengthen RileyLink battery life. This setting is ignored for other pump models."; + +/* Value string for MySentry config when MySentry is not being used */ +"No" = "No"; + /* Message display when no response from tuning pump */ "No response" = "无响应"; +/* Button text to cancel pump time sync */ +"No, Keep Pump As Is" = "No, Keep Pump As Is"; + /* Pump find device instruction */ "On your pump, go to the Find Device screen and select \"Find Device\".\n\nMain Menu >\nUtilities >\nConnect Devices >\nOther Devices >\nOn >\nFind Device" = "On your pump, go to the Find Device screen and select \"Find Device\".\n\nMain Menu >\nUtilities >\nConnect Devices >\nOther Devices >\nOn >\nFind Device"; @@ -69,6 +129,9 @@ Text for medtronic pump preferred data source */ "Preferred Data Source" = "首选数据源"; +/* Text for medtronic pump battery percent remaining */ +"Pump Battery Remaining" = "Pump Battery Remaining"; + /* navigation title for pump battery type selection Text for medtronic pump battery type */ "Pump Battery Type" = "胰岛素泵电池类型"; @@ -76,6 +139,9 @@ /* The title text for the pump ID config value */ "Pump ID" = "胰岛素泵序列号"; +/* The title of the command to change pump time zone */ +"Pump Time" = "Pump Time"; + /* Progress message for reading basal schedule */ "Reading basal schedule…" = "正在读取基础率配置文件…"; @@ -85,24 +151,70 @@ /* The title of the cell showing the pump region */ "Region" = "Region"; +/* Title text for button to resume insulin delivery */ +"Resume Delivery" = "Resume Delivery"; + +/* Title text for button when insulin delivery is in the process of being resumed */ +"Resuming" = "Resuming"; + /* Button title to retry sentry setup */ "Retry" = "重试"; +/* Title of insulin delivery section */ +"Scheduled Basal" = "Scheduled Basal"; + +/* Title text for insulin type confirmation page */ +"Select the type of insulin that you will be using in this pump." = "Select the type of insulin that you will be using in this pump."; + /* Progress message for sending button press to pump. */ "Sending button press…" = "正在发送亮屏指令…"; +/* Title text for suspend resume button when temp basal starting */ +"Starting Temp Basal" = "Starting Temp Basal"; + /* A message indicating a command succeeded */ "Succeeded" = "成功"; +/* Title text for button to suspend insulin delivery */ +"Suspend Delivery" = "暂停输注"; + /* The format string describing pump suspended state: (1: suspended) */ "Suspended: %1$@\n" = "暂停: %1$@\n"; +/* Title text for button when insulin delivery is in the process of being stopped */ +"Suspending" = "Suspending"; + +/* The title of the command to change pump time zone */ +"Sync to Current Time" = "Sync to Current Time"; + +/* Message for pod sync time action sheet */ +"The time on your pump is different from the current time. Do you want to update the time on your pump to the current time?" = "The time on your pump is different from the current time. Do you want to update the time on your pump to the current time?"; + +/* Title for pod sync time action sheet. */ +"Time Change Detected" = "Time Change Detected"; + /* The label indicating the results of each frequency trial */ "Trials" = "尝试"; /* Progress message for tuning radio */ "Tuning radio…" = "正在调频…"; +/* Units for showing temp basal rate */ +"U/hr" = "U/小时"; + +/* Text to indicate battery percentage is unknown */ +"unknown" = "unknown"; + /* Text shown in basal rate space when delivery status is unknown */ "Unknown" = "未知"; +/* Description for option to use MySentry + navigation title for pump battery type selection + Text for medtronic pump to use MySentry */ +"Use MySentry" = "Use MySentry"; + +/* Value string for MySentry config when MySentry is being used */ +"Yes" = "Yes"; + +/* Button text to confirm pump time sync */ +"Yes, Sync to Current Time" = "Yes, Sync to Current Time"; diff --git a/Dependencies/OmniBLE/Localizations/it.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/it.lproj/Localizable.strings index 2e39bcdd1c..26967b38c4 100644 --- a/Dependencies/OmniBLE/Localizations/it.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/it.lproj/Localizable.strings @@ -90,7 +90,7 @@ "Unfinished deactivation" = "Deattivazione incompleta"; /* Label for pod life state when no pod paired */ -"No Pod" = "No Pod"; +"No Pod" = "Nessun Pod"; /* Settings page link description when next lifecycle action is to pair new pod */ "Pair Pod" = "Connetti Pod"; @@ -171,7 +171,7 @@ "Unfinished deactivation" = "Deattivazione incompleta"; /* Label for pod life state when no pod paired */ -"No Pod" = "No Pod"; +"No Pod" = "Nessun Pod"; /* Pod life HUD view label */ "Fault" = "Guasto"; @@ -216,7 +216,7 @@ "Finish Deactivation" = "Termina Deattivazione"; /* Status highlight that when no pod is paired. */ -"No Pod" = "No Pod"; +"No Pod" = "Nessun Pod"; /* Status highlight message for emptyReservoir alarm. */ "No Insulin" = "Nessuna Insulina"; @@ -246,13 +246,13 @@ "Insert Cannula" = "Inserisci cannula"; /* Cannula insertion button text while inserting */ -"Inserting..." = "Inserting..."; +"Inserting..." = "Inserimento..."; /* Cannula insertion button text while showing error */ "Retry" = "Riprova"; /* Cannula insertion button text while checking insertion */ -"Checking..." = "Checking..."; +"Checking..." = "Controllo in corso..."; /* */ "Check cannula insertion finished" = "Controlla che l'inserimento della cannula é finito"; @@ -496,82 +496,82 @@ "Is the cannula inserted properly?" = "La cannula è inserita correttamente?"; /* Description of proper cannula insertion */ -"The window on the top of the Pod should be colored pink when the cannula is properly inserted into the skin." = "The window on the top of the Pod should be colored pink when the cannula is properly inserted into the skin."; +"The window on the top of the Pod should be colored pink when the cannula is properly inserted into the skin." = "La finestra nella parte superiore del Pod sara' di colore rosa quando la cannula è stata inserita correttamente nella pelle."; /* Button label for user to answer cannula was properly inserted */ -"Yes" = "Yes"; +"Yes" = "Sì"; /* Button label for user to answer cannula was not properly inserted */ "No" = "No"; /* Pod pairing action button text while pairing */ -"Pairing..." = "Pairing..."; +"Pairing..." = "Abbinamento in corso..."; /* Pod pairing action button text while priming */ -"Priming..." = "Priming..."; +"Priming..." = "Caricamento in corso..."; /* */ -"Deactivating..." = "Deactivating..."; +"Deactivating..." = "Sto disattivando..."; /* Pod state when pod has been deactivated */ -"Deactivated" = "Deactivated"; +"Deactivated" = "Disattivato"; /* Format string for instructions for setup complete view. (1: app name) */ -"Your Pod is ready for use.\n\n%1$@ will remind you to change your pod before it expires. You can change this to a time convenient for you." = "Your Pod is ready for use.\n\n%1$@ will remind you to change your pod before it expires. You can change this to a time convenient for you."; +"Your Pod is ready for use.\n\n%1$@ will remind you to change your pod before it expires. You can change this to a time convenient for you." = "Il tuo Pod è pronto per l'uso. \n\n %1$@. Verrà ricordato di cambiare il tuo pod prima che scada. Questo orario può essere cambiato con un altro a te più conveniente."; /* */ -"Scheduled Reminder" = "Scheduled Reminder"; +"Scheduled Reminder" = "Imposta promemoria"; /* Label for expiration reminder row */ "Time" = "Tempo"; /* Action button title to continue at Setup Complete */ -"Finish Setup" = "Finish Setup"; +"Finish Setup" = "Termina configurazione"; /* */ -"Setup Complete" = "Setup Complete"; +"Setup Complete" = "Configurazione terminata"; /* Value text for no expiration reminder */ -"No Reminder" = "No Reminder"; +"No Reminder" = "Nessun promemoria"; /* Error message description for PeripheralManagerError.notReady */ -"Peripheral Not Ready" = "Peripheral Not Ready"; +"Peripheral Not Ready" = "Periferica non pronta"; /* Error message description for PeripheralManagerError.incorrectResponse */ -"Incorrect Response" = "Incorrect Response"; +"Incorrect Response" = "Risposta errata"; /* Error message description for PeripheralManagerError.timeout */ -"Timeout" = "Timeout"; +"Timeout" = "Tempo scaduto"; /* Error message description for PeripheralManagerError.emptyValue */ -"Empty Value" = "Empty Value"; +"Empty Value" = "Valore vuoto"; /* Error message description for PeripheralManagerError.unknownCharacteristic */ -"Unknown Characteristic" = "Unknown Characteristic"; +"Unknown Characteristic" = "Caratteristica sconosciuta"; /* Error message description for PeripheralManagerError.nack */ "Nack" = "Nack"; /* Title for omnipod reminders section */ -"Omnipod Reminders" = "Omnipod Reminders"; +"Omnipod Reminders" = "Promemoria Omnipod"; /* Footer text for omnipod reminders section */ -"The app configures a reminder on the pod to notify you in advance of Pod expiration. Set the number of hours advance notice you would like to configure when pairing a new Pod." = "The app configures a reminder on the pod to notify you in advance of Pod expiration. Set the number of hours advance notice you would like to configure when pairing a new Pod."; +"The app configures a reminder on the pod to notify you in advance of Pod expiration. Set the number of hours advance notice you would like to configure when pairing a new Pod." = "L'App puo' configurare un promemoria capace di avvisare in anticipo della scadenza del Pod. Puoi impostare il numero di ore preferito per il preavviso dalla voce Omnipod della schermata principale cliccando Configurazione>Impostazioni Notifiche>Notifica Scadenza e sceglire il numero di ore desiderato per l'avviso di scadenza."; /* Footer text for scheduled reminder area */ -"This is a reminder that you scheduled when you paired your current Pod." = "This is a reminder that you scheduled when you paired your current Pod."; +"This is a reminder that you scheduled when you paired your current Pod." = "Questo è un promemoria che hai programmato quando hai abbinato il tuo attuale Pod."; /* */ -"Scheduled Reminder" = "Scheduled Reminder"; +"Scheduled Reminder" = "Imposta promemoria"; /* Footer text for low reservoir value row */ -"The App notifies you when the amount of insulin in the Pod reaches this level." = "The App notifies you when the amount of insulin in the Pod reaches this level."; +"The App notifies you when the amount of insulin in the Pod reaches this level." = "L'App ti avvisa quando la quantità d'insulina nel Pod raggiunge un determinato livello."; /* Description text for critical alerts */ -"Critical Alerts" = "Critical Alerts"; +"Critical Alerts" = "Avvisi critici"; /* Description text for critical alerts */ -"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode." = "The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode."; +"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode." = "I promemoria qui sopra non suoneranno se il dispositivo è in modalità Silenzioso o Non Disturbare.\n\nCi sono altri avvisi e avvisi di Pod critici che suoneranno anche se il dispositivo è impostato in modalità Silenzioso o Non Disturbare."; /* navigation title for notification settings */ "Notification Settings" = "Impostazioni di Notifica"; @@ -579,33 +579,33 @@ "Time" = "Tempo"; /* Value text for no expiration reminder */ -"No Reminder" = "No Reminder"; +"No Reminder" = "Nessun promemoria"; /* Label for low reservoir reminder row */ -"Low Reservoir Reminder" = "Low Reservoir Reminder"; +"Low Reservoir Reminder" = "Notifica di serbatoio basso"; /* The action string on pod status page when pod data is stale */ -"Make sure your phone and pod are close to each other. If communication issues persist, move to a new area." = "Make sure your phone and pod are close to each other. If communication issues persist, move to a new area."; +"Make sure your phone and pod are close to each other. If communication issues persist, move to a new area." = "Assicurati che il tuo telefono e il Pod siano vicini l'uno all'altro. Se il problema di comunicazione persiste, spostati in un'altra zona."; /* Format string for the action string on pod status page when pod expired. (1: service time remaining) */ -"Change Pod now. Insulin delivery will stop in %1$@ or when no more insulin remains." = "Change Pod now. Insulin delivery will stop in %1$@ or when no more insulin remains."; +"Change Pod now. Insulin delivery will stop in %1$@ or when no more insulin remains." = "Cambiare Pod adesso. L' erogazione d'insulina si interromperà tra %1$@ o quando non ci sarà più insulina nel serbatoio."; /* Title string for BeepPreference.silent */ -"Disabled" = "Disabled"; +"Disabled" = "Disabilitato"; /* Title string for BeepPreference.manualCommands */ "Enabled" = "Abilitato"; /* Title string for BeepPreference.extended */ -"Extended" = "Extended"; +"Extended" = "Esteso"; /* Description for BeepPreference.silent */ -"No confidence reminders are used." = "No confidence reminders are used."; +"No confidence reminders are used." = "Non vengono utilizzati promemoria di fiducia."; /* Description for BeepPreference.manualCommands */ -"Confidence reminders will sound for commands you initiate, like bolus, cancel bolus, suspend, resume, save notification reminders, etc. When Loop automatically adjusts delivery, no confidence reminders are used." = "Confidence reminders will sound for commands you initiate, like bolus, cancel bolus, suspend, resume, save notification reminders, etc. When Loop automatically adjusts delivery, no confidence reminders are used."; +"Confidence reminders will sound for commands you initiate, like bolus, cancel bolus, suspend, resume, save notification reminders, etc. When Loop automatically adjusts delivery, no confidence reminders are used." = "I promemoria di fiducia suoneranno per i comandi inoltrati, come boli, cancellazione boli, sospensioni, ripristini erogazione, salvataggi di promemoria, etc. Quando Loop invece regola in automatico l'erogazione allora non userà alcun promemoria di fiducia."; /* Description for BeepPreference.extended */ -"Confidence reminders will sound when Loop automatically adjusts delivery as well as for commands you initiate." = "Confidence reminders will sound when Loop automatically adjusts delivery as well as for commands you initiate."; +"Confidence reminders will sound when Loop automatically adjusts delivery as well as for commands you initiate." = "I promemoria di fiducia suonano quando Loop regola automaticamente l'erogazione e per i comandi avviati dall'utente."; /* Label text for temporary basal rate summary */ "Rate" = "Valore"; @@ -614,60 +614,60 @@ "U/hr" = "Unità/ora"; /* Summary string for temporary basal rate configuration page */ -"%1$@ for %2$@" = "%1$@ for %2$@"; +"%1$@ for %2$@" = "%1$@ per %2$@"; /* Description text on manual temp basal action sheet */ -"Loop will not automatically adjust your insulin delivery until the temporary basal rate finishes or is canceled." = "Loop will not automatically adjust your insulin delivery until the temporary basal rate finishes or is canceled."; +"Loop will not automatically adjust your insulin delivery until the temporary basal rate finishes or is canceled." = "Loop non regolerà automaticamente l'erogazione d'insulina fino a quando l'impostazione della basale temporanea non sarà terminata o cancellata."; /* Button text for setting manual temporary basal rate*/ -"Set Temporary Basal" = "Set Temporary Basal"; +"Set Temporary Basal" = "Imposta basale temporanea"; /* Navigation Title for ManualTempBasalEntryView */ -"Temporary Basal" = "Temporary Basal"; +"Temporary Basal" = "Basale temporanea"; /* Alert title for a failure to set temporary basal */ -"Temporary Basal Failed" = "Temporary Basal Failed"; +"Temporary Basal Failed" = "Basale temporanea fallita"; /* Alert format string for a failure to set temporary basal with recovery suggestion. (1: error description) (2: recovery text) */ -"Unable to set a temporary basal rate: %1$@\n\n%2$@" = "Unable to set a temporary basal rate: %1$@\n\n%2$@"; +"Unable to set a temporary basal rate: %1$@\n\n%2$@" = "Impossibile impostare una velocità basale temporanea: %1$@\n\n%2$@"; /* Alert format string for a failure to set temporary basal. (1: error description) */ -"Unable to set a temporary basal rate: %1$@" = "Unable to set a temporary basal rate: %1$@"; +"Unable to set a temporary basal rate: %1$@" = "Impossibile impostare una velocità basale temporanea: %1$@"; /* Alert title for missing temp basal configuration */ -"Missing Config" = "Missing Config"; +"Missing Config" = "Configurazione mancante"; /* Alert format string for missing temp basal configuration. */ -"This PumpManager has not been configured with a maximum basal rate because it was added before manual temp basal was a feature. Please go to therapy settings -> delivery limits and set a new maximum basal rate." = "This PumpManager has not been configured with a maximum basal rate because it was added before manual temp basal was a feature. Please go to therapy settings -> delivery limits and set a new maximum basal rate."; +"This PumpManager has not been configured with a maximum basal rate because it was added before manual temp basal was a feature. Please go to therapy settings -> delivery limits and set a new maximum basal rate." = "Questo microinfusore non è stato configurato con una dose di basale massima perché questa è stata inserita prima che la basale temporanea manuale diventasse una funzione attiva. Andare su Impostazioni terapia - > Limiti erogazione e impostare un nuovo profilo basale massimo."; /* Label text for expiration reminder default row */ -"Expiration Reminder Default" = "Expiration Reminder Default"; +"Expiration Reminder Default" = "Promemoria scadenza predefinito"; /* Text for previous pod information row */ -"Previous Pod Information" = "Previous Pod Information"; +"Previous Pod Information" = "Informazioni Pod precedente"; /* Text shown in insulin remaining space when no pod is paired (Please keep the '\n' while translating!) */ -"No\nDelivery" = "No\nDelivery"; +"No\nDelivery" = "No\n erogata"; /* description label for active time pod details row */ "Active Time" = "Tempo di attività"; /* description label for total delivery pod details row */ -"Total Delivery" = "Total Delivery"; +"Total Delivery" = "Erogazione totale"; /* description label for device name pod details row */ -"Device Name" = "Device Name"; +"Device Name" = "Nome dispositivo"; /* description label for lot number pod details row */ -"Lot Number" = "Lot Number"; +"Lot Number" = "Numero lotto"; /* description label for sequence number pod details row */ -"Sequence Number" = "Sequence Number"; +"Sequence Number" = "Numero di serie"; /* description label for firmware version pod details row */ -"Firmware Version" = "Firmware Version"; +"Firmware Version" = "Versione firmware"; /* description label for ble firmware version pod details row */ -"BLE Firmware Version" = "BLE Firmware Version"; +"BLE Firmware Version" = "Versione firmware BLE"; /* description label for activated at timne pod details row */ "Pod Activated" = "Pod attivato"; @@ -676,13 +676,13 @@ "Active Time" = "Tempo di attività"; /* description label for last status date pod details row */ -"Last Status" = "Last Status"; +"Last Status" = "Ultimo stato"; /* description label for pod fault details */ -"Pod Fault Details" = "Pod Fault Details"; +"Pod Fault Details" = "Dettagli errore Pod"; /* Title for PodSetupView */ -"Pod Setup" = "Pod Setup"; +"Pod Setup" = "Configurazione pod"; /* bodyText for PodSetupView */ "You will now begin the process of configuring your reminders, filling your Pod with insulin, pairing to your device and placing it on your body." = "You will now begin the process of configuring your reminders, filling your Pod with insulin, pairing to your device and placing it on your body."; @@ -694,13 +694,13 @@ "Continue" = "Continua"; /* Are you sure you want to skip Omnipod Onboarding? */ -"Skip Omnipod Onboarding?" = "Skip Omnipod Onboarding?"; +"Skip Omnipod Onboarding?" = "Saltare la procedura di installazione di Omnipod?"; /* Description text on ExpirationReminderSetupView */ "The App notifies you in advance of Pod expiration.\n\nScroll to set the number of hours advance notice you would like to have." = "The App notifies you in advance of Pod expiration.\n\nScroll to set the number of hours advance notice you would like to have."; /* Text of continue button on ExpirationReminderSetupView" */ -"Next" = "Next"; +"Next" = "Avanti"; /* */ "Expiration Reminder" = "Promemoria di scadenza"; @@ -718,40 +718,40 @@ "hr" = "hr"; /* Button title to cancel manual basal */ -"Cancel Manual Basal" = "Cancel Manual Basal"; +"Cancel Manual Basal" = "Annulla basale manuale"; /* Text shown in insulin delivery space when insulin suspended */ "Insulin\nSuspended" = "Insulin\nSuspended"; /* Text for suspend resume button when insulin delivery is suspended */ -"Resume Insulin Delivery" = "Resume Insulin Delivery"; +"Resume Insulin Delivery" = "Riprendi erogazione insulina"; /* Recovery suggestion when no pod is available */ -"Make sure your pod is nearby and try again." = "Make sure your pod is nearby and try again."; +"Make sure your pod is nearby and try again." = "Assicurati che il tuo pod sia vicino e riprova."; /* Error message shown when the pod is not connected */ -"Pod not connected" = "Pod not connected"; +"Pod not connected" = "Pod non connesso"; /* Label for suspended at time */ -"Suspended At" = "Suspended At"; +"Suspended At" = "Sospeso a"; /* Text for suspend resume button when insulin delivery is resuming */ -"Resuming insulin delivery..." = "Resuming insulin delivery..."; +"Resuming insulin delivery..." = "Sto riprendendo l'erogazione di insulina..."; /* Text for suspend resume button when insulin delivery is suspending */ -"Suspending insulin delivery..." = "Suspending insulin delivery..."; +"Suspending insulin delivery..." = "Sospendo erogazione di insulina..."; /* Error message for PodCommsError.noPodsFound */ -"No pods found" = "No pods found"; +"No pods found" = "Nessun pod trovato"; /* Error message for PodCommsError.tooManyPodsFound */ -"Too many pods found" = "Too many pods found"; +"Too many pods found" = "Trovati troppi pod"; /* Recovery suggestion when no response is received from pod */ "Make sure iPhone is nearby the active pod" = "Make sure iPhone is nearby the active pod"; /* Recovery suggestion when ack received instead of response */ -"Try again" = "Try again"; +"Try again" = "Riprovare"; /* Recovery suggestion for PodCommsError.tooManyPodsFound */ "Move to a new area away from any other pods and try again." = "Move to a new area away from any other pods and try again."; @@ -772,7 +772,7 @@ "Crosstalk possible. Please move to a new location" = "Crosstalk possible. Please move to a new location"; /* Recovery suggestion when no pod is available */ -"Make sure your pod is nearby and try again." = "Make sure your pod is nearby and try again."; +"Make sure your pod is nearby and try again." = "Assicurati che il tuo pod sia vicino e riprova."; /* Recovery suggestion when operation could not be completed due to existing bolus in progress */ "Wait for existing bolus to finish, or cancel bolus" = "Wait for existing bolus to finish, or cancel bolus"; diff --git a/Dependencies/OmniKit/OmniKit/Resources/it.lproj/Localizable.strings b/Dependencies/OmniKit/OmniKit/Resources/it.lproj/Localizable.strings index 982501c2ba..3b4abda616 100644 --- a/Dependencies/OmniKit/OmniKit/Resources/it.lproj/Localizable.strings +++ b/Dependencies/OmniKit/OmniKit/Resources/it.lproj/Localizable.strings @@ -191,7 +191,7 @@ "No Insulin" = "Insulina Terminata"; /* Status highlight that when no pod is paired. */ -"No Pod" = "No Pod"; +"No Pod" = "Nessun Pod"; /* Error message shown when no pod is paired */ "No pod paired" = "Nessun Pod abbinato"; diff --git a/Dependencies/OmniKit/OmniKit/Resources/uk.lproj/Localizable.strings b/Dependencies/OmniKit/OmniKit/Resources/uk.lproj/Localizable.strings index 745b547b8d..c6581ee465 100644 --- a/Dependencies/OmniKit/OmniKit/Resources/uk.lproj/Localizable.strings +++ b/Dependencies/OmniKit/OmniKit/Resources/uk.lproj/Localizable.strings @@ -1,8 +1,8 @@ /* Description for an inactive alert modifier */ -" (inactive)" = " (inactive)"; +" (inactive)" = " (неактивний)"; /* Format string for low battery alert body for RileyLink. (1: device name) */ -"\"%1$@\" has a low battery" = "\"%1$@\" has a low battery"; +"\"%1$@\" has a low battery" = "\"%1$@\" має низький заряд акумулятора"; /* Unit format string for an RSSI value in decibles */ "%@ dB" = "%@ dB"; @@ -12,40 +12,40 @@ /* Format string for activation time exceeded Pod state when activation not completed in the time allowed */ -"Activation time exceeded" = "Activation time exceeded"; +"Activation time exceeded" = "Час активації перевищений"; /* Description for auto-off */ -"Auto-off" = "Auto-Off"; +"Auto-off" = "Автоматичне вимкнення"; /* Description for auto-off alarm */ -"Auto-off alarm" = "Auto-off alarm"; +"Auto-off alarm" = "Авто-відключення сигналу"; /* Pod state when basal initialized */ -"Basal initialized" = "Basal initialized"; +"Basal initialized" = "Базал ініціалізовано"; /* Pod state when running below fifty units */ -"Below 50 units" = "Below 50 units"; +"Below 50 units" = "Нижче 50 одиниць"; /* Pump Event title for UnfinalizedDose with doseType of .bolus */ "Bolus" = "Болюс"; /* Error message shown when operation could not be completed due to existing bolus in progress */ -"Bolus in progress" = "Bolus in progress"; +"Bolus in progress" = "Подання болюса"; /* The format string describing a bolus. (1: The amount delivered)(2: Start time of the dose)(3: duration)(4: scheduled certainty) */ -"Bolus: %1$@U %2$@ %3$@ %4$@" = "Bolus: %1$@U %2$@ %3$@ %4$@"; +"Bolus: %1$@U %2$@ %3$@ %4$@" = "Болюс: %1$@U %2$@ %3$@ %4$@"; /* Delivery status when bolusing */ "Bolusing" = "Подача болюса"; /* Delivery status when bolusing and temp basal is running */ -"Bolusing with temp basal" = "Bolusing with temp basal"; +"Bolusing with temp basal" = "Болюс з тимчасовим базальним введенням"; /* Pod state when inserting cannula */ -"Cannula inserting" = "Cannula inserting"; +"Cannula inserting" = "Встановлення канюлі"; /* String describing a dose that was certainly scheduled */ -"Certain" = "Certain"; +"Certain" = "Безперечно"; /* Alert content body for podExpireImminent pod alert */ "Change Pod now. Insulin delivery will stop in 1 hour." = "Змінити Pod зараз. Подачу інсуліну буде зупинено через 1 годину."; @@ -54,13 +54,13 @@ "Change Pod now. Pod has been active for 72 hours." = "Змінити Pod зараз. Pod був активним протягом 72 годин."; /* Format string for invalid message error code (1: error code number) */ -"Command error %1$u" = "Command error %1$u"; +"Command error %1$u" = "Помилка команди %1$u"; /* Status highlight that delivery is uncertain. */ "Comms Issue" = "Помилка звʼязку"; /* Error message when command is rejected because an unacknowledged command is pending. */ -"Communication issue: Unacknowledged command pending." = "Communication issue: Unacknowledged command pending."; +"Communication issue: Unacknowledged command pending." = "Проблема комунікації: не визнана команда в очікуванні."; /* Description for BeepPreference.manualCommands */ "Confidence reminders will sound for commands you initiate, like bolus, cancel bolus, suspend, resume, save notification reminders, etc. When Loop automatically adjusts delivery, no confidence reminders are used." = "Сигнали підтвердження лунатимуть для команд, які ви ініціюєте, таких як болюс, скасування болюсу, призупинення, відновлення, збереження сповіщень тощо. Коли Loop автоматично регулює подачу, сигнали підтвердження не використовуються."; @@ -81,25 +81,25 @@ "Disabled" = "Вимкнено"; /* Description for Empty reservoir pod fault */ -"Empty reservoir" = "Empty reservoir"; +"Empty reservoir" = "Порожній резервуар"; /* Error message shown when empty response from pod was received */ -"Empty response from pod" = "Empty response from pod"; +"Empty response from pod" = "Немає відповіді від Pod"; /* Pod state error event logged shutting down */ -"Error event logged, shutting down" = "Error event logged, shutting down"; +"Error event logged, shutting down" = "Подія помилки зареєстрована, вимкнення"; /* Description for expiration alert */ -"Expiration alert" = "Expiration alert"; +"Expiration alert" = "Сповіщення про закінчення терміну дії"; /* Title string for BeepPreference.extended */ "Extended" = "Подовжено"; /* Delivery status when extended bolus is running */ -"Extended bolus running" = "Extended bolus running"; +"Extended bolus running" = "Вводиться розтягнутий болюс"; /* Delivery status when extended bolus and temp basal is running */ -"Extended bolus running with temp basal" = "Extended bolus running with temp basal"; +"Extended bolus running with temp basal" = "Подовжений болюс із тимчасовою базальною швидкістю"; /* Pod state when fault event has occurred */ "Fault event occurred" = "Виникла помилка"; @@ -117,10 +117,10 @@ "Finish setup reminder" = "Нагадування про завершення налаштування"; /* Pod inititialized */ -"Initialized" = "Initialized"; +"Initialized" = "Активований"; /* Pod state when inserting cannula */ -"Inserting cannula" = "Inserting cannula"; +"Inserting cannula" = "Вставка канюлі"; /* The default notification body for AlarmCodes */ "Insulin delivery stopped. Change Pod now." = "Подачу інсуліну припинено. Замініть Pod зараз."; @@ -132,19 +132,19 @@ "Insulin type not configured" = "Тип інсуліну не налаштований"; /* The format string for Internal pod fault (1: The fault code value) */ -"Internal pod fault %1$03d" = "Internal pod fault %1$03d"; +"Internal pod fault %1$03d" = "Внутрішня помилка Pod %1$03d"; /* The format string describing a bolus that was interrupted. (1: The amount delivered)(2: The amount scheduled)(3: Start time of the dose)(4: duration)(5: scheduled certainty) */ -"InterruptedBolus: %1$@ U (%2$@ U scheduled) %3$@ %4$@ %5$@" = "InterruptedBolus: %1$@ U (%2$@ U scheduled) %3$@ %4$@ %5$@"; +"InterruptedBolus: %1$@ U (%2$@ U scheduled) %3$@ %4$@ %5$@" = "Перерваний Болюс: %1$@ U (%2$@ U заплановано) %3$@ %4$@ %5$@"; /* Error message for when unexpected address is received (1: received address) (2: expected address) */ -"Invalid address 0x%x. Expected 0x%x" = "Invalid address 0x%x. Expected 0x%x"; +"Invalid address 0x%x. Expected 0x%x" = "Некоректна адреса 0x%x. Очікувалось 0x%x"; /* Description for MessageError invalidAddress */ -"Invalid address: (%1$@)" = "Invalid address: (%1$@)"; +"Invalid address: (%1$@)" = "Недійсна адреса: (%1$@)"; /* Description for MessageError invalidCrc */ -"Invalid CRC" = "Invalid CRC"; +"Invalid CRC" = "Некоректний CRC"; /* Error description for OmniBLEPumpManagerError.invalidSetting */ "Invalid Setting" = "Непридатні параметри"; @@ -153,10 +153,10 @@ "Low Reservoir" = "Пустий резервуар"; /* Format string for description for low reservoir advisory (1: reminder units) */ -"Low reservoir advisory (%1$gU)" = "Low reservoir advisory (%1$gU)"; +"Low reservoir advisory (%1$gU)" = "Попередження про низький рівень резервуара (%1$gU)"; /* Description for low reservoir alarm */ -"Low reservoir advisory alarm" = "Low reservoir advisory alarm"; +"Low reservoir advisory alarm" = "Оповіщення про малий запас інсуліну у резервуарі"; /* Title for RileyLink low battery alert */ "Low RileyLink Battery" = "Низький заряд RileyLink"; diff --git a/Dependencies/OmniKit/OmniKitUI/Resources/it.lproj/Localizable.strings b/Dependencies/OmniKit/OmniKitUI/Resources/it.lproj/Localizable.strings index 53e893e15c..c2aefd178f 100644 --- a/Dependencies/OmniKit/OmniKitUI/Resources/it.lproj/Localizable.strings +++ b/Dependencies/OmniKit/OmniKitUI/Resources/it.lproj/Localizable.strings @@ -397,7 +397,7 @@ /* Label for pod life state when no pod paired Text shown in insulin remaining space when no pod is paired */ -"No Pod" = "No Pod"; +"No Pod" = "Nessun Pod"; /* Value text for no expiration reminder */ "No Reminder" = "Nessun promemoria"; @@ -681,7 +681,7 @@ "The App notifies you when the amount of insulin in the Pod reaches this level." = "L'App puo' avvisare quando la quantità di insulina nel Pod raggiunge un predisposto determinato livello."; /* Description text for critical alerts */ -"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if your device is set to Silent or Do Not Disturb mode." = "The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if your device is set to Silent or Do Not Disturb mode."; +"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if your device is set to Silent or Do Not Disturb mode." = "I promemoria qui sopra non suoneranno se il dispositivo è in modalità Silenzioso o Non Disturbare.\n\nCi sono altri avvisi e avvisi di Pod critici che suoneranno anche se il dispositivo è impostato in modalità Silenzioso o Non Disturbare."; /* Message for pod sync time action sheet */ "The time on your pump is different from the current time. Do you want to update the time on your pump to the current time?" = "l'orario del microinfusore e' diverso da quello del tempo attuale. Vuoi fare un controllo e cambiare l'orario del microinfusore con il tempo attuale?"; diff --git a/Dependencies/OmniKit/OmniKitUI/Resources/uk.lproj/Localizable.strings b/Dependencies/OmniKit/OmniKitUI/Resources/uk.lproj/Localizable.strings index d52ff41a27..be4d8a39a3 100644 --- a/Dependencies/OmniKit/OmniKitUI/Resources/uk.lproj/Localizable.strings +++ b/Dependencies/OmniKit/OmniKitUI/Resources/uk.lproj/Localizable.strings @@ -2,26 +2,26 @@ "—" = "—"; /* Format string for last status date on pod details screen */ -"%@ ago" = "%@ ago"; +"%@ ago" = "%@ тому"; /* Unit format string for an RSSI value in decibles */ "%@ dB" = "%@ dB"; /* No comment provided by engineer. */ -"%@ has recovered communication with the pod on your body.\n\nInsulin delivery records have been updated and should match what has actually been delivered.\n\nYou may continue to use %@ normally now." = "%@ has recovered communication with the pod on your body.\n\nInsulin delivery records have been updated and should match what has actually been delivered.\n\nYou may continue to use %@ normally now."; +"%@ has recovered communication with the pod on your body.\n\nInsulin delivery records have been updated and should match what has actually been delivered.\n\nYou may continue to use %@ normally now." = "%@ відновив зв’язок із Pod на вашому тілі.\n\nЗаписи про доставку інсуліну оновлено та мають збігатися з фактично доставленою.\n\nВи можете продовжувати використовувати %@ у звичайному режимі."; /* Format string for delivered insulin. (1: The localized amount) Format string for insulin remaining in reservoir. (1: The localized amount) */ "%@ U" = "%@ U"; /* Format string for bolus progress when finished. (1: The localized amount) */ -"%@ U (Finished)" = "%@ U (Finished)"; +"%@ U (Finished)" = "%@ U (Завершено)"; /* Format string for bolus progress. (1: The delivered amount) (2: The programmed amount) (3: the percent progress) */ -"%@ U of %@ U (%@)" = "%@ U of %@ U (%@)"; +"%@ U of %@ U (%@)" = "%@ U з %@ U (%@)"; /* Format string for temp basal rate. (1: The localized amount) */ -"%@ U/hour" = "%@ U/hour"; +"%@ U/hour" = " %@U/год"; /* Appends a full-stop to a statement */ "%@." = "%@."; @@ -30,7 +30,7 @@ "%@%%" = "%@%%"; /* Format string for reservoir reading when above or equal to maximum reading. (1: The localized amount) */ -"%@+ U" = "%@+ U"; +"%@+ U" = "%@ U"; /* Format string for reservoir volume. (1: The localized volume) */ "%@U" = "%@U"; @@ -39,13 +39,13 @@ "%1$@ for %2$@" = "%1$@ для %2$@"; /* Format string for main text of delivery uncertainty recovery page. (1: app name)(2: date of command)(3: app name) */ -"%1$@ has been unable to communicate with the pod on your body since %2$@.\n\nWithout communication with the pod, the app cannot continue to send commands for insulin delivery or display accurate, recent information about your active insulin or the insulin being delivered by the Pod.\n\nMonitor your glucose closely for the next 6 or more hours, as there may or may not be insulin actively working in your body that %3$@ cannot display." = "%1$@ has been unable to communicate with the pod on your body since %2$@.\n\nWithout communication with the pod, the app cannot continue to send commands for insulin delivery or display accurate, recent information about your active insulin or the insulin being delivered by the Pod.\n\nMonitor your glucose closely for the next 6 or more hours, as there may or may not be insulin actively working in your body that %3$@ cannot display."; +"%1$@ has been unable to communicate with the pod on your body since %2$@.\n\nWithout communication with the pod, the app cannot continue to send commands for insulin delivery or display accurate, recent information about your active insulin or the insulin being delivered by the Pod.\n\nMonitor your glucose closely for the next 6 or more hours, as there may or may not be insulin actively working in your body that %3$@ cannot display." = "%1$@ не може зв’язатися з pod на вашому тілі з %2$@.\n\nБез зв’язку з pod програма не може продовжувати надсилати команди для доставки інсуліну або відображати точну, останню інформацію про ваш активний інсулін або інсуліну, який постачає Pod.\n\nУважно стежте за своїм рівнем глюкози протягом наступних 6 або більше годин, оскільки у вашому організмі може активно працювати або не працювати інсулін, який %3$@ не може відобразити."; /* Accessibility format string for (1: localized volume)(2: time) */ -"%1$@ units remaining at %2$@" = "%1$@ units remaining at %2$@"; +"%1$@ units remaining at %2$@" = "%1$@ одиниць залишилося на %2$@"; /* Format string providing instructions for replacing pod due to a fault. (1: The fault description) */ -"%1$@. Insulin delivery has stopped. Please deactivate and remove pod." = "%1$@. Insulin delivery has stopped. Please deactivate and remove pod."; +"%1$@. Insulin delivery has stopped. Please deactivate and remove pod." = "%1$@. Подача інсуліну спинилася. Будь ласка, вимкніть і видаліть POD."; /* The format string for displaying an offset from a time zone: (1: GMT)(2: -)(3: 4:00) */ "%1$@%2$@%3$@" = "%1$@%2$@%3$@"; @@ -84,34 +84,34 @@ "Are you sure you want to cancel Pod setup?" = "Ви впевнені, що бажаєте скасувати налаштування Pod? "; /* Confirmation message for shutting down a pod */ -"Are you sure you want to shutdown this pod?" = "Are you sure you want to shutdown this pod?"; +"Are you sure you want to shutdown this pod?" = "Ви впевнені, що хочете завершити цей Pod?"; /* No comment provided by engineer. */ -"Are you sure you want to skip Omnipod Onboarding?" = "Are you sure you want to skip Omnipod Onboarding?"; +"Are you sure you want to skip Omnipod Onboarding?" = "Ви впевнені, що хочете пропустити Omnipod Onboarding?"; /* Confirmation message for removing Omnipod PumpManager */ -"Are you sure you want to stop using Omnipod?" = "Are you sure you want to stop using Omnipod?"; +"Are you sure you want to stop using Omnipod?" = "Ви впевнені, що хочете припинити використовувати Omnipod?"; /* The title text for the address assigned to the pod */ -"Assigned Address" = "Assigned Address"; +"Assigned Address" = "Призначена адреса"; /* Title for Attach Pod screen */ "Attach Pod" = "Прикріпіть Pod"; /* Description string above progress indicator while attempting to re-establish communication from an unacknowledged command */ -"Attemping to re-establish communication" = "Attemping to re-establish communication"; +"Attemping to re-establish communication" = "Спроба відновити зв'язок"; /* Back button text on DeliveryUncertaintyRecoveryView */ -"Back" = "Back"; +"Back" = "Назад"; /* The title of the cell showing pod basal status */ -"Basal Delivery" = "Basal Delivery"; +"Basal Delivery" = "Подача Базалу"; /* The title text for the basal rate schedule */ -"Basal Rates" = "Basal Rates"; +"Basal Rates" = "Швидкості Базалу"; /* The title of the cell showing pod bolus status */ -"Bolus Delivery" = "Bolus Delivery"; +"Bolus Delivery" = "Подача Болюса"; /* The title of the cancel action in an action sheet */ "Cancel" = "Відмінити"; @@ -120,7 +120,7 @@ "Cancel Manual Basal" = "Скасувати базу вручну"; /* Insert cannula action button accessibility label when cannula insertion succeeded */ -"Cannula inserted successfully. Continue." = "Cannula inserted successfully. Continue."; +"Cannula inserted successfully. Continue." = "Канюлю введено успішно. Продовжити."; /* The action string on pod status page when pod expired */ "Change Pod now. Insulin delivery will stop 8 hours after the Pod has expired or when no more insulin remains." = "Змінити Pod зараз. Інсулінова доставка зупиниться на 8 годин після того, як Pod закінчиться або більше не залишиться інсуліну."; @@ -129,10 +129,10 @@ "Change Pod now. Insulin delivery will stop in %1$@ or when no more insulin remains." = "Змініть Pod зараз. Введення інсуліну припиниться через %1$@ або коли інсулін закінчиться."; /* The title of the command to change pump time zone */ -"Change Time Zone" = "Change Time Zone"; +"Change Time Zone" = "Змінити часовий пояс"; /* Progress message for changing pod time. */ -"Changing time…" = "Changing time…"; +"Changing time…" = "Зміна часу…"; /* Title for check cannula screen */ "Check Cannula" = "Перевірте канюлю"; @@ -141,13 +141,13 @@ "Check Pod, apply to site, then confirm pod attachment." = "Перевірити Pod, застосувати до сайту, а потім підтвердіть прикріплення pod."; /* Insert cannula action button accessibility label checking insertion */ -"Checking Insertion" = "Checking Insertion"; +"Checking Insertion" = "Перевірка введення канюлі"; /* Cannula insertion button text while checking insertion */ "Checking..." = "Перевірка..."; /* Title for uncertainty recovered screen */ -"Comms Recovered" = "Comms Recovered"; +"Comms Recovered" = "Зв'язок відновлено"; /* Text for confidence reminders navigation link */ "Confidence Reminders" = "Нагадування про Впевненість"; @@ -177,7 +177,7 @@ "days" = "дні"; /* Button title to deactivate pod because of fault during setup */ -"Deactivate" = "Deactivate"; +"Deactivate" = "Деактивувати"; /* Button title for pod deactivation Button title to deactivate pod */ @@ -193,23 +193,23 @@ "Deactivating..." = "Деактивувати..."; /* Button title to delete Omnipod PumpManager */ -"Delete Omnipod" = "Delete Omnipod"; +"Delete Omnipod" = "Видалити Omnipod "; /* Title text for delivery limits */ -"Delivery Limits" = "Delivery Limits"; +"Delivery Limits" = "Ліміт доставки"; /* Text for device details disclosure row title for device details page */ "Device Details" = "Деталі пристрою"; /* The title of the device information section in settings */ -"Device Information" = "Device Information"; +"Device Information" = "Відомості про пристрій"; /* Header for devices section of RileyLinkSetupView */ "Devices" = "Пристрої"; /* Title text for button to disable bolus beeps */ -"Disable Bolus Beeps" = "Disable Bolus Beeps"; +"Disable Bolus Beeps" = "Вимкнути звук Болюс"; /* Pairing interface navigation bar button text for discard pod action Text for discard pod button */ @@ -219,22 +219,22 @@ "Done" = "Готово"; /* Title text for button to enable bolus beeps */ -"Enable Bolus Beeps" = "Enable Bolus Beeps"; +"Enable Bolus Beeps" = "Увімкнути звук Болюс"; /* Accessibility label indicating an error occurred */ "Error" = "Помилка"; /* The alert title for disable bolus beeps error */ -"Error disabling bolus beeps" = "Error disabling bolus beeps"; +"Error disabling bolus beeps" = "Помилка вимкнення звуку Болюс "; /* The alert title for enable bolus beeps error */ -"Error enabling bolus beeps" = "Error enabling bolus beeps"; +"Error enabling bolus beeps" = "Помилка увімкнення звуку Болюс"; /* The alert title for a resume error */ -"Error Resuming" = "Error Resuming"; +"Error Resuming" = "Помилка при відновленні"; /* The alert title for a suspend error */ -"Error Suspending" = "Error Suspending"; +"Error Suspending" = "Помилка призупинення"; /* The title of the cell showing the pod expiration reminder date */ "Expiration Reminder" = "Нагадування про термін дії"; @@ -243,10 +243,10 @@ "Expiration Reminder Default" = "Нагадування про закінчення терміну дії за умовчанням"; /* The title of the cell showing the pod expiration after expiry */ -"Expired" = "Expired"; +"Expired" = "Минув термін дії"; /* The title of the cell showing the pod expiration */ -"Expires" = "Expires"; +"Expires" = "Термін закінчується"; /* Alert title for failing to cancel manual basal error */ "Failed to Cancel Manual Basal" = "Не вдалося скасувати ручний базал"; @@ -264,28 +264,28 @@ "Failed to update confidence reminder preference." = "Не вдалося оновити налаштування нагадування про конфіденційність."; /* Alert title for error when updating expiration reminder */ -"Failed to Update Expiration Reminder" = "Failed to Update Expiration Reminder"; +"Failed to Update Expiration Reminder" = "Не вдалося оновити нагадування про закінчення терміну дії"; /* Alert title for error when updating low reservoir reminder */ -"Failed to Update Low Reservoir Reminder" = "Failed to Update Low Reservoir Reminder"; +"Failed to Update Low Reservoir Reminder" = "Не вдалося оновити нагадування про низький рівень резервуару"; /* Pod life HUD view label */ "Fault" = "Збій"; /* Label text for step 1 of pair pod instructions */ -"Fill a new pod with U-100 Insulin (leave Pod needle cap on). Listen for 2 beeps." = "Fill a new pod with U-100 Insulin (leave Pod needle cap on). Listen for 2 beeps."; +"Fill a new pod with U-100 Insulin (leave Pod needle cap on). Listen for 2 beeps." = "Заправити новий pod інсуліном (не менше U-100, кришка канюлі повинна бути на місці). Зачекайте 2 звукових сигналів."; /* Settings page link description when next lifecycle action is to finish deactivation */ "Finish deactivation" = "Завершення деактивації"; /* The title of the command to finish pod setup */ -"Finish pod setup" = "Finish pod setup"; +"Finish pod setup" = "Завершити налаштування Pod"; /* Action button title to continue at Setup Complete */ "Finish Setup" = "Завершити налаштування"; /* Accessibility format string for (1: localized volume)(2: time) */ -"Greater than %1$@ units remaining at %2$@" = "Greater than %1$@ units remaining at %2$@"; +"Greater than %1$@ units remaining at %2$@" = "Залишилось більше %1$@ одиниць на %2$@"; /* Unit for singular hour in pod life remaining */ "hour" = "годин"; @@ -297,10 +297,10 @@ "If you cancel Pod setup, the current Pod will be deactivated and will be unusable." = "Якщо ви скасуєте налаштування Pod, поточний Pod буде дезактивовано та стане непридатним для використання."; /* Instructions when deactivating pod that has been paired, but not attached. */ -"Incompletely set up pod must be deactivated before pairing with a new one. Please deactivate and discard pod." = "Incompletely set up pod must be deactivated before pairing with a new one. Please deactivate and discard pod."; +"Incompletely set up pod must be deactivated before pairing with a new one. Please deactivate and discard pod." = "Старий Pod має бути деактивований, для створення пари з новим. Будь ласка, деактивуйте та зніміть старий Pod."; /* Instructions when deactivating pod that has been paired and possibly attached. */ -"Incompletely set up pod must be deactivated before pairing with a new one. Please deactivate and remove pod." = "Incompletely set up pod must be deactivated before pairing with a new one. Please deactivate and remove pod."; +"Incompletely set up pod must be deactivated before pairing with a new one. Please deactivate and remove pod." = "Старий Pod має бути деактивований, для створення пари з новим. Будь ласка, деактивуйте та зніміть старий Pod."; /* Button title to insert cannula during setup */ "Insert Cannula" = "Вставте канюлю"; @@ -309,7 +309,7 @@ "Inserted" = "Введено"; /* Insert cannula action button accessibility label while pairing */ -"Inserting. Please wait." = "Inserting. Please wait."; +"Inserting. Please wait." = "Введення канюлі. Будь ласка зачекайте."; /* Cannula insertion button text while inserting */ "Inserting..." = "Вставка ..."; @@ -318,7 +318,7 @@ "Insulin\nSuspended" = "Інсулін\nПризупинено"; /* The title of the cell showing delivered insulin */ -"Insulin Delivered" = "Insulin Delivered"; +"Insulin Delivered" = "Інсулін подано"; /* Title of insulin delivery section */ "Insulin Delivery" = "Доставка інсуліну"; diff --git a/Dependencies/rileylink_ios/RileyLinkKitUI/Base.lproj/Localizable.strings b/Dependencies/rileylink_ios/RileyLinkKitUI/Base.lproj/Localizable.strings index 4f1beecdc7..56422d08ea 100644 --- a/Dependencies/rileylink_ios/RileyLinkKitUI/Base.lproj/Localizable.strings +++ b/Dependencies/rileylink_ios/RileyLinkKitUI/Base.lproj/Localizable.strings @@ -1,3 +1,18 @@ +/* Unit format string for an RSSI value in decibles */ +"%@ dB" = "%@ dB"; + +/* Unit format string for an value in percent */ +"%@%%" = "%@%%"; + +/* The title of the section for alerts */ +"Alert" = "Alert"; + +/* Text indicating LED Mode is auto */ +"Auto" = "Auto"; + +/* The title of the cell showing battery level */ +"Battery level" = "Battery level"; + /* The title of the section describing commands */ "Commands" = "Commands"; @@ -7,9 +22,18 @@ /* The in-progress connecting state */ "Connecting" = "Connecting"; +/* The title of the cell for connection LED */ +"Connection LED" = "Connection LED"; + +/* The title of the section for connection monitoring */ +"Connection Monitoring" = "Connection Monitoring"; + /* The title of the cell showing BLE connection state */ "Connection State" = "Connection State"; +/* The title of the cell for connection vibration */ +"Connection Vibration" = "Connection Vibration"; + /* The title of the section describing the device */ "Device" = "Device"; @@ -22,20 +46,61 @@ /* The in-progress disconnecting state */ "Disconnecting" = "Disconnecting"; +/* The title of the cell for sounding device finding piezo */ +"Find Device" = "Find Device"; + /* The title of the cell showing firmware version */ "Firmware" = "Firmware"; /* The title of the cell showing current rileylink frequency */ -"Frequency" = "Frequency"; +"Frequency" = "Frequency" ; + +/* The title of the command to fetch RileyLink statistics */ +"Get RileyLink Statistics" = "Get RileyLink Statistics"; + +/* Progress message for getting statistics. */ +"Get Statistics…" = "Get Statistics…"; + +/* The title of the cell showing Lighten Red LED */ +"Lighten Red LED" = "Lighten Red LED"; + +/* The title of the cell showing Lighten Yellow LED */ +"Lighten Yellow LED" = "Lighten Yellow LED"; + +/* The title of the cell showing battery level */ +"Low Battery Alert" = "Low Battery Alert"; /* The title of the cell showing device name */ "Name" = "Name"; +/* Detail text when battery alert disabled. + Text indicating LED Mode is off */ +"Off" = "Off"; + +/* Text indicating LED Mode is on */ +"On" = "On"; + /* RileyLink setup description */ "RileyLink allows for communication with the pump over Bluetooth Low Energy." = "RileyLink allows for communication with the pump over Bluetooth Low Energy."; /* The title of the cell showing BLE signal strength (RSSI) */ "Signal Strength" = "Signal Strength"; +/* The title of the section for orangelink commands + The title of the section for rileylink commands */ +"Test Commands" = "Test Commands"; + +/* The title of the cell showing Test Vibration */ +"Test Vibration" = "Test Vibration"; + +/* The title of the command to update diagnostic LEDs */ +"Toggle Diagnostic LEDs" = "Toggle Diagnostic LEDs"; + +/* Progress message for changing diagnostic LED mode */ +"Updating diagnostic LEDs mode" = "Updating diagnostic LEDs mode"; + /* The title of the cell showing uptime */ "Uptime" = "Uptime"; + +/* The title of the cell showing ORL */ +"Voltage" = "Voltage"; diff --git a/Dependencies/rileylink_ios/RileyLinkKitUI/ar.lproj/Localizable.strings b/Dependencies/rileylink_ios/RileyLinkKitUI/ar.lproj/Localizable.strings index 446026f519..f74714bf35 100644 --- a/Dependencies/rileylink_ios/RileyLinkKitUI/ar.lproj/Localizable.strings +++ b/Dependencies/rileylink_ios/RileyLinkKitUI/ar.lproj/Localizable.strings @@ -1,6 +1,106 @@ +/* Unit format string for an RSSI value in decibles */ +"%@ dB" = "%@ dB"; + +/* Unit format string for an value in percent */ +"%@%%" = "%@%%"; + +/* The title of the section for alerts */ +"Alert" = "Alert"; + +/* Text indicating LED Mode is auto */ +"Auto" = "Auto"; + +/* The title of the cell showing battery level */ +"Battery level" = "Battery level"; + +/* The title of the section describing commands */ +"Commands" = "Commands"; + +/* The connected state */ +"Connected" = "Connected"; + +/* The in-progress connecting state */ +"Connecting" = "Connecting"; + +/* The title of the cell for connection LED */ +"Connection LED" = "Connection LED"; + +/* The title of the section for connection monitoring */ +"Connection Monitoring" = "Connection Monitoring"; + +/* The title of the cell showing BLE connection state */ +"Connection State" = "Connection State"; + +/* The title of the cell for connection vibration */ +"Connection Vibration" = "Connection Vibration"; + +/* The title of the section describing the device */ +"Device" = "Device"; + +/* The title of the devices table section in RileyLink settings */ +"Devices" = "Devices"; + +/* The disconnected state */ +"Disconnected" = "Disconnected"; + +/* The in-progress disconnecting state */ +"Disconnecting" = "Disconnecting"; + /* The title of the cell for sounding device finding piezo */ "Find Device" = "Find Device"; +/* The title of the cell showing firmware version */ +"Firmware" = "Firmware"; + +/* The title of the cell showing current rileylink frequency */ +"Frequency" = "Frequency"; + +/* The title of the command to fetch RileyLink statistics */ +"Get RileyLink Statistics" = "Get RileyLink Statistics"; + +/* Progress message for getting statistics. */ +"Get Statistics…" = "Get Statistics…"; + +/* The title of the cell showing Lighten Red LED */ +"Lighten Red LED" = "Lighten Red LED"; + +/* The title of the cell showing Lighten Yellow LED */ +"Lighten Yellow LED" = "Lighten Yellow LED"; + +/* The title of the cell showing battery level */ +"Low Battery Alert" = "Low Battery Alert"; + +/* The title of the cell showing device name */ +"Name" = "Name"; + +/* Detail text when battery alert disabled. + Text indicating LED Mode is off */ +"Off" = "Off"; + /* Text indicating LED Mode is on */ "On" = "On"; +/* RileyLink setup description */ +"RileyLink allows for communication with the pump over Bluetooth Low Energy." = "RileyLink allows for communication with the pump over Bluetooth Low Energy."; + +/* The title of the cell showing BLE signal strength (RSSI) */ +"Signal Strength" = "Signal Strength"; + +/* The title of the section for orangelink commands + The title of the section for rileylink commands */ +"Test Commands" = "Test Commands"; + +/* The title of the cell showing Test Vibration */ +"Test Vibration" = "Test Vibration"; + +/* The title of the command to update diagnostic LEDs */ +"Toggle Diagnostic LEDs" = "Toggle Diagnostic LEDs"; + +/* Progress message for changing diagnostic LED mode */ +"Updating diagnostic LEDs mode" = "Updating diagnostic LEDs mode"; + +/* The title of the cell showing uptime */ +"Uptime" = "Uptime"; + +/* The title of the cell showing ORL */ +"Voltage" = "Voltage"; diff --git a/Dependencies/rileylink_ios/RileyLinkKitUI/ca.lproj/Localizable.strings b/Dependencies/rileylink_ios/RileyLinkKitUI/ca.lproj/Localizable.strings new file mode 100644 index 0000000000..f74714bf35 --- /dev/null +++ b/Dependencies/rileylink_ios/RileyLinkKitUI/ca.lproj/Localizable.strings @@ -0,0 +1,106 @@ +/* Unit format string for an RSSI value in decibles */ +"%@ dB" = "%@ dB"; + +/* Unit format string for an value in percent */ +"%@%%" = "%@%%"; + +/* The title of the section for alerts */ +"Alert" = "Alert"; + +/* Text indicating LED Mode is auto */ +"Auto" = "Auto"; + +/* The title of the cell showing battery level */ +"Battery level" = "Battery level"; + +/* The title of the section describing commands */ +"Commands" = "Commands"; + +/* The connected state */ +"Connected" = "Connected"; + +/* The in-progress connecting state */ +"Connecting" = "Connecting"; + +/* The title of the cell for connection LED */ +"Connection LED" = "Connection LED"; + +/* The title of the section for connection monitoring */ +"Connection Monitoring" = "Connection Monitoring"; + +/* The title of the cell showing BLE connection state */ +"Connection State" = "Connection State"; + +/* The title of the cell for connection vibration */ +"Connection Vibration" = "Connection Vibration"; + +/* The title of the section describing the device */ +"Device" = "Device"; + +/* The title of the devices table section in RileyLink settings */ +"Devices" = "Devices"; + +/* The disconnected state */ +"Disconnected" = "Disconnected"; + +/* The in-progress disconnecting state */ +"Disconnecting" = "Disconnecting"; + +/* The title of the cell for sounding device finding piezo */ +"Find Device" = "Find Device"; + +/* The title of the cell showing firmware version */ +"Firmware" = "Firmware"; + +/* The title of the cell showing current rileylink frequency */ +"Frequency" = "Frequency"; + +/* The title of the command to fetch RileyLink statistics */ +"Get RileyLink Statistics" = "Get RileyLink Statistics"; + +/* Progress message for getting statistics. */ +"Get Statistics…" = "Get Statistics…"; + +/* The title of the cell showing Lighten Red LED */ +"Lighten Red LED" = "Lighten Red LED"; + +/* The title of the cell showing Lighten Yellow LED */ +"Lighten Yellow LED" = "Lighten Yellow LED"; + +/* The title of the cell showing battery level */ +"Low Battery Alert" = "Low Battery Alert"; + +/* The title of the cell showing device name */ +"Name" = "Name"; + +/* Detail text when battery alert disabled. + Text indicating LED Mode is off */ +"Off" = "Off"; + +/* Text indicating LED Mode is on */ +"On" = "On"; + +/* RileyLink setup description */ +"RileyLink allows for communication with the pump over Bluetooth Low Energy." = "RileyLink allows for communication with the pump over Bluetooth Low Energy."; + +/* The title of the cell showing BLE signal strength (RSSI) */ +"Signal Strength" = "Signal Strength"; + +/* The title of the section for orangelink commands + The title of the section for rileylink commands */ +"Test Commands" = "Test Commands"; + +/* The title of the cell showing Test Vibration */ +"Test Vibration" = "Test Vibration"; + +/* The title of the command to update diagnostic LEDs */ +"Toggle Diagnostic LEDs" = "Toggle Diagnostic LEDs"; + +/* Progress message for changing diagnostic LED mode */ +"Updating diagnostic LEDs mode" = "Updating diagnostic LEDs mode"; + +/* The title of the cell showing uptime */ +"Uptime" = "Uptime"; + +/* The title of the cell showing ORL */ +"Voltage" = "Voltage"; diff --git a/Dependencies/rileylink_ios/RileyLinkKitUI/da.lproj/Localizable.strings b/Dependencies/rileylink_ios/RileyLinkKitUI/da.lproj/Localizable.strings index 90694a3c0d..82d37ef86c 100644 --- a/Dependencies/rileylink_ios/RileyLinkKitUI/da.lproj/Localizable.strings +++ b/Dependencies/rileylink_ios/RileyLinkKitUI/da.lproj/Localizable.strings @@ -104,4 +104,3 @@ /* The title of the cell showing ORL */ "Voltage" = "Voltage"; - diff --git a/Dependencies/rileylink_ios/RileyLinkKitUI/de.lproj/Localizable.strings b/Dependencies/rileylink_ios/RileyLinkKitUI/de.lproj/Localizable.strings index e0a906345e..5c3aba063c 100644 --- a/Dependencies/rileylink_ios/RileyLinkKitUI/de.lproj/Localizable.strings +++ b/Dependencies/rileylink_ios/RileyLinkKitUI/de.lproj/Localizable.strings @@ -8,7 +8,7 @@ "Alert" = "Alarm"; /* Text indicating LED Mode is auto */ -"Auto" = "Auto"; +"Auto" = "Automatisch"; /* The title of the cell showing battery level */ "Battery level" = "Batteriefüllung"; @@ -104,4 +104,3 @@ /* The title of the cell showing ORL */ "Voltage" = "Spannung"; - diff --git a/Dependencies/rileylink_ios/RileyLinkKitUI/es.lproj/Localizable.strings b/Dependencies/rileylink_ios/RileyLinkKitUI/es.lproj/Localizable.strings index 25345b1623..9e7e169df4 100644 --- a/Dependencies/rileylink_ios/RileyLinkKitUI/es.lproj/Localizable.strings +++ b/Dependencies/rileylink_ios/RileyLinkKitUI/es.lproj/Localizable.strings @@ -104,4 +104,3 @@ /* The title of the cell showing ORL */ "Voltage" = "Voltaje"; - diff --git a/Dependencies/rileylink_ios/RileyLinkKitUI/fi.lproj/Localizable.strings b/Dependencies/rileylink_ios/RileyLinkKitUI/fi.lproj/Localizable.strings index 26bb829ecb..36f2f2deab 100644 --- a/Dependencies/rileylink_ios/RileyLinkKitUI/fi.lproj/Localizable.strings +++ b/Dependencies/rileylink_ios/RileyLinkKitUI/fi.lproj/Localizable.strings @@ -4,6 +4,15 @@ /* Unit format string for an value in percent */ "%@%%" = "%@%%"; +/* The title of the section for alerts */ +"Alert" = "Alert"; + +/* Text indicating LED Mode is auto */ +"Auto" = "Auto"; + +/* The title of the cell showing battery level */ +"Battery level" = "Battery level"; + /* The title of the section describing commands */ "Commands" = "Komennot"; @@ -13,9 +22,18 @@ /* The in-progress connecting state */ "Connecting" = "Yhdistetään"; +/* The title of the cell for connection LED */ +"Connection LED" = "Connection LED"; + +/* The title of the section for connection monitoring */ +"Connection Monitoring" = "Connection Monitoring"; + /* The title of the cell showing BLE connection state */ "Connection State" = "Yhteyden tila"; +/* The title of the cell for connection vibration */ +"Connection Vibration" = "Connection Vibration"; + /* The title of the section describing the device */ "Device" = "Laite"; @@ -37,9 +55,21 @@ /* The title of the cell showing current rileylink frequency */ "Frequency" = "Taajuus"; +/* The title of the command to fetch RileyLink statistics */ +"Get RileyLink Statistics" = "Get RileyLink Statistics"; + /* Progress message for getting statistics. */ "Get Statistics…" = "Hae tilastotiedot…"; +/* The title of the cell showing Lighten Red LED */ +"Lighten Red LED" = "Lighten Red LED"; + +/* The title of the cell showing Lighten Yellow LED */ +"Lighten Yellow LED" = "Lighten Yellow LED"; + +/* The title of the cell showing battery level */ +"Low Battery Alert" = "Low Battery Alert"; + /* The title of the cell showing device name */ "Name" = "Nimi"; @@ -56,6 +86,21 @@ /* The title of the cell showing BLE signal strength (RSSI) */ "Signal Strength" = "Signaalin vahvuus"; +/* The title of the section for orangelink commands + The title of the section for rileylink commands */ +"Test Commands" = "Test Commands"; + +/* The title of the cell showing Test Vibration */ +"Test Vibration" = "Test Vibration"; + +/* The title of the command to update diagnostic LEDs */ +"Toggle Diagnostic LEDs" = "Toggle Diagnostic LEDs"; + +/* Progress message for changing diagnostic LED mode */ +"Updating diagnostic LEDs mode" = "Updating diagnostic LEDs mode"; + /* The title of the cell showing uptime */ "Uptime" = "Päällä"; +/* The title of the cell showing ORL */ +"Voltage" = "Voltage"; diff --git a/Dependencies/rileylink_ios/RileyLinkKitUI/fr.lproj/Localizable.strings b/Dependencies/rileylink_ios/RileyLinkKitUI/fr.lproj/Localizable.strings index 485ac87baa..30a839d7c3 100644 --- a/Dependencies/rileylink_ios/RileyLinkKitUI/fr.lproj/Localizable.strings +++ b/Dependencies/rileylink_ios/RileyLinkKitUI/fr.lproj/Localizable.strings @@ -50,7 +50,7 @@ "Find Device" = "Découvrir dispositif"; /* The title of the cell showing firmware version */ -"Firmware" = "Firmware"; +"Firmware" = "Microprogramme"; /* The title of the cell showing current rileylink frequency */ "Frequency" = "Fréquence"; @@ -104,4 +104,3 @@ /* The title of the cell showing ORL */ "Voltage" = "Voltage"; - diff --git a/Dependencies/rileylink_ios/RileyLinkKitUI/he.lproj/Localizable.strings b/Dependencies/rileylink_ios/RileyLinkKitUI/he.lproj/Localizable.strings index 5325cd3429..3135ac2940 100644 --- a/Dependencies/rileylink_ios/RileyLinkKitUI/he.lproj/Localizable.strings +++ b/Dependencies/rileylink_ios/RileyLinkKitUI/he.lproj/Localizable.strings @@ -25,6 +25,9 @@ /* The title of the cell for connection LED */ "Connection LED" = "נורית חיבור"; +/* The title of the section for connection monitoring */ +"Connection Monitoring" = "Connection Monitoring"; + /* The title of the cell showing BLE connection state */ "Connection State" = "מצב החיבור"; @@ -52,6 +55,9 @@ /* The title of the cell showing current rileylink frequency */ "Frequency" = "Frequency"; +/* The title of the command to fetch RileyLink statistics */ +"Get RileyLink Statistics" = "Get RileyLink Statistics"; + /* Progress message for getting statistics. */ "Get Statistics…" = "Get Statistics…"; @@ -87,9 +93,14 @@ /* The title of the cell showing Test Vibration */ "Test Vibration" = "בדוק רטט"; +/* The title of the command to update diagnostic LEDs */ +"Toggle Diagnostic LEDs" = "Toggle Diagnostic LEDs"; + +/* Progress message for changing diagnostic LED mode */ +"Updating diagnostic LEDs mode" = "Updating diagnostic LEDs mode"; + /* The title of the cell showing uptime */ "Uptime" = "Uptime"; /* The title of the cell showing ORL */ "Voltage" = "מתח"; - diff --git a/Dependencies/rileylink_ios/RileyLinkKitUI/it.lproj/Localizable.strings b/Dependencies/rileylink_ios/RileyLinkKitUI/it.lproj/Localizable.strings index 7810ffbb74..171306d1d1 100644 --- a/Dependencies/rileylink_ios/RileyLinkKitUI/it.lproj/Localizable.strings +++ b/Dependencies/rileylink_ios/RileyLinkKitUI/it.lproj/Localizable.strings @@ -84,7 +84,7 @@ "RileyLink allows for communication with the pump over Bluetooth Low Energy." = "RileyLink consente la comunicazione con il microinfusore tramite Bluetooth Low Energy."; /* The title of the cell showing BLE signal strength (RSSI) */ -"Signal Strength" = "Potenza Segnale"; +"Signal Strength" = "Potenza segnale"; /* The title of the section for orangelink commands The title of the section for rileylink commands */ @@ -100,8 +100,7 @@ "Updating diagnostic LEDs mode" = "Aggiornamento modalità LED diagnostici"; /* The title of the cell showing uptime */ -"Uptime" = "Tempo Attività"; +"Uptime" = "Tempo attività"; /* The title of the cell showing ORL */ "Voltage" = "Voltaggio"; - diff --git a/Dependencies/rileylink_ios/RileyLinkKitUI/nb.lproj/Localizable.strings b/Dependencies/rileylink_ios/RileyLinkKitUI/nb.lproj/Localizable.strings index fbfc31e1ae..8fd3e8c67d 100644 --- a/Dependencies/rileylink_ios/RileyLinkKitUI/nb.lproj/Localizable.strings +++ b/Dependencies/rileylink_ios/RileyLinkKitUI/nb.lproj/Localizable.strings @@ -104,4 +104,3 @@ /* The title of the cell showing ORL */ "Voltage" = "Spenning (V)"; - diff --git a/Dependencies/rileylink_ios/RileyLinkKitUI/nl.lproj/Localizable.strings b/Dependencies/rileylink_ios/RileyLinkKitUI/nl.lproj/Localizable.strings index c69f4b1307..58bfe369a4 100644 --- a/Dependencies/rileylink_ios/RileyLinkKitUI/nl.lproj/Localizable.strings +++ b/Dependencies/rileylink_ios/RileyLinkKitUI/nl.lproj/Localizable.strings @@ -104,4 +104,3 @@ /* The title of the cell showing ORL */ "Voltage" = "Spanning"; - diff --git a/Dependencies/rileylink_ios/RileyLinkKitUI/pl.lproj/Localizable.strings b/Dependencies/rileylink_ios/RileyLinkKitUI/pl.lproj/Localizable.strings index f0307f10c1..425318e472 100644 --- a/Dependencies/rileylink_ios/RileyLinkKitUI/pl.lproj/Localizable.strings +++ b/Dependencies/rileylink_ios/RileyLinkKitUI/pl.lproj/Localizable.strings @@ -104,4 +104,3 @@ /* The title of the cell showing ORL */ "Voltage" = "Napięcie"; - diff --git a/Dependencies/rileylink_ios/RileyLinkKitUI/pt-BR.lproj/Localizable.strings b/Dependencies/rileylink_ios/RileyLinkKitUI/pt-BR.lproj/Localizable.strings index 4946b96077..6e7c4703ba 100644 --- a/Dependencies/rileylink_ios/RileyLinkKitUI/pt-BR.lproj/Localizable.strings +++ b/Dependencies/rileylink_ios/RileyLinkKitUI/pt-BR.lproj/Localizable.strings @@ -1,6 +1,18 @@ +/* Unit format string for an RSSI value in decibles */ +"%@ dB" = "%@ dB"; + /* Unit format string for an value in percent */ "%@%%" = "%@%%"; +/* The title of the section for alerts */ +"Alert" = "Alert"; + +/* Text indicating LED Mode is auto */ +"Auto" = "Auto"; + +/* The title of the cell showing battery level */ +"Battery level" = "Battery level"; + /* The title of the section describing commands */ "Commands" = "Comandos"; @@ -10,9 +22,18 @@ /* The in-progress connecting state */ "Connecting" = "Conectando"; +/* The title of the cell for connection LED */ +"Connection LED" = "Connection LED"; + +/* The title of the section for connection monitoring */ +"Connection Monitoring" = "Connection Monitoring"; + /* The title of the cell showing BLE connection state */ "Connection State" = "Estado da Conexão"; +/* The title of the cell for connection vibration */ +"Connection Vibration" = "Connection Vibration"; + /* The title of the section describing the device */ "Device" = "Dispositivo"; @@ -34,12 +55,28 @@ /* The title of the cell showing current rileylink frequency */ "Frequency" = "Frequência"; +/* The title of the command to fetch RileyLink statistics */ +"Get RileyLink Statistics" = "Get RileyLink Statistics"; + /* Progress message for getting statistics. */ "Get Statistics…" = "Extrair Estatísticas…"; +/* The title of the cell showing Lighten Red LED */ +"Lighten Red LED" = "Lighten Red LED"; + +/* The title of the cell showing Lighten Yellow LED */ +"Lighten Yellow LED" = "Lighten Yellow LED"; + +/* The title of the cell showing battery level */ +"Low Battery Alert" = "Low Battery Alert"; + /* The title of the cell showing device name */ "Name" = "Nome"; +/* Detail text when battery alert disabled. + Text indicating LED Mode is off */ +"Off" = "Off"; + /* Text indicating LED Mode is on */ "On" = "Ligado"; @@ -49,6 +86,21 @@ /* The title of the cell showing BLE signal strength (RSSI) */ "Signal Strength" = "Potência do Sinal"; +/* The title of the section for orangelink commands + The title of the section for rileylink commands */ +"Test Commands" = "Test Commands"; + +/* The title of the cell showing Test Vibration */ +"Test Vibration" = "Test Vibration"; + +/* The title of the command to update diagnostic LEDs */ +"Toggle Diagnostic LEDs" = "Toggle Diagnostic LEDs"; + +/* Progress message for changing diagnostic LED mode */ +"Updating diagnostic LEDs mode" = "Updating diagnostic LEDs mode"; + /* The title of the cell showing uptime */ "Uptime" = "Tempo de Atividade"; +/* The title of the cell showing ORL */ +"Voltage" = "Voltage"; diff --git a/Dependencies/rileylink_ios/RileyLinkKitUI/pt-PT.lproj/Localizable.strings b/Dependencies/rileylink_ios/RileyLinkKitUI/pt-PT.lproj/Localizable.strings new file mode 100644 index 0000000000..6b26da574f --- /dev/null +++ b/Dependencies/rileylink_ios/RileyLinkKitUI/pt-PT.lproj/Localizable.strings @@ -0,0 +1,106 @@ +/* Unit format string for an RSSI value in decibles */ +"%@ dB" = "%@ dB"; + +/* Unit format string for an value in percent */ +"%@%%" = "%@%%"; + +/* The title of the section for alerts */ +"Alert" = "Alert"; + +/* Text indicating LED Mode is auto */ +"Auto" = "Auto"; + +/* The title of the cell showing battery level */ +"Battery level" = "Battery level"; + +/* The title of the section describing commands */ +"Commands" = "Commands"; + +/* The connected state */ +"Connected" = "Connected"; + +/* The in-progress connecting state */ +"Connecting" = "Connecting"; + +/* The title of the cell for connection LED */ +"Connection LED" = "Connection LED"; + +/* The title of the section for connection monitoring */ +"Connection Monitoring" = "Connection Monitoring"; + +/* The title of the cell showing BLE connection state */ +"Connection State" = "Connection State"; + +/* The title of the cell for connection vibration */ +"Connection Vibration" = "Connection Vibration"; + +/* The title of the section describing the device */ +"Device" = "Device"; + +/* The title of the devices table section in RileyLink settings */ +"Devices" = "Dispositivos"; + +/* The disconnected state */ +"Disconnected" = "Disconnected"; + +/* The in-progress disconnecting state */ +"Disconnecting" = "Disconnecting"; + +/* The title of the cell for sounding device finding piezo */ +"Find Device" = "Find Device"; + +/* The title of the cell showing firmware version */ +"Firmware" = "Firmware"; + +/* The title of the cell showing current rileylink frequency */ +"Frequency" = "Frequency"; + +/* The title of the command to fetch RileyLink statistics */ +"Get RileyLink Statistics" = "Get RileyLink Statistics"; + +/* Progress message for getting statistics. */ +"Get Statistics…" = "Get Statistics…"; + +/* The title of the cell showing Lighten Red LED */ +"Lighten Red LED" = "Lighten Red LED"; + +/* The title of the cell showing Lighten Yellow LED */ +"Lighten Yellow LED" = "Lighten Yellow LED"; + +/* The title of the cell showing battery level */ +"Low Battery Alert" = "Low Battery Alert"; + +/* The title of the cell showing device name */ +"Name" = "Nome"; + +/* Detail text when battery alert disabled. + Text indicating LED Mode is off */ +"Off" = "Off"; + +/* Text indicating LED Mode is on */ +"On" = "On"; + +/* RileyLink setup description */ +"RileyLink allows for communication with the pump over Bluetooth Low Energy." = "RileyLink allows for communication with the pump over Bluetooth Low Energy."; + +/* The title of the cell showing BLE signal strength (RSSI) */ +"Signal Strength" = "Signal Strength"; + +/* The title of the section for orangelink commands + The title of the section for rileylink commands */ +"Test Commands" = "Test Commands"; + +/* The title of the cell showing Test Vibration */ +"Test Vibration" = "Test Vibration"; + +/* The title of the command to update diagnostic LEDs */ +"Toggle Diagnostic LEDs" = "Toggle Diagnostic LEDs"; + +/* Progress message for changing diagnostic LED mode */ +"Updating diagnostic LEDs mode" = "Updating diagnostic LEDs mode"; + +/* The title of the cell showing uptime */ +"Uptime" = "Uptime"; + +/* The title of the cell showing ORL */ +"Voltage" = "Voltage"; diff --git a/Dependencies/rileylink_ios/RileyLinkKitUI/sk.lproj/Localizable.strings b/Dependencies/rileylink_ios/RileyLinkKitUI/sk.lproj/Localizable.strings index d8836fd373..e658b11636 100644 --- a/Dependencies/rileylink_ios/RileyLinkKitUI/sk.lproj/Localizable.strings +++ b/Dependencies/rileylink_ios/RileyLinkKitUI/sk.lproj/Localizable.strings @@ -99,6 +99,8 @@ /* Progress message for changing diagnostic LED mode */ "Updating diagnostic LEDs mode" = "Aktualizuje sa režim diagnostických LED diód"; +/* The title of the cell showing uptime */ +"Uptime" = "Uptime"; + /* The title of the cell showing ORL */ "Voltage" = "Napätie"; - diff --git a/Dependencies/rileylink_ios/RileyLinkKitUI/sv.lproj/Localizable.strings b/Dependencies/rileylink_ios/RileyLinkKitUI/sv.lproj/Localizable.strings index 38902ae8dd..299ed5b050 100644 --- a/Dependencies/rileylink_ios/RileyLinkKitUI/sv.lproj/Localizable.strings +++ b/Dependencies/rileylink_ios/RileyLinkKitUI/sv.lproj/Localizable.strings @@ -4,6 +4,15 @@ /* Unit format string for an value in percent */ "%@%%" = "%@%%"; +/* The title of the section for alerts */ +"Alert" = "Varning"; + +/* Text indicating LED Mode is auto */ +"Auto" = "Auto"; + +/* The title of the cell showing battery level */ +"Battery level" = "Batterinivå"; + /* The title of the section describing commands */ "Commands" = "Kommandon"; @@ -13,9 +22,18 @@ /* The in-progress connecting state */ "Connecting" = "Ansluter"; +/* The title of the cell for connection LED */ +"Connection LED" = "Anslutnings-LED"; + +/* The title of the section for connection monitoring */ +"Connection Monitoring" = "Anslutningsstatus"; + /* The title of the cell showing BLE connection state */ "Connection State" = "Anslutningsstatus"; +/* The title of the cell for connection vibration */ +"Connection Vibration" = "Anslutningsvibration"; + /* The title of the section describing the device */ "Device" = "Enhet"; @@ -37,9 +55,21 @@ /* The title of the cell showing current rileylink frequency */ "Frequency" = "Frekvens"; +/* The title of the command to fetch RileyLink statistics */ +"Get RileyLink Statistics" = "Hämta RileyLink-statistik"; + /* Progress message for getting statistics. */ "Get Statistics…" = "Hämtar statistik…"; +/* The title of the cell showing Lighten Red LED */ +"Lighten Red LED" = "Ljusare röd LED"; + +/* The title of the cell showing Lighten Yellow LED */ +"Lighten Yellow LED" = "Ljusare gul LED"; + +/* The title of the cell showing battery level */ +"Low Battery Alert" = "Låg batterinivå"; + /* The title of the cell showing device name */ "Name" = "Namn"; @@ -56,6 +86,21 @@ /* The title of the cell showing BLE signal strength (RSSI) */ "Signal Strength" = "Signalstyrka"; +/* The title of the section for orangelink commands + The title of the section for rileylink commands */ +"Test Commands" = "Testkommandon"; + +/* The title of the cell showing Test Vibration */ +"Test Vibration" = "Testa vibration"; + +/* The title of the command to update diagnostic LEDs */ +"Toggle Diagnostic LEDs" = "Slå på diagnostiska LED"; + +/* Progress message for changing diagnostic LED mode */ +"Updating diagnostic LEDs mode" = "Uppdaterar diagnostiska LED"; + /* The title of the cell showing uptime */ "Uptime" = "Körs sedan"; +/* The title of the cell showing ORL */ +"Voltage" = "Spänning (V)"; diff --git a/Dependencies/rileylink_ios/RileyLinkKitUI/tr.lproj/Localizable.strings b/Dependencies/rileylink_ios/RileyLinkKitUI/tr.lproj/Localizable.strings index 7eaa98e94d..a2a4d97de1 100644 --- a/Dependencies/rileylink_ios/RileyLinkKitUI/tr.lproj/Localizable.strings +++ b/Dependencies/rileylink_ios/RileyLinkKitUI/tr.lproj/Localizable.strings @@ -104,4 +104,3 @@ /* The title of the cell showing ORL */ "Voltage" = "Voltaj"; - diff --git a/Dependencies/rileylink_ios/RileyLinkKitUI/uk.lproj/Localizable.strings b/Dependencies/rileylink_ios/RileyLinkKitUI/uk.lproj/Localizable.strings index 43f5b88181..fcb1927ab3 100644 --- a/Dependencies/rileylink_ios/RileyLinkKitUI/uk.lproj/Localizable.strings +++ b/Dependencies/rileylink_ios/RileyLinkKitUI/uk.lproj/Localizable.strings @@ -1,3 +1,18 @@ +/* Unit format string for an RSSI value in decibles */ +"%@ dB" = "%@ dB"; + +/* Unit format string for an value in percent */ +"%@%%" = "%@%%"; + +/* The title of the section for alerts */ +"Alert" = "Сповіщення"; + +/* Text indicating LED Mode is auto */ +"Auto" = "Авто"; + +/* The title of the cell showing battery level */ +"Battery level" = "Рівень заряду"; + /* The title of the section describing commands */ "Commands" = "Команди"; @@ -7,9 +22,18 @@ /* The in-progress connecting state */ "Connecting" = "Під'єднання"; +/* The title of the cell for connection LED */ +"Connection LED" = "Індикатор з’єднання"; + +/* The title of the section for connection monitoring */ +"Connection Monitoring" = "Моніторинг з'єднання"; + /* The title of the cell showing BLE connection state */ "Connection State" = "Стан з'єднання"; +/* The title of the cell for connection vibration */ +"Connection Vibration" = "Вібрація при роз'єднанні"; + /* The title of the section describing the device */ "Device" = "Пристрій"; @@ -22,20 +46,61 @@ /* The in-progress disconnecting state */ "Disconnecting" = "Від'єднання"; +/* The title of the cell for sounding device finding piezo */ +"Find Device" = "Знайти пристрій"; + /* The title of the cell showing firmware version */ "Firmware" = "Прошивка"; /* The title of the cell showing current rileylink frequency */ "Frequency" = "Частота"; +/* The title of the command to fetch RileyLink statistics */ +"Get RileyLink Statistics" = "Отримати статистику RileyLink"; + +/* Progress message for getting statistics. */ +"Get Statistics…" = "Отримати статистику…"; + +/* The title of the cell showing Lighten Red LED */ +"Lighten Red LED" = "Засвітіть червоний світлодіод"; + +/* The title of the cell showing Lighten Yellow LED */ +"Lighten Yellow LED" = "Засвітіть жовтий світлодіод"; + +/* The title of the cell showing battery level */ +"Low Battery Alert" = "Низький заряд"; + /* The title of the cell showing device name */ "Name" = "Ім’я"; +/* Detail text when battery alert disabled. + Text indicating LED Mode is off */ +"Off" = "Off"; + +/* Text indicating LED Mode is on */ +"On" = "On"; + /* RileyLink setup description */ "RileyLink allows for communication with the pump over Bluetooth Low Energy." = "RileyLink дозволяє зв'язуватися з насосом через Bluetooth Low Energy."; /* The title of the cell showing BLE signal strength (RSSI) */ "Signal Strength" = "Рівень сигналу"; +/* The title of the section for orangelink commands + The title of the section for rileylink commands */ +"Test Commands" = "Перевірка команд"; + +/* The title of the cell showing Test Vibration */ +"Test Vibration" = "Перевірка вібрації"; + +/* The title of the command to update diagnostic LEDs */ +"Toggle Diagnostic LEDs" = "Перемкнути діагностичні світлодіоди"; + +/* Progress message for changing diagnostic LED mode */ +"Updating diagnostic LEDs mode" = "Змінити режим світлодіодів"; + /* The title of the cell showing uptime */ "Uptime" = "Час роботи"; + +/* The title of the cell showing ORL */ +"Voltage" = "Напруга"; diff --git a/Dependencies/rileylink_ios/RileyLinkKitUI/zh-Hans.lproj/Localizable.strings b/Dependencies/rileylink_ios/RileyLinkKitUI/zh-Hans.lproj/Localizable.strings index e3a814009f..3a858dbc36 100644 --- a/Dependencies/rileylink_ios/RileyLinkKitUI/zh-Hans.lproj/Localizable.strings +++ b/Dependencies/rileylink_ios/RileyLinkKitUI/zh-Hans.lproj/Localizable.strings @@ -1,3 +1,18 @@ +/* Unit format string for an RSSI value in decibles */ +"%@ dB" = "%@ dB"; + +/* Unit format string for an value in percent */ +"%@%%" = "%@%%"; + +/* The title of the section for alerts */ +"Alert" = "Alert"; + +/* Text indicating LED Mode is auto */ +"Auto" = "Auto"; + +/* The title of the cell showing battery level */ +"Battery level" = "Battery level"; + /* The title of the section describing commands */ "Commands" = "命令"; @@ -7,9 +22,18 @@ /* The in-progress connecting state */ "Connecting" = "正在连接"; +/* The title of the cell for connection LED */ +"Connection LED" = "Connection LED"; + +/* The title of the section for connection monitoring */ +"Connection Monitoring" = "Connection Monitoring"; + /* The title of the cell showing BLE connection state */ "Connection State" = "连接状态"; +/* The title of the cell for connection vibration */ +"Connection Vibration" = "Connection Vibration"; + /* The title of the section describing the device */ "Device" = "设备"; @@ -31,9 +55,28 @@ /* The title of the cell showing current rileylink frequency */ "Frequency" = "Frequency"; +/* The title of the command to fetch RileyLink statistics */ +"Get RileyLink Statistics" = "Get RileyLink Statistics"; + +/* Progress message for getting statistics. */ +"Get Statistics…" = "Get Statistics…"; + +/* The title of the cell showing Lighten Red LED */ +"Lighten Red LED" = "Lighten Red LED"; + +/* The title of the cell showing Lighten Yellow LED */ +"Lighten Yellow LED" = "Lighten Yellow LED"; + +/* The title of the cell showing battery level */ +"Low Battery Alert" = "Low Battery Alert"; + /* The title of the cell showing device name */ "Name" = "设备名称"; +/* Detail text when battery alert disabled. + Text indicating LED Mode is off */ +"Off" = "Off"; + /* Text indicating LED Mode is on */ "On" = "开"; @@ -43,6 +86,21 @@ /* The title of the cell showing BLE signal strength (RSSI) */ "Signal Strength" = "信号强度"; +/* The title of the section for orangelink commands + The title of the section for rileylink commands */ +"Test Commands" = "Test Commands"; + +/* The title of the cell showing Test Vibration */ +"Test Vibration" = "Test Vibration"; + +/* The title of the command to update diagnostic LEDs */ +"Toggle Diagnostic LEDs" = "Toggle Diagnostic LEDs"; + +/* Progress message for changing diagnostic LED mode */ +"Updating diagnostic LEDs mode" = "Updating diagnostic LEDs mode"; + /* The title of the cell showing uptime */ "Uptime" = "Uptime"; +/* The title of the cell showing ORL */ +"Voltage" = "Voltage"; diff --git a/FreeAPS/Resources/it.lproj/InfoPlist.strings b/FreeAPS/Resources/it.lproj/InfoPlist.strings index 3b3e5961e7..7441fe5746 100644 --- a/FreeAPS/Resources/it.lproj/InfoPlist.strings +++ b/FreeAPS/Resources/it.lproj/InfoPlist.strings @@ -14,7 +14,7 @@ "NSCalendarsUsageDescription" = "Il calendario è usato per creare nuovi eventi di glicemia."; /* Privacy - Health Update Usage Description */ -"NSHealthUpdateUsageDescription" = "Health App is used to store blood glucose, insulin and carbohydrates"; +"NSHealthUpdateUsageDescription" = "L'app Salute è usata per memorizzare glicemie, insulina e carboidrati"; /* Privacy - Health Share Usage Description */ -"NSHealthShareUsageDescription" = "Health App is used to store blood glucose, insulin and carbohydrates"; +"NSHealthShareUsageDescription" = "L'app Salute è usata per memorizzare glicemie, insulina e carboidrati"; diff --git a/FreeAPS/Resources/javascript/bundle/determine-basal.js b/FreeAPS/Resources/javascript/bundle/determine-basal.js index 684997e1a7..eebb77c82d 100644 --- a/FreeAPS/Resources/javascript/bundle/determine-basal.js +++ b/FreeAPS/Resources/javascript/bundle/determine-basal.js @@ -1 +1 @@ -var freeaps_determineBasal;(()=>{var e={5546:(e,t,a)=>{var r=a(6880);function o(e,t){t||(t=0);var a=Math.pow(10,t);return Math.round(e*a)/a}function n(e,t){return"mmol/L"===t.out_units?o(.0555*e,1):Math.round(e)}e.exports=function(e,t,a,i,s,l,m,d,u,c,g,h,p,v){var f=i.min_bg,B=v.overrideTarget;const b=v.smbIsOff;var M=0,_="",y="",x="",S="",D="",w=0,T=0,C=0,U=0,G=0,O=0;const R=v.weightedAverage;var A=1,I=i.sens,j=i.carb_ratio;v.useOverride&&(I/=A=v.overridePercentage/100,j/=A);const F=i.weightPercentage,P=v.average_total_data;function E(e,t){var a=e.getTime();return new Date(a+36e5*t)}function q(e){var t=i.bolus_increment;.025!=t&&(t=.05);var a=e/t;return a>=1?o(Math.floor(a)*t,5):0}function W(e){function t(e){return e<10&&(e="0"+e),e}return t(e.getHours())+":"+t(e.getMinutes())+":00"}function k(e,t){var a=new Date("1/1/1999 "+e),r=new Date("1/1/1999 "+t);return(a.getTime()-r.getTime())/36e5}function L(e,t){var a=0,r=t,o=(e-t)/36e5,n=0,i=o,s=0;do{if(o>0){var l=W(r),m=p[0].rate;for(let e=0;e=(s=k(p[e+1].start,p[e].start))?n=s:o=(s=24-k(p[e].start,t))?n=s:od)if(e+1=(s=k(u,l))?n=s:o=(s=k("23:59:59",l))?n=s:o0&&o21)G=L(z,(H=24-M,Z=z.getTime(),new Date(Z-36e5*H))),S="24 hours of data is required for an accurate tdd calculation. Currently only "+M.toPrecision(3)+" hours of pump history data are available. Using your pump scheduled basals to fill in the missing hours. Scheduled basals added: "+G.toPrecision(5)+" U. ";else M<21?(oe=!1,enableDynamicCR=!1):S=""}else console.log("Pumphistory is empty!"),oe=!1,enableDynamicCR=!1;var H,Z;for(let e=0;e0){w=e,O=g[e].rate;var $=g[e-1]["duration (min)"]/60,J=$,K=new Date(g[e-1].timestamp),Q=K,V=0;do{if(e--,0==e){Q=new Date;break}if("TempBasal"==g[e]._type||"PumpSuspend"==g[e]._type){Q=new Date(g[e].timestamp);break}var X=e-2;if(X>=0&&"Rewind"==g[X]._type){let e=g[X].timestamp;for(;X-1>=0&&"Prime"==g[X-=1]._type;)V=(g[X].timestamp-e)/36e5;V>=$&&(Q=e,V=0)}}while(e>0);var Y=(Q-K)/36e5;Y0&&(--r,"TempBasal"==g[r]._type)){a=new Date(g[r].timestamp);break}}while(r>0);(a-t)/36e5>0&&(G+=L(a,t))}for(let e=g.length-1;e>0;e--)if("TempBasalDuration"==g[e]._type){let t=g[e]["duration (min)"]/60,a=new Date(g[e].timestamp);var ee=a;let r=e;do{if(--r,r>=0&&("TempBasal"==g[r]._type||"PumpSuspend"==g[r]._type)){ee=new Date(g[r].timestamp);break}}while(r>0);if(0==e&&"TempBasalDuration"==g[0]._type&&(ee=new Date,t=g[e]["duration (min)"]/60),(ee-a)/36e5-t>0){G+=L(ee,E(a,t))}}var te,ae={TDD:o(T=U+C+G,5),bolus:o(U,5),temp_basal:o(C,5),scheduled_basal:o(G,5)};M>21?(y=". Bolus insulin: "+U.toPrecision(5)+" U",x=". Temporary basal insulin: "+C.toPrecision(5)+" U",_=". Insulin with scheduled basal rate: "+G.toPrecision(5)+" U",D=S+(" TDD past 24h is: "+T.toPrecision(5)+" U")+y+x+_,tddReason=", Total insulin: "+o(T,2)+" U, "+o(U/T*100,0)+"% Bolus "+o((C+G)/T*100,0)+"% Basal"):tddReason=", TDD: Not enough pumpData (< 21h)";const re=e.glucose;var oe=h.useNewFormula;const ne=h.enableDynamicCR,ie=Math.min(i.autosens_min,i.autosens_max),se=Math.max(i.autosens_min,i.autosens_max);(se==ie||se<1||ie>1)&&(oe=!1,console.log("Dynamic ISF disabled due to current autosens settings"));const le=h.adjustmentFactor,me=i.min_bg;var de=!1,ue="",ce=1,ge="";P>0&&(ce=R/P),ge=ce>1?"Basal adjustment with a 24 hour to total average (up to 14 days of data) TDD ratio (limited by Autosens max setting). Basal Ratio: "+(ce=o(ce=Math.min(ce,i.autosens_max),2))+". Upper limit = Autosens max ("+i.autosens_max+")":ce<1?"Basal adjustment with a 24 hour to to total average (up to 14 days of data) TDD ratio (limited by Autosens min setting). Basal Ratio: "+(ce=o(ce=Math.max(ce,i.autosens_min),2))+". Lower limit = Autosens min ("+i.autosens_min+")":"Basal adjusted with a 24 hour to total average (up to 14 days of data) TDD ratio: "+ce,ge=", Basal ratio: "+ce,(i.high_temptarget_raises_sensitivity||i.exercise_mode||v.isEnabled)&&(de=!0),me>=118&&de&&(oe=!1,ue="Dynamic ISF temporarily off due to a high temp target/exercising. Current min target: "+me);var he=", Dynamic ratios log: ",pe=", AF: "+le,ve="BG: "+re+" mg/dl ("+(.0555*re).toPrecision(2)+" mmol/l)",fe="",Be="";const be=h.curve,Me=h.insulinPeakTime,_e=h.useCustomPeakTime;var ye=55,xe=65;switch(be){case"rapid-acting":xe=65;break;case"ultra-rapid":xe=50}_e?(ye=120-Me,console.log("Custom insulinpeakTime set to :"+Me+", insulinFactor: "+ye)):(ye=120-xe,console.log("insulinFactor set to : "+ye)),te=T,F<1&&R>0&&(T=R,console.log("Using weighted TDD average: "+o(T,2)+" U, instead of past 24 h ("+o(te,2)+" U), weight: "+F),Be=", Weighted TDD: "+o(T,2)+" U");const Se=h.sigmoid;var De="";if(oe){var we=I*le*T*Math.log(re/ye+1)/1800;fe=", Logarithmic formula"}if(oe&&Se){const e=ie,t=se-e,a=.0555*(re-i.min_bg);var Te=ce,Ce=se-1;1==se&&(Ce=se+.01-1);const r=Math.log10(1/Ce-e/Ce)/Math.log10(Math.E),o=a*le*Te+r;we=t/(1+Math.exp(-o))+e,fe=", Sigmoid function"}var Ue=j;const Ge=o(j,1);var Oe="",Re="";if(oe&&T>0){if(Oe=", Dynamic ISF/CR: On/",we>se?(ue=", Dynamic ISF limited by autosens_max setting: "+se+" ("+o(we,2)+"), ",Re=", Autosens/Dynamic Limit: "+se+" ("+o(we,2)+")",we=se):we1&&(Ae=(we-1)/2+1);var Ie=" CR: "+(Ue=o(Ue/Ae,2))+" g/U";j=Ue}else Ie=" CR: "+Ue+" g/U",Oe+="Off";const e=I/we;s.ratio=we,De=". Using Sigmoid function, the autosens ratio has been adjusted with sigmoid factor to: "+o(s.ratio,2)+". New ISF = "+o(e,2)+" mg/dl ("+o(.0555*e,2)+" (mmol/l). CR adjusted from "+o(Ge,2)+" to "+o(Ue,2),D+=he+ve+pe+fe+(ue+=Se?De:", Dynamic autosens.ratio set to "+o(we,2)+" with ISF: "+e.toPrecision(3)+" mg/dl/U ("+(.0555*e).toPrecision(3)+" mmol/l/U)")+Oe+Ie+Be}else D+=he+"Dynamic Settings disabled";console.log(D),oe||ne?oe&&i.tddAdjBasal?tddReason+=Oe+fe+Re+pe+ge:oe&&!i.tddAdjBasal&&(tddReason+=Oe+fe+Re+pe):tddReason+="";var je={},Fe=new Date;if(c&&(Fe=c),void 0===i||void 0===i.current_basal)return je.error="Error: could not get current basal rate",je;var Pe=r(i.current_basal,i)*A,Ee=Pe;v.useOverride&&(0==v.duration?console.log("Profile Override is active. Override "+o(100*A,0)+"%. Override Duration: Enabled indefinitely"):console.log("Profile Override is active. Override "+o(100*A,0)+"%. Override Expires in: "+v.duration+" min."));var qe=new Date;c&&(qe=c);var We,ke=new Date(e.date),Le=o((qe-ke)/60/1e3,1),ze=e.glucose,Ne=e.noise;We=e.delta>-.5?"+"+o(e.delta,0):o(e.delta,0);var He=Math.min(e.delta,e.short_avgdelta),Ze=Math.min(e.short_avgdelta,e.long_avgdelta),$e=Math.max(e.delta,e.short_avgdelta,e.long_avgdelta);(ze<=10||38===ze||Ne>=3)&&(je.reason="CGM is calibrating, in ??? state, or noise is high");if(ze>60&&0==e.delta&&e.short_avgdelta>-1&&e.short_avgdelta<1&&e.long_avgdelta>-1&&e.long_avgdelta<1&&("fakecgm"==e.device?(console.error("CGM data is unchanged ("+n(ze,i)+"+"+n(e.delta,i)+") for 5m w/ "+n(e.short_avgdelta,i)+" mg/dL ~15m change & "+n(e.long_avgdelta,2)+" mg/dL ~45m change"),console.error("Simulator mode detected ("+e.device+"): continuing anyway")):!0),Le>12||Le<-5?je.reason="If current system time "+qe+" is correct, then BG data is too old. The last BG data was read "+Le+"m ago at "+ke:0===e.short_avgdelta&&0===e.long_avgdelta&&(e.last_cal&&e.last_cal<3?je.reason="CGM was just calibrated":je.reason="CGM data is unchanged ("+n(ze,i)+"+"+n(e.delta,i)+") for 5m w/ "+n(e.short_avgdelta,i)+" mg/dL ~15m change & "+n(e.long_avgdelta,i)+" mg/dL ~45m change"),ze<=10||38===ze||Ne>=3||Le>12||Le<-5||0===e.short_avgdelta&&0===e.long_avgdelta)return t.rate>=Ee?(je.reason+=". Canceling high temp basal of "+t.rate,je.deliverAt=Fe,je.temp="absolute",je.duration=0,je.rate=0,je):0===t.rate&&t.duration>30?(je.reason+=". Shortening "+t.duration+"m long zero temp to 30m. ",je.deliverAt=Fe,je.temp="absolute",je.duration=30,je.rate=0,je):(je.reason+=". Temp "+t.rate+" <= current basal "+Ee+"U/hr; doing nothing. ",je);var Je,Ke,Qe,Ve,Xe=i.max_iob;if(void 0!==i.min_bg&&(Ke=i.min_bg),void 0!==i.max_bg&&(Qe=i.max_bg),void 0!==i.enableSMB_high_bg_target&&(Ve=i.enableSMB_high_bg_target),void 0===i.min_bg||void 0===i.max_bg)return je.error="Error: could not determine target_bg. ",je;Je=(i.min_bg+i.max_bg)/2;var Ye=i.exercise_mode||i.high_temptarget_raises_sensitivity||v.isEnabled,et=100,tt=160;if(tt=i.half_basal_exercise_target,v.isEnabled){const e=v.hbt;console.log("Half Basal Target used: "+n(e,i)+" "+i.out_units),tt=e}else console.log("Default Half Basal Target used: "+n(tt,i)+" "+i.out_units);if(Ye&&i.temptargetSet&&Je>et||i.low_temptarget_lowers_sensitivity&&i.temptargetSet&&Je=Je&&sensitivityRatio0&&(process.stderr.write("TDD-adjustment of basals activated, using tdd24h_14d_Ratio "+o(ce,2)+", TDD 24h = "+o(te,2)+"U, Weighted average TDD = "+o(R,2)+"U, (Weight percentage = "+F+"), Total data of TDDs (up to 14 days) average = "+o(P,2)+"U. "),Ee!==Pe*A?process.stderr.write("Adjusting basal from "+Pe*A+" U/h to "+Ee+" U/h; "):process.stderr.write("Basal unchanged: "+Ee+" U/h; "))),i.temptargetSet);else if(void 0!==s&&s&&(i.sensitivity_raises_target&&s.ratio<1||i.resistance_lowers_target&&s.ratio>1)){Ke=o((Ke-60)/s.ratio)+60,Qe=o((Qe-60)/s.ratio)+60;var rt=o((Je-60)/s.ratio)+60;Je===(rt=Math.max(80,rt))?process.stderr.write("target_bg unchanged: "+n(rt,i)+"; "):process.stderr.write("target_bg from "+n(rt,i)+" to "+n(rt,i)+"; "),Je=rt}var ot=n(Je,i);Je!=f&&(ot=0!==B&&B!==Je?n(f,i)+"→"+n(B,i)+"→"+n(Je,i):n(f,i)+"→"+n(Je,i));var nt=200,it=200,st=200;if(e.noise>=2){var lt=Math.max(1.1,i.noisyCGMTargetMultiplier);Math.min(250,i.maxRaw);nt=o(Math.min(200,Ke*lt)),it=o(Math.min(200,Je*lt)),st=o(Math.min(200,Qe*lt)),process.stderr.write("Raising target_bg for noisy / raw CGM data, from "+n(rt,i)+" to "+n(it,i)+"; "),Ke=nt,Je=it,Qe=st}var mt=Ke-.5*(Ke-40),dt=i.threshold_setting;dt>mt&&dt<=120&&dt>=65?(console.error("Threshold changed in settings from "+n(mt,i)+" to "+n(dt,i)+". "),mt=dt):console.error("Current threshold: "+n(mt,i));var ut="",ct=(o(I,1),I);if(void 0!==s&&s&&((ct=o(ct=I/sensitivityRatio,1))!==I?process.stderr.write("ISF from "+n(I,i)+" to "+n(ct,i)):process.stderr.write("ISF unchanged: "+n(ct,i)),ut+="Autosens ratio: "+o(sensitivityRatio,2)+", ISF: "+n(I,i)+"→"+n(ct,i)),console.error("CR:"+j),void 0===a)return je.error="Error: iob_data undefined. ",je;var gt,ht=a;if(a.length,a.length>1&&(a=ht[0]),void 0===a.activity||void 0===a.iob)return je.error="Error: iob_data missing some property. ",je;var pt=((gt=void 0!==a.lastTemp?o((new Date(qe).getTime()-a.lastTemp.date)/6e4):0)+t.duration)%30;if(console.error("currenttemp:"+t.rate+" lastTempAge:"+gt+"m, tempModulus:"+pt+"m"),je.temp="absolute",je.deliverAt=Fe,d&&t&&a.lastTemp&&t.rate!==a.lastTemp.rate&>>10&&t.duration)return je.reason="Warning: currenttemp rate "+t.rate+" != lastTemp rate "+a.lastTemp.rate+" from pumphistory; canceling temp",m.setTempBasal(0,0,i,je,t);if(t&&a.lastTemp&&t.duration>0){var vt=gt-a.lastTemp.duration;if(vt>5&>>10)return je.reason="Warning: currenttemp running but lastTemp from pumphistory ended "+vt+"m ago; canceling temp",m.setTempBasal(0,0,i,je,t)}var ft=o(-a.activity*ct*5,2),Bt=o(6*(He-ft));Bt<0&&(Bt=o(6*(Ze-ft)))<0&&(Bt=o(6*(e.long_avgdelta-ft)));var bt=ze,Mt=(bt=a.iob>0?o(ze-a.iob*ct):o(ze-a.iob*Math.min(ct,I)))+Bt;if(void 0===Mt||isNaN(Mt))return je.error="Error: could not calculate eventualBG. Sensitivity: "+ct+" Deviation: "+Bt,je;var _t=function(e,t,a){return o(a+(e-t)/24,1)}(Je,Mt,ft);je={temp:"absolute",bg:ze,tick:We,eventualBG:Mt,insulinReq:0,reservoir:u,deliverAt:Fe,sensitivityRatio,TDD:te,insulin:ae,current_target:Je};var yt=[],xt=[],St=[],Dt=[];yt.push(ze),xt.push(ze),Dt.push(ze),St.push(ze);var wt=function(e,t,a,r,o,i){return t?!e.allowSMB_with_high_temptarget&&e.temptargetSet&&o>100?(console.error("SMB disabled due to high temptarget of "+o),!1):!0===a.bwFound&&!1===e.A52_risk_enable?(console.error("SMB disabled due to Bolus Wizard activity in the last 6 hours."),!1):!0===e.enableSMB_always?(a.bwFound?console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled due to enableSMB_always"),!0):!0===e.enableSMB_with_COB&&a.mealCOB?(a.bwCarbs?console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for COB of "+a.mealCOB),!0):!0===e.enableSMB_after_carbs&&a.carbs?(a.bwCarbs?console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for 6h after carb entry"),!0):!0===e.enableSMB_with_temptarget&&e.temptargetSet&&o<100?(a.bwFound?console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for temptarget of "+n(o,e)),!0):!0===e.enableSMB_high_bg&&null!==i&&r>=i?(console.error("Checking BG to see if High for SMB enablement."),console.error("Current BG",r," | High BG ",i),a.bwFound?console.error("Warning: High BG SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("High BG detected. Enabling SMB."),!0):(console.error("SMB disabled (no enableSMB preferences active or no condition satisfied)"),!1):(console.error("SMB disabled (!microBolusAllowed)"),!1)}(i,d,l,ze,Je,Ve);b&&(console.error("SMB disabled (an Override is active with SMBs disabled)"),wt=!1);var Tt=i.enableUAM,Ct=0,Ut=0;Ct=o(He-ft,1);var Gt=o(He-ft,1);csf=ct/j,console.error("profile.sens:"+n(I,i)+", sens:"+n(ct,i)+", CSF:"+o(csf,1));var Ot=o(30*csf*5/60,1);Ct>Ot&&(console.error("Limiting carb impact from "+Ct+" to "+Ot+"mg/dL/5m (30g/h)"),Ct=Ot);var Rt=3;sensitivityRatio&&(Rt/=sensitivityRatio);var At=Rt;if(l.carbs){Rt=Math.max(Rt,l.mealCOB/20);var It=o((new Date(qe).getTime()-l.lastCarbTime)/6e4),jt=(l.carbs-l.mealCOB)/l.carbs;At=o(At=Rt+1.5*It/60,1),console.error("Last carbs "+It+" minutes ago; remainingCATime:"+At+"hours; "+o(100*jt,1)+"% carbs absorbed")}var Ft=Math.max(0,Ct/5*60*At/2)/csf,Pt=90,Et=1;i.remainingCarbsCap&&(Pt=Math.min(90,i.remainingCarbsCap)),i.remainingCarbsFraction&&(Et=Math.min(1,i.remainingCarbsFraction));var qt=1-Et,Wt=Math.max(0,l.mealCOB-Ft-l.carbs*qt),kt=(Wt=Math.min(Pt,Wt))*csf*5/60/(At/2),Lt=o(l.slopeFromMaxDeviation,2),zt=o(l.slopeFromMinDeviation,2),Nt=Math.min(Lt,-zt/3);Ut=0===Ct?0:Math.min(60*At/5/2,Math.max(0,l.mealCOB*csf/Ct)),console.error("Carb Impact:"+Ct+"mg/dL per 5m; CI Duration:"+o(5*Ut/60*2,1)+"hours; remaining CI ("+At/2+"h peak):"+o(kt,1)+"mg/dL per 5m");var Ht,Zt,$t,Jt,Kt,Qt=999,Vt=999,Xt=999,Yt=ze,ea=999,ta=999,aa=999,ra=999,oa=Mt,na=ze,ia=ze,sa=0,la=[],ma=[];try{ht.forEach((function(e){var t=o(-e.activity*ct*5,2),a=o(-e.iobWithZeroTemp.activity*ct*5,2),r=bt,n=Ct*(1-Math.min(1,xt.length/12));if(!0===(oe&&!Se))oa=xt[xt.length-1]+o(-e.activity*(1800/(T*le*Math.log(Math.max(xt[xt.length-1],39)/ye+1)))*5,2)+n,r=Dt[Dt.length-1]+o(-e.iobWithZeroTemp.activity*(1800/(T*le*Math.log(Math.max(Dt[Dt.length-1],39)/ye+1)))*5,2),console.log("Dynamic ISF (Logarithmic Formula) )adjusted predictions for IOB and ZT: IOBpredBG: "+o(oa,2)+" , ZTpredBG: "+o(r,2));else oa=xt[xt.length-1]+t+n,r=Dt[Dt.length-1]+a;var i=Math.max(0,Math.max(0,Ct)*(1-yt.length/Math.max(2*Ut,1))),s=Math.min(yt.length,12*At-yt.length),l=Math.max(0,s/(At/2*12)*kt);i+l,la.push(o(l,0)),ma.push(o(i,0)),COBpredBG=yt[yt.length-1]+t+Math.min(0,n)+i+l;var m=Math.max(0,Gt+St.length*Nt),d=Math.max(0,Gt*(1-St.length/Math.max(36,1))),u=Math.min(m,d);if(u>0&&(sa=o(5*(St.length+1)/60,1)),!0===(oe&&!Se))UAMpredBG=St[St.length-1]+o(-e.activity*(1800/(T*le*Math.log(Math.max(St[St.length-1],39)/ye+1)))*5,2)+Math.min(0,n)+u,console.log("Dynamic ISF (Logarithmic Formula) adjusted prediction for UAM: UAMpredBG: "+o(UAMpredBG,2));else UAMpredBG=St[St.length-1]+t+Math.min(0,n)+u;xt.length<48&&xt.push(oa),yt.length<48&&yt.push(COBpredBG),St.length<48&&St.push(UAMpredBG),Dt.length<48&&Dt.push(r),COBpredBG18&&oana&&(na=oa),(Ut||kt>0)&&yt.length>18&&COBpredBG0)&&COBpredBG>na&&(ia=COBpredBG),Tt&&St.length>12&&UAMpredBGna&&UAMpredBG}))}catch(e){console.error("Problem with iobArray. Optional feature Advanced Meal Assist disabled")}l.mealCOB&&(console.error("predCIs (mg/dL/5m):"+ma.join(" ")),console.error("remainingCIs: "+la.join(" "))),je.predBGs={},xt.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))}));for(var da=xt.length-1;da>12&&xt[da-1]===xt[da];da--)xt.pop();for(je.predBGs.IOB=xt,$t=o(xt[xt.length-1]),Dt.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),da=Dt.length-1;da>6&&!(Dt[da-1]>=Dt[da]||Dt[da]<=Je);da--)Dt.pop();if(je.predBGs.ZT=Dt,o(Dt[Dt.length-1]),l.mealCOB>0&&(Ct>0||kt>0)){for(yt.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),da=yt.length-1;da>12&&yt[da-1]===yt[da];da--)yt.pop();je.predBGs.COB=yt,Jt=o(yt[yt.length-1]),Mt=Math.max(Mt,o(yt[yt.length-1]))}if(Ct>0||kt>0){if(Tt){for(St.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),da=St.length-1;da>12&&St[da-1]===St[da];da--)St.pop();je.predBGs.UAM=St,Kt=o(St[St.length-1]),St[St.length-1]&&(Mt=Math.max(Mt,o(St[St.length-1])))}je.eventualBG=Mt}console.error("UAM Impact:"+Gt+"mg/dL per 5m; UAM Duration:"+sa+"hours"),Qt=Math.max(39,Qt),Vt=Math.max(39,Vt),Xt=Math.max(39,Xt),Ht=o(Qt);var ua=l.mealCOB/l.carbs;Zt=o(Xt<999&&Vt<999?(1-ua)*UAMpredBG+ua*COBpredBG:Vt<999?(oa+COBpredBG)/2:Xt<999?(oa+UAMpredBG)/2:oa),ra>Zt&&(Zt=ra),Yt=o(Yt=Ut||kt>0?Tt?ua*ea+(1-ua)*ta:ea:Tt?ta:aa);var ca=Xt;if(raXt&&(ca=(Xt+ra)/2);if(ca=o(ca),l.carbs)if(!Tt&&Vt<999)Ht=o(Math.max(Qt,Vt));else if(Vt<999){var ha=ua*Vt+(1-ua)*ca;Ht=o(Math.max(Qt,Vt,ha))}else Ht=Tt?ca:Yt;else Tt&&(Ht=o(Math.max(Qt,ca)));Ht=Math.min(Ht,Zt),process.stderr.write("minPredBG: "+Ht+" minIOBPredBG: "+Qt+" minZTGuardBG: "+ra),Vt<999&&process.stderr.write(" minCOBPredBG: "+Vt),Xt<999&&process.stderr.write(" minUAMPredBG: "+Xt),console.error(" avgPredBG:"+Zt+" COB/Carbs:"+l.mealCOB+"/"+l.carbs),ia>ze&&(Ht=Math.min(Ht,ia)),je.COB=l.mealCOB,je.IOB=a.iob,je.BGI=n(ft,i),je.deviation=n(Bt,i),je.ISF=n(ct,i),je.CR=o(j,1),je.target_bg=n(Je,i),je.TDD=o(te,2),je.current_target=o(Je,0);var pa=je.CR;Ge!=je.CR&&(pa=Ge+"→"+je.CR),je.reason=ut+", COB: "+je.COB+", Dev: "+je.deviation+", BGI: "+je.BGI+", CR: "+pa+", Target: "+ot+", minPredBG "+n(Ht,i)+", minGuardBG "+n(Yt,i)+", IOBpredBG "+n($t,i),Jt>0&&(je.reason+=", COBpredBG "+n(Jt,i)),Kt>0&&(je.reason+=", UAMpredBG "+n(Kt,i)),je.reason+=tddReason,je.reason+="; ";var va=bt;va<40&&(va=Math.min(Yt,va));var fa,Ba=mt-va,ba=240,Ma=240;if(l.mealCOB>0&&(Ct>0||kt>0)){for(da=0;dafa*ze&&(console.error("maxDelta "+n($e,i)+" > "+100*fa+"% of BG "+n(ze,i)+" - disabling SMB"),je.reason+="maxDelta "+n($e,i)+" > "+100*fa+"% of BG "+n(ze,i)+" - SMB disabled!, ",wt=!1),console.error("BG projected to remain above "+n(Ke,i)+" for "+ba+"minutes"),(Ma<240||ba<60)&&console.error("BG projected to remain above "+n(mt,i)+" for "+Ma+"minutes");var _a=Ma,ya=i.current_basal*A*ct*_a/60,xa=Math.max(0,l.mealCOB-.25*l.carbs),Sa=(Ba-ya)/csf-xa;ya=o(ya),Sa=o(Sa),console.error("naive_eventualBG:",bt,"bgUndershoot:",Ba,"zeroTempDuration:",_a,"zeroTempEffect:",ya,"carbsReq:",Sa),"Could not parse clock data"==l.reason?console.error("carbsReq unknown: Could not parse clock data"):Sa>=i.carbsReqThreshold&&Ma<=45&&(je.carbsReq=Sa,je.reason+=Sa+" add'l carbs req w/in "+Ma+"m; ");var Da=0;if(ze0&&He>_t)je.reason+="IOB "+a.iob+" < "+o(-i.current_basal*A*20/60,2),je.reason+=" and minDelta "+n(He,i)+" > expectedDelta "+n(_t,i)+"; ";else if(ze=55)return je.reason+="; Canceling temp at "+je.deliverAt.getMinutes()+"m past the hour. ",m.setTempBasal(0,0,i,je,t);var wa=0,Ta=Ee;if(Mt_t&&He>0&&!Sa)return bt<40?(je.reason+=", naive_eventualBG < 40. ",m.setTempBasal(0,30,i,je,t)):(e.delta>He?je.reason+=", but Delta "+n(We,i)+" > expectedDelta "+n(_t,i):je.reason+=", but Min. Delta "+He.toFixed(2)+" > Exp. Delta "+n(_t,i),t.duration>15&&r(Ee,i)===r(t.rate,i)?(je.reason+=", temp "+t.rate+" ~ req "+Ee+"U/hr. ",je):(je.reason+="; setting current basal of "+Ee+" as temp. ",m.setTempBasal(Ee,30,i,je,t)));wa=o(wa=2*Math.min(0,(Mt-Je)/ct),2);var Ca=Math.min(0,(bt-Je)/ct);if(Ca=o(Ca,2),He<0&&He>_t)wa=o(wa*(He/_t),2);if(Ta=r(Ta=Ee+2*wa,i),t.duration*(t.rate-Ee)/605&&Ta>=.8*t.rate)return je.reason+=", temp "+t.rate+" ~< req "+Ta+"U/hr. ",je;if(Ta<=0){if((Da=o(60*((Ba=Je-bt)/ct)/i.current_basal*A))<0?Da=0:(Da=30*o(Da/30),Da=Math.min(120,Math.max(0,Da))),Da>0)return je.reason+=", setting "+Da+"m zero temp. ",m.setTempBasal(Ta,Da,i,je,t)}else je.reason+=", setting "+Ta+"U/hr. ";return m.setTempBasal(Ta,30,i,je,t)}if(He<_t&&(!d||!wt))return e.delta "+n(Ke,i)+" but Delta "+n(We,i)+" < Exp. Delta "+n(_t,i):je.reason+="Eventual BG "+n(Mt,i)+" > "+n(Ke,i)+" but Min. Delta "+He.toFixed(2)+" < Exp. Delta "+n(_t,i),t.duration>15&&r(Ee,i)===r(t.rate,i)?(je.reason+=", temp "+t.rate+" ~ req "+Ee+"U/hr. ",je):(je.reason+="; setting current basal of "+Ee+" as temp. ",m.setTempBasal(Ee,30,i,je,t));if(Math.min(Mt,Ht)15&&r(Ee,i)===r(t.rate,i)?(je.reason+=", temp "+t.rate+" ~ req "+Ee+"U/hr. ",je):(je.reason+="; setting current basal of "+Ee+" as temp. ",m.setTempBasal(Ee,30,i,je,t));if(Mt>=Qe&&(je.reason+="Eventual BG "+n(Mt,i)+" >= "+n(Qe,i)+", "),a.iob>Xe)return je.reason+="IOB "+o(a.iob,2)+" > max_iob "+Xe,t.duration>15&&r(Ee,i)===r(t.rate,i)?(je.reason+=", temp "+t.rate+" ~ req "+Ee+"U/hr. ",je):(je.reason+="; setting current basal of "+Ee+" as temp. ",m.setTempBasal(Ee,30,i,je,t));(wa=o((Math.min(Ht,Mt)-Je)/ct,2))>Xe-a.iob?(console.error("SMB limited by maxIOB: "+Xe-a.iob+" (. insulinReq: "+wa+" U)"),je.reason+="max_iob "+Xe+", ",wa=Xe-a.iob):console.error("SMB not limited by maxIOB ( insulinReq: "+wa+" U)."),Ta=r(Ta=Ee+2*wa,i),wa=o(wa,3),je.insulinReq=wa;var Ua=o((new Date(qe).getTime()-a.lastBolusTime)/6e4,1);if(d&&wt&&ze>mt){var Ga=o(l.mealCOB/j,3),Oa=0;void 0===i.maxSMBBasalMinutes?(Oa=o(i.current_basal*A*30/60,1),console.error("profile.maxSMBBasalMinutes undefined: defaulting to 30m"),wa>Oa&&console.error("SMB limited by maxBolus: "+Oa+" ( "+wa+" U)")):a.iob>Ga&&a.iob>0?(console.error("IOB"+a.iob+"> COB"+l.mealCOB+"; mealInsulinReq ="+Ga),i.maxUAMSMBBasalMinutes?(console.error("profile.maxUAMSMBBasalMinutes: "+i.maxUAMSMBBasalMinutes+", profile.current_basal: "+i.current_basal*A),Oa=o(i.current_basal*A*i.maxUAMSMBBasalMinutes/60,1)):(console.error("profile.maxUAMSMBBasalMinutes undefined: defaulting to 30m"),Oa=o(i.current_basal*A*30/60,1)),wa>Oa?console.error("SMB limited by maxUAMSMBBasalMinutes [ "+i.maxUAMSMBBasalMinutes+"m ]: "+Oa+"U ( "+wa+"U )"):console.error("SMB is not limited by maxUAMSMBBasalMinutes. ( insulinReq: "+wa+"U )")):(console.error("profile.maxSMBBasalMinutes: "+i.maxSMBBasalMinutes+", profile.current_basal: "+i.current_basal*A),wa>(Oa=o(i.current_basal*i.maxSMBBasalMinutes/60,1))?console.error("SMB limited by maxSMBBasalMinutes: "+i.maxSMBBasalMinutes+"m ]: "+Oa+"U ( insulinReq: "+wa+"U )"):console.error("SMB is not limited by maxSMBBasalMinutes. ( insulinReq: "+wa+"U )"));var Ra=i.bolus_increment,Aa=1/Ra,Ia=i.smb_delivery_ratio;Ia>.5&&console.error("SMB Delivery Ratio increased from default 0.5 to "+o(Ia,2));var ja=Math.min(wa*Ia,Oa);ja=Math.floor(ja*Aa)/Aa,Da=o(60*((Je-(bt+Qt)/2)/ct)/i.current_basal*A),wa>0&&ja=30?(Da=30*o(Da/30),Da=Math.min(60,Math.max(0,Da))):(Fa=o(Ee*Da/30,2),Da=30),je.reason+=" insulinReq "+wa,ja>=Oa&&(je.reason+="; maxBolus "+Oa),Da>0&&(je.reason+="; setting "+Da+"m low temp of "+Fa+"U/h"),je.reason+=". ";var Pa=3;i.SMBInterval&&(Pa=Math.min(10,Math.max(1,i.SMBInterval)));var Ea=o(Pa-Ua,0),qa=o(60*(Pa-Ua),0)%60;if(console.error("naive_eventualBG "+bt+","+Da+"m "+Fa+"U/h temp needed; last bolus "+Ua+"m ago; maxBolus: "+Oa),Ua>Pa?ja>0&&(je.units=ja,je.reason+="Microbolusing "+ja+"U. "):je.reason+="Waiting "+Ea+"m "+qa+"s to microbolus again. ",Da>0)return je.rate=Fa,je.duration=Da,je}var Wa=m.getMaxSafeBasal(i);return Ta>Wa&&(je.reason+="adj. req. rate: "+Ta+" to maxSafeBasal: "+o(Wa,2)+", ",Ta=r(Wa,i)),t.duration*(t.rate-Ee)/60>=2*wa?(je.reason+=t.duration+"m@"+t.rate.toFixed(2)+" > 2 * insulinReq. Setting temp basal of "+Ta+"U/hr. ",m.setTempBasal(Ta,30,i,je,t)):void 0===t.duration||0===t.duration?(je.reason+="no temp, setting "+Ta+"U/hr. ",m.setTempBasal(Ta,30,i,je,t)):t.duration>5&&r(Ta,i)<=r(t.rate,i)?(je.reason+="temp "+t.rate+" >~ req "+Ta+"U/hr. ",je):(je.reason+="temp "+t.rate+"<"+Ta+"U/hr. ",m.setTempBasal(Ta,30,i,je,t))}},6880:(e,t,a)=>{var r=a(6654);e.exports=function(e,t){var a=20;void 0!==t&&"string"==typeof t.model&&(r(t.model,"54")||r(t.model,"23"))&&(a=40);return e<1?Math.round(e*a)/a:e<10?Math.round(20*e)/20:Math.round(10*e)/10}},2705:(e,t,a)=>{var r=a(5639).Symbol;e.exports=r},9932:e=>{e.exports=function(e,t){for(var a=-1,r=null==e?0:e.length,o=Array(r);++a{e.exports=function(e,t,a){return e==e&&(void 0!==a&&(e=e<=a?e:a),void 0!==t&&(e=e>=t?e:t)),e}},4239:(e,t,a)=>{var r=a(2705),o=a(9607),n=a(2333),i=r?r.toStringTag:void 0;e.exports=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":i&&i in Object(e)?o(e):n(e)}},531:(e,t,a)=>{var r=a(2705),o=a(9932),n=a(1469),i=a(3448),s=r?r.prototype:void 0,l=s?s.toString:void 0;e.exports=function e(t){if("string"==typeof t)return t;if(n(t))return o(t,e)+"";if(i(t))return l?l.call(t):"";var a=t+"";return"0"==a&&1/t==-Infinity?"-0":a}},7561:(e,t,a)=>{var r=a(7990),o=/^\s+/;e.exports=function(e){return e?e.slice(0,r(e)+1).replace(o,""):e}},1957:(e,t,a)=>{var r="object"==typeof a.g&&a.g&&a.g.Object===Object&&a.g;e.exports=r},9607:(e,t,a)=>{var r=a(2705),o=Object.prototype,n=o.hasOwnProperty,i=o.toString,s=r?r.toStringTag:void 0;e.exports=function(e){var t=n.call(e,s),a=e[s];try{e[s]=void 0;var r=!0}catch(e){}var o=i.call(e);return r&&(t?e[s]=a:delete e[s]),o}},2333:e=>{var t=Object.prototype.toString;e.exports=function(e){return t.call(e)}},5639:(e,t,a)=>{var r=a(1957),o="object"==typeof self&&self&&self.Object===Object&&self,n=r||o||Function("return this")();e.exports=n},7990:e=>{var t=/\s/;e.exports=function(e){for(var a=e.length;a--&&t.test(e.charAt(a)););return a}},6654:(e,t,a)=>{var r=a(9750),o=a(531),n=a(554),i=a(9833);e.exports=function(e,t,a){e=i(e),t=o(t);var s=e.length,l=a=void 0===a?s:r(n(a),0,s);return(a-=t.length)>=0&&e.slice(a,l)==t}},1469:e=>{var t=Array.isArray;e.exports=t},3218:e=>{e.exports=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}},7005:e=>{e.exports=function(e){return null!=e&&"object"==typeof e}},3448:(e,t,a)=>{var r=a(4239),o=a(7005);e.exports=function(e){return"symbol"==typeof e||o(e)&&"[object Symbol]"==r(e)}},8601:(e,t,a)=>{var r=a(4841),o=1/0;e.exports=function(e){return e?(e=r(e))===o||e===-1/0?17976931348623157e292*(e<0?-1:1):e==e?e:0:0===e?e:0}},554:(e,t,a)=>{var r=a(8601);e.exports=function(e){var t=r(e),a=t%1;return t==t?a?t-a:t:0}},4841:(e,t,a)=>{var r=a(7561),o=a(3218),n=a(3448),i=/^[-+]0x[0-9a-f]+$/i,s=/^0b[01]+$/i,l=/^0o[0-7]+$/i,m=parseInt;e.exports=function(e){if("number"==typeof e)return e;if(n(e))return NaN;if(o(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=o(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=r(e);var a=s.test(e);return a||l.test(e)?m(e.slice(2),a?2:8):i.test(e)?NaN:+e}},9833:(e,t,a)=>{var r=a(531);e.exports=function(e){return null==e?"":r(e)}}},t={};function a(r){var o=t[r];if(void 0!==o)return o.exports;var n=t[r]={exports:{}};return e[r](n,n.exports,a),n.exports}a.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}();var r=a(5546);freeaps_determineBasal=r})(); \ No newline at end of file +var freeaps_determineBasal;(()=>{var e={5546:(e,t,a)=>{var r=a(6880);function o(e,t){t||(t=0);var a=Math.pow(10,t);return Math.round(e*a)/a}function n(e,t){return"mmol/L"===t.out_units?o(.0555*e,1):Math.round(e)}e.exports=function(e,t,a,i,s,l,m,d,u,c,g,h,p,v){var f=i.min_bg,b=v.overrideTarget;const B=v.smbIsOff,M=v.advancedSettings,_=v.isfAndCr,y=v.isf,x=v.cr,S=v.smbIsAlwaysOff,w=v.start,D=v.end,T=v.smbMinutes,C=v.uamMinutes;var U=0,G="",O="",R="",A="",I="",j=0,F=0,P=0,E=0,q=0,W=0;const k=v.weightedAverage;var L=1,z=i.sens,N=i.carb_ratio;v.useOverride&&(L=v.overridePercentage/100,_?(z/=L,N/=L):(x&&(N/=L),y&&(z/=L)));const H=i.weightPercentage,Z=v.average_total_data;function $(e,t){var a=e.getTime();return new Date(a+36e5*t)}function J(e){var t=i.bolus_increment;.025!=t&&(t=.05);var a=e/t;return a>=1?o(Math.floor(a)*t,5):0}function K(e){function t(e){return e<10&&(e="0"+e),e}return t(e.getHours())+":"+t(e.getMinutes())+":00"}function Q(e,t){var a=new Date("1/1/1999 "+e),r=new Date("1/1/1999 "+t);return(a.getTime()-r.getTime())/36e5}function V(e,t){var a=0,r=t,o=(e-t)/36e5,n=0,i=o,s=0;do{if(o>0){var l=K(r),m=p[0].rate;for(let e=0;e=(s=Q(p[e+1].start,p[e].start))?n=s:o=s?n=s:od)if(e+1=(s=Q(u,l))?n=s:o=(s=Q("23:59:59",l))?n=s:o0&&o21)q=V(X,(ee=24-U,te=X.getTime(),new Date(te-36e5*ee))),A="24 hours of data is required for an accurate tdd calculation. Currently only "+U.toPrecision(3)+" hours of pump history data are available. Using your pump scheduled basals to fill in the missing hours. Scheduled basals added: "+q.toPrecision(5)+" U. ";else U<21?(ge=!1,enableDynamicCR=!1):A=""}else console.log("Pumphistory is empty!"),ge=!1,enableDynamicCR=!1;var ee,te;for(let e=0;e0){j=e,W=g[e].rate;var ae=g[e-1]["duration (min)"]/60,re=ae,oe=new Date(g[e-1].timestamp),ne=oe,ie=0;do{if(e--,0==e){ne=new Date;break}if("TempBasal"==g[e]._type||"PumpSuspend"==g[e]._type){ne=new Date(g[e].timestamp);break}var se=e-2;if(se>=0&&"Rewind"==g[se]._type){let e=g[se].timestamp;for(;se-1>=0&&"Prime"==g[se-=1]._type;)ie=(g[se].timestamp-e)/36e5;ie>=ae&&(ne=e,ie=0)}}while(e>0);var le=(ne-oe)/36e5;le0&&(--r,"TempBasal"==g[r]._type)){a=new Date(g[r].timestamp);break}}while(r>0);(a-t)/36e5>0&&(q+=V(a,t))}for(let e=g.length-1;e>0;e--)if("TempBasalDuration"==g[e]._type){let t=g[e]["duration (min)"]/60,a=new Date(g[e].timestamp);var me=a;let r=e;do{if(--r,r>=0&&("TempBasal"==g[r]._type||"PumpSuspend"==g[r]._type)){me=new Date(g[r].timestamp);break}}while(r>0);if(0==e&&"TempBasalDuration"==g[0]._type&&(me=new Date,t=g[e]["duration (min)"]/60),(me-a)/36e5-t>0){q+=V(me,$(a,t))}}var de,ue={TDD:o(F=E+P+q,5),bolus:o(E,5),temp_basal:o(P,5),scheduled_basal:o(q,5)};U>21?(O=". Bolus insulin: "+E.toPrecision(5)+" U",R=". Temporary basal insulin: "+P.toPrecision(5)+" U",G=". Insulin with scheduled basal rate: "+q.toPrecision(5)+" U",I=A+(" TDD past 24h is: "+F.toPrecision(5)+" U")+O+R+G,tddReason=", Total insulin: "+o(F,2)+" U, "+o(E/F*100,0)+"% Bolus "+o((P+q)/F*100,0)+"% Basal"):tddReason=", TDD: Not enough pumpData (< 21h)";const ce=e.glucose;var ge=h.useNewFormula;const he=h.enableDynamicCR,pe=Math.min(i.autosens_min,i.autosens_max),ve=Math.max(i.autosens_min,i.autosens_max);(ve==pe||ve<1||pe>1)&&(ge=!1,console.log("Dynamic ISF disabled due to current autosens settings"));const fe=h.adjustmentFactor,be=i.min_bg;var Be=!1,Me="",_e=1,ye="";Z>0&&(_e=k/Z),ye=_e>1?"Basal adjustment with a 24 hour to total average (up to 14 days of data) TDD ratio (limited by Autosens max setting). Basal Ratio: "+(_e=o(_e=Math.min(_e,i.autosens_max),2))+". Upper limit = Autosens max ("+i.autosens_max+")":_e<1?"Basal adjustment with a 24 hour to to total average (up to 14 days of data) TDD ratio (limited by Autosens min setting). Basal Ratio: "+(_e=o(_e=Math.max(_e,i.autosens_min),2))+". Lower limit = Autosens min ("+i.autosens_min+")":"Basal adjusted with a 24 hour to total average (up to 14 days of data) TDD ratio: "+_e,ye=", Basal ratio: "+_e,(i.high_temptarget_raises_sensitivity||i.exercise_mode||v.isEnabled)&&(Be=!0),be>=118&&Be&&(ge=!1,Me="Dynamic ISF temporarily off due to a high temp target/exercising. Current min target: "+be);var xe=", Dynamic ratios log: ",Se=", AF: "+fe,we="BG: "+ce+" mg/dl ("+(.0555*ce).toPrecision(2)+" mmol/l)",De="",Te="";const Ce=h.curve,Ue=h.insulinPeakTime,Ge=h.useCustomPeakTime;var Oe=55,Re=65;switch(Ce){case"rapid-acting":Re=65;break;case"ultra-rapid":Re=50}Ge?(Oe=120-Ue,console.log("Custom insulinpeakTime set to :"+Ue+", insulinFactor: "+Oe)):(Oe=120-Re,console.log("insulinFactor set to : "+Oe)),de=F,H<1&&k>0&&(F=k,console.log("Using weighted TDD average: "+o(F,2)+" U, instead of past 24 h ("+o(de,2)+" U), weight: "+H),Te=", Weighted TDD: "+o(F,2)+" U");const Ae=h.sigmoid;var Ie="";if(ge){var je=z*fe*F*Math.log(ce/Oe+1)/1800;De=", Logarithmic formula"}if(ge&&Ae){const e=pe,t=ve-e,a=.0555*(ce-i.min_bg);var Fe=_e,Pe=ve-1;1==ve&&(Pe=ve+.01-1);const r=Math.log10(1/Pe-e/Pe)/Math.log10(Math.E),o=a*fe*Fe+r;je=t/(1+Math.exp(-o))+e,De=", Sigmoid function"}var Ee=N;const qe=o(N,1);var We="",ke="";if(ge&&F>0){if(We=", Dynamic ISF/CR: On/",je>ve?(Me=", Dynamic ISF limited by autosens_max setting: "+ve+" ("+o(je,2)+"), ",ke=", Autosens/Dynamic Limit: "+ve+" ("+o(je,2)+")",je=ve):je1&&(Le=(je-1)/2+1);var ze=" CR: "+(Ee=o(Ee/Le,2))+" g/U";N=Ee}else ze=" CR: "+Ee+" g/U",We+="Off";const e=z/je;s.ratio=je,Ie=". Using Sigmoid function, the autosens ratio has been adjusted with sigmoid factor to: "+o(s.ratio,2)+". New ISF = "+o(e,2)+" mg/dl ("+o(.0555*e,2)+" (mmol/l). CR adjusted from "+o(qe,2)+" to "+o(Ee,2),Me+=Ae?Ie:", Dynamic autosens.ratio set to "+o(je,2)+" with ISF: "+e.toPrecision(3)+" mg/dl/U ("+(.0555*e).toPrecision(3)+" mmol/l/U)",I+=xe+we+Se+De+Me+We+ze+Te}else I+=xe+"Dynamic Settings disabled";console.log(I),ge||he?ge&&i.tddAdjBasal?tddReason+=We+De+ke+Se+ye:ge&&!i.tddAdjBasal&&(tddReason+=We+De+ke+Se):tddReason+="";var Ne={},He=new Date;if(c&&(He=c),void 0===i||void 0===i.current_basal)return Ne.error="Error: could not get current basal rate",Ne;var Ze=r(i.current_basal,i)*L,$e=Ze;v.useOverride&&(0==v.duration?console.log("Profile Override is active. Override "+o(100*L,0)+"%. Override Duration: Enabled indefinitely"):console.log("Profile Override is active. Override "+o(100*L,0)+"%. Override Expires in: "+v.duration+" min."));var Je=new Date;c&&(Je=c);var Ke,Qe=new Date(e.date),Ve=o((Je-Qe)/60/1e3,1),Xe=e.glucose,Ye=e.noise;Ke=e.delta>-.5?"+"+o(e.delta,0):o(e.delta,0);var et=Math.min(e.delta,e.short_avgdelta),tt=Math.min(e.short_avgdelta,e.long_avgdelta),at=Math.max(e.delta,e.short_avgdelta,e.long_avgdelta);(Xe<=10||38===Xe||Ye>=3)&&(Ne.reason="CGM is calibrating, in ??? state, or noise is high");if(Xe>60&&0==e.delta&&e.short_avgdelta>-1&&e.short_avgdelta<1&&e.long_avgdelta>-1&&e.long_avgdelta<1&&("fakecgm"==e.device?(console.error("CGM data is unchanged ("+n(Xe,i)+"+"+n(e.delta,i)+") for 5m w/ "+n(e.short_avgdelta,i)+" mg/dL ~15m change & "+n(e.long_avgdelta,2)+" mg/dL ~45m change"),console.error("Simulator mode detected ("+e.device+"): continuing anyway")):!0),Ve>12||Ve<-5?Ne.reason="If current system time "+Je+" is correct, then BG data is too old. The last BG data was read "+Ve+"m ago at "+Qe:0===e.short_avgdelta&&0===e.long_avgdelta&&(e.last_cal&&e.last_cal<3?Ne.reason="CGM was just calibrated":Ne.reason="CGM data is unchanged ("+n(Xe,i)+"+"+n(e.delta,i)+") for 5m w/ "+n(e.short_avgdelta,i)+" mg/dL ~15m change & "+n(e.long_avgdelta,i)+" mg/dL ~45m change"),Xe<=10||38===Xe||Ye>=3||Ve>12||Ve<-5||0===e.short_avgdelta&&0===e.long_avgdelta)return t.rate>=$e?(Ne.reason+=". Canceling high temp basal of "+t.rate,Ne.deliverAt=He,Ne.temp="absolute",Ne.duration=0,Ne.rate=0,Ne):0===t.rate&&t.duration>30?(Ne.reason+=". Shortening "+t.duration+"m long zero temp to 30m. ",Ne.deliverAt=He,Ne.temp="absolute",Ne.duration=30,Ne.rate=0,Ne):(Ne.reason+=". Temp "+t.rate+" <= current basal "+$e+"U/hr; doing nothing. ",Ne);var rt,ot,nt,it,st=i.max_iob;if(void 0!==i.min_bg&&(ot=i.min_bg),void 0!==i.max_bg&&(nt=i.max_bg),void 0!==i.enableSMB_high_bg_target&&(it=i.enableSMB_high_bg_target),void 0===i.min_bg||void 0===i.max_bg)return Ne.error="Error: could not determine target_bg. ",Ne;rt=(i.min_bg+i.max_bg)/2;var lt=i.exercise_mode||i.high_temptarget_raises_sensitivity||v.isEnabled,mt=100,dt=160;if(dt=i.half_basal_exercise_target,v.isEnabled){const e=v.hbt;console.log("Half Basal Target used: "+n(e,i)+" "+i.out_units),dt=e}else console.log("Default Half Basal Target used: "+n(dt,i)+" "+i.out_units);if(lt&&i.temptargetSet&&rt>mt||i.low_temptarget_lowers_sensitivity&&i.temptargetSet&&rt=rt&&sensitivityRatio0&&(process.stderr.write("TDD-adjustment of basals activated, using tdd24h_14d_Ratio "+o(_e,2)+", TDD 24h = "+o(de,2)+"U, Weighted average TDD = "+o(k,2)+"U, (Weight percentage = "+H+"), Total data of TDDs (up to 14 days) average = "+o(Z,2)+"U. "),$e!==Ze*L?process.stderr.write("Adjusting basal from "+Ze*L+" U/h to "+$e+" U/h; "):process.stderr.write("Basal unchanged: "+$e+" U/h; "))),i.temptargetSet);else if(void 0!==s&&s&&(i.sensitivity_raises_target&&s.ratio<1||i.resistance_lowers_target&&s.ratio>1)){ot=o((ot-60)/s.ratio)+60,nt=o((nt-60)/s.ratio)+60;var ct=o((rt-60)/s.ratio)+60;rt===(ct=Math.max(80,ct))?process.stderr.write("target_bg unchanged: "+n(ct,i)+"; "):process.stderr.write("target_bg from "+n(ct,i)+" to "+n(ct,i)+"; "),rt=ct}var gt=n(rt,i);rt!=f&&(gt=0!==b&&b!==rt?n(f,i)+"→"+n(b,i)+"→"+n(rt,i):n(f,i)+"→"+n(rt,i));var ht=200,pt=200,vt=200;if(e.noise>=2){var ft=Math.max(1.1,i.noisyCGMTargetMultiplier);Math.min(250,i.maxRaw);ht=o(Math.min(200,ot*ft)),pt=o(Math.min(200,rt*ft)),vt=o(Math.min(200,nt*ft)),process.stderr.write("Raising target_bg for noisy / raw CGM data, from "+n(ct,i)+" to "+n(pt,i)+"; "),ot=ht,rt=pt,nt=vt}var bt=ot-.5*(ot-40),Bt=i.threshold_setting;Bt>bt&&Bt<=120&&Bt>=65?(console.error("Threshold changed in settings from "+n(bt,i)+" to "+n(Bt,i)+". "),bt=Bt):console.error("Current threshold: "+n(bt,i));var Mt="",_t=(o(z,1),z);if(void 0!==s&&s&&((_t=o(_t=z/sensitivityRatio,1))!==z?process.stderr.write("ISF from "+n(z,i)+" to "+n(_t,i)):process.stderr.write("ISF unchanged: "+n(_t,i)),Mt+="Autosens ratio: "+o(sensitivityRatio,2)+", ISF: "+n(z,i)+"→"+n(_t,i)),console.error("CR:"+N),void 0===a)return Ne.error="Error: iob_data undefined. ",Ne;var yt,xt=a;if(a.length,a.length>1&&(a=xt[0]),void 0===a.activity||void 0===a.iob)return Ne.error="Error: iob_data missing some property. ",Ne;var St=((yt=void 0!==a.lastTemp?o((new Date(Je).getTime()-a.lastTemp.date)/6e4):0)+t.duration)%30;if(console.error("currenttemp:"+t.rate+" lastTempAge:"+yt+"m, tempModulus:"+St+"m"),Ne.temp="absolute",Ne.deliverAt=He,d&&t&&a.lastTemp&&t.rate!==a.lastTemp.rate&&yt>10&&t.duration)return Ne.reason="Warning: currenttemp rate "+t.rate+" != lastTemp rate "+a.lastTemp.rate+" from pumphistory; canceling temp",m.setTempBasal(0,0,i,Ne,t);if(t&&a.lastTemp&&t.duration>0){var wt=yt-a.lastTemp.duration;if(wt>5&&yt>10)return Ne.reason="Warning: currenttemp running but lastTemp from pumphistory ended "+wt+"m ago; canceling temp",m.setTempBasal(0,0,i,Ne,t)}var Dt=o(-a.activity*_t*5,2),Tt=o(6*(et-Dt));Tt<0&&(Tt=o(6*(tt-Dt)))<0&&(Tt=o(6*(e.long_avgdelta-Dt)));var Ct=Xe,Ut=(Ct=a.iob>0?o(Xe-a.iob*_t):o(Xe-a.iob*Math.min(_t,z)))+Tt;if(void 0===Ut||isNaN(Ut))return Ne.error="Error: could not calculate eventualBG. Sensitivity: "+_t+" Deviation: "+Tt,Ne;var Gt=function(e,t,a){return o(a+(e-t)/24,1)}(rt,Ut,Dt);Ne={temp:"absolute",bg:Xe,tick:Ke,eventualBG:Ut,insulinReq:0,reservoir:u,deliverAt:He,sensitivityRatio,TDD:de,insulin:ue,current_target:rt};var Ot=[],Rt=[],At=[],It=[];Ot.push(Xe),Rt.push(Xe),It.push(Xe),At.push(Xe);var jt=function(e,t,a,r,o,i){return t?!e.allowSMB_with_high_temptarget&&e.temptargetSet&&o>100?(console.error("SMB disabled due to high temptarget of "+o),!1):!0===a.bwFound&&!1===e.A52_risk_enable?(console.error("SMB disabled due to Bolus Wizard activity in the last 6 hours."),!1):!0===e.enableSMB_always?(a.bwFound?console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled due to enableSMB_always"),!0):!0===e.enableSMB_with_COB&&a.mealCOB?(a.bwCarbs?console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for COB of "+a.mealCOB),!0):!0===e.enableSMB_after_carbs&&a.carbs?(a.bwCarbs?console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for 6h after carb entry"),!0):!0===e.enableSMB_with_temptarget&&e.temptargetSet&&o<100?(a.bwFound?console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for temptarget of "+n(o,e)),!0):!0===e.enableSMB_high_bg&&null!==i&&r>=i?(console.error("Checking BG to see if High for SMB enablement."),console.error("Current BG",r," | High BG ",i),a.bwFound?console.error("Warning: High BG SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("High BG detected. Enabling SMB."),!0):(console.error("SMB disabled (no enableSMB preferences active or no condition satisfied)"),!1):(console.error("SMB disabled (!microBolusAllowed)"),!1)}(i,d,l,Xe,rt,it);if(B)if(S){let e=c.getHours();e>=w&&e<=D&&(console.error("SMB disabled by schedule (a Profile is active with SMBs disabled)"),jt=!1)}else console.error("SMBs are disabled (a Profile is active with SMBs disabled)"),jt=!1;var Ft=i.enableUAM,Pt=0,Et=0;Pt=o(et-Dt,1);var qt=o(et-Dt,1);csf=_t/N,console.error("profile.sens:"+n(z,i)+", sens:"+n(_t,i)+", CSF:"+o(csf,1));var Wt=o(30*csf*5/60,1);Pt>Wt&&(console.error("Limiting carb impact from "+Pt+" to "+Wt+"mg/dL/5m (30g/h)"),Pt=Wt);var kt=3;sensitivityRatio&&(kt/=sensitivityRatio);var Lt=kt;if(l.carbs){kt=Math.max(kt,l.mealCOB/20);var zt=o((new Date(Je).getTime()-l.lastCarbTime)/6e4),Nt=(l.carbs-l.mealCOB)/l.carbs;Lt=o(Lt=kt+1.5*zt/60,1),console.error("Last carbs "+zt+" minutes ago; remainingCATime:"+Lt+"hours; "+o(100*Nt,1)+"% carbs absorbed")}var Ht=Math.max(0,Pt/5*60*Lt/2)/csf,Zt=90,$t=1;i.remainingCarbsCap&&(Zt=Math.min(90,i.remainingCarbsCap)),i.remainingCarbsFraction&&($t=Math.min(1,i.remainingCarbsFraction));var Jt=1-$t,Kt=Math.max(0,l.mealCOB-Ht-l.carbs*Jt),Qt=(Kt=Math.min(Zt,Kt))*csf*5/60/(Lt/2),Vt=o(l.slopeFromMaxDeviation,2),Xt=o(l.slopeFromMinDeviation,2),Yt=Math.min(Vt,-Xt/3);Et=0===Pt?0:Math.min(60*Lt/5/2,Math.max(0,l.mealCOB*csf/Pt)),console.error("Carb Impact:"+Pt+"mg/dL per 5m; CI Duration:"+o(5*Et/60*2,1)+"hours; remaining CI ("+Lt/2+"h peak):"+o(Qt,1)+"mg/dL per 5m");var ea,ta,aa,ra,oa,na=999,ia=999,sa=999,la=Xe,ma=999,da=999,ua=999,ca=999,ga=Ut,ha=Xe,pa=Xe,va=0,fa=[],ba=[];try{xt.forEach((function(e){var t=o(-e.activity*_t*5,2),a=o(-e.iobWithZeroTemp.activity*_t*5,2),r=Ct,n=Pt*(1-Math.min(1,Rt.length/12));if(!0===(ge&&!Ae))ga=Rt[Rt.length-1]+o(-e.activity*(1800/(F*fe*Math.log(Math.max(Rt[Rt.length-1],39)/Oe+1)))*5,2)+n,r=It[It.length-1]+o(-e.iobWithZeroTemp.activity*(1800/(F*fe*Math.log(Math.max(It[It.length-1],39)/Oe+1)))*5,2),console.log("Dynamic ISF (Logarithmic Formula) )adjusted predictions for IOB and ZT: IOBpredBG: "+o(ga,2)+" , ZTpredBG: "+o(r,2));else ga=Rt[Rt.length-1]+t+n,r=It[It.length-1]+a;var i=Math.max(0,Math.max(0,Pt)*(1-Ot.length/Math.max(2*Et,1))),s=Math.min(Ot.length,12*Lt-Ot.length),l=Math.max(0,s/(Lt/2*12)*Qt);i+l,fa.push(o(l,0)),ba.push(o(i,0)),COBpredBG=Ot[Ot.length-1]+t+Math.min(0,n)+i+l;var m=Math.max(0,qt+At.length*Yt),d=Math.max(0,qt*(1-At.length/Math.max(36,1))),u=Math.min(m,d);if(u>0&&(va=o(5*(At.length+1)/60,1)),!0===(ge&&!Ae))UAMpredBG=At[At.length-1]+o(-e.activity*(1800/(F*fe*Math.log(Math.max(At[At.length-1],39)/Oe+1)))*5,2)+Math.min(0,n)+u,console.log("Dynamic ISF (Logarithmic Formula) adjusted prediction for UAM: UAMpredBG: "+o(UAMpredBG,2));else UAMpredBG=At[At.length-1]+t+Math.min(0,n)+u;Rt.length<48&&Rt.push(ga),Ot.length<48&&Ot.push(COBpredBG),At.length<48&&At.push(UAMpredBG),It.length<48&&It.push(r),COBpredBG18&&gaha&&(ha=ga),(Et||Qt>0)&&Ot.length>18&&COBpredBG0)&&COBpredBG>ha&&(pa=COBpredBG),Ft&&At.length>12&&UAMpredBGha&&UAMpredBG}))}catch(e){console.error("Problem with iobArray. Optional feature Advanced Meal Assist disabled")}l.mealCOB&&(console.error("predCIs (mg/dL/5m):"+ba.join(" ")),console.error("remainingCIs: "+fa.join(" "))),Ne.predBGs={},Rt.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))}));for(var Ba=Rt.length-1;Ba>12&&Rt[Ba-1]===Rt[Ba];Ba--)Rt.pop();for(Ne.predBGs.IOB=Rt,aa=o(Rt[Rt.length-1]),It.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),Ba=It.length-1;Ba>6&&!(It[Ba-1]>=It[Ba]||It[Ba]<=rt);Ba--)It.pop();if(Ne.predBGs.ZT=It,o(It[It.length-1]),l.mealCOB>0&&(Pt>0||Qt>0)){for(Ot.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),Ba=Ot.length-1;Ba>12&&Ot[Ba-1]===Ot[Ba];Ba--)Ot.pop();Ne.predBGs.COB=Ot,ra=o(Ot[Ot.length-1]),Ut=Math.max(Ut,o(Ot[Ot.length-1]))}if(Pt>0||Qt>0){if(Ft){for(At.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),Ba=At.length-1;Ba>12&&At[Ba-1]===At[Ba];Ba--)At.pop();Ne.predBGs.UAM=At,oa=o(At[At.length-1]),At[At.length-1]&&(Ut=Math.max(Ut,o(At[At.length-1])))}Ne.eventualBG=Ut}console.error("UAM Impact:"+qt+"mg/dL per 5m; UAM Duration:"+va+"hours"),na=Math.max(39,na),ia=Math.max(39,ia),sa=Math.max(39,sa),ea=o(na);var Ma=l.mealCOB/l.carbs;ta=o(sa<999&&ia<999?(1-Ma)*UAMpredBG+Ma*COBpredBG:ia<999?(ga+COBpredBG)/2:sa<999?(ga+UAMpredBG)/2:ga),ca>ta&&(ta=ca),la=o(la=Et||Qt>0?Ft?Ma*ma+(1-Ma)*da:ma:Ft?da:ua);var _a=sa;if(casa&&(_a=(sa+ca)/2);if(_a=o(_a),l.carbs)if(!Ft&&ia<999)ea=o(Math.max(na,ia));else if(ia<999){var xa=Ma*ia+(1-Ma)*_a;ea=o(Math.max(na,ia,xa))}else ea=Ft?_a:la;else Ft&&(ea=o(Math.max(na,_a)));ea=Math.min(ea,ta),process.stderr.write("minPredBG: "+ea+" minIOBPredBG: "+na+" minZTGuardBG: "+ca),ia<999&&process.stderr.write(" minCOBPredBG: "+ia),sa<999&&process.stderr.write(" minUAMPredBG: "+sa),console.error(" avgPredBG:"+ta+" COB/Carbs:"+l.mealCOB+"/"+l.carbs),pa>Xe&&(ea=Math.min(ea,pa)),Ne.COB=l.mealCOB,Ne.IOB=a.iob,Ne.BGI=n(Dt,i),Ne.deviation=n(Tt,i),Ne.ISF=n(_t,i),Ne.CR=o(N,1),Ne.target_bg=n(rt,i),Ne.TDD=o(de,2),Ne.current_target=o(rt,0);var Sa=Ne.CR;qe!=Ne.CR&&(Sa=qe+"→"+Ne.CR),Ne.reason=Mt+", COB: "+Ne.COB+", Dev: "+Ne.deviation+", BGI: "+Ne.BGI+", CR: "+Sa+", Target: "+gt+", minPredBG "+n(ea,i)+", minGuardBG "+n(la,i)+", IOBpredBG "+n(aa,i),ra>0&&(Ne.reason+=", COBpredBG "+n(ra,i)),oa>0&&(Ne.reason+=", UAMpredBG "+n(oa,i)),Ne.reason+=tddReason,Ne.reason+="; ";var wa=Ct;wa<40&&(wa=Math.min(la,wa));var Da,Ta=bt-wa,Ca=240,Ua=240;if(l.mealCOB>0&&(Pt>0||Qt>0)){for(Ba=0;BaDa*Xe&&(console.error("maxDelta "+n(at,i)+" > "+100*Da+"% of BG "+n(Xe,i)+" - disabling SMB"),Ne.reason+="maxDelta "+n(at,i)+" > "+100*Da+"% of BG "+n(Xe,i)+" - SMB disabled!, ",jt=!1),console.error("BG projected to remain above "+n(ot,i)+" for "+Ca+"minutes"),(Ua<240||Ca<60)&&console.error("BG projected to remain above "+n(bt,i)+" for "+Ua+"minutes");var Ga=Ua,Oa=i.current_basal*L*_t*Ga/60,Ra=Math.max(0,l.mealCOB-.25*l.carbs),Aa=(Ta-Oa)/csf-Ra;Oa=o(Oa),Aa=o(Aa),console.error("naive_eventualBG:",Ct,"bgUndershoot:",Ta,"zeroTempDuration:",Ga,"zeroTempEffect:",Oa,"carbsReq:",Aa),"Could not parse clock data"==l.reason?console.error("carbsReq unknown: Could not parse clock data"):Aa>=i.carbsReqThreshold&&Ua<=45&&(Ne.carbsReq=Aa,Ne.reason+=Aa+" add'l carbs req w/in "+Ua+"m; ");var Ia=0;if(Xe0&&et>Gt)Ne.reason+="IOB "+a.iob+" < "+o(-i.current_basal*L*20/60,2),Ne.reason+=" and minDelta "+n(et,i)+" > expectedDelta "+n(Gt,i)+"; ";else if(Xe=55)return Ne.reason+="; Canceling temp at "+Ne.deliverAt.getMinutes()+"m past the hour. ",m.setTempBasal(0,0,i,Ne,t);var ja=0,Fa=$e;if(UtGt&&et>0&&!Aa)return Ct<40?(Ne.reason+=", naive_eventualBG < 40. ",m.setTempBasal(0,30,i,Ne,t)):(e.delta>et?Ne.reason+=", but Delta "+n(Ke,i)+" > expectedDelta "+n(Gt,i):Ne.reason+=", but Min. Delta "+et.toFixed(2)+" > Exp. Delta "+n(Gt,i),t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",m.setTempBasal($e,30,i,Ne,t)));ja=o(ja=2*Math.min(0,(Ut-rt)/_t),2);var Pa=Math.min(0,(Ct-rt)/_t);if(Pa=o(Pa,2),et<0&&et>Gt)ja=o(ja*(et/Gt),2);if(Fa=r(Fa=$e+2*ja,i),t.duration*(t.rate-$e)/605&&Fa>=.8*t.rate)return Ne.reason+=", temp "+t.rate+" ~< req "+Fa+"U/hr. ",Ne;if(Fa<=0){if((Ia=o(60*((Ta=rt-Ct)/_t)/i.current_basal*L))<0?Ia=0:(Ia=30*o(Ia/30),Ia=Math.min(120,Math.max(0,Ia))),Ia>0)return Ne.reason+=", setting "+Ia+"m zero temp. ",m.setTempBasal(Fa,Ia,i,Ne,t)}else Ne.reason+=", setting "+Fa+"U/hr. ";return m.setTempBasal(Fa,30,i,Ne,t)}if(et "+n(ot,i)+" but Delta "+n(Ke,i)+" < Exp. Delta "+n(Gt,i):Ne.reason+="Eventual BG "+n(Ut,i)+" > "+n(ot,i)+" but Min. Delta "+et.toFixed(2)+" < Exp. Delta "+n(Gt,i),t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",m.setTempBasal($e,30,i,Ne,t));if(Math.min(Ut,ea)15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",m.setTempBasal($e,30,i,Ne,t));if(Ut>=nt&&(Ne.reason+="Eventual BG "+n(Ut,i)+" >= "+n(nt,i)+", "),a.iob>st)return Ne.reason+="IOB "+o(a.iob,2)+" > max_iob "+st,t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",m.setTempBasal($e,30,i,Ne,t));(ja=o((Math.min(ea,Ut)-rt)/_t,2))>st-a.iob?(console.error("SMB limited by maxIOB: "+st-a.iob+" (. insulinReq: "+ja+" U)"),Ne.reason+="max_iob "+st+", ",ja=st-a.iob):console.error("SMB not limited by maxIOB ( insulinReq: "+ja+" U)."),Fa=r(Fa=$e+2*ja,i),ja=o(ja,3),Ne.insulinReq=ja;var Ea=o((new Date(Je).getTime()-a.lastBolusTime)/6e4,1);if(d&&jt&&Xe>bt){var qa=30;void 0!==i.maxSMBBasalMinutes&&(qa=i.maxSMBBasalMinutes);var Wa=30;void 0!==i.maxUAMSMBBasalMinutes&&(Wa=i.maxUAMSMBBasalMinutes),v.useOverride&&M&&T!==qa&&(console.error("SMB Max Minutes - setting overriden from "+qa+" to "+T),qa=T),v.useOverride&&M&&C!==Wa&&(console.error("UAM Max Minutes - setting overriden from "+Wa+" to "+C),Wa=C);var ka=o(l.mealCOB/N,3),La=0;void 0===qa?(La=o(i.current_basal*L*30/60,1),console.error("smbMinutesSetting undefined: defaulting to 30m"),ja>La&&console.error("SMB limited by maxBolus: "+La+" ( "+ja+" U)")):a.iob>ka&&a.iob>0?(console.error("IOB"+a.iob+"> COB"+l.mealCOB+"; mealInsulinReq ="+ka),Wa?(console.error("maxUAMSMBBasalMinutes: "+Wa+", profile.current_basal: "+i.current_basal*L),La=o(i.current_basal*L*Wa/60,1)):(console.error("maxUAMSMBBasalMinutes undefined: defaulting to 30m"),La=o(i.current_basal*L*30/60,1)),ja>La?console.error("SMB limited by maxUAMSMBBasalMinutes [ "+Wa+"m ]: "+La+"U ( "+ja+"U )"):console.error("SMB is not limited by maxUAMSMBBasalMinutes. ( insulinReq: "+ja+"U )")):(console.error(".maxSMBBasalMinutes: "+qa+", profile.current_basal: "+i.current_basal*L),ja>(La=o(i.current_basal*qa/60,1))?console.error("SMB limited by maxSMBBasalMinutes: "+qa+"m ]: "+La+"U ( insulinReq: "+ja+"U )"):console.error("SMB is not limited by maxSMBBasalMinutes. ( insulinReq: "+ja+"U )"));var za=i.bolus_increment,Na=1/za,Ha=i.smb_delivery_ratio;Ha>.5&&console.error("SMB Delivery Ratio increased from default 0.5 to "+o(Ha,2));var Za=Math.min(ja*Ha,La);Za=Math.floor(Za*Na)/Na,Ia=o(60*((rt-(Ct+na)/2)/_t)/i.current_basal*L),ja>0&&Za=30?(Ia=30*o(Ia/30),Ia=Math.min(60,Math.max(0,Ia))):($a=o($e*Ia/30,2),Ia=30),Ne.reason+=" insulinReq "+ja,Za>=La&&(Ne.reason+="; maxBolus "+La),Ia>0&&(Ne.reason+="; setting "+Ia+"m low temp of "+$a+"U/h"),Ne.reason+=". ";var Ja=3;i.SMBInterval&&(Ja=Math.min(10,Math.max(1,i.SMBInterval)));var Ka=o(Ja-Ea,0),Qa=o(60*(Ja-Ea),0)%60;if(console.error("naive_eventualBG "+Ct+","+Ia+"m "+$a+"U/h temp needed; last bolus "+Ea+"m ago; maxBolus: "+La),Ea>Ja?Za>0&&(Ne.units=Za,Ne.reason+="Microbolusing "+Za+"U. "):Ne.reason+="Waiting "+Ka+"m "+Qa+"s to microbolus again. ",Ia>0)return Ne.rate=$a,Ne.duration=Ia,Ne}var Va=m.getMaxSafeBasal(i);return Fa>Va&&(Ne.reason+="adj. req. rate: "+Fa+" to maxSafeBasal: "+o(Va,2)+", ",Fa=r(Va,i)),t.duration*(t.rate-$e)/60>=2*ja?(Ne.reason+=t.duration+"m@"+t.rate.toFixed(2)+" > 2 * insulinReq. Setting temp basal of "+Fa+"U/hr. ",m.setTempBasal(Fa,30,i,Ne,t)):void 0===t.duration||0===t.duration?(Ne.reason+="no temp, setting "+Fa+"U/hr. ",m.setTempBasal(Fa,30,i,Ne,t)):t.duration>5&&r(Fa,i)<=r(t.rate,i)?(Ne.reason+="temp "+t.rate+" >~ req "+Fa+"U/hr. ",Ne):(Ne.reason+="temp "+t.rate+"<"+Fa+"U/hr. ",m.setTempBasal(Fa,30,i,Ne,t))}},6880:(e,t,a)=>{var r=a(6654);e.exports=function(e,t){var a=20;void 0!==t&&"string"==typeof t.model&&(r(t.model,"54")||r(t.model,"23"))&&(a=40);return e<1?Math.round(e*a)/a:e<10?Math.round(20*e)/20:Math.round(10*e)/10}},2705:(e,t,a)=>{var r=a(5639).Symbol;e.exports=r},9932:e=>{e.exports=function(e,t){for(var a=-1,r=null==e?0:e.length,o=Array(r);++a{e.exports=function(e,t,a){return e==e&&(void 0!==a&&(e=e<=a?e:a),void 0!==t&&(e=e>=t?e:t)),e}},4239:(e,t,a)=>{var r=a(2705),o=a(9607),n=a(2333),i=r?r.toStringTag:void 0;e.exports=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":i&&i in Object(e)?o(e):n(e)}},531:(e,t,a)=>{var r=a(2705),o=a(9932),n=a(1469),i=a(3448),s=r?r.prototype:void 0,l=s?s.toString:void 0;e.exports=function e(t){if("string"==typeof t)return t;if(n(t))return o(t,e)+"";if(i(t))return l?l.call(t):"";var a=t+"";return"0"==a&&1/t==-Infinity?"-0":a}},7561:(e,t,a)=>{var r=a(7990),o=/^\s+/;e.exports=function(e){return e?e.slice(0,r(e)+1).replace(o,""):e}},1957:(e,t,a)=>{var r="object"==typeof a.g&&a.g&&a.g.Object===Object&&a.g;e.exports=r},9607:(e,t,a)=>{var r=a(2705),o=Object.prototype,n=o.hasOwnProperty,i=o.toString,s=r?r.toStringTag:void 0;e.exports=function(e){var t=n.call(e,s),a=e[s];try{e[s]=void 0;var r=!0}catch(e){}var o=i.call(e);return r&&(t?e[s]=a:delete e[s]),o}},2333:e=>{var t=Object.prototype.toString;e.exports=function(e){return t.call(e)}},5639:(e,t,a)=>{var r=a(1957),o="object"==typeof self&&self&&self.Object===Object&&self,n=r||o||Function("return this")();e.exports=n},7990:e=>{var t=/\s/;e.exports=function(e){for(var a=e.length;a--&&t.test(e.charAt(a)););return a}},6654:(e,t,a)=>{var r=a(9750),o=a(531),n=a(554),i=a(9833);e.exports=function(e,t,a){e=i(e),t=o(t);var s=e.length,l=a=void 0===a?s:r(n(a),0,s);return(a-=t.length)>=0&&e.slice(a,l)==t}},1469:e=>{var t=Array.isArray;e.exports=t},3218:e=>{e.exports=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}},7005:e=>{e.exports=function(e){return null!=e&&"object"==typeof e}},3448:(e,t,a)=>{var r=a(4239),o=a(7005);e.exports=function(e){return"symbol"==typeof e||o(e)&&"[object Symbol]"==r(e)}},8601:(e,t,a)=>{var r=a(4841),o=1/0;e.exports=function(e){return e?(e=r(e))===o||e===-1/0?17976931348623157e292*(e<0?-1:1):e==e?e:0:0===e?e:0}},554:(e,t,a)=>{var r=a(8601);e.exports=function(e){var t=r(e),a=t%1;return t==t?a?t-a:t:0}},4841:(e,t,a)=>{var r=a(7561),o=a(3218),n=a(3448),i=/^[-+]0x[0-9a-f]+$/i,s=/^0b[01]+$/i,l=/^0o[0-7]+$/i,m=parseInt;e.exports=function(e){if("number"==typeof e)return e;if(n(e))return NaN;if(o(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=o(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=r(e);var a=s.test(e);return a||l.test(e)?m(e.slice(2),a?2:8):i.test(e)?NaN:+e}},9833:(e,t,a)=>{var r=a(531);e.exports=function(e){return null==e?"":r(e)}}},t={};function a(r){var o=t[r];if(void 0!==o)return o.exports;var n=t[r]={exports:{}};return e[r](n,n.exports,a),n.exports}a.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}();var r=a(5546);freeaps_determineBasal=r})(); \ No newline at end of file diff --git a/FreeAPS/Sources/APS/APSManager.swift b/FreeAPS/Sources/APS/APSManager.swift index 7856bbaaf2..04e16f8a31 100644 --- a/FreeAPS/Sources/APS/APSManager.swift +++ b/FreeAPS/Sources/APS/APSManager.swift @@ -757,13 +757,10 @@ final class BaseAPSManager: APSManager, Injectable { let sortCarbs = NSSortDescriptor(key: "date", ascending: true) requestCarbs.sortDescriptors = [sortCarbs] - try? carbs = coredataContext.fetch(requestCarbs) carbTotal = carbs.map({ carbs in carbs.carbs as? Decimal ?? 0 }).reduce(0, +) - // MARK: Fetch TDD from CoreData - var tdds = [TDD]() var currentTDD: Decimal = 0 var tddTotalAverage: Decimal = 0 @@ -1073,8 +1070,6 @@ final class BaseAPSManager: APSManager, Injectable { total: roundDecimal(Decimal(medianBG), 1) ) - // MARK: Save to Median to CoreData - let saveMedianToCoreData = BGmedian(context: self.coredataContext) saveMedianToCoreData.date = Date() saveMedianToCoreData.median = median.total as NSDecimalNumber diff --git a/FreeAPS/Sources/APS/OpenAPS/OpenAPS.swift b/FreeAPS/Sources/APS/OpenAPS/OpenAPS.swift index 837281c91c..5e26b774c8 100644 --- a/FreeAPS/Sources/APS/OpenAPS/OpenAPS.swift +++ b/FreeAPS/Sources/APS/OpenAPS/OpenAPS.swift @@ -124,6 +124,8 @@ final class OpenAPS { let preferences = storage.retrieve(OpenAPS.Settings.preferences, as: Preferences.self) var hbt_ = preferences?.halfBasalExerciseTarget ?? 160 let wp = preferences?.weightPercentage ?? 1 + let smbMinutes = (preferences?.maxSMBBasalMinutes ?? 30) as NSDecimalNumber + let uamMinutes = (preferences?.maxUAMSMBBasalMinutes ?? 30) as NSDecimalNumber let tenDaysAgo = Date().addingTimeInterval(-10.days.timeInterval) let twoHoursAgo = Date().addingTimeInterval(-2.hours.timeInterval) @@ -146,7 +148,7 @@ final class OpenAPS { let requestOverrides = Override.fetchRequest() as NSFetchRequest let sortOverride = NSSortDescriptor(key: "date", ascending: false) requestOverrides.sortDescriptors = [sortOverride] - requestOverrides.fetchLimit = 1 + // requestOverrides.fetchLimit = 1 try? overrideArray = coredataContext.fetch(requestOverrides) var tempTargetsArray = [TempTargets]() @@ -193,6 +195,7 @@ final class OpenAPS { if useOverride { duration = (overrideArray.first?.duration ?? 0) as Decimal overrideTarget = (overrideArray.first?.target ?? 0) as Decimal + let advancedSettings = overrideArray.first?.advancedSettings ?? false let addedMinutes = Int(duration) let date = overrideArray.first?.date ?? Date() if date.addingTimeInterval(addedMinutes.minutes.timeInterval) < Date(), @@ -204,38 +207,11 @@ final class OpenAPS { saveToCoreData.date = Date() saveToCoreData.duration = 0 saveToCoreData.indefinite = false - saveToCoreData.percentage = Double(overridePercentage) - try? self.coredataContext.save() - } else if overrideArray.first?.indefinite ?? false { - let saveToCoreData = Override(context: self.coredataContext) - saveToCoreData.enabled = true - saveToCoreData.date = Date() - saveToCoreData.duration = 0 - saveToCoreData.indefinite = true - saveToCoreData.percentage = Double(overridePercentage) - saveToCoreData.target = overrideTarget as NSDecimalNumber - saveToCoreData.smbIsOff = disableSMBs - try? self.coredataContext.save() - } else { - newDuration = Decimal(Date().distance(to: date.addingTimeInterval(addedMinutes.minutes.timeInterval)).minutes) - let saveToCoreData = Override(context: self.coredataContext) - saveToCoreData.enabled = true - saveToCoreData.date = Date() - saveToCoreData.duration = newDuration as NSDecimalNumber - saveToCoreData.indefinite = false - saveToCoreData.percentage = Double(overridePercentage) - saveToCoreData.target = overrideTarget as NSDecimalNumber - saveToCoreData.smbIsOff = disableSMBs + saveToCoreData.percentage = 100 try? self.coredataContext.save() } } - if newDuration < 0 { - newDuration = 0 - } else { - duration = newDuration - } - if !useOverride { unlimited = true overridePercentage = 100 @@ -244,7 +220,7 @@ final class OpenAPS { disableSMBs = false } - if temptargetActive /* || isPercentageEnabled */ { + if temptargetActive { var duration_ = 0 var hbt = Double(hbt_) var dd = 0.0 @@ -258,7 +234,6 @@ final class OpenAPS { if dd > 0.1 { hbt_ = Decimal(hbt) - // isPercentageEnabled = false temptargetActive = true } else { temptargetActive = false @@ -280,7 +255,16 @@ final class OpenAPS { unlimited: unlimited, hbt: hbt_, overrideTarget: overrideTarget, - smbIsOff: disableSMBs + smbIsOff: disableSMBs, + advancedSettings: overrideArray.first?.advancedSettings ?? false, + isfAndCr: overrideArray.first?.isfAndCr ?? false, + isf: overrideArray.first?.isf ?? false, + cr: overrideArray.first?.cr ?? false, + smbIsAlwaysOff: overrideArray.first?.smbIsAlwaysOff ?? false, + start: (overrideArray.first?.start ?? 0) as Decimal, + end: (overrideArray.first?.end ?? 0) as Decimal, + smbMinutes: (overrideArray.first?.smbMinutes ?? smbMinutes) as Decimal, + uamMinutes: (overrideArray.first?.uamMinutes ?? uamMinutes) as Decimal ) storage.save(averages, as: OpenAPS.Monitor.oref2_variables) print("Test time for oref2_variables: \(-now.timeIntervalSinceNow) seconds") @@ -300,7 +284,16 @@ final class OpenAPS { unlimited: unlimited, hbt: hbt_, overrideTarget: overrideTarget, - smbIsOff: disableSMBs + smbIsOff: disableSMBs, + advancedSettings: overrideArray.first?.advancedSettings ?? false, + isfAndCr: overrideArray.first?.isfAndCr ?? false, + isf: overrideArray.first?.isf ?? false, + cr: overrideArray.first?.cr ?? false, + smbIsAlwaysOff: overrideArray.first?.smbIsAlwaysOff ?? false, + start: (overrideArray.first?.start ?? 0) as Decimal, + end: (overrideArray.first?.end ?? 0) as Decimal, + smbMinutes: (overrideArray.first?.smbMinutes ?? smbMinutes) as Decimal, + uamMinutes: (overrideArray.first?.uamMinutes ?? uamMinutes) as Decimal ) storage.save(averages, as: OpenAPS.Monitor.oref2_variables) return self.loadFileFromStorage(name: Monitor.oref2_variables) diff --git a/FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings index cbe47a4f3c..4213f99c46 100644 --- a/FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings @@ -402,7 +402,7 @@ Enact a temp Basal or a temp target */ "Watch" = "Watch"; /* */ -"Watch Configuration" = "Watch Configuration"; +"Watch Configuration" = "Apple Watch Einstellungen"; /* */ "Apple Watch" = "Apple Watch"; @@ -414,16 +414,16 @@ Enact a temp Basal or a temp target */ "Garmin Watch" = "Garmin Watch"; /* */ -"Add devices" = "Add devices"; +"Add devices" = "Geräte hinzufügen"; /* */ "Glucose Target" = "Glucose Target"; /* */ -"Heart Rate" = "Heart Rate"; +"Heart Rate" = "Herzfrequenz"; /* */ -"Steps" = "Steps"; +"Steps" = "Schritte"; /* */ "ISF" = "ISF"; @@ -432,7 +432,7 @@ Enact a temp Basal or a temp target */ "The app Garmin Connect must be installed to use for iAPS.\n Go to App Store to download it" = "The app Garmin Connect must be installed to use for iAPS.\n Go to App Store to download it"; /* */ -"Garmin is not available" = "Garmin is not available"; +"Garmin is not available" = "Garmin ist nicht verfügbar"; /* */ "Services" = "Dienste"; @@ -501,7 +501,7 @@ Enact a temp Basal or a temp target */ "Treatments" = "Behandlungen"; /* " min" in Treatments list */ -" min" = " min"; +" min" = " Min"; /* */ "Unable to change anything" = "Keine Änderungen möglich"; @@ -1132,7 +1132,7 @@ Enact a temp Basal or a temp target */ "Interval In Minutes" = "Intervall in Minuten"; /* Override */ -"Override With A Factor Of " = "Override With A Factor Of "; +"Override With A Factor Of " = "Übersteuern mit einem Faktor von "; /* Description */ "Allows fat and protein to be converted into future carb equivalents using the Warsaw formula of kilocalories divided by 10.\n\nThis spreads the carb equivilants over a maximum duration setting that can be configured from 5-12 hours.\n\nDelay is time from now until the first future carb entry.\n\nInterval in minutes is how many minutes are between entries. The shorter the interval, the smoother the result. 10, 15, 20, 30, or 60 are reasonable choices.\n\nAdjustment factor is how much effect the fat and protein has on the entries. 1.0 is full effect (original Warsaw Method) and 0.5 is half effect. Note that you may find that your normal carb ratio needs to increase to a larger number if you begin adding fat and protein entries. For this reason, it is best to start with a factor of about 0.5 to ease into it.\n\nDefault settings: Time Cap: 8 h, Interval: 30 min, Factor: 0.5, Delay 60 min" = "Allows fat and protein to be converted into future carb equivalents using the Warsaw formula of kilocalories divided by 10.\n\nThis spreads the carb equivilants over a maximum duration setting that can be configured from 5-12 hours.\n\nDelay is time from now until the first future carb entry.\n\nInterval in minutes is how many minutes are between entries. The shorter the interval, the smoother the result. 10, 15, 20, 30, or 60 are reasonable choices.\n\nAdjustment factor is how much effect the fat and protein has on the entries. 1.0 is full effect (original Warsaw Method) and 0.5 is half effect. Note that you may find that your normal carb ratio needs to increase to a larger number if you begin adding fat and protein entries. For this reason, it is best to start with a factor of about 0.5 to ease into it.\n\nDefault settings: Time Cap: 8 h, Interval: 30 min, Factor: 0.5, Delay 60 min"; @@ -1144,7 +1144,7 @@ Enact a temp Basal or a temp target */ "Fat & Protein" = "Fat & Protein"; /* */ -"Hide Fat & Protein" = "Hide Fat & Protein"; +"Hide Fat & Protein" = "Fett & Eiweiß ausblenden"; /* Add Fat */ "Fat" = "Fett"; @@ -1186,7 +1186,7 @@ Enact a temp Basal or a temp target */ "App Icons" = "App Icons"; /* Service Section */ -"Statistics and Home View" = "Statistics and Home View"; +"Statistics and Home View" = "Statistiken und Home-Ansicht"; /* Alert text */ "Delete carb equivalents?" = "Delete carb equivalents?"; @@ -1355,16 +1355,16 @@ Enact a temp Basal or a temp target */ /* */ -"Today" = "Today"; +"Today" = "Heute"; /* */ -"Day" = "Day"; +"Day" = "Tag"; /* */ -"Week" = "Week"; +"Week" = "Woche"; /* */ -"Month" = "Month"; +"Month" = "Monat"; /* */ "Total" = "Gesamt"; @@ -1382,10 +1382,10 @@ Enact a temp Basal or a temp target */ "High" = "Hoch"; /* In Range */ -"In Range" = "In Range"; +"In Range" = "Im Zielbereich"; /* Display % */ -"Change HbA1c Unit" = "Change HbA1c Unit"; +"Change HbA1c Unit" = "HbA1c Einheit wechseln"; /* */ "Display Chart X - Grid lines" = "Display Chart X - Grid lines"; @@ -1415,7 +1415,7 @@ Enact a temp Basal or a temp target */ "Readings / 24h" = "Readings / 24h"; /* Days of saved readings*/ -"Days" = "Days"; +"Days" = "Tage"; /* Normal BG (within TIR) */ "Normal" = "im Zielbereich"; @@ -1505,9 +1505,9 @@ Enact a temp Basal or a temp target */ "Are you sure you want to delete this CGM?" = "Möchten Sie das CGM wirklich löschen?"; /* New Experimental feature */ -"Experimental" = "Experimental"; +"Experimental" = "Experimentell"; /* Smoothing of CGM readings */ -"Smooth Glucose Value" = "Smooth Glucose Value"; +"Smooth Glucose Value" = "Glätten der Glukosewerte"; /* ----------------------------------------------------------------------------------------------------------- diff --git a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings index a72559498f..f9a9a18ea6 100644 --- a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings @@ -1162,6 +1162,12 @@ Enact a temp Basal or a temp target */ /* */ "Override Profiles" = "Override Profiles"; +/* */ +"Normal " = "Normal "; + +/* */ +"Add / Delete" = "Add / Delete"; + /* */ "Currently no Override active" = "Currently no Override active"; diff --git a/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings index ff98128099..752ae77b77 100644 --- a/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings @@ -44,13 +44,13 @@ "Agree and continue" = "Acconsenti e Continua"; /* Headline in enacted pop up (at: at what time) */ -"Enacted at" = "Enacted at"; +"Enacted at" = "Eseguito alle"; /* Headline in suggested pop up (at: at what time) */ -"Suggested at" = "Suggested at"; +"Suggested at" = "Suggerito alle"; /* Headline in enacted pop up (at: at what time) */ -"Error at" = "Error at"; +"Error at" = "Errore a"; /* Home title */ "Home" = "Home"; @@ -113,16 +113,16 @@ "Enact Temp Target" = "Attiva target temporaneo"; /* */ -"Target" = "Target"; +"Target" = "Obiettivo"; /* */ -"Basal Insulin and Sensitivity ratio" = "Basal Insulin and Sensitivity ratio"; +"Basal Insulin and Sensitivity ratio" = "Rapporto basale insulina e sensibilità"; /* */ "A lower 'Half Basal Target' setting will reduce the basal and raise the ISF earlier, at a lower target glucose." = "A lower 'Half Basal Target' setting will reduce the basal and raise the ISF earlier, at a lower target glucose."; /* */ -" Your setting: " = " Your setting: "; +" Your setting: " = " Le tue impostazioni: "; /* */ "mg/dl. Autosens.max limits the max endpoint" = "mg/dl. Autosens.max limits the max endpoint"; @@ -155,7 +155,7 @@ "No" = "No"; /* Button */ -"Yes" = "Yes"; +"Yes" = "Sì"; /* + Button */ "[ +1 ]" = "[ +1 ]"; @@ -402,28 +402,28 @@ Enact a temp Basal or a temp target */ "Watch" = "Watch"; /* */ -"Watch Configuration" = "Watch Configuration"; +"Watch Configuration" = "Configurazione Watch"; /* */ "Apple Watch" = "Apple Watch"; /* */ -"Display on Watch" = "Display on Watch"; +"Display on Watch" = "Mostra sul Watch"; /* */ "Garmin Watch" = "Garmin Watch"; /* */ -"Add devices" = "Add devices"; +"Add devices" = "Aggiungi dispositivi"; /* */ -"Glucose Target" = "Glucose Target"; +"Glucose Target" = "Obiettivo glicemico"; /* */ -"Heart Rate" = "Heart Rate"; +"Heart Rate" = "Frequenza cardiaca"; /* */ -"Steps" = "Steps"; +"Steps" = "Passi"; /* */ "ISF" = "ISF"; @@ -495,7 +495,7 @@ Enact a temp Basal or a temp target */ "Delete carbs?" = "Elimina carboidrati?"; /* Delete insulin from pump history and Nightscout */ -"Delete insulin?" = "Delete insulin?"; +"Delete insulin?" = "Eliminare l'insulina?"; /* Treatments list */ "Treatments" = "Trattamenti"; @@ -504,7 +504,7 @@ Enact a temp Basal or a temp target */ " min" = " minuti"; /* */ -"Unable to change anything" = "Unable to change anything"; +"Unable to change anything" = "Impossibile modificare lo stato"; /* Calendar and Libre transmitter settings --------------- @@ -525,7 +525,7 @@ Enact a temp Basal or a temp target */ "Other" = "Altro"; /* */ -"Libre Transmitter" = "Libre Transmitter"; +"Libre Transmitter" = "Trasmettitore Libre"; /* */ "Libre Transmitters" = "Libre Transmitter"; @@ -558,7 +558,7 @@ Enact a temp Basal or a temp target */ "Meter glucose" = "Misuratore di glucosio"; /* */ -"Info" = "Info"; +"Info" = "Informazioni"; /*v*/ "Slope" = "Pendenza"; @@ -1091,7 +1091,7 @@ Enact a temp Basal or a temp target */ /* New ALerts ------------------------- */ /* Info title */ -"Info" = "Info"; +"Info" = "Informazioni"; /* Warning title */ "Warning" = "Avvertimento"; @@ -1123,13 +1123,13 @@ Enact a temp Basal or a temp target */ "Conversion settings" = "Conversion settings"; /* Delay */ -"Delay In Minutes" = "Delay In Minutes"; +"Delay In Minutes" = "Ritardo in minuti"; /* Duration */ -"Maximum Duration In Hours" = "Maximum Duration In Hours"; +"Maximum Duration In Hours" = "Durata massima in ore"; /* Interval */ -"Interval In Minutes" = "Interval In Minutes"; +"Interval In Minutes" = "Intervallo in minuti"; /* Override */ "Override With A Factor Of " = "Override With A Factor Of "; @@ -1138,22 +1138,22 @@ Enact a temp Basal or a temp target */ "Allows fat and protein to be converted into future carb equivalents using the Warsaw formula of kilocalories divided by 10.\n\nThis spreads the carb equivilants over a maximum duration setting that can be configured from 5-12 hours.\n\nDelay is time from now until the first future carb entry.\n\nInterval in minutes is how many minutes are between entries. The shorter the interval, the smoother the result. 10, 15, 20, 30, or 60 are reasonable choices.\n\nAdjustment factor is how much effect the fat and protein has on the entries. 1.0 is full effect (original Warsaw Method) and 0.5 is half effect. Note that you may find that your normal carb ratio needs to increase to a larger number if you begin adding fat and protein entries. For this reason, it is best to start with a factor of about 0.5 to ease into it.\n\nDefault settings: Time Cap: 8 h, Interval: 30 min, Factor: 0.5, Delay 60 min" = "Allows fat and protein to be converted into future carb equivalents using the Warsaw formula of kilocalories divided by 10.\n\nThis spreads the carb equivilants over a maximum duration setting that can be configured from 5-12 hours.\n\nDelay is time from now until the first future carb entry.\n\nInterval in minutes is how many minutes are between entries. The shorter the interval, the smoother the result. 10, 15, 20, 30, or 60 are reasonable choices.\n\nAdjustment factor is how much effect the fat and protein has on the entries. 1.0 is full effect (original Warsaw Method) and 0.5 is half effect. Note that you may find that your normal carb ratio needs to increase to a larger number if you begin adding fat and protein entries. For this reason, it is best to start with a factor of about 0.5 to ease into it.\n\nDefault settings: Time Cap: 8 h, Interval: 30 min, Factor: 0.5, Delay 60 min"; /* FPU Settings Title */ -"Fat and Protein" = "Fat and Protein"; +"Fat and Protein" = "Grassi e proteine"; /* Display fat and protein entities */ -"Fat & Protein" = "Fat & Protein"; +"Fat & Protein" = "Grassi e proteine"; /* */ -"Hide Fat & Protein" = "Hide Fat & Protein"; +"Hide Fat & Protein" = "Nascondi grassi e proteine"; /* Add Fat */ -"Fat" = "Fat"; +"Fat" = "Grassi"; /* Add Protein */ -"Protein" = "Protein"; +"Protein" = "Proteine"; /* Service Section */ -"Fat And Protein Conversion" = "Fat And Protein Conversion"; +"Fat And Protein Conversion" = "Conversione di grassi e proteine"; /* Service Section */ "Profile Override" = "Profile Override"; diff --git a/FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings index a1e9b25ff6..1c878eb590 100644 --- a/FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings @@ -378,7 +378,7 @@ Enact a temp Basal or a temp target */ "0 U/hr" = "0 E/t"; /* abbreviation for days */ -"d" = "dager"; +"d" = "d"; /* abbreviation for hours */ "h" = "t"; @@ -399,40 +399,40 @@ Enact a temp Basal or a temp target */ "Pump" = "Pumpe"; /* */ -"Watch" = "Watch"; +"Watch" = "Klokke"; /* */ -"Watch Configuration" = "Watch Configuration"; +"Watch Configuration" = "Klokkeinnstillinger"; /* */ "Apple Watch" = "Apple Watch"; /* */ -"Display on Watch" = "Display on Watch"; +"Display on Watch" = "Vis på klokke"; /* */ "Garmin Watch" = "Garmin Watch"; /* */ -"Add devices" = "Add devices"; +"Add devices" = "Legg til enheter"; /* */ -"Glucose Target" = "Glucose Target"; +"Glucose Target" = "Blodsukkermål"; /* */ -"Heart Rate" = "Heart Rate"; +"Heart Rate" = "Puls"; /* */ -"Steps" = "Steps"; +"Steps" = "Skritt"; /* */ "ISF" = "ISF"; /* */ -"The app Garmin Connect must be installed to use for iAPS.\n Go to App Store to download it" = "The app Garmin Connect must be installed to use for iAPS.\n Go to App Store to download it"; +"The app Garmin Connect must be installed to use for iAPS.\n Go to App Store to download it" = "Garmin Connect-appen må være installert.\n Gå til App Store for å laste den ned"; /* */ -"Garmin is not available" = "Garmin is not available"; +"Garmin is not available" = "Garmin er ikke tilgjengelig"; /* */ "Services" = "Tjenester"; @@ -1397,7 +1397,7 @@ Enact a temp Basal or a temp target */ "Display Chart Threshold lines for Low and High" = "Vise grenselinjer for høye og lave verdier"; /* */ -"Standing / Laying TIR Chart" = "Standing / Laying TIR Chart"; +"Standing / Laying TIR Chart" = "Stående / liggende TIR-diagram"; /* */ "Hours X-Axis (6 default)" = "Timer å vise (6 er standard)"; diff --git a/FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings index 840dea6928..8507cb1f85 100644 --- a/FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings @@ -260,7 +260,7 @@ Enact a temp Basal or a temp target */ /* */ "Manual Temp Basal" = "Ручная ВБС"; -/* Allow uploads data to NS */ +/* Allow uploads tp NS */ "Allow uploads" = "Разрешить выгрузку"; /* API secret in NS */ @@ -403,7 +403,6 @@ Enact a temp Basal or a temp target */ /* */ "Watch Configuration" = "Конфигурация часов"; -"Watch" = "Watch"; /* */ "Apple Watch" = "Apple Watch"; diff --git a/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings index 2f1c0b6a84..71f5eada18 100644 --- a/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings @@ -1191,39 +1191,6 @@ Enact a temp Basal or a temp target */ /* Alert text */ "Delete carb equivalents?" = "Radera dessa poster?"; -/* */ -"Currently no Override active" = "Inget undantag aktivt"; - -/* */ -"Total Insulin Adjustment" = "Total justering av ditt insulinbehov"; - -/* */ -"Override your Basal, ISF, CR and Target profiles" = "Ändra sparad basal, korrektionsfaktor, insulinkvot and målvärde med ett tillfäligt undantag"; - -/* */ -"Enable indefinitely" = "Aktivera tillsvidare"; - -/* */ -"Override Profiles" = "Aktivera tillfälligt undantag"; - -/* */ -"Override Profile Target" = "Ändra målvärde"; - -/* */ -"Disable SMBs" = "Stäng av autobolusar (SMBs)"; - -/* */ -"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal." = "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal."; - -/* Service Section */ -"App Icons" = "Ikoner"; - -/* */ -"iAPS Icon" = "iAPS - ikon"; - -/* Service Section */ -"Statistics and Home View" = "Statistik och Diagram"; - /* */ "Meal Presets" = "Måltider"; @@ -1387,8 +1354,6 @@ Enact a temp Basal or a temp target */ /* ----------------------Statistics strings -------------------------------*/ /* */ -/* */ -"Today" = "Idag"; "Today" = "Idag"; diff --git a/FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings index 2385e1c9c3..e0d19dc329 100644 --- a/FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings @@ -399,40 +399,40 @@ Enact a temp Basal or a temp target */ "Pump" = "Помпа"; /* */ -"Watch" = "Watch"; +"Watch" = "Годинник"; /* */ -"Watch Configuration" = "Watch Configuration"; +"Watch Configuration" = "Конфігурація годинника"; /* */ "Apple Watch" = "Apple Watch"; /* */ -"Display on Watch" = "Display on Watch"; +"Display on Watch" = "Відображати на годиннику"; /* */ "Garmin Watch" = "Garmin Watch"; /* */ -"Add devices" = "Add devices"; +"Add devices" = "Додати пристрій"; /* */ -"Glucose Target" = "Glucose Target"; +"Glucose Target" = "Мета глюкози"; /* */ -"Heart Rate" = "Heart Rate"; +"Heart Rate" = "Пульс"; /* */ -"Steps" = "Steps"; +"Steps" = "Кроки"; /* */ "ISF" = "ISF"; /* */ -"The app Garmin Connect must be installed to use for iAPS.\n Go to App Store to download it" = "The app Garmin Connect must be installed to use for iAPS.\n Go to App Store to download it"; +"The app Garmin Connect must be installed to use for iAPS.\n Go to App Store to download it" = "Щоб використовувати iAPS, необхідно встановити програму Garmin Connect.\n Перейдіть до App Store, щоб завантажити її"; /* */ -"Garmin is not available" = "Garmin is not available"; +"Garmin is not available" = "Garmin недоступний"; /* */ "Services" = "Сервіси"; diff --git a/FreeAPS/Sources/Models/Oref2_variables.swift b/FreeAPS/Sources/Models/Oref2_variables.swift index a55f03b674..69a1622306 100644 --- a/FreeAPS/Sources/Models/Oref2_variables.swift +++ b/FreeAPS/Sources/Models/Oref2_variables.swift @@ -14,6 +14,15 @@ struct Oref2_variables: JSON, Equatable { var hbt: Decimal var overrideTarget: Decimal var smbIsOff: Bool + var advancedSettings: Bool + var isfAndCr: Bool + var isf: Bool + var cr: Bool + var smbIsAlwaysOff: Bool + var start: Decimal + var end: Decimal + var smbMinutes: Decimal + var uamMinutes: Decimal init( average_total_data: Decimal, @@ -28,7 +37,16 @@ struct Oref2_variables: JSON, Equatable { unlimited: Bool, hbt: Decimal, overrideTarget: Decimal, - smbIsOff: Bool + smbIsOff: Bool, + advancedSettings: Bool, + isfAndCr: Bool, + isf: Bool, + cr: Bool, + smbIsAlwaysOff: Bool, + start: Decimal, + end: Decimal, + smbMinutes: Decimal, + uamMinutes: Decimal ) { self.average_total_data = average_total_data self.weightedAverage = weightedAverage @@ -43,6 +61,15 @@ struct Oref2_variables: JSON, Equatable { self.hbt = hbt self.overrideTarget = overrideTarget self.smbIsOff = smbIsOff + self.advancedSettings = advancedSettings + self.isfAndCr = isfAndCr + self.isf = isf + self.cr = cr + self.smbIsAlwaysOff = smbIsAlwaysOff + self.start = start + self.end = end + self.smbMinutes = smbMinutes + self.uamMinutes = uamMinutes } } @@ -61,5 +88,14 @@ extension Oref2_variables { case hbt case overrideTarget case smbIsOff + case advancedSettings + case isfAndCr + case isf + case cr + case smbIsAlwaysOff + case start + case end + case smbMinutes + case uamMinutes } } diff --git a/FreeAPS/Sources/Modules/AddCarbs/AddCarbsStateModel.swift b/FreeAPS/Sources/Modules/AddCarbs/AddCarbsStateModel.swift index a3fd73a88f..a18f8417b0 100644 --- a/FreeAPS/Sources/Modules/AddCarbs/AddCarbsStateModel.swift +++ b/FreeAPS/Sources/Modules/AddCarbs/AddCarbsStateModel.swift @@ -18,7 +18,6 @@ extension AddCarbs { @Published var summation: [String] = [] let coredataContext = CoreDataStack.shared.persistentContainer.viewContext - // @Environment(\.managedObjectContext) var moc override func subscribe() { subscribeSetting(\.useFPUconversion, on: $useFPUconversion) { useFPUconversion = $0 } diff --git a/FreeAPS/Sources/Modules/Home/HomeStateModel.swift b/FreeAPS/Sources/Modules/Home/HomeStateModel.swift index bfcc465709..725947725c 100644 --- a/FreeAPS/Sources/Modules/Home/HomeStateModel.swift +++ b/FreeAPS/Sources/Modules/Home/HomeStateModel.swift @@ -1,4 +1,5 @@ import Combine +import CoreData import LoopKitUI import SwiftDate import SwiftUI @@ -10,7 +11,6 @@ extension Home { @Injected() var nightscoutManager: NightscoutManager! private let timer = DispatchTimer(timeInterval: 5) private(set) var filteredHours = 24 - @Published var glucose: [BloodGlucose] = [] @Published var suggestion: Suggestion? @Published var uploadStats = false @@ -59,6 +59,8 @@ extension Home { @Published var displayYgridLines: Bool = false @Published var thresholdLines: Bool = false + let coredataContext = CoreDataStack.shared.persistentContainer.viewContext + override func subscribe() { setupGlucose() setupBasals() @@ -201,6 +203,15 @@ extension Home { apsManager.cancelBolus() } + func cancelProfile() { + coredataContext.perform { [self] in + let profiles = Override(context: self.coredataContext) + profiles.enabled = false + profiles.date = Date() + try? self.coredataContext.save() + } + } + private func setupGlucose() { DispatchQueue.main.async { [weak self] in guard let self = self else { return } diff --git a/FreeAPS/Sources/Modules/Home/View/HomeRootView.swift b/FreeAPS/Sources/Modules/Home/View/HomeRootView.swift index b98ffc0342..7b3d3013a5 100644 --- a/FreeAPS/Sources/Modules/Home/View/HomeRootView.swift +++ b/FreeAPS/Sources/Modules/Home/View/HomeRootView.swift @@ -10,26 +10,23 @@ extension Home { @StateObject var state = StateModel() @State var isStatusPopupPresented = false + @State var showCancelAlert = false - // Average/Median/Readings and CV/SD titles and values switches when you tap them - @State var averageOrMedianTitle = NSLocalizedString("Average", comment: "") - @State var median_ = "" - @State var average_ = "" - @State var readings = "" - - @State var averageOrmedian = "" - @State var CV_or_SD_Title = NSLocalizedString("CV", comment: "CV") - @State var cv_ = "" - @State var sd_ = "" - @State var CVorSD = "" - // Switch between Loops and Errors when tapping in statPanel - @State var loopStatTitle = NSLocalizedString("Loops", comment: "Nr of Loops in statPanel") + @Environment(\.managedObjectContext) var moc + @Environment(\.colorScheme) var colorScheme @FetchRequest( entity: Override.entity(), sortDescriptors: [NSSortDescriptor(key: "date", ascending: false)] ) var fetchedPercent: FetchedResults + @FetchRequest( + entity: OverridePresets.entity(), + sortDescriptors: [NSSortDescriptor(key: "name", ascending: true)], predicate: NSPredicate( + format: "name != %@", "" as String + ) + ) var fetchedProfiles: FetchedResults + @FetchRequest( entity: TempTargets.entity(), sortDescriptors: [NSSortDescriptor(key: "date", ascending: false)] @@ -96,8 +93,8 @@ extension Home { Spacer() } .frame(maxWidth: .infinity) - .padding(.top, geo.safeAreaInsets.top) - .padding(.bottom, 6) + .padding(.top, 10 + geo.safeAreaInsets.top) + .padding(.bottom, 10) .background(Color.gray.opacity(0.2)) } @@ -211,10 +208,7 @@ extension Home { if sliderTTpresets.first?.active ?? false { let hbt = sliderTTpresets.first?.hbt ?? 0 string = ", " + (tirFormatter.string(from: state.infoPanelTTPercentage(hbt, target) as NSNumber) ?? "") + " %" - } /* else if enactedSliderTT.first?.enabled ?? false { - let hbt = enactedSliderTT.first?.hbt ?? 0 - string = ", " + (tirFormatter.string(from: state.infoPanelTTPercentage(hbt, target) as NSNumber) ?? "") + " %" - } */ + } let percentString = state .units == .mmolL ? (unitString + " mmol/L" + string) : (rawString + (string == "0" ? "" : string)) @@ -235,10 +229,27 @@ extension Home { var targetString = (fetchedTargetFormatter.string(from: target as NSNumber) ?? "") + " " + unit if tempTargetString != nil || target == 0 { targetString = "" } percentString = percentString == "100 %" ? "" : percentString + + let duration = (fetchedPercent.first?.duration ?? 0) as Decimal + let addedMinutes = Int(duration) + let date = fetchedPercent.first?.date ?? Date() + var newDuration: Decimal = 0 + + if date.addingTimeInterval(addedMinutes.minutes.timeInterval) > Date() { + newDuration = Decimal(Date().distance(to: date.addingTimeInterval(addedMinutes.minutes.timeInterval)).minutes) + } + var durationString = indefinite ? - "" : ((tirFormatter.string(from: (fetchedPercent.first?.duration ?? 0) as NSNumber) ?? "") + " min") - let smbToggleString = (fetchedPercent.first?.smbIsOff ?? false) ? " \u{20e0}" : "" + "" : newDuration >= 1 ? + (newDuration.formatted(.number.grouping(.never).rounded().precision(.fractionLength(0))) + " min") : + ( + newDuration > 0 ? ( + newDuration.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1))) + "min" + ) : + "" + ) + let smbToggleString = (fetchedPercent.first?.smbIsOff ?? false) ? " \u{20e0}" : "" var comma1 = ", " var comma2 = comma1 var comma3 = comma1 @@ -262,6 +273,10 @@ extension Home { if smbToggleString == "" { comma3 = "" } + + if durationString == "", !indefinite { + return nil + } return percentString + comma1 + targetString + comma2 + durationString + comma3 + smbToggleString } @@ -287,9 +302,9 @@ extension Home { Spacer() if let overrideString = overrideString { - Text(overrideString) + Text("👤 " + overrideString) .font(.system(size: 12)) - .foregroundColor(.orange) + .foregroundColor(.secondary) .padding(.trailing, 8) } @@ -389,6 +404,71 @@ extension Home { .modal(for: .dataTable, from: self) } + @ViewBuilder private func profiles(_: GeometryProxy) -> some View { + let colour: Color = colorScheme == .dark ? .black : .white + // Rectangle().fill(colour).frame(maxHeight: 1) + ZStack { + Rectangle().fill(Color.gray.opacity(0.2)).frame(maxHeight: 40) + let cancel = fetchedPercent.first?.enabled ?? false + HStack(spacing: cancel ? 25 : 15) { + Text(selectedProfile().name).foregroundColor(.secondary) + if cancel, selectedProfile().isOn { + Button { showCancelAlert.toggle() } + label: { + Image(systemName: "xmark") + .foregroundStyle(.secondary) + } + } + Button { state.showModal(for: .overrideProfilesConfig) } + label: { + Image(systemName: "person.3.sequence.fill") + .symbolRenderingMode(.palette) + .foregroundStyle( + !(fetchedPercent.first?.enabled ?? false) ? .green : .cyan, + !(fetchedPercent.first?.enabled ?? false) ? .cyan : .green, + .purple + ) + } + } + } + .alert( + "Return to Normal?", isPresented: $showCancelAlert, + actions: { + Button("No", role: .cancel) {} + Button("Yes", role: .destructive) { + state.cancelProfile() + } + }, message: { Text("This will change settings back to your normal profile.") } + ) + Rectangle().fill(colour).frame(maxHeight: 1) + } + + private func selectedProfile() -> (name: String, isOn: Bool) { + var profileString = "" + var display: Bool = false + + let duration = (fetchedPercent.first?.duration ?? 0) as Decimal + let indefinite = fetchedPercent.first?.indefinite ?? false + let addedMinutes = Int(duration) + let date = fetchedPercent.first?.date ?? Date() + if date.addingTimeInterval(addedMinutes.minutes.timeInterval) > Date() || indefinite { + display.toggle() + } + + if fetchedPercent.first?.enabled ?? false, !(fetchedPercent.first?.isPreset ?? false) { + profileString = NSLocalizedString("Custom Profile", comment: "Custom but unsaved Profile") + } else if !(fetchedPercent.first?.enabled ?? false) || !display { + profileString = NSLocalizedString("Normal Profile", comment: "Your normal Profile. Use a short string") + } else { + let id_ = fetchedPercent.first?.id ?? "" + let profile = fetchedProfiles.filter({ $0.id == id_ }).first + if profile != nil { + profileString = profile?.name?.description ?? "" + } + } + return (name: profileString, isOn: display) + } + @ViewBuilder private func bottomPanel(_ geo: GeometryProxy) -> some View { ZStack { Rectangle().fill(Color.gray.opacity(0.2)).frame(height: 50 + geo.safeAreaInsets.bottom) @@ -473,6 +553,7 @@ extension Home { infoPanel mainChart legendPanel + profiles(geo) bottomPanel(geo) } .edgesIgnoringSafeArea(.vertical) diff --git a/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift b/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift index 22aecbe76f..0045b09911 100644 --- a/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift +++ b/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift @@ -10,11 +10,29 @@ extension OverrideProfilesConfig { @Published var target: Decimal = 0 @Published var override_target: Bool = false @Published var smbIsOff: Bool = false + @Published var id: String = "" + @Published var profileName: String = "" + @Published var isPreset: Bool = false + @Published var presets: [OverridePresets] = [] + @Published var selection: OverridePresets? + @Published var isPromtPresented: Bool = false + @Published var advancedSettings: Bool = false + @Published var isfAndCr: Bool = true + @Published var isf: Bool = true + @Published var cr: Bool = true + @Published var smbIsAlwaysOff: Bool = false + @Published var start: Decimal = 0 + @Published var end: Decimal = 23 + @Published var smbMinutes: Decimal = 0 + @Published var uamMinutes: Decimal = 0 var units: GlucoseUnits = .mmolL override func subscribe() { units = settingsManager.settings.units + smbMinutes = settingsManager.preferences.maxSMBBasalMinutes + uamMinutes = settingsManager.preferences.maxUAMSMBBasalMinutes + presets = [OverridePresets(context: coredataContext)] } let coredataContext = CoreDataStack.shared.persistentContainer.viewContext @@ -25,8 +43,12 @@ extension OverrideProfilesConfig { saveOverride.duration = self.duration as NSDecimalNumber saveOverride.indefinite = self._indefinite saveOverride.percentage = self.percentage - saveOverride.enabled = self.isEnabled + saveOverride.enabled = true saveOverride.smbIsOff = self.smbIsOff + if self.isPreset { + saveOverride.isPreset = true + saveOverride.id = id + } else { saveOverride.isPreset = false } saveOverride.date = Date() if override_target { if units == .mmolL { @@ -34,6 +56,116 @@ extension OverrideProfilesConfig { } saveOverride.target = target as NSDecimalNumber } else { saveOverride.target = 0 } + + if advancedSettings { + saveOverride.advancedSettings = true + + if !isfAndCr { + saveOverride.isfAndCr = false + saveOverride.isf = isf + saveOverride.cr = cr + } else { saveOverride.isfAndCr = true } + if smbIsAlwaysOff { + saveOverride.smbIsAlwaysOff = true + saveOverride.start = start as NSDecimalNumber + saveOverride.end = end as NSDecimalNumber + } else { saveOverride.smbIsAlwaysOff = false } + if smbMinutes != self.settingsManager.preferences.maxSMBBasalMinutes { + saveOverride.smbMinutes = smbMinutes as NSDecimalNumber + } + if uamMinutes != self.settingsManager.preferences.maxUAMSMBBasalMinutes { + saveOverride.uamMinutes = uamMinutes as NSDecimalNumber + } + } + try? self.coredataContext.save() + } + } + + func savePreset() { + coredataContext.perform { [self] in + let saveOverride = OverridePresets(context: self.coredataContext) + saveOverride.duration = self.duration as NSDecimalNumber + saveOverride.indefinite = self._indefinite + saveOverride.percentage = self.percentage + saveOverride.smbIsOff = self.smbIsOff + saveOverride.name = self.profileName + id = UUID().uuidString + self.isPreset.toggle() + saveOverride.id = id + saveOverride.date = Date() + if override_target { + if units == .mmolL { + target = target.asMgdL + } + saveOverride.target = target as NSDecimalNumber + } else { saveOverride.target = 0 } + + if advancedSettings { + saveOverride.advancedSettings = true + + if !isfAndCr { + saveOverride.isfAndCr = false + saveOverride.isf = isf + saveOverride.cr = cr + } else { saveOverride.isfAndCr = true } + if smbIsAlwaysOff { + saveOverride.smbIsAlwaysOff = true + saveOverride.start = start as NSDecimalNumber + saveOverride.end = end as NSDecimalNumber + } else { smbIsAlwaysOff = false } + if smbMinutes != self.settingsManager.preferences.maxSMBBasalMinutes { + saveOverride.smbMinutes = smbMinutes as NSDecimalNumber + } + if uamMinutes != self.settingsManager.preferences.maxUAMSMBBasalMinutes { + saveOverride.uamMinutes = uamMinutes as NSDecimalNumber + } + } + try? self.coredataContext.save() + isPromtPresented = false + } + } + + func selectProfile(id_: String) { + guard id_ != "" else { return } + coredataContext.performAndWait { + var profileArray = [OverridePresets]() + let requestProfiles = OverridePresets.fetchRequest() as NSFetchRequest + try? profileArray = coredataContext.fetch(requestProfiles) + + guard let profile = profileArray.filter({ $0.id == id_ }).first else { return } + + let saveOverride = Override(context: self.coredataContext) + saveOverride.duration = (profile.duration ?? 0) as NSDecimalNumber + saveOverride.indefinite = profile.indefinite + saveOverride.percentage = profile.percentage + saveOverride.enabled = true + saveOverride.smbIsOff = profile.smbIsOff + saveOverride.isPreset = true + saveOverride.date = Date() + saveOverride.target = profile.target + saveOverride.id = id_ + + if profile.advancedSettings { + if !isfAndCr { + saveOverride.isfAndCr = false + saveOverride.isf = profile.isf + saveOverride.cr = profile.cr + } else { saveOverride.isfAndCr = true } + if profile.smbIsAlwaysOff { + saveOverride.smbIsAlwaysOff = true + saveOverride.start = profile.start + saveOverride.end = profile.end + } else { saveOverride.smbIsAlwaysOff = false } + + let smb = (profile.smbMinutes ?? 30) as Decimal + if smb != self.settingsManager.preferences.maxSMBBasalMinutes { + saveOverride.smbMinutes = profile.smbMinutes + } + let uam = (profile.uamMinutes ?? 30) as Decimal + if uam != self.settingsManager.preferences.maxUAMSMBBasalMinutes { + saveOverride.uamMinutes = profile.uamMinutes + } + } try? self.coredataContext.save() } } @@ -44,13 +176,37 @@ extension OverrideProfilesConfig { let requestEnabled = Override.fetchRequest() as NSFetchRequest let sortIsEnabled = NSSortDescriptor(key: "date", ascending: false) requestEnabled.sortDescriptors = [sortIsEnabled] - requestEnabled.fetchLimit = 1 + // requestEnabled.fetchLimit = 1 try? overrideArray = coredataContext.fetch(requestEnabled) isEnabled = overrideArray.first?.enabled ?? false percentage = overrideArray.first?.percentage ?? 100 _indefinite = overrideArray.first?.indefinite ?? true duration = (overrideArray.first?.duration ?? 0) as Decimal smbIsOff = overrideArray.first?.smbIsOff ?? false + advancedSettings = overrideArray.first?.advancedSettings ?? false + isfAndCr = overrideArray.first?.isfAndCr ?? true + smbIsAlwaysOff = overrideArray.first?.smbIsAlwaysOff ?? false + + if advancedSettings { + if !isfAndCr { + isf = overrideArray.first?.isf ?? false + cr = overrideArray.first?.cr ?? false + } + if smbIsAlwaysOff { + start = (overrideArray.first?.start ?? 0) as Decimal + end = (overrideArray.first?.end ?? 0) as Decimal + } + + let smb = (overrideArray.first?.smbMinutes ?? 30) as Decimal + if smb != self.settingsManager.preferences.maxSMBBasalMinutes { + smbMinutes = (overrideArray.first?.smbMinutes ?? 30) as Decimal + } + let uam = (overrideArray.first?.uamMinutes ?? 30) as Decimal + if uam != self.settingsManager.preferences.maxUAMSMBBasalMinutes { + uamMinutes = (overrideArray.first?.uamMinutes ?? 30) as Decimal + } + } + let overrideTarget = (overrideArray.first?.target ?? 0) as Decimal var newDuration = Double(duration) @@ -77,8 +233,26 @@ extension OverrideProfilesConfig { target = 0 override_target = false smbIsOff = false + advancedSettings = false } } } + + func cancelProfile() { + _indefinite = true + isEnabled = false + percentage = 100 + duration = 0 + target = 0 + override_target = false + smbIsOff = false + advancedSettings = false + coredataContext.perform { [self] in + let profiles = Override(context: self.coredataContext) + profiles.enabled = false + profiles.date = Date() + try? self.coredataContext.save() + } + } } } diff --git a/FreeAPS/Sources/Modules/OverrideProfilesConfig/View/OverrideProfilesRootView.swift b/FreeAPS/Sources/Modules/OverrideProfilesConfig/View/OverrideProfilesRootView.swift index a595742f21..4fae15f5c7 100644 --- a/FreeAPS/Sources/Modules/OverrideProfilesConfig/View/OverrideProfilesRootView.swift +++ b/FreeAPS/Sources/Modules/OverrideProfilesConfig/View/OverrideProfilesRootView.swift @@ -10,9 +10,17 @@ extension OverrideProfilesConfig { @State private var isEditing = false @State private var showAlert = false @State private var showingDetail = false - @State private var isPresented = true @State private var alertSring = "" + @Environment(\.dismiss) var dismiss + @Environment(\.managedObjectContext) var moc + + @FetchRequest( + entity: OverridePresets.entity(), + sortDescriptors: [NSSortDescriptor(key: "name", ascending: true)], predicate: NSPredicate( + format: "name != %@", "" as String + ) + ) var fetchedProfiles: FetchedResults private var formatter: NumberFormatter { let formatter = NumberFormatter() @@ -32,79 +40,148 @@ extension OverrideProfilesConfig { return formatter } + var presetPopover: some View { + Form { + Section(header: Text("Enter Profile Name")) { + TextField("Name Of Profile", text: $state.profileName) + Button { + state.savePreset() + } + + label: { Text("Save") } + .disabled( + state.profileName == "" || + fetchedProfiles.filter({ $0.name == state.profileName }).isNotEmpty + ) + Button { + state.isPromtPresented = false } + label: { Text("Cancel") } + } + } + } + var body: some View { Form { - Section( - header: Text("Override your Basal, ISF, CR and Target profiles"), - footer: Text("" + (!state.isEnabled ? NSLocalizedString("Currently no Override active", comment: "") : "")) - ) { - Toggle(isOn: $state.isEnabled) { - Text("Override Profiles") - }._onBindingChange($state.isEnabled, perform: { _ in - if !state.isEnabled { - state.duration = 0 - state.percentage = 100 - state._indefinite = true - state.override_target = false - state.saveSettings() - } - }) + if state.presets.isNotEmpty { + Section { + ForEach(fetchedProfiles) { preset in + profilesView(for: preset) + }.onDelete(perform: removeProfile) + } } - if state.isEnabled { - Section( - header: Text("Total Insulin Adjustment"), - footer: Text( - "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal." - ) - ) { - VStack { - Slider( - value: $state.percentage, - in: 10 ... 200, - step: 1, - onEditingChanged: { editing in - isEditing = editing - } - ).accentColor(state.percentage >= 130 ? .red : .blue) - Text("\(state.percentage.formatted(.number)) %") - .foregroundColor( - state - .percentage >= 130 ? .red : - (isEditing ? .orange : .blue) - ) - .font(.largeTitle) - Spacer() - Toggle(isOn: $state._indefinite) { - Text("Enable indefinitely") + Section { + VStack { + Slider( + value: $state.percentage, + in: 10 ... 200, + step: 1, + onEditingChanged: { editing in + isEditing = editing } + ).accentColor(state.percentage >= 130 ? .red : .blue) + Text("\(state.percentage.formatted(.number)) %") + .foregroundColor( + state + .percentage >= 130 ? .red : + (isEditing ? .orange : .blue) + ) + .font(.largeTitle) + Spacer() + Toggle(isOn: $state._indefinite) { + Text("Enable indefinitely") } - if !state._indefinite { - HStack { - Text("Duration") - DecimalTextField("0", value: $state.duration, formatter: formatter, cleanInput: false) - Text("minutes").foregroundColor(.secondary) - } + } + if !state._indefinite { + HStack { + Text("Duration") + DecimalTextField("0", value: $state.duration, formatter: formatter, cleanInput: false) + Text("minutes").foregroundColor(.secondary) } + } + HStack { + Toggle(isOn: $state.override_target) { + Text("Override Profile Target") + } + } + if state.override_target { HStack { - Toggle(isOn: $state.override_target) { - Text("Override Profile Target") + Text("Target Glucose") + DecimalTextField("0", value: $state.target, formatter: glucoseFormatter, cleanInput: false) + Text(state.units.rawValue).foregroundColor(.secondary) + } + } + HStack { + Toggle(isOn: $state.advancedSettings) { + Text("More options") + } + } + if state.advancedSettings { + HStack { + Toggle(isOn: $state.smbIsOff) { + Text("Disable SMBs") } } - if state.override_target { + HStack { + Toggle(isOn: $state.smbIsAlwaysOff) { + Text("Schedule when SMBs are Off") + }.disabled(!state.smbIsOff) + } + if state.smbIsAlwaysOff { + HStack { + Text("First Hour SMBs are Off (24 hours)") + DecimalTextField("0", value: $state.start, formatter: formatter, cleanInput: false) + Text("hour").foregroundColor(.secondary) + } HStack { - Text("Target Glucose") - DecimalTextField("0", value: $state.target, formatter: glucoseFormatter, cleanInput: false) - Text(state.units.rawValue).foregroundColor(.secondary) + Text("Last Hour SMBs are Off (24 hours)") + DecimalTextField("0", value: $state.end, formatter: formatter, cleanInput: false) + Text("hour").foregroundColor(.secondary) } } HStack { - Toggle(isOn: $state.smbIsOff) { - Text("Disable SMBs") + Toggle(isOn: $state.isfAndCr) { + Text("Change ISF and CR") + } + } + if !state.isfAndCr { + HStack { + Toggle(isOn: $state.isf) { + Text("Change ISF") + } + } + HStack { + Toggle(isOn: $state.cr) { + Text("Change CR") + } } } + HStack { + Text("SMB Minutes") + let minutes = state.settingsManager.preferences.maxSMBBasalMinutes + DecimalTextField( + minutes.formatted(), + value: $state.smbMinutes, + formatter: formatter, + cleanInput: false + ) + Text("minutes").foregroundColor(.secondary) + } + HStack { + Text("UAM SMB Minutes") + let uam_minutes = state.settingsManager.preferences.maxUAMSMBBasalMinutes + DecimalTextField( + uam_minutes.formatted(), + value: $state.uamMinutes, + formatter: formatter, + cleanInput: false + ) + Text("minutes").foregroundColor(.secondary) + } + } - Button("Save") { + HStack { + Button("Start new Profile") { showAlert.toggle() alertSring = "\(state.percentage.formatted(.number)) %, " + ( @@ -126,29 +203,24 @@ extension OverrideProfilesConfig { + "\n\n" + - "Saving this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping save will start your new overide or edit your current active override." + "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start” will start your new overide or edit your current active override." } .disabled( - !state - .isEnabled || (state.percentage == 100 && !state.override_target && !state.smbIsOff) || - (!state._indefinite && state.duration == 0 || (state.override_target && state.target == 0)) + (state.percentage == 100 && !state.override_target && !state.smbIsOff) || + (!state._indefinite && state.duration == 0) || (state.override_target && state.target == 0) ) - .accentColor(.orange) + // .tint(.blue) .buttonStyle(BorderlessButtonStyle()) .font(.callout) - .frame(maxWidth: .infinity, alignment: .center) .controlSize(.mini) .alert( - "Save Override", + "Start Profile", isPresented: $showAlert, actions: { - Button("Cancel", role: .cancel) {} + Button("Cancel", role: .cancel) { state.isEnabled = false } Button("Start Override", role: .destructive) { - if state._indefinite { - state.duration = 0 - } else if state.duration == 0 { - state.isEnabled = false - } + if state._indefinite { state.duration = 0 } + state.isEnabled.toggle() state.saveSettings() dismiss() } @@ -157,11 +229,107 @@ extension OverrideProfilesConfig { Text(alertSring) } ) + Button { + state.isPromtPresented.toggle() + } + label: { Text("Save as Profile") } + .tint(.orange) + .frame(maxWidth: .infinity, alignment: .trailing) + .buttonStyle(BorderlessButtonStyle()) + .controlSize(.mini) + .disabled( + (state.percentage == 100 && !state.override_target && !state.smbIsOff) || + (!state._indefinite && state.duration == 0) || (state.override_target && state.target == 0) + ) + } + .popover(isPresented: $state.isPromtPresented) { + presetPopover } } + + header: { Text("Insulin") } + footer: { + Text( + "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage." + ) + } + + Button("Return to Normal") { + state.cancelProfile() + dismiss() + } + .frame(maxWidth: .infinity, alignment: .center) + .buttonStyle(BorderlessButtonStyle()) + .disabled(!state.isEnabled) + .tint(.red) } .onAppear(perform: configureView) .onAppear { state.savedSettings() } + .navigationBarTitle("Profiles") + .navigationBarTitleDisplayMode(.automatic) + .navigationBarItems(leading: Button("Close", action: state.hideModal)) + } + + @ViewBuilder private func profilesView(for preset: OverridePresets) -> some View { + let target = state.units == .mmolL ? (((preset.target ?? 0) as NSDecimalNumber) as Decimal) + .asMmolL : (preset.target ?? 0) as Decimal + let duration = (preset.duration ?? 0) as Decimal + let name = ((preset.name ?? "") == "") || (preset.name?.isEmpty ?? true) ? "" : preset.name! + let percent = preset.percentage / 100 + let perpetual = preset.indefinite + let durationString = perpetual ? "" : "\(formatter.string(from: duration as NSNumber)!)" + let scheduledSMBstring = (preset.smbIsOff && preset.smbIsAlwaysOff) ? "Scheduled SMBs" : "" + let smbString = (preset.smbIsOff && scheduledSMBstring == "") ? "SMBs are off" : "" + let targetString = target != 0 ? "\(formatter.string(from: target as NSNumber)!)" : "" + + if name != "" { + HStack { + VStack { + HStack { + Text(name) + Spacer() + } + HStack(spacing: 5) { + Text(percent.formatted(.percent.grouping(.never).rounded().precision(.fractionLength(0)))) + .foregroundColor(.secondary) + .font(.caption) + if targetString != "" { + Text(targetString) + .foregroundColor(.secondary) + .font(.caption) + Text(targetString != "" ? state.units.rawValue : "") + .foregroundColor(.secondary) + .font(.caption) } + if durationString != "" { + Text(durationString + (perpetual ? "" : "min")) + .foregroundColor(.secondary) + .font(.caption) } + if smbString != "" { Text(smbString).foregroundColor(.secondary).font(.caption) } + Text(scheduledSMBstring) + .foregroundColor(.secondary) + .font(.caption) + Spacer() + }.padding(.top, 2) + } + .contentShape(Rectangle()) + .onTapGesture { + state.selectProfile(id_: preset.id ?? "") + state.hideModal() + } + } + } + } + + private func removeProfile(at offsets: IndexSet) { + for index in offsets { + let language = fetchedProfiles[index] + moc.delete(language) + } + do { + try moc.save() + } catch { + // To do: add error + } } } } diff --git a/FreeAPS/Sources/Modules/Settings/View/SettingsRootView.swift b/FreeAPS/Sources/Modules/Settings/View/SettingsRootView.swift index 2668512e54..ffceb56288 100644 --- a/FreeAPS/Sources/Modules/Settings/View/SettingsRootView.swift +++ b/FreeAPS/Sources/Modules/Settings/View/SettingsRootView.swift @@ -31,7 +31,6 @@ extension Settings { } Text("Notifications").navigationLink(to: .notificationsConfig, from: self) Text("Fat And Protein Conversion").navigationLink(to: .fpuConfig, from: self) - Text("Profile Override").navigationLink(to: .overrideProfilesConfig, from: self) Text("App Icons").navigationLink(to: .iconConfig, from: self) Text("Statistics and Home View").navigationLink(to: .statisticsConfig, from: self) } From b7a206de476c14169dd41e7d5795845449dd8267 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Fri, 26 May 2023 13:13:56 +0200 Subject: [PATCH 02/45] 25. Sync duration. Missing commit (cherry picked from commit 6d0226b87013a825cd2e6d4c1ed783c26adf0565) --- FreeAPS/Sources/Modules/Home/View/HomeRootView.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FreeAPS/Sources/Modules/Home/View/HomeRootView.swift b/FreeAPS/Sources/Modules/Home/View/HomeRootView.swift index 7b3d3013a5..60806f8fab 100644 --- a/FreeAPS/Sources/Modules/Home/View/HomeRootView.swift +++ b/FreeAPS/Sources/Modules/Home/View/HomeRootView.swift @@ -244,7 +244,7 @@ extension Home { (newDuration.formatted(.number.grouping(.never).rounded().precision(.fractionLength(0))) + " min") : ( newDuration > 0 ? ( - newDuration.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1))) + "min" + (newDuration * 60).formatted(.number.grouping(.never).rounded().precision(.fractionLength(0))) + " s" ) : "" ) @@ -455,7 +455,7 @@ extension Home { display.toggle() } - if fetchedPercent.first?.enabled ?? false, !(fetchedPercent.first?.isPreset ?? false) { + if fetchedPercent.first?.enabled ?? false, !(fetchedPercent.first?.isPreset ?? false), display { profileString = NSLocalizedString("Custom Profile", comment: "Custom but unsaved Profile") } else if !(fetchedPercent.first?.enabled ?? false) || !display { profileString = NSLocalizedString("Normal Profile", comment: "Your normal Profile. Use a short string") From 985ed2212d0f0616ac3f1f6100cc3d7cf6267345 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Sat, 27 May 2023 01:51:08 +0200 Subject: [PATCH 03/45] Fix for weird popover bug I can't explain. Replace the popover with sheet. (cherry picked from commit f7ecb89eb0aa7b10975d89f7b4ac267f925f1fa5) --- .../OverrideProfilesStateModel.swift | 2 -- .../View/OverrideProfilesRootView.swift | 27 ++++++++++--------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift b/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift index 0045b09911..481f7fa4e2 100644 --- a/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift +++ b/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift @@ -15,7 +15,6 @@ extension OverrideProfilesConfig { @Published var isPreset: Bool = false @Published var presets: [OverridePresets] = [] @Published var selection: OverridePresets? - @Published var isPromtPresented: Bool = false @Published var advancedSettings: Bool = false @Published var isfAndCr: Bool = true @Published var isf: Bool = true @@ -121,7 +120,6 @@ extension OverrideProfilesConfig { } } try? self.coredataContext.save() - isPromtPresented = false } } diff --git a/FreeAPS/Sources/Modules/OverrideProfilesConfig/View/OverrideProfilesRootView.swift b/FreeAPS/Sources/Modules/OverrideProfilesConfig/View/OverrideProfilesRootView.swift index 4fae15f5c7..642fcf8674 100644 --- a/FreeAPS/Sources/Modules/OverrideProfilesConfig/View/OverrideProfilesRootView.swift +++ b/FreeAPS/Sources/Modules/OverrideProfilesConfig/View/OverrideProfilesRootView.swift @@ -11,6 +11,7 @@ extension OverrideProfilesConfig { @State private var showAlert = false @State private var showingDetail = false @State private var alertSring = "" + @State var isSheetPresented: Bool = false @Environment(\.dismiss) var dismiss @Environment(\.managedObjectContext) var moc @@ -42,20 +43,20 @@ extension OverrideProfilesConfig { var presetPopover: some View { Form { - Section(header: Text("Enter Profile Name")) { + Section { TextField("Name Of Profile", text: $state.profileName) - Button { + } header: { Text("Enter Name of Profile") } + + Section { + Button("Save") { state.savePreset() + isSheetPresented = false } + .disabled(state.profileName.isEmpty || fetchedProfiles.filter({ $0.name == state.profileName }).isNotEmpty) - label: { Text("Save") } - .disabled( - state.profileName == "" || - fetchedProfiles.filter({ $0.name == state.profileName }).isNotEmpty - ) - Button { - state.isPromtPresented = false } - label: { Text("Cancel") } + Button("Cancel") { + isSheetPresented = false + } } } } @@ -209,7 +210,6 @@ extension OverrideProfilesConfig { (state.percentage == 100 && !state.override_target && !state.smbIsOff) || (!state._indefinite && state.duration == 0) || (state.override_target && state.target == 0) ) - // .tint(.blue) .buttonStyle(BorderlessButtonStyle()) .font(.callout) .controlSize(.mini) @@ -230,7 +230,7 @@ extension OverrideProfilesConfig { } ) Button { - state.isPromtPresented.toggle() + isSheetPresented = true } label: { Text("Save as Profile") } .tint(.orange) @@ -242,7 +242,8 @@ extension OverrideProfilesConfig { (!state._indefinite && state.duration == 0) || (state.override_target && state.target == 0) ) } - .popover(isPresented: $state.isPromtPresented) { + + .sheet(isPresented: $isSheetPresented) { presetPopover } } From 35e73626ee9a3ad345a9ca6ef18c435d24b43328 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Sat, 27 May 2023 10:52:09 +0200 Subject: [PATCH 04/45] Add all profile settings to card info. (cherry picked from commit 4d22482bdd87814fa90b91858ac9b6701cbaa14b) --- .../OverrideProfilesStateModel.swift | 35 ++++++------------- .../View/OverrideProfilesRootView.swift | 33 +++++++++-------- 2 files changed, 30 insertions(+), 38 deletions(-) diff --git a/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift b/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift index 481f7fa4e2..038ce9e99e 100644 --- a/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift +++ b/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift @@ -69,12 +69,9 @@ extension OverrideProfilesConfig { saveOverride.start = start as NSDecimalNumber saveOverride.end = end as NSDecimalNumber } else { saveOverride.smbIsAlwaysOff = false } - if smbMinutes != self.settingsManager.preferences.maxSMBBasalMinutes { - saveOverride.smbMinutes = smbMinutes as NSDecimalNumber - } - if uamMinutes != self.settingsManager.preferences.maxUAMSMBBasalMinutes { - saveOverride.uamMinutes = uamMinutes as NSDecimalNumber - } + + saveOverride.smbMinutes = smbMinutes as NSDecimalNumber + saveOverride.uamMinutes = uamMinutes as NSDecimalNumber } try? self.coredataContext.save() } @@ -112,12 +109,9 @@ extension OverrideProfilesConfig { saveOverride.start = start as NSDecimalNumber saveOverride.end = end as NSDecimalNumber } else { smbIsAlwaysOff = false } - if smbMinutes != self.settingsManager.preferences.maxSMBBasalMinutes { - saveOverride.smbMinutes = smbMinutes as NSDecimalNumber - } - if uamMinutes != self.settingsManager.preferences.maxUAMSMBBasalMinutes { - saveOverride.uamMinutes = uamMinutes as NSDecimalNumber - } + + saveOverride.smbMinutes = smbMinutes as NSDecimalNumber + saveOverride.uamMinutes = uamMinutes as NSDecimalNumber } try? self.coredataContext.save() } @@ -155,14 +149,8 @@ extension OverrideProfilesConfig { saveOverride.end = profile.end } else { saveOverride.smbIsAlwaysOff = false } - let smb = (profile.smbMinutes ?? 30) as Decimal - if smb != self.settingsManager.preferences.maxSMBBasalMinutes { - saveOverride.smbMinutes = profile.smbMinutes - } - let uam = (profile.uamMinutes ?? 30) as Decimal - if uam != self.settingsManager.preferences.maxUAMSMBBasalMinutes { - saveOverride.uamMinutes = profile.uamMinutes - } + saveOverride.smbMinutes = smbMinutes as NSDecimalNumber + saveOverride.uamMinutes = uamMinutes as NSDecimalNumber } try? self.coredataContext.save() } @@ -195,12 +183,11 @@ extension OverrideProfilesConfig { end = (overrideArray.first?.end ?? 0) as Decimal } - let smb = (overrideArray.first?.smbMinutes ?? 30) as Decimal - if smb != self.settingsManager.preferences.maxSMBBasalMinutes { + if (overrideArray[0].smbMinutes as Decimal?) != nil { smbMinutes = (overrideArray.first?.smbMinutes ?? 30) as Decimal } - let uam = (overrideArray.first?.uamMinutes ?? 30) as Decimal - if uam != self.settingsManager.preferences.maxUAMSMBBasalMinutes { + + if (overrideArray[0].uamMinutes as Decimal?) != nil { uamMinutes = (overrideArray.first?.uamMinutes ?? 30) as Decimal } } diff --git a/FreeAPS/Sources/Modules/OverrideProfilesConfig/View/OverrideProfilesRootView.swift b/FreeAPS/Sources/Modules/OverrideProfilesConfig/View/OverrideProfilesRootView.swift index 642fcf8674..cb71ab7267 100644 --- a/FreeAPS/Sources/Modules/OverrideProfilesConfig/View/OverrideProfilesRootView.swift +++ b/FreeAPS/Sources/Modules/OverrideProfilesConfig/View/OverrideProfilesRootView.swift @@ -282,6 +282,13 @@ extension OverrideProfilesConfig { let scheduledSMBstring = (preset.smbIsOff && preset.smbIsAlwaysOff) ? "Scheduled SMBs" : "" let smbString = (preset.smbIsOff && scheduledSMBstring == "") ? "SMBs are off" : "" let targetString = target != 0 ? "\(formatter.string(from: target as NSNumber)!)" : "" + let maxMinutesSMB = (preset.smbMinutes as Decimal?) != nil ? (preset.smbMinutes ?? 0) as Decimal : 0 + let maxMinutesUAM = (preset.uamMinutes as Decimal?) != nil ? (preset.uamMinutes ?? 0) as Decimal : 0 + + let isfString = preset.isf ? "ISF" : "" + let crString = preset.cr ? "CR" : "" + let dash = crString != "" ? "/" : "" + let isfAndCRstring = isfString + dash + crString if name != "" { HStack { @@ -292,25 +299,23 @@ extension OverrideProfilesConfig { } HStack(spacing: 5) { Text(percent.formatted(.percent.grouping(.never).rounded().precision(.fractionLength(0)))) - .foregroundColor(.secondary) - .font(.caption) if targetString != "" { Text(targetString) - .foregroundColor(.secondary) - .font(.caption) Text(targetString != "" ? state.units.rawValue : "") - .foregroundColor(.secondary) - .font(.caption) } - if durationString != "" { - Text(durationString + (perpetual ? "" : "min")) - .foregroundColor(.secondary) - .font(.caption) } + } + if durationString != "" { Text(durationString + (perpetual ? "" : "min")) } if smbString != "" { Text(smbString).foregroundColor(.secondary).font(.caption) } - Text(scheduledSMBstring) - .foregroundColor(.secondary) - .font(.caption) + if scheduledSMBstring != "" { Text(scheduledSMBstring) } + if preset.advancedSettings { + Text(maxMinutesSMB == 0 ? "" : maxMinutesSMB.formatted() + " SMB") + Text(maxMinutesUAM == 0 ? "" : maxMinutesUAM.formatted() + " UAM") + Text(isfAndCRstring) + } Spacer() - }.padding(.top, 2) + } + .padding(.top, 2) + .foregroundColor(.secondary) + .font(.caption) } .contentShape(Rectangle()) .onTapGesture { From 241ea1615ab9771a2fbacf609fcd804961c94d7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Sat, 27 May 2023 11:17:24 +0200 Subject: [PATCH 05/45] Profles select prest bug (cherry picked from commit 62a52e0d0498380f3469aade2f57074078d1d7fd) --- .../OverrideProfilesConfig/OverrideProfilesStateModel.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift b/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift index 038ce9e99e..402dc45c01 100644 --- a/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift +++ b/FreeAPS/Sources/Modules/OverrideProfilesConfig/OverrideProfilesStateModel.swift @@ -138,6 +138,7 @@ extension OverrideProfilesConfig { saveOverride.id = id_ if profile.advancedSettings { + saveOverride.advancedSettings = true if !isfAndCr { saveOverride.isfAndCr = false saveOverride.isf = profile.isf From 1820508d0061319c73b9e99c32c942dad477c6a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Wed, 31 May 2023 01:52:39 +0200 Subject: [PATCH 06/45] Format new Watch display options (cherry picked from commit 9aeef260b1c6eab7b0155a8432de99acdadd5cc9) --- FreeAPSWatch WatchKit Extension/Views/MainView.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/FreeAPSWatch WatchKit Extension/Views/MainView.swift b/FreeAPSWatch WatchKit Extension/Views/MainView.swift index 07c46ba59d..cdd5cc687e 100644 --- a/FreeAPSWatch WatchKit Extension/Views/MainView.swift +++ b/FreeAPSWatch WatchKit Extension/Views/MainView.swift @@ -176,8 +176,8 @@ struct MainView: View { Image(systemName: "arrow.up.arrow.down") .renderingMode(.template) .resizable() - .frame(width: 16, height: 16) - .foregroundColor(.blue) + .frame(width: 12, height: 12) + .foregroundColor(.loopGreen) Text("\(isf)") .fontWeight(.regular) .font(.caption2) @@ -190,9 +190,9 @@ struct MainView: View { let override: String = state.override != nil ? state.override! : "-" HStack { Image(systemName: "person.3.sequence.fill") - .renderingMode(.template) .resizable() - .frame(width: 24, height: 12) + .symbolRenderingMode(.palette).foregroundStyle(.green, .cyan, .purple) + .frame(height: 12) .foregroundColor(.blue) Text("\(override)") .fontWeight(.regular) From 078d291bb33915965122f0ef36917a0f8af8f23d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Wed, 31 May 2023 13:27:40 +0200 Subject: [PATCH 07/45] Format Apple Watch Override (cherry picked from commit 2f4a861b7c872816859cf1ccf6373fff13aec664) --- FreeAPSWatch WatchKit Extension/Views/MainView.swift | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/FreeAPSWatch WatchKit Extension/Views/MainView.swift b/FreeAPSWatch WatchKit Extension/Views/MainView.swift index cdd5cc687e..ab2268523c 100644 --- a/FreeAPSWatch WatchKit Extension/Views/MainView.swift +++ b/FreeAPSWatch WatchKit Extension/Views/MainView.swift @@ -189,12 +189,7 @@ struct MainView: View { Spacer() let override: String = state.override != nil ? state.override! : "-" HStack { - Image(systemName: "person.3.sequence.fill") - .resizable() - .symbolRenderingMode(.palette).foregroundStyle(.green, .cyan, .purple) - .frame(height: 12) - .foregroundColor(.blue) - Text("\(override)") + Text("👤 \(override)") .fontWeight(.regular) .font(.caption2) .scaledToFill() From 1a4ab879e984303a51f33545fb4ed817aaef13c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20B=20M=C3=A5rtensson?= <53905247+Jon-b-m@users.noreply.github.com> Date: Sat, 3 Jun 2023 18:22:14 +0200 Subject: [PATCH 08/45] More localization and Crowdin translations --- .../OmniBLE/Localizations/ar.lproj/Localizable.strings | 5 ++++- .../OmniBLE/Localizations/da.lproj/Localizable.strings | 5 ++++- .../OmniBLE/Localizations/de.lproj/Localizable.strings | 3 +++ .../OmniBLE/Localizations/en.lproj/Localizable.strings | 5 ++++- .../OmniBLE/Localizations/es.lproj/Localizable.strings | 5 ++++- .../OmniBLE/Localizations/fi.lproj/Localizable.strings | 5 ++++- .../OmniBLE/Localizations/fr.lproj/Localizable.strings | 5 ++++- .../OmniBLE/Localizations/he.lproj/Localizable.strings | 5 ++++- .../OmniBLE/Localizations/it.lproj/Localizable.strings | 5 ++++- .../OmniBLE/Localizations/nb.lproj/Localizable.strings | 3 +++ .../OmniBLE/Localizations/nl.lproj/Localizable.strings | 5 ++++- .../OmniBLE/Localizations/pl.lproj/Localizable.strings | 5 ++++- .../OmniBLE/Localizations/pt-BR.lproj/Localizable.strings | 5 ++++- .../OmniBLE/Localizations/pt-PT.lproj/Localizable.strings | 5 ++++- .../OmniBLE/Localizations/ru.lproj/Localizable.strings | 5 ++++- .../OmniBLE/Localizations/sk.lproj/Localizable.strings | 5 ++++- .../OmniBLE/Localizations/sv.lproj/Localizable.strings | 3 +++ .../OmniBLE/Localizations/tr.lproj/Localizable.strings | 5 ++++- .../OmniBLE/Localizations/uk.lproj/Localizable.strings | 5 ++++- .../OmniBLE/Localizations/zh-Hans.lproj/Localizable.strings | 5 ++++- Dependencies/OmniBLE/OmniBLE/en.lproj/Localizable.strings | 3 +++ .../Sources/Localizations/Main/ar.lproj/Localizable.strings | 5 ++++- .../Sources/Localizations/Main/da.lproj/Localizable.strings | 5 ++++- .../Sources/Localizations/Main/de.lproj/Localizable.strings | 5 ++++- .../Sources/Localizations/Main/en.lproj/Localizable.strings | 3 +++ .../Sources/Localizations/Main/es.lproj/Localizable.strings | 5 ++++- .../Sources/Localizations/Main/fi.lproj/Localizable.strings | 5 ++++- .../Sources/Localizations/Main/fr.lproj/Localizable.strings | 5 ++++- .../Sources/Localizations/Main/he.lproj/Localizable.strings | 5 ++++- .../Sources/Localizations/Main/it.lproj/Localizable.strings | 5 ++++- .../Sources/Localizations/Main/nb.lproj/Localizable.strings | 5 ++++- .../Sources/Localizations/Main/nl.lproj/Localizable.strings | 5 ++++- .../Sources/Localizations/Main/pl.lproj/Localizable.strings | 5 ++++- .../Localizations/Main/pt-BR.lproj/Localizable.strings | 5 ++++- .../Localizations/Main/pt-PT.lproj/Localizable.strings | 5 ++++- .../Sources/Localizations/Main/ru.lproj/Localizable.strings | 5 ++++- .../Sources/Localizations/Main/sk.lproj/Localizable.strings | 5 ++++- .../Sources/Localizations/Main/sv.lproj/Localizable.strings | 3 +++ .../Sources/Localizations/Main/tr.lproj/Localizable.strings | 5 ++++- .../Sources/Localizations/Main/uk.lproj/Localizable.strings | 5 ++++- .../Localizations/Main/zh-Hans.lproj/Localizable.strings | 5 ++++- 41 files changed, 158 insertions(+), 35 deletions(-) diff --git a/Dependencies/OmniBLE/Localizations/ar.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/ar.lproj/Localizable.strings index 5305555e86..2f76433a27 100644 --- a/Dependencies/OmniBLE/Localizations/ar.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/ar.lproj/Localizable.strings @@ -571,7 +571,7 @@ "Critical Alerts" = "Critical Alerts"; /* Description text for critical alerts */ -"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode." = "The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode."; +"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if your device is set to Silent or Do Not Disturb mode." = "The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode."; /* navigation title for notification settings */ "Notification Settings" = "Notification Settings"; @@ -782,3 +782,6 @@ /* Recovery suggestion when operation could not be completed due to existing temp basal in progress */ "Wait for existing temp basal to finish, or suspend to cancel" = "Wait for existing temp basal to finish, or suspend to cancel"; + +/* DASH Pod time ago since last status */ +"%@ ago" = "%@ ago"; diff --git a/Dependencies/OmniBLE/Localizations/da.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/da.lproj/Localizable.strings index 8914b0ab78..804053dcee 100644 --- a/Dependencies/OmniBLE/Localizations/da.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/da.lproj/Localizable.strings @@ -571,7 +571,7 @@ "Critical Alerts" = "Critical Alerts"; /* Description text for critical alerts */ -"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode." = "The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode."; +"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if your device is set to Silent or Do Not Disturb mode." = "The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode."; /* navigation title for notification settings */ "Notification Settings" = "Notification Settings"; @@ -782,3 +782,6 @@ /* Recovery suggestion when operation could not be completed due to existing temp basal in progress */ "Wait for existing temp basal to finish, or suspend to cancel" = "Wait for existing temp basal to finish, or suspend to cancel"; + +/* DASH Pod time ago since last status */ +"%@ ago" = "%@ siden"; diff --git a/Dependencies/OmniBLE/Localizations/de.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/de.lproj/Localizable.strings index 66a04b27cb..85eb6c3b15 100644 --- a/Dependencies/OmniBLE/Localizations/de.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/de.lproj/Localizable.strings @@ -782,3 +782,6 @@ /* Recovery suggestion when operation could not be completed due to existing temp basal in progress */ "Wait for existing temp basal to finish, or suspend to cancel" = "Warte, bis die aktuelle temporäre Basalrate beendet wurde, oder brich sie ab."; + +/* DASH Pod time ago since last status */ +"%@ ago" = "%@ vor"; diff --git a/Dependencies/OmniBLE/Localizations/en.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/en.lproj/Localizable.strings index d63473b325..bd8013e51b 100644 --- a/Dependencies/OmniBLE/Localizations/en.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/en.lproj/Localizable.strings @@ -573,7 +573,7 @@ "Critical Alerts" = "Critical Alerts"; /* Description text for critical alerts */ -"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode." = "The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode."; +"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if your device is set to Silent or Do Not Disturb mode." = "The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode."; /* navigation title for notification settings */ "Notification Settings" = "Notification Settings"; @@ -787,3 +787,6 @@ /* Recovery suggestion when operation could not be completed due to existing temp basal in progress */ "Wait for existing temp basal to finish, or suspend to cancel" = "Wait for existing temp basal to finish, or suspend to cancel"; + +/* DASH Pod time ago since last status */ +"%@ ago" = "%@ ago"; diff --git a/Dependencies/OmniBLE/Localizations/es.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/es.lproj/Localizable.strings index f60e5ef0fd..887b5e5ece 100644 --- a/Dependencies/OmniBLE/Localizations/es.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/es.lproj/Localizable.strings @@ -571,7 +571,7 @@ "Critical Alerts" = "Critical Alerts"; /* Description text for critical alerts */ -"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode." = "The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode."; +"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if your device is set to Silent or Do Not Disturb mode." = "The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode."; /* navigation title for notification settings */ "Notification Settings" = "Notification Settings"; @@ -782,3 +782,6 @@ /* Recovery suggestion when operation could not be completed due to existing temp basal in progress */ "Wait for existing temp basal to finish, or suspend to cancel" = "Wait for existing temp basal to finish, or suspend to cancel"; + +/* DASH Pod time ago since last status */ +"%@ ago" = "Hace %@"; diff --git a/Dependencies/OmniBLE/Localizations/fi.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/fi.lproj/Localizable.strings index fb1ccd1bf4..febdf4e6fb 100644 --- a/Dependencies/OmniBLE/Localizations/fi.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/fi.lproj/Localizable.strings @@ -571,7 +571,7 @@ "Critical Alerts" = "Critical Alerts"; /* Description text for critical alerts */ -"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode." = "The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode."; +"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if your device is set to Silent or Do Not Disturb mode." = "The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode."; /* navigation title for notification settings */ "Notification Settings" = "Notification Settings"; @@ -782,3 +782,6 @@ /* Recovery suggestion when operation could not be completed due to existing temp basal in progress */ "Wait for existing temp basal to finish, or suspend to cancel" = "Wait for existing temp basal to finish, or suspend to cancel"; + +/* DASH Pod time ago since last status */ +"%@ ago" = "%@"; diff --git a/Dependencies/OmniBLE/Localizations/fr.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/fr.lproj/Localizable.strings index 453c5b5add..d127cd2965 100644 --- a/Dependencies/OmniBLE/Localizations/fr.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/fr.lproj/Localizable.strings @@ -571,7 +571,7 @@ "Critical Alerts" = "Alertes critiques"; /* Description text for critical alerts */ -"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode." = "Les rappels ci-dessus ne sonneront pas si votre appareil est en mode silencieux ou Ne pas déranger.\n\nIl y a d'autres alertes et alarmes de Pod critiques qui sonneront même si votre appareil est réglé sur mode Silencieux ou Ne pas déranger."; +"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if your device is set to Silent or Do Not Disturb mode." = "The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode."; /* navigation title for notification settings */ "Notification Settings" = "Paramètres des notifications"; @@ -782,3 +782,6 @@ /* Recovery suggestion when operation could not be completed due to existing temp basal in progress */ "Wait for existing temp basal to finish, or suspend to cancel" = "Wait for existing temp basal to finish, or suspend to cancel"; + +/* DASH Pod time ago since last status */ +"%@ ago" = "Il y a %@"; diff --git a/Dependencies/OmniBLE/Localizations/he.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/he.lproj/Localizable.strings index 5305555e86..2f76433a27 100644 --- a/Dependencies/OmniBLE/Localizations/he.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/he.lproj/Localizable.strings @@ -571,7 +571,7 @@ "Critical Alerts" = "Critical Alerts"; /* Description text for critical alerts */ -"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode." = "The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode."; +"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if your device is set to Silent or Do Not Disturb mode." = "The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode."; /* navigation title for notification settings */ "Notification Settings" = "Notification Settings"; @@ -782,3 +782,6 @@ /* Recovery suggestion when operation could not be completed due to existing temp basal in progress */ "Wait for existing temp basal to finish, or suspend to cancel" = "Wait for existing temp basal to finish, or suspend to cancel"; + +/* DASH Pod time ago since last status */ +"%@ ago" = "%@ ago"; diff --git a/Dependencies/OmniBLE/Localizations/it.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/it.lproj/Localizable.strings index 075235f97f..bbb48733d1 100644 --- a/Dependencies/OmniBLE/Localizations/it.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/it.lproj/Localizable.strings @@ -571,7 +571,7 @@ "Critical Alerts" = "Avvisi critici"; /* Description text for critical alerts */ -"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode." = "I promemoria qui sopra non suoneranno se il dispositivo è in modalità Silenzioso o Non Disturbare.\n\nCi sono altri avvisi e avvisi di Pod critici che suoneranno anche se il dispositivo è impostato in modalità Silenzioso o Non Disturbare."; +"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if your device is set to Silent or Do Not Disturb mode." = "I promemoria qui sopra non suoneranno se il dispositivo è in modalità silenzioso o non disturbare.\n\nCi sono altri avvisi e avvisi di pod critici che suoneranno anche se il dispositivo è impostato in modalità silenzioso o non disturbare."; /* navigation title for notification settings */ "Notification Settings" = "Impostazioni di Notifica"; @@ -782,3 +782,6 @@ /* Recovery suggestion when operation could not be completed due to existing temp basal in progress */ "Wait for existing temp basal to finish, or suspend to cancel" = "Attendi il termine della velocità basale temporanea esistente oppure sospendi per annullare"; + +/* DASH Pod time ago since last status */ +"%@ ago" = "%@ fa"; diff --git a/Dependencies/OmniBLE/Localizations/nb.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/nb.lproj/Localizable.strings index 3b77fed171..a23bd629fd 100644 --- a/Dependencies/OmniBLE/Localizations/nb.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/nb.lproj/Localizable.strings @@ -782,3 +782,6 @@ /* Recovery suggestion when operation could not be completed due to existing temp basal in progress */ "Wait for existing temp basal to finish, or suspend to cancel" = "Vent til eksisterende midlertidig basal er ferdig, eller sett insulintilførsel på pause for å avbryte."; + +/* DASH Pod time ago since last status */ +"%@ ago" = "%@ siden"; diff --git a/Dependencies/OmniBLE/Localizations/nl.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/nl.lproj/Localizable.strings index 8fbd71b9ee..b6e2cf9ad9 100644 --- a/Dependencies/OmniBLE/Localizations/nl.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/nl.lproj/Localizable.strings @@ -571,7 +571,7 @@ "Critical Alerts" = "Kritieke waarschuwingen"; /* Description text for critical alerts */ -"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode." = "De bovenstaande herinneringen waarschuwen zonder geluid als uw apparaat in de modus Stil of Niet storen staat.\n\nEr zijn nog andere belangrijke Pod waarschuwingen en -alarmen die klinken, zelfs als uw apparaat in de modus Stil of Niet storen staat."; +"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if your device is set to Silent or Do Not Disturb mode." = "De bovenstaande meldingen waarschuwen zonder geluid als uw apparaat in de modus Stil of Niet storen staat.\n\nEr zijn andere belangrijke Pod waarschuwingen en -alarmen die wel klinken, zelfs als uw apparaat in de modus Stil of Niet storen staat."; /* navigation title for notification settings */ "Notification Settings" = "Instellingen voor meldingen"; @@ -782,3 +782,6 @@ /* Recovery suggestion when operation could not be completed due to existing temp basal in progress */ "Wait for existing temp basal to finish, or suspend to cancel" = "Wacht op huidig tijdelijk basaal of onderbreek om te annuleren"; + +/* DASH Pod time ago since last status */ +"%@ ago" = "%@ geleden"; diff --git a/Dependencies/OmniBLE/Localizations/pl.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/pl.lproj/Localizable.strings index ea5b7ab360..60976f83ed 100644 --- a/Dependencies/OmniBLE/Localizations/pl.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/pl.lproj/Localizable.strings @@ -571,7 +571,7 @@ "Critical Alerts" = "Critical Alerts"; /* Description text for critical alerts */ -"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode." = "The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode."; +"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if your device is set to Silent or Do Not Disturb mode." = "The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode."; /* navigation title for notification settings */ "Notification Settings" = "Notification Settings"; @@ -782,3 +782,6 @@ /* Recovery suggestion when operation could not be completed due to existing temp basal in progress */ "Wait for existing temp basal to finish, or suspend to cancel" = "Wait for existing temp basal to finish, or suspend to cancel"; + +/* DASH Pod time ago since last status */ +"%@ ago" = "%@ temu"; diff --git a/Dependencies/OmniBLE/Localizations/pt-BR.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/pt-BR.lproj/Localizable.strings index 8d8dfda73e..a5a676276a 100644 --- a/Dependencies/OmniBLE/Localizations/pt-BR.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/pt-BR.lproj/Localizable.strings @@ -571,7 +571,7 @@ "Critical Alerts" = "Critical Alerts"; /* Description text for critical alerts */ -"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode." = "The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode."; +"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if your device is set to Silent or Do Not Disturb mode." = "The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode."; /* navigation title for notification settings */ "Notification Settings" = "Notification Settings"; @@ -782,3 +782,6 @@ /* Recovery suggestion when operation could not be completed due to existing temp basal in progress */ "Wait for existing temp basal to finish, or suspend to cancel" = "Wait for existing temp basal to finish, or suspend to cancel"; + +/* DASH Pod time ago since last status */ +"%@ ago" = "%@ atrás"; diff --git a/Dependencies/OmniBLE/Localizations/pt-PT.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/pt-PT.lproj/Localizable.strings index 8b222792cf..c0c73d2a78 100644 --- a/Dependencies/OmniBLE/Localizations/pt-PT.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/pt-PT.lproj/Localizable.strings @@ -571,7 +571,7 @@ "Critical Alerts" = "Critical Alerts"; /* Description text for critical alerts */ -"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode." = "The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode."; +"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if your device is set to Silent or Do Not Disturb mode." = "The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode."; /* navigation title for notification settings */ "Notification Settings" = "Notification Settings"; @@ -782,3 +782,6 @@ /* Recovery suggestion when operation could not be completed due to existing temp basal in progress */ "Wait for existing temp basal to finish, or suspend to cancel" = "Wait for existing temp basal to finish, or suspend to cancel"; + +/* DASH Pod time ago since last status */ +"%@ ago" = "%@ ago"; diff --git a/Dependencies/OmniBLE/Localizations/ru.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/ru.lproj/Localizable.strings index b89a7e056a..9829fbfae3 100644 --- a/Dependencies/OmniBLE/Localizations/ru.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/ru.lproj/Localizable.strings @@ -571,7 +571,7 @@ "Critical Alerts" = "Критические предупреждения"; /* Description text for critical alerts */ -"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode." = "Напоминания выше не будут издавать звуков, если Ваше устройство в беззвучном режиме или в режиме не беспокоить.\n\nСуществуют другие критические предупреждения Пода и будильники, которые будут звучать, даже если Ваш телефон в беззвучном режиме или в режиме не беспокоить."; +"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if your device is set to Silent or Do Not Disturb mode." = "Приведенные выше напоминания не будут звучать, если ваше устройство находится в режиме отключения звука или \"Не беспокоить\".\n\nСуществуют и другие важные оповещения Pod и сигналы тревоги, которые будут звучать, даже если ваше устройство настроено на беззвучный режим или режим \"Не беспокоить\"."; /* navigation title for notification settings */ "Notification Settings" = "Настройки уведомлений"; @@ -782,3 +782,6 @@ /* Recovery suggestion when operation could not be completed due to existing temp basal in progress */ "Wait for existing temp basal to finish, or suspend to cancel" = "Дождитесь окончания текущего временного базала или отмените его"; + +/* DASH Pod time ago since last status */ +"%@ ago" = "%@ назад"; diff --git a/Dependencies/OmniBLE/Localizations/sk.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/sk.lproj/Localizable.strings index 7122f688e3..61b21cee17 100644 --- a/Dependencies/OmniBLE/Localizations/sk.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/sk.lproj/Localizable.strings @@ -571,7 +571,7 @@ "Critical Alerts" = "Critical Alerts"; /* Description text for critical alerts */ -"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode." = "The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode."; +"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if your device is set to Silent or Do Not Disturb mode." = "The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode."; /* navigation title for notification settings */ "Notification Settings" = "Notification Settings"; @@ -782,3 +782,6 @@ /* Recovery suggestion when operation could not be completed due to existing temp basal in progress */ "Wait for existing temp basal to finish, or suspend to cancel" = "Wait for existing temp basal to finish, or suspend to cancel"; + +/* DASH Pod time ago since last status */ +"%@ ago" = "pred %@"; diff --git a/Dependencies/OmniBLE/Localizations/sv.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/sv.lproj/Localizable.strings index c368fb1469..8b24408d10 100644 --- a/Dependencies/OmniBLE/Localizations/sv.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/sv.lproj/Localizable.strings @@ -782,3 +782,6 @@ /* Recovery suggestion when operation could not be completed due to existing temp basal in progress */ "Wait for existing temp basal to finish, or suspend to cancel" = "Vänta på pågående temp. basal är färdig, alternativt pausa eller avbryt"; + +/* DASH Pod time ago since last status */ +"%@ ago" = "%@ sedan"; diff --git a/Dependencies/OmniBLE/Localizations/tr.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/tr.lproj/Localizable.strings index 575f00b908..86849df9a5 100644 --- a/Dependencies/OmniBLE/Localizations/tr.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/tr.lproj/Localizable.strings @@ -571,7 +571,7 @@ "Critical Alerts" = "Kritik Uyarılar"; /* Description text for critical alerts */ -"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode." = "Cihazınız Sessiz veya Rahatsız Etmeyin modundaysa yukarıdaki hatırlatıcılar çalmaz.\n\nCihazınız Sessiz veya Rahatsız Etmeyin moduna ayarlanmış olsa bile çalacak başka kritik Pod uyarıları ve alarmları vardır."; +"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if your device is set to Silent or Do Not Disturb mode." = "The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode."; /* navigation title for notification settings */ "Notification Settings" = "Bildirim ayarları"; @@ -782,3 +782,6 @@ /* Recovery suggestion when operation could not be completed due to existing temp basal in progress */ "Wait for existing temp basal to finish, or suspend to cancel" = "Mevcut geçici bazalın bitmesini bekleyin veya askıya almak için iptal edin"; + +/* DASH Pod time ago since last status */ +"%@ ago" = "%@ önce"; diff --git a/Dependencies/OmniBLE/Localizations/uk.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/uk.lproj/Localizable.strings index 0f06c541ff..bec8fa3cd6 100644 --- a/Dependencies/OmniBLE/Localizations/uk.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/uk.lproj/Localizable.strings @@ -571,7 +571,7 @@ "Critical Alerts" = "Критичні сповіщення"; /* Description text for critical alerts */ -"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode." = "Нагадування вище не звучатимуть, якщо ваш пристрій перебуває в беззвучному режимі або режимі «Не турбувати».\n\nІснують інші важливі сповіщення та будильники Pod, які лунатимуть, навіть якщо на пристрої встановлено режим «Без звуку» або «Не турбувати»."; +"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if your device is set to Silent or Do Not Disturb mode." = "Нагадування вище не звучатимуть, якщо ваш пристрій перебуває в беззвучному режимі або режимі «Не турбувати».\n\nІснують інші важливі сповіщення та будильники Pod, які лунатимуть, навіть якщо на пристрої встановлено режим «Без звуку» або «Не турбувати»."; /* navigation title for notification settings */ "Notification Settings" = "Параметри сповіщень"; @@ -782,3 +782,6 @@ /* Recovery suggestion when operation could not be completed due to existing temp basal in progress */ "Wait for existing temp basal to finish, or suspend to cancel" = "Зачекайте, доки завершиться наявний тимчасовий базал, або призупиніть, щоб скасувати"; + +/* DASH Pod time ago since last status */ +"%@ ago" = "%@ тому"; diff --git a/Dependencies/OmniBLE/Localizations/zh-Hans.lproj/Localizable.strings b/Dependencies/OmniBLE/Localizations/zh-Hans.lproj/Localizable.strings index 5537a72fa4..446ebb6a11 100644 --- a/Dependencies/OmniBLE/Localizations/zh-Hans.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/Localizations/zh-Hans.lproj/Localizable.strings @@ -571,7 +571,7 @@ "Critical Alerts" = "Critical Alerts"; /* Description text for critical alerts */ -"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode." = "The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode."; +"The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if your device is set to Silent or Do Not Disturb mode." = "The reminders above will not sound if your device is in Silent or Do Not Disturb mode.\n\nThere are other critical Pod alerts and alarms that will sound even if you device is set to Silent or Do Not Disturb mode."; /* navigation title for notification settings */ "Notification Settings" = "通知设置"; @@ -782,3 +782,6 @@ /* Recovery suggestion when operation could not be completed due to existing temp basal in progress */ "Wait for existing temp basal to finish, or suspend to cancel" = "Wait for existing temp basal to finish, or suspend to cancel"; + +/* DASH Pod time ago since last status */ +"%@ ago" = "%@ ago"; diff --git a/Dependencies/OmniBLE/OmniBLE/en.lproj/Localizable.strings b/Dependencies/OmniBLE/OmniBLE/en.lproj/Localizable.strings index acdec02594..0150a675a9 100644 --- a/Dependencies/OmniBLE/OmniBLE/en.lproj/Localizable.strings +++ b/Dependencies/OmniBLE/OmniBLE/en.lproj/Localizable.strings @@ -176,3 +176,6 @@ /* Description waiting for pairing reminder */ "Waiting for pairing reminder" = "Waiting for pairing reminder"; + +/* DASH Pod time ago since last status */ +"%@ ago" = "%@ ago"; diff --git a/FreeAPS/Sources/Localizations/Main/ar.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/ar.lproj/Localizable.strings index 894d22e081..775b7c81b7 100644 --- a/FreeAPS/Sources/Localizations/Main/ar.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/ar.lproj/Localizable.strings @@ -1231,7 +1231,7 @@ Enact a temp Basal or a temp target */ "Start Profile" = "Start Profile"; /* */ -"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal." = "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal."; +"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage." = "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage."; /* */ "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile." = "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile."; @@ -1248,6 +1248,9 @@ Enact a temp Basal or a temp target */ /* Service Section */ "App Icons" = "App Icons"; +/* */ +"iAPS Icon" = "iAPS Icon"; + /* Service Section */ "Statistics and Home View" = "Statistics and Home View"; diff --git a/FreeAPS/Sources/Localizations/Main/da.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/da.lproj/Localizable.strings index 8fc10759d0..5906fd49b9 100644 --- a/FreeAPS/Sources/Localizations/Main/da.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/da.lproj/Localizable.strings @@ -1231,7 +1231,7 @@ Enact a temp Basal or a temp target */ "Start Profile" = "Start Profile"; /* */ -"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal." = "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal."; +"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage." = "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage."; /* */ "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile." = "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile."; @@ -1248,6 +1248,9 @@ Enact a temp Basal or a temp target */ /* Service Section */ "App Icons" = "App Icons"; +/* */ +"iAPS Icon" = "iAPS Icon"; + /* Service Section */ "Statistics and Home View" = "Statistics and Home View"; diff --git a/FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings index 866543945c..cd69e677eb 100644 --- a/FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/de.lproj/Localizable.strings @@ -1231,7 +1231,7 @@ Enact a temp Basal or a temp target */ "Start Profile" = "Profil starten"; /* */ -"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal." = "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal."; +"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage." = "Ihr Profil Basalinsulin wird mit dem Prozentsatz der Überschreibung angepasst und Ihr Profil ISF und CR wird direkt an den Prozentsatz angepasst."; /* */ "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile." = "Das Starten dieser Überschreibung ändert Ihre Profile und/oder Ihren Zielglukosegehalt, der für die Schleifenbildung während der gesamten ausgewählten Dauer verwendet wird. Tippen Sie auf \"Profil starten\", um Ihr neues Profil zu starten oder Ihr aktuell aktives Profil zu bearbeiten."; @@ -1248,6 +1248,9 @@ Enact a temp Basal or a temp target */ /* Service Section */ "App Icons" = "App-Symbole"; +/* */ +"iAPS Icon" = "iAPS Symbol"; + /* Service Section */ "Statistics and Home View" = "Statistiken und Home-Ansicht"; diff --git a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings index 2ff6f1245b..b35aae1fb5 100644 --- a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings @@ -1249,6 +1249,9 @@ Enact a temp Basal or a temp target */ /* Service Section */ "App Icons" = "App Icons"; +/* */ +"iAPS Icon" = "iAPS Icon"; + /* Service Section */ "Statistics and Home View" = "Statistics and Home View"; diff --git a/FreeAPS/Sources/Localizations/Main/es.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/es.lproj/Localizable.strings index 0bc0368efc..96b49b4b5f 100644 --- a/FreeAPS/Sources/Localizations/Main/es.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/es.lproj/Localizable.strings @@ -1231,7 +1231,7 @@ Enact a temp Basal or a temp target */ "Start Profile" = "Start Profile"; /* */ -"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal." = "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal."; +"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage." = "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage."; /* */ "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile." = "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile."; @@ -1248,6 +1248,9 @@ Enact a temp Basal or a temp target */ /* Service Section */ "App Icons" = "App Icons"; +/* */ +"iAPS Icon" = "iAPS Icon"; + /* Service Section */ "Statistics and Home View" = "Statistics and Home View"; diff --git a/FreeAPS/Sources/Localizations/Main/fi.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/fi.lproj/Localizable.strings index 054e5c8067..c02faa49e5 100644 --- a/FreeAPS/Sources/Localizations/Main/fi.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/fi.lproj/Localizable.strings @@ -1231,7 +1231,7 @@ Enact a temp Basal or a temp target */ "Start Profile" = "Start Profile"; /* */ -"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal." = "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal."; +"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage." = "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage."; /* */ "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile." = "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile."; @@ -1248,6 +1248,9 @@ Enact a temp Basal or a temp target */ /* Service Section */ "App Icons" = "App Icons"; +/* */ +"iAPS Icon" = "iAPS Icon"; + /* Service Section */ "Statistics and Home View" = "Statistics and Home View"; diff --git a/FreeAPS/Sources/Localizations/Main/fr.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/fr.lproj/Localizable.strings index 93af0c0670..51f3626c16 100644 --- a/FreeAPS/Sources/Localizations/Main/fr.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/fr.lproj/Localizable.strings @@ -1231,7 +1231,7 @@ Enact a temp Basal or a temp target */ "Start Profile" = "Start Profile"; /* */ -"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal." = "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal."; +"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage." = "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage."; /* */ "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile." = "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile."; @@ -1248,6 +1248,9 @@ Enact a temp Basal or a temp target */ /* Service Section */ "App Icons" = "App Icons"; +/* */ +"iAPS Icon" = "iAPS Icon"; + /* Service Section */ "Statistics and Home View" = "Statistics and Home View"; diff --git a/FreeAPS/Sources/Localizations/Main/he.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/he.lproj/Localizable.strings index 894d22e081..775b7c81b7 100644 --- a/FreeAPS/Sources/Localizations/Main/he.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/he.lproj/Localizable.strings @@ -1231,7 +1231,7 @@ Enact a temp Basal or a temp target */ "Start Profile" = "Start Profile"; /* */ -"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal." = "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal."; +"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage." = "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage."; /* */ "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile." = "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile."; @@ -1248,6 +1248,9 @@ Enact a temp Basal or a temp target */ /* Service Section */ "App Icons" = "App Icons"; +/* */ +"iAPS Icon" = "iAPS Icon"; + /* Service Section */ "Statistics and Home View" = "Statistics and Home View"; diff --git a/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings index 63060cab8f..d87ec9e9aa 100644 --- a/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/it.lproj/Localizable.strings @@ -1231,7 +1231,7 @@ Enact a temp Basal or a temp target */ "Start Profile" = "Avvia Profilo"; /* */ -"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal." = "L'insulina basale del profilo verrà regolata con la percentuale di override e l'ISF e la CR del profilo verranno regolate inversamente con la percentuale.\n\nIf Se si disattiva l'override, ogni impostazione del profilo tornerà alla normalità."; +"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage." = "Il profilo dell’insulina basale sarà regolato con la percentuale di override e invece il profilo ISF e CR sarà regolato in maniera inversamente proporzionale alla percentuale."; /* */ "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile." = "Avviando questa regolazione cambieranno i tuoi profili e/o la tuo Target Glicemico usato per il looping durante l'intera durata selezionata. Toccando ”Profilo di avvio” inizierai il tuo nuovo profilo o modificherai il tuo profilo attivo."; @@ -1248,6 +1248,9 @@ Enact a temp Basal or a temp target */ /* Service Section */ "App Icons" = "Icone App"; +/* */ +"iAPS Icon" = "Icona di iAPS"; + /* Service Section */ "Statistics and Home View" = "Statistiche e Vista Iniziale"; diff --git a/FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings index be32789503..b2550ab120 100644 --- a/FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/nb.lproj/Localizable.strings @@ -1231,7 +1231,7 @@ Enact a temp Basal or a temp target */ "Start Profile" = "Start profil"; /* */ -"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal." = "Profilens basaldose vil bli justert med prosentsatsen og profilens ISF og CR vil bli omvendt justert med prosentsatsen. \n\nHvis du slår av overstyringen vil alle profilinnstillinger gå tilbake til normalen."; +"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage." = "Profilens basaldose vil bli justert med prosentsatsen og profilens ISF og CR vil bli omvendt justert med prosentsatsen."; /* */ "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile." = "Ved å starte denne overstyringen, endres profilen og/eller blodsukkermålet som brukes ved looping, gjennom hele den valgte varigheten. Ved å trykke \"Start profil\" vil den nye profilen starte eller du vil kunne redigere den aktive profilen."; @@ -1248,6 +1248,9 @@ Enact a temp Basal or a temp target */ /* Service Section */ "App Icons" = "App-ikon"; +/* */ +"iAPS Icon" = "iAPS ikon"; + /* Service Section */ "Statistics and Home View" = "Statistikk og startskjerm"; diff --git a/FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings index 6983e85026..e9a2ccd456 100644 --- a/FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/nl.lproj/Localizable.strings @@ -1231,7 +1231,7 @@ Enact a temp Basal or a temp target */ "Start Profile" = "Start profiel"; /* */ -"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal." = "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal."; +"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage." = "Uw basale insuline zal worden aangepast met het overschrijvingspercentage en uw ISF en CR profiel zullen direct worden aangepast aan het percentage."; /* */ "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile." = "Door deze overschrijving te starten, verandert u uw profielen en/of uw streefwaarde voor glucose die voor de looping gedurende de hele geselecteerde duur wordt gebruikt. Door op \"Start profiel\" te tikken, start u uw nieuwe profiel of wijzigt u uw huidige actieve profiel."; @@ -1248,6 +1248,9 @@ Enact a temp Basal or a temp target */ /* Service Section */ "App Icons" = "App iconen"; +/* */ +"iAPS Icon" = "iAPS icoon"; + /* Service Section */ "Statistics and Home View" = "Statistieken en Home View"; diff --git a/FreeAPS/Sources/Localizations/Main/pl.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/pl.lproj/Localizable.strings index dc15e7414f..5685db7796 100644 --- a/FreeAPS/Sources/Localizations/Main/pl.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/pl.lproj/Localizable.strings @@ -1233,7 +1233,7 @@ Połączono z Nightscout!"; "Start Profile" = "Start Profile"; /* */ -"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal." = "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal."; +"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage." = "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage."; /* */ "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile." = "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile."; @@ -1250,6 +1250,9 @@ Połączono z Nightscout!"; /* Service Section */ "App Icons" = "App Icons"; +/* */ +"iAPS Icon" = "iAPS Icon"; + /* Service Section */ "Statistics and Home View" = "Statistics and Home View"; diff --git a/FreeAPS/Sources/Localizations/Main/pt-BR.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/pt-BR.lproj/Localizable.strings index 1304ed77e5..ed569b8146 100644 --- a/FreeAPS/Sources/Localizations/Main/pt-BR.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/pt-BR.lproj/Localizable.strings @@ -1231,7 +1231,7 @@ Enact a temp Basal or a temp target */ "Start Profile" = "Start Profile"; /* */ -"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal." = "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal."; +"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage." = "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage."; /* */ "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile." = "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile."; @@ -1248,6 +1248,9 @@ Enact a temp Basal or a temp target */ /* Service Section */ "App Icons" = "App Icons"; +/* */ +"iAPS Icon" = "iAPS Icon"; + /* Service Section */ "Statistics and Home View" = "Statistics and Home View"; diff --git a/FreeAPS/Sources/Localizations/Main/pt-PT.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/pt-PT.lproj/Localizable.strings index e3383fd93e..bcd4bbf2d7 100644 --- a/FreeAPS/Sources/Localizations/Main/pt-PT.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/pt-PT.lproj/Localizable.strings @@ -1231,7 +1231,7 @@ Enact a temp Basal or a temp target */ "Start Profile" = "Start Profile"; /* */ -"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal." = "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal."; +"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage." = "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage."; /* */ "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile." = "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile."; @@ -1248,6 +1248,9 @@ Enact a temp Basal or a temp target */ /* Service Section */ "App Icons" = "App Icons"; +/* */ +"iAPS Icon" = "iAPS Icon"; + /* Service Section */ "Statistics and Home View" = "Statistics and Home View"; diff --git a/FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings index bc9475a8e8..4a403db32a 100644 --- a/FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/ru.lproj/Localizable.strings @@ -1231,7 +1231,7 @@ Enact a temp Basal or a temp target */ "Start Profile" = "Запустить профиль"; /* */ -"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal." = "Ваш профиль базального инсулина будет скорректирован с учетом процента переопределения, а ваши профили ISF и CR будут скорректированы обратно пропорционально этому проценту.\n\nЕсли вы отключите переопределение, все настройки профиля вернутся в нормальное состояние."; +"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage." = "Ваш профиль базального инсулина будет скорректирован с учетом процента переопределения, а ваши профили ISF и CR будут скорректированы обратно пропорционально этому проценту."; /* */ "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile." = "Запуск этого переопределения приведет к изменению ваших профилей и / или целевого уровня глюкозы, используемого для зацикливания в течение всей выбранной продолжительности. Нажав \"Запустить профиль\", вы запустите свой новый профиль или отредактируете свой текущий активный профиль."; @@ -1248,6 +1248,9 @@ Enact a temp Basal or a temp target */ /* Service Section */ "App Icons" = "Иконки приложения"; +/* */ +"iAPS Icon" = "iAPS иконка"; + /* Service Section */ "Statistics and Home View" = "Статистика и экран"; diff --git a/FreeAPS/Sources/Localizations/Main/sk.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/sk.lproj/Localizable.strings index f9d72a1b72..53d35dfafe 100644 --- a/FreeAPS/Sources/Localizations/Main/sk.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/sk.lproj/Localizable.strings @@ -1231,7 +1231,7 @@ Enact a temp Basal or a temp target */ "Start Profile" = "Start Profile"; /* */ -"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal." = "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal."; +"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage." = "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage."; /* */ "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile." = "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile."; @@ -1248,6 +1248,9 @@ Enact a temp Basal or a temp target */ /* Service Section */ "App Icons" = "App Icons"; +/* */ +"iAPS Icon" = "iAPS Icon"; + /* Service Section */ "Statistics and Home View" = "Statistics and Home View"; diff --git a/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings index d41cf2c3b2..586a798132 100644 --- a/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings @@ -1248,6 +1248,9 @@ Enact a temp Basal or a temp target */ /* Service Section */ "App Icons" = "Ikoner"; +/* */ +"iAPS Icon" = "iAPS - ikon"; + /* Service Section */ "Statistics and Home View" = "Statistik och Diagram"; diff --git a/FreeAPS/Sources/Localizations/Main/tr.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/tr.lproj/Localizable.strings index df3413ccf1..b81203517f 100644 --- a/FreeAPS/Sources/Localizations/Main/tr.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/tr.lproj/Localizable.strings @@ -1231,7 +1231,7 @@ Enact a temp Basal or a temp target */ "Start Profile" = "Start Profile"; /* */ -"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal." = "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal."; +"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage." = "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage."; /* */ "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile." = "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile."; @@ -1248,6 +1248,9 @@ Enact a temp Basal or a temp target */ /* Service Section */ "App Icons" = "App Icons"; +/* */ +"iAPS Icon" = "iAPS Icon"; + /* Service Section */ "Statistics and Home View" = "Statistics and Home View"; diff --git a/FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings index 2dcb1023df..e6112f3fa3 100644 --- a/FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/uk.lproj/Localizable.strings @@ -1231,7 +1231,7 @@ Enact a temp Basal or a temp target */ "Start Profile" = "Почати профіль"; /* */ -"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal." = "Базальний інсулін у вашому профілі буде скориговано з відсотком перевизначення, а ISF і CR у вашому профілі будуть скориговані обернено до відсотка.\n\nЯкщо ви вимкнете перевизначення, усі налаштування профілю повернеться до нормального."; +"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage." = "Ваш профіль базального інсуліну буде скориговано з відсотком перевизначення, а ваш профіль ISF і CR буде обернено скориговано з відсотком."; /* */ "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile." = "Початок цього перевизначення змінить ваші профілі та/або цільовий рівень глюкози, який використовується для циклу протягом усього вибраного періоду. Торкнувшись «Почати профіль», ви запустите новий профіль або відредагуєте поточний активний профіль."; @@ -1248,6 +1248,9 @@ Enact a temp Basal or a temp target */ /* Service Section */ "App Icons" = "Іконки додатку"; +/* */ +"iAPS Icon" = "iAPS значок"; + /* Service Section */ "Statistics and Home View" = "Статистика та Домашня сторінка"; diff --git a/FreeAPS/Sources/Localizations/Main/zh-Hans.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/zh-Hans.lproj/Localizable.strings index 6a3514552b..0715fbb615 100644 --- a/FreeAPS/Sources/Localizations/Main/zh-Hans.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/zh-Hans.lproj/Localizable.strings @@ -1231,7 +1231,7 @@ Enact a temp Basal or a temp target */ "Start Profile" = "Start Profile"; /* */ -"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal." = "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal."; +"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage." = "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage."; /* */ "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile." = "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile."; @@ -1248,6 +1248,9 @@ Enact a temp Basal or a temp target */ /* Service Section */ "App Icons" = "App Icons"; +/* */ +"iAPS Icon" = "iAPS Icon"; + /* Service Section */ "Statistics and Home View" = "Statistics and Home View"; From bd6b40f4178b3ee3f021fb5120e9ea115bda1e6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Sat, 3 Jun 2023 18:30:58 +0200 Subject: [PATCH 09/45] Add % < 3.3 mmol/l and % > 11 mmol/l. Add more for layingTIR chart. Reformat Laying Chart. Typo in Swedish. (cherry picked from commit f359faa6cc326ea8c16cd34309292851fc42396d) --- .../Modules/Stat/View/ChartsView.swift | 141 ++++++++++++++---- 1 file changed, 110 insertions(+), 31 deletions(-) diff --git a/FreeAPS/Sources/Modules/Stat/View/ChartsView.swift b/FreeAPS/Sources/Modules/Stat/View/ChartsView.swift index cbdea0141d..6382c859ab 100644 --- a/FreeAPS/Sources/Modules/Stat/View/ChartsView.swift +++ b/FreeAPS/Sources/Modules/Stat/View/ChartsView.swift @@ -25,7 +25,18 @@ struct ChartsView: View { var body: some View { glucoseChart Rectangle().fill(.cyan.opacity(0.2)).frame(maxHeight: 3) - if standing { tirChart } else { standingTIRchart } + if standing { + VStack { + tirChart + Rectangle().fill(.cyan.opacity(0.2)).frame(maxHeight: 3) + groupedGlucoseStatsLaying + } + } else { + HStack(spacing: 20) { + standingTIRchart + groupedGlucose + } + } } init( @@ -96,12 +107,11 @@ struct ChartsView: View { units == .mmolL ? 15 : 270 ] ) - } // .background(.gray.opacity(0.05)) + } } var tirChart: some View { let fetched = tir() - let low = lowLimit * (units == .mmolL ? Decimal(conversionFactor) : 1) let high = highLimit * (units == .mmolL ? Decimal(conversionFactor) : 1) @@ -110,7 +120,7 @@ struct ChartsView: View { type: NSLocalizedString( "Low", comment: "" - ) + " (\(low.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1)))))", + ) + " (≤\(low.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1)))))", percent: fetched[0].decimal ), .init(type: NSLocalizedString("In Range", comment: ""), percent: fetched[1].decimal), @@ -118,7 +128,7 @@ struct ChartsView: View { type: NSLocalizedString( "High", comment: "" - ) + " (\(high.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1)))))", + ) + " (≥\(high.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1)))))", percent: fetched[2].decimal ) ] @@ -138,12 +148,12 @@ struct ChartsView: View { NSLocalizedString( "Low", comment: "" - ) + " (\(low.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1)))))": .red, + ) + " (≤\(low.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1)))))": .red, NSLocalizedString("In Range", comment: ""): .green, NSLocalizedString( "High", comment: "" - ) + " (\(high.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1)))))": .orange + ) + " (≥\(high.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1)))))": .orange ]).frame(maxHeight: 25) } @@ -156,7 +166,7 @@ struct ChartsView: View { type: NSLocalizedString( "Low", comment: "" - ) + " (\(low.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1)))))", + ) + " (≤ \(low.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1)))))", percent: fetched[0].decimal ), .init(type: NSLocalizedString("In Range", comment: ""), percent: fetched[1].decimal), @@ -164,35 +174,104 @@ struct ChartsView: View { type: NSLocalizedString( "High", comment: "" - ) + " (\(high.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1)))))", + ) + " (≥ \(high.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1)))))", percent: fetched[2].decimal ) ] + return Chart(data) { shape in + BarMark( + x: .value("Shape", shape.type), + y: .value("Percentage", shape.percent) + ) + .foregroundStyle(by: .value("Group", shape.type)) + .annotation(position: .automatic, alignment: .center) { + Text(shape.percent == 0 ? "" : "\(shape.percent, format: .number.precision(.fractionLength(0)))") + } + } + .chartXAxis(.hidden) + .chartForegroundStyleScale([ + NSLocalizedString( + "Low", + comment: "" + ) + " (≤ \(low.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1)))))": .red, + NSLocalizedString("In Range", comment: ""): .green, + NSLocalizedString( + "High", + comment: "" + ) + " (≥ \(high.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1)))))": .orange + ]) + } - return VStack(alignment: .center) { - Chart(data) { shape in - BarMark( - x: .value("Shape", shape.type), - y: .value("Percentage", shape.percent) - ) - .foregroundStyle(by: .value("Group", shape.type)) - .annotation(position: shape.percent <= 9 ? .top : .overlay, alignment: .center) { - Text(shape.percent == 0 ? "" : "\(shape.percent, format: .number.precision(.fractionLength(0))) %") + var groupedGlucose: some View { + VStack(alignment: .leading, spacing: 20) { + let glucose = fetchRequest + let mapGlucose = glucose.compactMap({ each in each.glucose }) + let mapGlucoseAcuteLow = mapGlucose.filter({ $0 < Int16(3.3 / 0.0555) }) + let mapGlucoseHigh = mapGlucose.filter({ $0 > Int16(11 / 0.0555) }) + + HStack { + let value = Double(mapGlucoseHigh.count * 100 / mapGlucose.count) + if value != 0 { + Text(units == .mmolL ? "> 11" : "> 200").foregroundColor(.secondary) + Text(value.formatted()).foregroundColor(.orange) + Text("%").foregroundColor(.secondary) + } + }.font(.caption) + HStack { + let value = Double(mapGlucoseAcuteLow.count * 100 / mapGlucose.count) + if value != 0 { + Text(units == .mmolL ? "< 3.3" : "< 59").foregroundColor(.secondary) + Text(value.formatted()).foregroundColor(.red) + Text("%").foregroundColor(.secondary) + } + }.font(.caption) + } + } + + var groupedGlucoseStatsLaying: some View { + HStack { + let glucose = fetchRequest + + let mapGlucose = glucose.compactMap({ each in each.glucose }) + let mapGlucoseLow = mapGlucose.filter({ $0 < Int16(3.3 / 0.0555) }) + let mapGlucoseAcuteLow = mapGlucose.filter({ $0 < Int16(2.6 / 0.0555) }) + + let mapGlucoseHigh = mapGlucose.filter({ $0 > Int(8.5 / 0.0555) }) + let mapGlucoseAcuteHigh = mapGlucose.filter({ $0 > Int16(11 / 0.0555) }) + + HStack { + let value = Double(mapGlucoseAcuteLow.count * 100 / mapGlucose.count) + if value != 0 { + Text(units == .mmolL ? "< 2.6" : "< 47").font(.caption2).foregroundColor(.secondary) + Text(value.formatted()).font(.caption).foregroundColor(value == 0 ? .green : .red) + Text("%").font(.caption) + } + }.padding(.horizontal, 10) + HStack { + let value = Double(mapGlucoseLow.count * 100 / mapGlucose.count) + if value != 0 { + Text(units == .mmolL ? "< 3.3" : "< 59").font(.caption2).foregroundColor(.secondary) + Text(value.formatted()).font(.caption).foregroundColor(value == 0 ? .green : .orange) + Text("%").font(.caption) + } + } + Spacer() + HStack { + let value = Double(mapGlucoseHigh.count * 100 / mapGlucose.count) + if value != 0 { + Text(units == .mmolL ? "> 8.5" : "> 144").font(.caption).foregroundColor(.secondary) + Text(value.formatted()).font(.caption).foregroundColor(value == 0 ? .green : .orange) + Text("%").font(.caption) + } + }.padding(.horizontal, 10) + HStack { + let value = Double(mapGlucoseAcuteHigh.count * 100 / mapGlucose.count) + if value != 0 { + Text(units == .mmolL ? "> 11.0" : "> 216").font(.caption).foregroundColor(.secondary) + Text(value.formatted()).font(.caption).foregroundColor(value == 0 ? .green : .red) + Text("%").font(.caption) } } - .chartYAxis(.hidden) - .chartLegend(.hidden) - .chartForegroundStyleScale([ - NSLocalizedString( - "Low", - comment: "" - ) + " (\(low.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1)))))": .red, - NSLocalizedString("In Range", comment: ""): .green, - NSLocalizedString( - "High", - comment: "" - ) + " (\(high.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1)))))": .orange - ]) } } From e0454e4849ed52495ab9166c3f6b82448b5f8b6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20B=20M=C3=A5rtensson?= <53905247+Jon-b-m@users.noreply.github.com> Date: Sat, 3 Jun 2023 21:47:28 +0200 Subject: [PATCH 10/45] Single target range (#94) --- .../TargetsEditor/TargetsEditorDataFlow.swift | 4 ++-- .../TargetsEditorStateModel.swift | 6 +++--- .../View/TargetsEditorRootView.swift | 18 +----------------- 3 files changed, 6 insertions(+), 22 deletions(-) diff --git a/FreeAPS/Sources/Modules/TargetsEditor/TargetsEditorDataFlow.swift b/FreeAPS/Sources/Modules/TargetsEditor/TargetsEditorDataFlow.swift index e375fff7e4..bfcd99957a 100644 --- a/FreeAPS/Sources/Modules/TargetsEditor/TargetsEditorDataFlow.swift +++ b/FreeAPS/Sources/Modules/TargetsEditor/TargetsEditorDataFlow.swift @@ -9,9 +9,9 @@ enum TargetsEditor { var highIndex = 0 var timeIndex = 0 - init(lowIndex: Int, highIndex: Int, timeIndex: Int) { + init(lowIndex: Int, highIndex _: Int, timeIndex: Int) { self.lowIndex = lowIndex - self.highIndex = highIndex + highIndex = lowIndex self.timeIndex = timeIndex } diff --git a/FreeAPS/Sources/Modules/TargetsEditor/TargetsEditorStateModel.swift b/FreeAPS/Sources/Modules/TargetsEditor/TargetsEditorStateModel.swift index b50f5ad0e9..723af7d0ed 100644 --- a/FreeAPS/Sources/Modules/TargetsEditor/TargetsEditorStateModel.swift +++ b/FreeAPS/Sources/Modules/TargetsEditor/TargetsEditorStateModel.swift @@ -28,7 +28,7 @@ extension TargetsEditor { items = profile.targets.map { value in let timeIndex = timeValues.firstIndex(of: Double(value.offset * 60)) ?? 0 let lowIndex = rateValues.firstIndex(of: Double(value.low)) ?? 0 - let highIndex = rateValues.firstIndex(of: Double(value.high)) ?? 0 + let highIndex = lowIndex return Item(lowIndex: lowIndex, highIndex: highIndex, timeIndex: timeIndex) } } @@ -40,7 +40,7 @@ extension TargetsEditor { if let last = items.last { time = last.timeIndex + 1 low = last.lowIndex - high = last.highIndex + high = low } let newItem = Item(lowIndex: low, highIndex: high, timeIndex: time) @@ -56,7 +56,7 @@ extension TargetsEditor { let date = Date(timeIntervalSince1970: self.timeValues[item.timeIndex]) let minutes = Int(date.timeIntervalSince1970 / 60) let low = Decimal(self.rateValues[item.lowIndex]) - let high = Decimal(self.rateValues[item.highIndex]) + let high = low return BGTargetEntry(low: low, high: high, start: fotmatter.string(from: date), offset: minutes) } let profile = BGTargets(units: units, userPrefferedUnits: settingsManager.settings.units, targets: targets) diff --git a/FreeAPS/Sources/Modules/TargetsEditor/View/TargetsEditorRootView.swift b/FreeAPS/Sources/Modules/TargetsEditor/View/TargetsEditorRootView.swift index 39a992f9e2..ef4bc4e5bf 100644 --- a/FreeAPS/Sources/Modules/TargetsEditor/View/TargetsEditorRootView.swift +++ b/FreeAPS/Sources/Modules/TargetsEditor/View/TargetsEditorRootView.swift @@ -54,8 +54,7 @@ extension TargetsEditor { GeometryReader { geometry in VStack { HStack { - Text("Low target").frame(width: geometry.size.width / 3) - Text("High target").frame(width: geometry.size.width / 3) + Text("Target").frame(width: geometry.size.width / 3) Text("Time").frame(width: geometry.size.width / 3) } HStack(spacing: 0) { @@ -69,17 +68,6 @@ extension TargetsEditor { } .frame(maxWidth: geometry.size.width / 3) .clipped() - Picker(selection: $state.items[index].highIndex, label: EmptyView()) { - ForEach(0 ..< state.rateValues.count, id: \.self) { i in - Text( - self.rateFormatter - .string(from: state.rateValues[i] as NSNumber) ?? "" - ).tag(i) - } - } - .frame(maxWidth: geometry.size.width / 3) - .clipped() - Picker(selection: $state.items[index].timeIndex, label: EmptyView()) { ForEach(0 ..< state.timeValues.count, id: \.self) { i in Text( @@ -106,10 +94,6 @@ extension TargetsEditor { Text( "\(rateFormatter.string(from: state.rateValues[item.lowIndex] as NSNumber) ?? "0")" ) - Text("–").foregroundColor(.secondary) - Text( - "\(rateFormatter.string(from: state.rateValues[item.highIndex] as NSNumber) ?? "0")" - ) Text("\(state.units.rawValue)").foregroundColor(.secondary) Spacer() Text("starts at").foregroundColor(.secondary) From 23f8999ffcde88614e4a84d27975fd0920e2259b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Sun, 4 Jun 2023 14:16:56 +0200 Subject: [PATCH 11/45] Change Sigmoid dynamic CR ratio to 100% of dynamic ISF ratio. --- FreeAPS/Resources/javascript/bundle/determine-basal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FreeAPS/Resources/javascript/bundle/determine-basal.js b/FreeAPS/Resources/javascript/bundle/determine-basal.js index eebb77c82d..358340d7fe 100644 --- a/FreeAPS/Resources/javascript/bundle/determine-basal.js +++ b/FreeAPS/Resources/javascript/bundle/determine-basal.js @@ -1 +1 @@ -var freeaps_determineBasal;(()=>{var e={5546:(e,t,a)=>{var r=a(6880);function o(e,t){t||(t=0);var a=Math.pow(10,t);return Math.round(e*a)/a}function n(e,t){return"mmol/L"===t.out_units?o(.0555*e,1):Math.round(e)}e.exports=function(e,t,a,i,s,l,m,d,u,c,g,h,p,v){var f=i.min_bg,b=v.overrideTarget;const B=v.smbIsOff,M=v.advancedSettings,_=v.isfAndCr,y=v.isf,x=v.cr,S=v.smbIsAlwaysOff,w=v.start,D=v.end,T=v.smbMinutes,C=v.uamMinutes;var U=0,G="",O="",R="",A="",I="",j=0,F=0,P=0,E=0,q=0,W=0;const k=v.weightedAverage;var L=1,z=i.sens,N=i.carb_ratio;v.useOverride&&(L=v.overridePercentage/100,_?(z/=L,N/=L):(x&&(N/=L),y&&(z/=L)));const H=i.weightPercentage,Z=v.average_total_data;function $(e,t){var a=e.getTime();return new Date(a+36e5*t)}function J(e){var t=i.bolus_increment;.025!=t&&(t=.05);var a=e/t;return a>=1?o(Math.floor(a)*t,5):0}function K(e){function t(e){return e<10&&(e="0"+e),e}return t(e.getHours())+":"+t(e.getMinutes())+":00"}function Q(e,t){var a=new Date("1/1/1999 "+e),r=new Date("1/1/1999 "+t);return(a.getTime()-r.getTime())/36e5}function V(e,t){var a=0,r=t,o=(e-t)/36e5,n=0,i=o,s=0;do{if(o>0){var l=K(r),m=p[0].rate;for(let e=0;e=(s=Q(p[e+1].start,p[e].start))?n=s:o=s?n=s:od)if(e+1=(s=Q(u,l))?n=s:o=(s=Q("23:59:59",l))?n=s:o0&&o21)q=V(X,(ee=24-U,te=X.getTime(),new Date(te-36e5*ee))),A="24 hours of data is required for an accurate tdd calculation. Currently only "+U.toPrecision(3)+" hours of pump history data are available. Using your pump scheduled basals to fill in the missing hours. Scheduled basals added: "+q.toPrecision(5)+" U. ";else U<21?(ge=!1,enableDynamicCR=!1):A=""}else console.log("Pumphistory is empty!"),ge=!1,enableDynamicCR=!1;var ee,te;for(let e=0;e0){j=e,W=g[e].rate;var ae=g[e-1]["duration (min)"]/60,re=ae,oe=new Date(g[e-1].timestamp),ne=oe,ie=0;do{if(e--,0==e){ne=new Date;break}if("TempBasal"==g[e]._type||"PumpSuspend"==g[e]._type){ne=new Date(g[e].timestamp);break}var se=e-2;if(se>=0&&"Rewind"==g[se]._type){let e=g[se].timestamp;for(;se-1>=0&&"Prime"==g[se-=1]._type;)ie=(g[se].timestamp-e)/36e5;ie>=ae&&(ne=e,ie=0)}}while(e>0);var le=(ne-oe)/36e5;le0&&(--r,"TempBasal"==g[r]._type)){a=new Date(g[r].timestamp);break}}while(r>0);(a-t)/36e5>0&&(q+=V(a,t))}for(let e=g.length-1;e>0;e--)if("TempBasalDuration"==g[e]._type){let t=g[e]["duration (min)"]/60,a=new Date(g[e].timestamp);var me=a;let r=e;do{if(--r,r>=0&&("TempBasal"==g[r]._type||"PumpSuspend"==g[r]._type)){me=new Date(g[r].timestamp);break}}while(r>0);if(0==e&&"TempBasalDuration"==g[0]._type&&(me=new Date,t=g[e]["duration (min)"]/60),(me-a)/36e5-t>0){q+=V(me,$(a,t))}}var de,ue={TDD:o(F=E+P+q,5),bolus:o(E,5),temp_basal:o(P,5),scheduled_basal:o(q,5)};U>21?(O=". Bolus insulin: "+E.toPrecision(5)+" U",R=". Temporary basal insulin: "+P.toPrecision(5)+" U",G=". Insulin with scheduled basal rate: "+q.toPrecision(5)+" U",I=A+(" TDD past 24h is: "+F.toPrecision(5)+" U")+O+R+G,tddReason=", Total insulin: "+o(F,2)+" U, "+o(E/F*100,0)+"% Bolus "+o((P+q)/F*100,0)+"% Basal"):tddReason=", TDD: Not enough pumpData (< 21h)";const ce=e.glucose;var ge=h.useNewFormula;const he=h.enableDynamicCR,pe=Math.min(i.autosens_min,i.autosens_max),ve=Math.max(i.autosens_min,i.autosens_max);(ve==pe||ve<1||pe>1)&&(ge=!1,console.log("Dynamic ISF disabled due to current autosens settings"));const fe=h.adjustmentFactor,be=i.min_bg;var Be=!1,Me="",_e=1,ye="";Z>0&&(_e=k/Z),ye=_e>1?"Basal adjustment with a 24 hour to total average (up to 14 days of data) TDD ratio (limited by Autosens max setting). Basal Ratio: "+(_e=o(_e=Math.min(_e,i.autosens_max),2))+". Upper limit = Autosens max ("+i.autosens_max+")":_e<1?"Basal adjustment with a 24 hour to to total average (up to 14 days of data) TDD ratio (limited by Autosens min setting). Basal Ratio: "+(_e=o(_e=Math.max(_e,i.autosens_min),2))+". Lower limit = Autosens min ("+i.autosens_min+")":"Basal adjusted with a 24 hour to total average (up to 14 days of data) TDD ratio: "+_e,ye=", Basal ratio: "+_e,(i.high_temptarget_raises_sensitivity||i.exercise_mode||v.isEnabled)&&(Be=!0),be>=118&&Be&&(ge=!1,Me="Dynamic ISF temporarily off due to a high temp target/exercising. Current min target: "+be);var xe=", Dynamic ratios log: ",Se=", AF: "+fe,we="BG: "+ce+" mg/dl ("+(.0555*ce).toPrecision(2)+" mmol/l)",De="",Te="";const Ce=h.curve,Ue=h.insulinPeakTime,Ge=h.useCustomPeakTime;var Oe=55,Re=65;switch(Ce){case"rapid-acting":Re=65;break;case"ultra-rapid":Re=50}Ge?(Oe=120-Ue,console.log("Custom insulinpeakTime set to :"+Ue+", insulinFactor: "+Oe)):(Oe=120-Re,console.log("insulinFactor set to : "+Oe)),de=F,H<1&&k>0&&(F=k,console.log("Using weighted TDD average: "+o(F,2)+" U, instead of past 24 h ("+o(de,2)+" U), weight: "+H),Te=", Weighted TDD: "+o(F,2)+" U");const Ae=h.sigmoid;var Ie="";if(ge){var je=z*fe*F*Math.log(ce/Oe+1)/1800;De=", Logarithmic formula"}if(ge&&Ae){const e=pe,t=ve-e,a=.0555*(ce-i.min_bg);var Fe=_e,Pe=ve-1;1==ve&&(Pe=ve+.01-1);const r=Math.log10(1/Pe-e/Pe)/Math.log10(Math.E),o=a*fe*Fe+r;je=t/(1+Math.exp(-o))+e,De=", Sigmoid function"}var Ee=N;const qe=o(N,1);var We="",ke="";if(ge&&F>0){if(We=", Dynamic ISF/CR: On/",je>ve?(Me=", Dynamic ISF limited by autosens_max setting: "+ve+" ("+o(je,2)+"), ",ke=", Autosens/Dynamic Limit: "+ve+" ("+o(je,2)+")",je=ve):je1&&(Le=(je-1)/2+1);var ze=" CR: "+(Ee=o(Ee/Le,2))+" g/U";N=Ee}else ze=" CR: "+Ee+" g/U",We+="Off";const e=z/je;s.ratio=je,Ie=". Using Sigmoid function, the autosens ratio has been adjusted with sigmoid factor to: "+o(s.ratio,2)+". New ISF = "+o(e,2)+" mg/dl ("+o(.0555*e,2)+" (mmol/l). CR adjusted from "+o(qe,2)+" to "+o(Ee,2),Me+=Ae?Ie:", Dynamic autosens.ratio set to "+o(je,2)+" with ISF: "+e.toPrecision(3)+" mg/dl/U ("+(.0555*e).toPrecision(3)+" mmol/l/U)",I+=xe+we+Se+De+Me+We+ze+Te}else I+=xe+"Dynamic Settings disabled";console.log(I),ge||he?ge&&i.tddAdjBasal?tddReason+=We+De+ke+Se+ye:ge&&!i.tddAdjBasal&&(tddReason+=We+De+ke+Se):tddReason+="";var Ne={},He=new Date;if(c&&(He=c),void 0===i||void 0===i.current_basal)return Ne.error="Error: could not get current basal rate",Ne;var Ze=r(i.current_basal,i)*L,$e=Ze;v.useOverride&&(0==v.duration?console.log("Profile Override is active. Override "+o(100*L,0)+"%. Override Duration: Enabled indefinitely"):console.log("Profile Override is active. Override "+o(100*L,0)+"%. Override Expires in: "+v.duration+" min."));var Je=new Date;c&&(Je=c);var Ke,Qe=new Date(e.date),Ve=o((Je-Qe)/60/1e3,1),Xe=e.glucose,Ye=e.noise;Ke=e.delta>-.5?"+"+o(e.delta,0):o(e.delta,0);var et=Math.min(e.delta,e.short_avgdelta),tt=Math.min(e.short_avgdelta,e.long_avgdelta),at=Math.max(e.delta,e.short_avgdelta,e.long_avgdelta);(Xe<=10||38===Xe||Ye>=3)&&(Ne.reason="CGM is calibrating, in ??? state, or noise is high");if(Xe>60&&0==e.delta&&e.short_avgdelta>-1&&e.short_avgdelta<1&&e.long_avgdelta>-1&&e.long_avgdelta<1&&("fakecgm"==e.device?(console.error("CGM data is unchanged ("+n(Xe,i)+"+"+n(e.delta,i)+") for 5m w/ "+n(e.short_avgdelta,i)+" mg/dL ~15m change & "+n(e.long_avgdelta,2)+" mg/dL ~45m change"),console.error("Simulator mode detected ("+e.device+"): continuing anyway")):!0),Ve>12||Ve<-5?Ne.reason="If current system time "+Je+" is correct, then BG data is too old. The last BG data was read "+Ve+"m ago at "+Qe:0===e.short_avgdelta&&0===e.long_avgdelta&&(e.last_cal&&e.last_cal<3?Ne.reason="CGM was just calibrated":Ne.reason="CGM data is unchanged ("+n(Xe,i)+"+"+n(e.delta,i)+") for 5m w/ "+n(e.short_avgdelta,i)+" mg/dL ~15m change & "+n(e.long_avgdelta,i)+" mg/dL ~45m change"),Xe<=10||38===Xe||Ye>=3||Ve>12||Ve<-5||0===e.short_avgdelta&&0===e.long_avgdelta)return t.rate>=$e?(Ne.reason+=". Canceling high temp basal of "+t.rate,Ne.deliverAt=He,Ne.temp="absolute",Ne.duration=0,Ne.rate=0,Ne):0===t.rate&&t.duration>30?(Ne.reason+=". Shortening "+t.duration+"m long zero temp to 30m. ",Ne.deliverAt=He,Ne.temp="absolute",Ne.duration=30,Ne.rate=0,Ne):(Ne.reason+=". Temp "+t.rate+" <= current basal "+$e+"U/hr; doing nothing. ",Ne);var rt,ot,nt,it,st=i.max_iob;if(void 0!==i.min_bg&&(ot=i.min_bg),void 0!==i.max_bg&&(nt=i.max_bg),void 0!==i.enableSMB_high_bg_target&&(it=i.enableSMB_high_bg_target),void 0===i.min_bg||void 0===i.max_bg)return Ne.error="Error: could not determine target_bg. ",Ne;rt=(i.min_bg+i.max_bg)/2;var lt=i.exercise_mode||i.high_temptarget_raises_sensitivity||v.isEnabled,mt=100,dt=160;if(dt=i.half_basal_exercise_target,v.isEnabled){const e=v.hbt;console.log("Half Basal Target used: "+n(e,i)+" "+i.out_units),dt=e}else console.log("Default Half Basal Target used: "+n(dt,i)+" "+i.out_units);if(lt&&i.temptargetSet&&rt>mt||i.low_temptarget_lowers_sensitivity&&i.temptargetSet&&rt=rt&&sensitivityRatio0&&(process.stderr.write("TDD-adjustment of basals activated, using tdd24h_14d_Ratio "+o(_e,2)+", TDD 24h = "+o(de,2)+"U, Weighted average TDD = "+o(k,2)+"U, (Weight percentage = "+H+"), Total data of TDDs (up to 14 days) average = "+o(Z,2)+"U. "),$e!==Ze*L?process.stderr.write("Adjusting basal from "+Ze*L+" U/h to "+$e+" U/h; "):process.stderr.write("Basal unchanged: "+$e+" U/h; "))),i.temptargetSet);else if(void 0!==s&&s&&(i.sensitivity_raises_target&&s.ratio<1||i.resistance_lowers_target&&s.ratio>1)){ot=o((ot-60)/s.ratio)+60,nt=o((nt-60)/s.ratio)+60;var ct=o((rt-60)/s.ratio)+60;rt===(ct=Math.max(80,ct))?process.stderr.write("target_bg unchanged: "+n(ct,i)+"; "):process.stderr.write("target_bg from "+n(ct,i)+" to "+n(ct,i)+"; "),rt=ct}var gt=n(rt,i);rt!=f&&(gt=0!==b&&b!==rt?n(f,i)+"→"+n(b,i)+"→"+n(rt,i):n(f,i)+"→"+n(rt,i));var ht=200,pt=200,vt=200;if(e.noise>=2){var ft=Math.max(1.1,i.noisyCGMTargetMultiplier);Math.min(250,i.maxRaw);ht=o(Math.min(200,ot*ft)),pt=o(Math.min(200,rt*ft)),vt=o(Math.min(200,nt*ft)),process.stderr.write("Raising target_bg for noisy / raw CGM data, from "+n(ct,i)+" to "+n(pt,i)+"; "),ot=ht,rt=pt,nt=vt}var bt=ot-.5*(ot-40),Bt=i.threshold_setting;Bt>bt&&Bt<=120&&Bt>=65?(console.error("Threshold changed in settings from "+n(bt,i)+" to "+n(Bt,i)+". "),bt=Bt):console.error("Current threshold: "+n(bt,i));var Mt="",_t=(o(z,1),z);if(void 0!==s&&s&&((_t=o(_t=z/sensitivityRatio,1))!==z?process.stderr.write("ISF from "+n(z,i)+" to "+n(_t,i)):process.stderr.write("ISF unchanged: "+n(_t,i)),Mt+="Autosens ratio: "+o(sensitivityRatio,2)+", ISF: "+n(z,i)+"→"+n(_t,i)),console.error("CR:"+N),void 0===a)return Ne.error="Error: iob_data undefined. ",Ne;var yt,xt=a;if(a.length,a.length>1&&(a=xt[0]),void 0===a.activity||void 0===a.iob)return Ne.error="Error: iob_data missing some property. ",Ne;var St=((yt=void 0!==a.lastTemp?o((new Date(Je).getTime()-a.lastTemp.date)/6e4):0)+t.duration)%30;if(console.error("currenttemp:"+t.rate+" lastTempAge:"+yt+"m, tempModulus:"+St+"m"),Ne.temp="absolute",Ne.deliverAt=He,d&&t&&a.lastTemp&&t.rate!==a.lastTemp.rate&&yt>10&&t.duration)return Ne.reason="Warning: currenttemp rate "+t.rate+" != lastTemp rate "+a.lastTemp.rate+" from pumphistory; canceling temp",m.setTempBasal(0,0,i,Ne,t);if(t&&a.lastTemp&&t.duration>0){var wt=yt-a.lastTemp.duration;if(wt>5&&yt>10)return Ne.reason="Warning: currenttemp running but lastTemp from pumphistory ended "+wt+"m ago; canceling temp",m.setTempBasal(0,0,i,Ne,t)}var Dt=o(-a.activity*_t*5,2),Tt=o(6*(et-Dt));Tt<0&&(Tt=o(6*(tt-Dt)))<0&&(Tt=o(6*(e.long_avgdelta-Dt)));var Ct=Xe,Ut=(Ct=a.iob>0?o(Xe-a.iob*_t):o(Xe-a.iob*Math.min(_t,z)))+Tt;if(void 0===Ut||isNaN(Ut))return Ne.error="Error: could not calculate eventualBG. Sensitivity: "+_t+" Deviation: "+Tt,Ne;var Gt=function(e,t,a){return o(a+(e-t)/24,1)}(rt,Ut,Dt);Ne={temp:"absolute",bg:Xe,tick:Ke,eventualBG:Ut,insulinReq:0,reservoir:u,deliverAt:He,sensitivityRatio,TDD:de,insulin:ue,current_target:rt};var Ot=[],Rt=[],At=[],It=[];Ot.push(Xe),Rt.push(Xe),It.push(Xe),At.push(Xe);var jt=function(e,t,a,r,o,i){return t?!e.allowSMB_with_high_temptarget&&e.temptargetSet&&o>100?(console.error("SMB disabled due to high temptarget of "+o),!1):!0===a.bwFound&&!1===e.A52_risk_enable?(console.error("SMB disabled due to Bolus Wizard activity in the last 6 hours."),!1):!0===e.enableSMB_always?(a.bwFound?console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled due to enableSMB_always"),!0):!0===e.enableSMB_with_COB&&a.mealCOB?(a.bwCarbs?console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for COB of "+a.mealCOB),!0):!0===e.enableSMB_after_carbs&&a.carbs?(a.bwCarbs?console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for 6h after carb entry"),!0):!0===e.enableSMB_with_temptarget&&e.temptargetSet&&o<100?(a.bwFound?console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for temptarget of "+n(o,e)),!0):!0===e.enableSMB_high_bg&&null!==i&&r>=i?(console.error("Checking BG to see if High for SMB enablement."),console.error("Current BG",r," | High BG ",i),a.bwFound?console.error("Warning: High BG SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("High BG detected. Enabling SMB."),!0):(console.error("SMB disabled (no enableSMB preferences active or no condition satisfied)"),!1):(console.error("SMB disabled (!microBolusAllowed)"),!1)}(i,d,l,Xe,rt,it);if(B)if(S){let e=c.getHours();e>=w&&e<=D&&(console.error("SMB disabled by schedule (a Profile is active with SMBs disabled)"),jt=!1)}else console.error("SMBs are disabled (a Profile is active with SMBs disabled)"),jt=!1;var Ft=i.enableUAM,Pt=0,Et=0;Pt=o(et-Dt,1);var qt=o(et-Dt,1);csf=_t/N,console.error("profile.sens:"+n(z,i)+", sens:"+n(_t,i)+", CSF:"+o(csf,1));var Wt=o(30*csf*5/60,1);Pt>Wt&&(console.error("Limiting carb impact from "+Pt+" to "+Wt+"mg/dL/5m (30g/h)"),Pt=Wt);var kt=3;sensitivityRatio&&(kt/=sensitivityRatio);var Lt=kt;if(l.carbs){kt=Math.max(kt,l.mealCOB/20);var zt=o((new Date(Je).getTime()-l.lastCarbTime)/6e4),Nt=(l.carbs-l.mealCOB)/l.carbs;Lt=o(Lt=kt+1.5*zt/60,1),console.error("Last carbs "+zt+" minutes ago; remainingCATime:"+Lt+"hours; "+o(100*Nt,1)+"% carbs absorbed")}var Ht=Math.max(0,Pt/5*60*Lt/2)/csf,Zt=90,$t=1;i.remainingCarbsCap&&(Zt=Math.min(90,i.remainingCarbsCap)),i.remainingCarbsFraction&&($t=Math.min(1,i.remainingCarbsFraction));var Jt=1-$t,Kt=Math.max(0,l.mealCOB-Ht-l.carbs*Jt),Qt=(Kt=Math.min(Zt,Kt))*csf*5/60/(Lt/2),Vt=o(l.slopeFromMaxDeviation,2),Xt=o(l.slopeFromMinDeviation,2),Yt=Math.min(Vt,-Xt/3);Et=0===Pt?0:Math.min(60*Lt/5/2,Math.max(0,l.mealCOB*csf/Pt)),console.error("Carb Impact:"+Pt+"mg/dL per 5m; CI Duration:"+o(5*Et/60*2,1)+"hours; remaining CI ("+Lt/2+"h peak):"+o(Qt,1)+"mg/dL per 5m");var ea,ta,aa,ra,oa,na=999,ia=999,sa=999,la=Xe,ma=999,da=999,ua=999,ca=999,ga=Ut,ha=Xe,pa=Xe,va=0,fa=[],ba=[];try{xt.forEach((function(e){var t=o(-e.activity*_t*5,2),a=o(-e.iobWithZeroTemp.activity*_t*5,2),r=Ct,n=Pt*(1-Math.min(1,Rt.length/12));if(!0===(ge&&!Ae))ga=Rt[Rt.length-1]+o(-e.activity*(1800/(F*fe*Math.log(Math.max(Rt[Rt.length-1],39)/Oe+1)))*5,2)+n,r=It[It.length-1]+o(-e.iobWithZeroTemp.activity*(1800/(F*fe*Math.log(Math.max(It[It.length-1],39)/Oe+1)))*5,2),console.log("Dynamic ISF (Logarithmic Formula) )adjusted predictions for IOB and ZT: IOBpredBG: "+o(ga,2)+" , ZTpredBG: "+o(r,2));else ga=Rt[Rt.length-1]+t+n,r=It[It.length-1]+a;var i=Math.max(0,Math.max(0,Pt)*(1-Ot.length/Math.max(2*Et,1))),s=Math.min(Ot.length,12*Lt-Ot.length),l=Math.max(0,s/(Lt/2*12)*Qt);i+l,fa.push(o(l,0)),ba.push(o(i,0)),COBpredBG=Ot[Ot.length-1]+t+Math.min(0,n)+i+l;var m=Math.max(0,qt+At.length*Yt),d=Math.max(0,qt*(1-At.length/Math.max(36,1))),u=Math.min(m,d);if(u>0&&(va=o(5*(At.length+1)/60,1)),!0===(ge&&!Ae))UAMpredBG=At[At.length-1]+o(-e.activity*(1800/(F*fe*Math.log(Math.max(At[At.length-1],39)/Oe+1)))*5,2)+Math.min(0,n)+u,console.log("Dynamic ISF (Logarithmic Formula) adjusted prediction for UAM: UAMpredBG: "+o(UAMpredBG,2));else UAMpredBG=At[At.length-1]+t+Math.min(0,n)+u;Rt.length<48&&Rt.push(ga),Ot.length<48&&Ot.push(COBpredBG),At.length<48&&At.push(UAMpredBG),It.length<48&&It.push(r),COBpredBG18&&gaha&&(ha=ga),(Et||Qt>0)&&Ot.length>18&&COBpredBG0)&&COBpredBG>ha&&(pa=COBpredBG),Ft&&At.length>12&&UAMpredBGha&&UAMpredBG}))}catch(e){console.error("Problem with iobArray. Optional feature Advanced Meal Assist disabled")}l.mealCOB&&(console.error("predCIs (mg/dL/5m):"+ba.join(" ")),console.error("remainingCIs: "+fa.join(" "))),Ne.predBGs={},Rt.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))}));for(var Ba=Rt.length-1;Ba>12&&Rt[Ba-1]===Rt[Ba];Ba--)Rt.pop();for(Ne.predBGs.IOB=Rt,aa=o(Rt[Rt.length-1]),It.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),Ba=It.length-1;Ba>6&&!(It[Ba-1]>=It[Ba]||It[Ba]<=rt);Ba--)It.pop();if(Ne.predBGs.ZT=It,o(It[It.length-1]),l.mealCOB>0&&(Pt>0||Qt>0)){for(Ot.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),Ba=Ot.length-1;Ba>12&&Ot[Ba-1]===Ot[Ba];Ba--)Ot.pop();Ne.predBGs.COB=Ot,ra=o(Ot[Ot.length-1]),Ut=Math.max(Ut,o(Ot[Ot.length-1]))}if(Pt>0||Qt>0){if(Ft){for(At.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),Ba=At.length-1;Ba>12&&At[Ba-1]===At[Ba];Ba--)At.pop();Ne.predBGs.UAM=At,oa=o(At[At.length-1]),At[At.length-1]&&(Ut=Math.max(Ut,o(At[At.length-1])))}Ne.eventualBG=Ut}console.error("UAM Impact:"+qt+"mg/dL per 5m; UAM Duration:"+va+"hours"),na=Math.max(39,na),ia=Math.max(39,ia),sa=Math.max(39,sa),ea=o(na);var Ma=l.mealCOB/l.carbs;ta=o(sa<999&&ia<999?(1-Ma)*UAMpredBG+Ma*COBpredBG:ia<999?(ga+COBpredBG)/2:sa<999?(ga+UAMpredBG)/2:ga),ca>ta&&(ta=ca),la=o(la=Et||Qt>0?Ft?Ma*ma+(1-Ma)*da:ma:Ft?da:ua);var _a=sa;if(casa&&(_a=(sa+ca)/2);if(_a=o(_a),l.carbs)if(!Ft&&ia<999)ea=o(Math.max(na,ia));else if(ia<999){var xa=Ma*ia+(1-Ma)*_a;ea=o(Math.max(na,ia,xa))}else ea=Ft?_a:la;else Ft&&(ea=o(Math.max(na,_a)));ea=Math.min(ea,ta),process.stderr.write("minPredBG: "+ea+" minIOBPredBG: "+na+" minZTGuardBG: "+ca),ia<999&&process.stderr.write(" minCOBPredBG: "+ia),sa<999&&process.stderr.write(" minUAMPredBG: "+sa),console.error(" avgPredBG:"+ta+" COB/Carbs:"+l.mealCOB+"/"+l.carbs),pa>Xe&&(ea=Math.min(ea,pa)),Ne.COB=l.mealCOB,Ne.IOB=a.iob,Ne.BGI=n(Dt,i),Ne.deviation=n(Tt,i),Ne.ISF=n(_t,i),Ne.CR=o(N,1),Ne.target_bg=n(rt,i),Ne.TDD=o(de,2),Ne.current_target=o(rt,0);var Sa=Ne.CR;qe!=Ne.CR&&(Sa=qe+"→"+Ne.CR),Ne.reason=Mt+", COB: "+Ne.COB+", Dev: "+Ne.deviation+", BGI: "+Ne.BGI+", CR: "+Sa+", Target: "+gt+", minPredBG "+n(ea,i)+", minGuardBG "+n(la,i)+", IOBpredBG "+n(aa,i),ra>0&&(Ne.reason+=", COBpredBG "+n(ra,i)),oa>0&&(Ne.reason+=", UAMpredBG "+n(oa,i)),Ne.reason+=tddReason,Ne.reason+="; ";var wa=Ct;wa<40&&(wa=Math.min(la,wa));var Da,Ta=bt-wa,Ca=240,Ua=240;if(l.mealCOB>0&&(Pt>0||Qt>0)){for(Ba=0;BaDa*Xe&&(console.error("maxDelta "+n(at,i)+" > "+100*Da+"% of BG "+n(Xe,i)+" - disabling SMB"),Ne.reason+="maxDelta "+n(at,i)+" > "+100*Da+"% of BG "+n(Xe,i)+" - SMB disabled!, ",jt=!1),console.error("BG projected to remain above "+n(ot,i)+" for "+Ca+"minutes"),(Ua<240||Ca<60)&&console.error("BG projected to remain above "+n(bt,i)+" for "+Ua+"minutes");var Ga=Ua,Oa=i.current_basal*L*_t*Ga/60,Ra=Math.max(0,l.mealCOB-.25*l.carbs),Aa=(Ta-Oa)/csf-Ra;Oa=o(Oa),Aa=o(Aa),console.error("naive_eventualBG:",Ct,"bgUndershoot:",Ta,"zeroTempDuration:",Ga,"zeroTempEffect:",Oa,"carbsReq:",Aa),"Could not parse clock data"==l.reason?console.error("carbsReq unknown: Could not parse clock data"):Aa>=i.carbsReqThreshold&&Ua<=45&&(Ne.carbsReq=Aa,Ne.reason+=Aa+" add'l carbs req w/in "+Ua+"m; ");var Ia=0;if(Xe0&&et>Gt)Ne.reason+="IOB "+a.iob+" < "+o(-i.current_basal*L*20/60,2),Ne.reason+=" and minDelta "+n(et,i)+" > expectedDelta "+n(Gt,i)+"; ";else if(Xe=55)return Ne.reason+="; Canceling temp at "+Ne.deliverAt.getMinutes()+"m past the hour. ",m.setTempBasal(0,0,i,Ne,t);var ja=0,Fa=$e;if(UtGt&&et>0&&!Aa)return Ct<40?(Ne.reason+=", naive_eventualBG < 40. ",m.setTempBasal(0,30,i,Ne,t)):(e.delta>et?Ne.reason+=", but Delta "+n(Ke,i)+" > expectedDelta "+n(Gt,i):Ne.reason+=", but Min. Delta "+et.toFixed(2)+" > Exp. Delta "+n(Gt,i),t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",m.setTempBasal($e,30,i,Ne,t)));ja=o(ja=2*Math.min(0,(Ut-rt)/_t),2);var Pa=Math.min(0,(Ct-rt)/_t);if(Pa=o(Pa,2),et<0&&et>Gt)ja=o(ja*(et/Gt),2);if(Fa=r(Fa=$e+2*ja,i),t.duration*(t.rate-$e)/605&&Fa>=.8*t.rate)return Ne.reason+=", temp "+t.rate+" ~< req "+Fa+"U/hr. ",Ne;if(Fa<=0){if((Ia=o(60*((Ta=rt-Ct)/_t)/i.current_basal*L))<0?Ia=0:(Ia=30*o(Ia/30),Ia=Math.min(120,Math.max(0,Ia))),Ia>0)return Ne.reason+=", setting "+Ia+"m zero temp. ",m.setTempBasal(Fa,Ia,i,Ne,t)}else Ne.reason+=", setting "+Fa+"U/hr. ";return m.setTempBasal(Fa,30,i,Ne,t)}if(et "+n(ot,i)+" but Delta "+n(Ke,i)+" < Exp. Delta "+n(Gt,i):Ne.reason+="Eventual BG "+n(Ut,i)+" > "+n(ot,i)+" but Min. Delta "+et.toFixed(2)+" < Exp. Delta "+n(Gt,i),t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",m.setTempBasal($e,30,i,Ne,t));if(Math.min(Ut,ea)15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",m.setTempBasal($e,30,i,Ne,t));if(Ut>=nt&&(Ne.reason+="Eventual BG "+n(Ut,i)+" >= "+n(nt,i)+", "),a.iob>st)return Ne.reason+="IOB "+o(a.iob,2)+" > max_iob "+st,t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",m.setTempBasal($e,30,i,Ne,t));(ja=o((Math.min(ea,Ut)-rt)/_t,2))>st-a.iob?(console.error("SMB limited by maxIOB: "+st-a.iob+" (. insulinReq: "+ja+" U)"),Ne.reason+="max_iob "+st+", ",ja=st-a.iob):console.error("SMB not limited by maxIOB ( insulinReq: "+ja+" U)."),Fa=r(Fa=$e+2*ja,i),ja=o(ja,3),Ne.insulinReq=ja;var Ea=o((new Date(Je).getTime()-a.lastBolusTime)/6e4,1);if(d&&jt&&Xe>bt){var qa=30;void 0!==i.maxSMBBasalMinutes&&(qa=i.maxSMBBasalMinutes);var Wa=30;void 0!==i.maxUAMSMBBasalMinutes&&(Wa=i.maxUAMSMBBasalMinutes),v.useOverride&&M&&T!==qa&&(console.error("SMB Max Minutes - setting overriden from "+qa+" to "+T),qa=T),v.useOverride&&M&&C!==Wa&&(console.error("UAM Max Minutes - setting overriden from "+Wa+" to "+C),Wa=C);var ka=o(l.mealCOB/N,3),La=0;void 0===qa?(La=o(i.current_basal*L*30/60,1),console.error("smbMinutesSetting undefined: defaulting to 30m"),ja>La&&console.error("SMB limited by maxBolus: "+La+" ( "+ja+" U)")):a.iob>ka&&a.iob>0?(console.error("IOB"+a.iob+"> COB"+l.mealCOB+"; mealInsulinReq ="+ka),Wa?(console.error("maxUAMSMBBasalMinutes: "+Wa+", profile.current_basal: "+i.current_basal*L),La=o(i.current_basal*L*Wa/60,1)):(console.error("maxUAMSMBBasalMinutes undefined: defaulting to 30m"),La=o(i.current_basal*L*30/60,1)),ja>La?console.error("SMB limited by maxUAMSMBBasalMinutes [ "+Wa+"m ]: "+La+"U ( "+ja+"U )"):console.error("SMB is not limited by maxUAMSMBBasalMinutes. ( insulinReq: "+ja+"U )")):(console.error(".maxSMBBasalMinutes: "+qa+", profile.current_basal: "+i.current_basal*L),ja>(La=o(i.current_basal*qa/60,1))?console.error("SMB limited by maxSMBBasalMinutes: "+qa+"m ]: "+La+"U ( insulinReq: "+ja+"U )"):console.error("SMB is not limited by maxSMBBasalMinutes. ( insulinReq: "+ja+"U )"));var za=i.bolus_increment,Na=1/za,Ha=i.smb_delivery_ratio;Ha>.5&&console.error("SMB Delivery Ratio increased from default 0.5 to "+o(Ha,2));var Za=Math.min(ja*Ha,La);Za=Math.floor(Za*Na)/Na,Ia=o(60*((rt-(Ct+na)/2)/_t)/i.current_basal*L),ja>0&&Za=30?(Ia=30*o(Ia/30),Ia=Math.min(60,Math.max(0,Ia))):($a=o($e*Ia/30,2),Ia=30),Ne.reason+=" insulinReq "+ja,Za>=La&&(Ne.reason+="; maxBolus "+La),Ia>0&&(Ne.reason+="; setting "+Ia+"m low temp of "+$a+"U/h"),Ne.reason+=". ";var Ja=3;i.SMBInterval&&(Ja=Math.min(10,Math.max(1,i.SMBInterval)));var Ka=o(Ja-Ea,0),Qa=o(60*(Ja-Ea),0)%60;if(console.error("naive_eventualBG "+Ct+","+Ia+"m "+$a+"U/h temp needed; last bolus "+Ea+"m ago; maxBolus: "+La),Ea>Ja?Za>0&&(Ne.units=Za,Ne.reason+="Microbolusing "+Za+"U. "):Ne.reason+="Waiting "+Ka+"m "+Qa+"s to microbolus again. ",Ia>0)return Ne.rate=$a,Ne.duration=Ia,Ne}var Va=m.getMaxSafeBasal(i);return Fa>Va&&(Ne.reason+="adj. req. rate: "+Fa+" to maxSafeBasal: "+o(Va,2)+", ",Fa=r(Va,i)),t.duration*(t.rate-$e)/60>=2*ja?(Ne.reason+=t.duration+"m@"+t.rate.toFixed(2)+" > 2 * insulinReq. Setting temp basal of "+Fa+"U/hr. ",m.setTempBasal(Fa,30,i,Ne,t)):void 0===t.duration||0===t.duration?(Ne.reason+="no temp, setting "+Fa+"U/hr. ",m.setTempBasal(Fa,30,i,Ne,t)):t.duration>5&&r(Fa,i)<=r(t.rate,i)?(Ne.reason+="temp "+t.rate+" >~ req "+Fa+"U/hr. ",Ne):(Ne.reason+="temp "+t.rate+"<"+Fa+"U/hr. ",m.setTempBasal(Fa,30,i,Ne,t))}},6880:(e,t,a)=>{var r=a(6654);e.exports=function(e,t){var a=20;void 0!==t&&"string"==typeof t.model&&(r(t.model,"54")||r(t.model,"23"))&&(a=40);return e<1?Math.round(e*a)/a:e<10?Math.round(20*e)/20:Math.round(10*e)/10}},2705:(e,t,a)=>{var r=a(5639).Symbol;e.exports=r},9932:e=>{e.exports=function(e,t){for(var a=-1,r=null==e?0:e.length,o=Array(r);++a{e.exports=function(e,t,a){return e==e&&(void 0!==a&&(e=e<=a?e:a),void 0!==t&&(e=e>=t?e:t)),e}},4239:(e,t,a)=>{var r=a(2705),o=a(9607),n=a(2333),i=r?r.toStringTag:void 0;e.exports=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":i&&i in Object(e)?o(e):n(e)}},531:(e,t,a)=>{var r=a(2705),o=a(9932),n=a(1469),i=a(3448),s=r?r.prototype:void 0,l=s?s.toString:void 0;e.exports=function e(t){if("string"==typeof t)return t;if(n(t))return o(t,e)+"";if(i(t))return l?l.call(t):"";var a=t+"";return"0"==a&&1/t==-Infinity?"-0":a}},7561:(e,t,a)=>{var r=a(7990),o=/^\s+/;e.exports=function(e){return e?e.slice(0,r(e)+1).replace(o,""):e}},1957:(e,t,a)=>{var r="object"==typeof a.g&&a.g&&a.g.Object===Object&&a.g;e.exports=r},9607:(e,t,a)=>{var r=a(2705),o=Object.prototype,n=o.hasOwnProperty,i=o.toString,s=r?r.toStringTag:void 0;e.exports=function(e){var t=n.call(e,s),a=e[s];try{e[s]=void 0;var r=!0}catch(e){}var o=i.call(e);return r&&(t?e[s]=a:delete e[s]),o}},2333:e=>{var t=Object.prototype.toString;e.exports=function(e){return t.call(e)}},5639:(e,t,a)=>{var r=a(1957),o="object"==typeof self&&self&&self.Object===Object&&self,n=r||o||Function("return this")();e.exports=n},7990:e=>{var t=/\s/;e.exports=function(e){for(var a=e.length;a--&&t.test(e.charAt(a)););return a}},6654:(e,t,a)=>{var r=a(9750),o=a(531),n=a(554),i=a(9833);e.exports=function(e,t,a){e=i(e),t=o(t);var s=e.length,l=a=void 0===a?s:r(n(a),0,s);return(a-=t.length)>=0&&e.slice(a,l)==t}},1469:e=>{var t=Array.isArray;e.exports=t},3218:e=>{e.exports=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}},7005:e=>{e.exports=function(e){return null!=e&&"object"==typeof e}},3448:(e,t,a)=>{var r=a(4239),o=a(7005);e.exports=function(e){return"symbol"==typeof e||o(e)&&"[object Symbol]"==r(e)}},8601:(e,t,a)=>{var r=a(4841),o=1/0;e.exports=function(e){return e?(e=r(e))===o||e===-1/0?17976931348623157e292*(e<0?-1:1):e==e?e:0:0===e?e:0}},554:(e,t,a)=>{var r=a(8601);e.exports=function(e){var t=r(e),a=t%1;return t==t?a?t-a:t:0}},4841:(e,t,a)=>{var r=a(7561),o=a(3218),n=a(3448),i=/^[-+]0x[0-9a-f]+$/i,s=/^0b[01]+$/i,l=/^0o[0-7]+$/i,m=parseInt;e.exports=function(e){if("number"==typeof e)return e;if(n(e))return NaN;if(o(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=o(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=r(e);var a=s.test(e);return a||l.test(e)?m(e.slice(2),a?2:8):i.test(e)?NaN:+e}},9833:(e,t,a)=>{var r=a(531);e.exports=function(e){return null==e?"":r(e)}}},t={};function a(r){var o=t[r];if(void 0!==o)return o.exports;var n=t[r]={exports:{}};return e[r](n,n.exports,a),n.exports}a.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}();var r=a(5546);freeaps_determineBasal=r})(); \ No newline at end of file +var freeaps_determineBasal;(()=>{var e={5546:(e,t,a)=>{var r=a(6880);function o(e,t){t||(t=0);var a=Math.pow(10,t);return Math.round(e*a)/a}function n(e,t){return"mmol/L"===t.out_units?o(.0555*e,1):Math.round(e)}e.exports=function(e,t,a,i,s,l,m,d,u,c,g,h,p,v){var f=i.min_bg,b=v.overrideTarget;const B=v.smbIsOff,M=v.advancedSettings,_=v.isfAndCr,y=v.isf,x=v.cr,w=v.smbIsAlwaysOff,D=v.start,S=v.end,T=v.smbMinutes,C=v.uamMinutes;var U=0,G="",O="",R="",A="",I="",j=0,F=0,P=0,E=0,q=0,W=0;const k=v.weightedAverage;var L=1,z=i.sens,N=i.carb_ratio;v.useOverride&&(L=v.overridePercentage/100,_?(z/=L,N/=L):(x&&(N/=L),y&&(z/=L)));const H=i.weightPercentage,Z=v.average_total_data;function $(e,t){var a=e.getTime();return new Date(a+36e5*t)}function J(e){var t=i.bolus_increment;.025!=t&&(t=.05);var a=e/t;return a>=1?o(Math.floor(a)*t,5):0}function K(e){function t(e){return e<10&&(e="0"+e),e}return t(e.getHours())+":"+t(e.getMinutes())+":00"}function Q(e,t){var a=new Date("1/1/1999 "+e),r=new Date("1/1/1999 "+t);return(a.getTime()-r.getTime())/36e5}function V(e,t){var a=0,r=t,o=(e-t)/36e5,n=0,i=o,s=0;do{if(o>0){var l=K(r),m=p[0].rate;for(let e=0;e=(s=Q(p[e+1].start,p[e].start))?n=s:o=s?n=s:od)if(e+1=(s=Q(u,l))?n=s:o=(s=Q("23:59:59",l))?n=s:o0&&o21)q=V(X,(ee=24-U,te=X.getTime(),new Date(te-36e5*ee))),A="24 hours of data is required for an accurate tdd calculation. Currently only "+U.toPrecision(3)+" hours of pump history data are available. Using your pump scheduled basals to fill in the missing hours. Scheduled basals added: "+q.toPrecision(5)+" U. ";else U<21?(ge=!1,enableDynamicCR=!1):A=""}else console.log("Pumphistory is empty!"),ge=!1,enableDynamicCR=!1;var ee,te;for(let e=0;e0){j=e,W=g[e].rate;var ae=g[e-1]["duration (min)"]/60,re=ae,oe=new Date(g[e-1].timestamp),ne=oe,ie=0;do{if(e--,0==e){ne=new Date;break}if("TempBasal"==g[e]._type||"PumpSuspend"==g[e]._type){ne=new Date(g[e].timestamp);break}var se=e-2;if(se>=0&&"Rewind"==g[se]._type){let e=g[se].timestamp;for(;se-1>=0&&"Prime"==g[se-=1]._type;)ie=(g[se].timestamp-e)/36e5;ie>=ae&&(ne=e,ie=0)}}while(e>0);var le=(ne-oe)/36e5;le0&&(--r,"TempBasal"==g[r]._type)){a=new Date(g[r].timestamp);break}}while(r>0);(a-t)/36e5>0&&(q+=V(a,t))}for(let e=g.length-1;e>0;e--)if("TempBasalDuration"==g[e]._type){let t=g[e]["duration (min)"]/60,a=new Date(g[e].timestamp);var me=a;let r=e;do{if(--r,r>=0&&("TempBasal"==g[r]._type||"PumpSuspend"==g[r]._type)){me=new Date(g[r].timestamp);break}}while(r>0);if(0==e&&"TempBasalDuration"==g[0]._type&&(me=new Date,t=g[e]["duration (min)"]/60),(me-a)/36e5-t>0){q+=V(me,$(a,t))}}var de,ue={TDD:o(F=E+P+q,5),bolus:o(E,5),temp_basal:o(P,5),scheduled_basal:o(q,5)};U>21?(O=". Bolus insulin: "+E.toPrecision(5)+" U",R=". Temporary basal insulin: "+P.toPrecision(5)+" U",G=". Insulin with scheduled basal rate: "+q.toPrecision(5)+" U",I=A+(" TDD past 24h is: "+F.toPrecision(5)+" U")+O+R+G,tddReason=", Total insulin: "+o(F,2)+" U, "+o(E/F*100,0)+"% Bolus "+o((P+q)/F*100,0)+"% Basal"):tddReason=", TDD: Not enough pumpData (< 21h)";const ce=e.glucose;var ge=h.useNewFormula;const he=h.enableDynamicCR,pe=Math.min(i.autosens_min,i.autosens_max),ve=Math.max(i.autosens_min,i.autosens_max);(ve==pe||ve<1||pe>1)&&(ge=!1,console.log("Dynamic ISF disabled due to current autosens settings"));const fe=h.adjustmentFactor,be=i.min_bg;var Be=!1,Me="",_e=1,ye="";Z>0&&(_e=k/Z),ye=_e>1?"Basal adjustment with a 24 hour to total average (up to 14 days of data) TDD ratio (limited by Autosens max setting). Basal Ratio: "+(_e=o(_e=Math.min(_e,i.autosens_max),2))+". Upper limit = Autosens max ("+i.autosens_max+")":_e<1?"Basal adjustment with a 24 hour to to total average (up to 14 days of data) TDD ratio (limited by Autosens min setting). Basal Ratio: "+(_e=o(_e=Math.max(_e,i.autosens_min),2))+". Lower limit = Autosens min ("+i.autosens_min+")":"Basal adjusted with a 24 hour to total average (up to 14 days of data) TDD ratio: "+_e,ye=", Basal ratio: "+_e,(i.high_temptarget_raises_sensitivity||i.exercise_mode||v.isEnabled)&&(Be=!0),be>=118&&Be&&(ge=!1,Me="Dynamic ISF temporarily off due to a high temp target/exercising. Current min target: "+be);var xe=", Dynamic ratios log: ",we=", AF: "+fe,De="BG: "+ce+" mg/dl ("+(.0555*ce).toPrecision(2)+" mmol/l)",Se="",Te="";const Ce=h.curve,Ue=h.insulinPeakTime,Ge=h.useCustomPeakTime;var Oe=55,Re=65;switch(Ce){case"rapid-acting":Re=65;break;case"ultra-rapid":Re=50}Ge?(Oe=120-Ue,console.log("Custom insulinpeakTime set to :"+Ue+", insulinFactor: "+Oe)):(Oe=120-Re,console.log("insulinFactor set to : "+Oe)),de=F,H<1&&k>0&&(F=k,console.log("Using weighted TDD average: "+o(F,2)+" U, instead of past 24 h ("+o(de,2)+" U), weight: "+H),Te=", Weighted TDD: "+o(F,2)+" U");const Ae=h.sigmoid;var Ie="";if(ge){var je=z*fe*F*Math.log(ce/Oe+1)/1800;Se=", Logarithmic formula"}if(ge&&Ae){const e=pe,t=ve-e,a=.0555*(ce-i.min_bg);var Fe=_e,Pe=ve-1;1==ve&&(Pe=ve+.01-1);const r=Math.log10(1/Pe-e/Pe)/Math.log10(Math.E),o=a*fe*Fe+r;je=t/(1+Math.exp(-o))+e,Se=", Sigmoid function"}var Ee=N;const qe=o(N,1);var We="",ke="";if(ge&&F>0){if(We=", Dynamic ISF/CR: On/",je>ve?(Me=", Dynamic ISF limited by autosens_max setting: "+ve+" ("+o(je,2)+"), ",ke=", Autosens/Dynamic Limit: "+ve+" ("+o(je,2)+")",je=ve):je-.5?"+"+o(e.delta,0):o(e.delta,0);var Ye=Math.min(e.delta,e.short_avgdelta),et=Math.min(e.short_avgdelta,e.long_avgdelta),tt=Math.max(e.delta,e.short_avgdelta,e.long_avgdelta);(Ve<=10||38===Ve||Xe>=3)&&(ze.reason="CGM is calibrating, in ??? state, or noise is high");if(Ve>60&&0==e.delta&&e.short_avgdelta>-1&&e.short_avgdelta<1&&e.long_avgdelta>-1&&e.long_avgdelta<1&&("fakecgm"==e.device?(console.error("CGM data is unchanged ("+n(Ve,i)+"+"+n(e.delta,i)+") for 5m w/ "+n(e.short_avgdelta,i)+" mg/dL ~15m change & "+n(e.long_avgdelta,2)+" mg/dL ~45m change"),console.error("Simulator mode detected ("+e.device+"): continuing anyway")):!0),Qe>12||Qe<-5?ze.reason="If current system time "+$e+" is correct, then BG data is too old. The last BG data was read "+Qe+"m ago at "+Ke:0===e.short_avgdelta&&0===e.long_avgdelta&&(e.last_cal&&e.last_cal<3?ze.reason="CGM was just calibrated":ze.reason="CGM data is unchanged ("+n(Ve,i)+"+"+n(e.delta,i)+") for 5m w/ "+n(e.short_avgdelta,i)+" mg/dL ~15m change & "+n(e.long_avgdelta,i)+" mg/dL ~45m change"),Ve<=10||38===Ve||Xe>=3||Qe>12||Qe<-5||0===e.short_avgdelta&&0===e.long_avgdelta)return t.rate>=Ze?(ze.reason+=". Canceling high temp basal of "+t.rate,ze.deliverAt=Ne,ze.temp="absolute",ze.duration=0,ze.rate=0,ze):0===t.rate&&t.duration>30?(ze.reason+=". Shortening "+t.duration+"m long zero temp to 30m. ",ze.deliverAt=Ne,ze.temp="absolute",ze.duration=30,ze.rate=0,ze):(ze.reason+=". Temp "+t.rate+" <= current basal "+Ze+"U/hr; doing nothing. ",ze);var at,rt,ot,nt,it=i.max_iob;if(void 0!==i.min_bg&&(rt=i.min_bg),void 0!==i.max_bg&&(ot=i.max_bg),void 0!==i.enableSMB_high_bg_target&&(nt=i.enableSMB_high_bg_target),void 0===i.min_bg||void 0===i.max_bg)return ze.error="Error: could not determine target_bg. ",ze;at=(i.min_bg+i.max_bg)/2;var st=i.exercise_mode||i.high_temptarget_raises_sensitivity||v.isEnabled,lt=100,mt=160;if(mt=i.half_basal_exercise_target,v.isEnabled){const e=v.hbt;console.log("Half Basal Target used: "+n(e,i)+" "+i.out_units),mt=e}else console.log("Default Half Basal Target used: "+n(mt,i)+" "+i.out_units);if(st&&i.temptargetSet&&at>lt||i.low_temptarget_lowers_sensitivity&&i.temptargetSet&&at=at&&sensitivityRatio0&&(process.stderr.write("TDD-adjustment of basals activated, using tdd24h_14d_Ratio "+o(_e,2)+", TDD 24h = "+o(de,2)+"U, Weighted average TDD = "+o(k,2)+"U, (Weight percentage = "+H+"), Total data of TDDs (up to 14 days) average = "+o(Z,2)+"U. "),Ze!==He*L?process.stderr.write("Adjusting basal from "+He*L+" U/h to "+Ze+" U/h; "):process.stderr.write("Basal unchanged: "+Ze+" U/h; "))),i.temptargetSet);else if(void 0!==s&&s&&(i.sensitivity_raises_target&&s.ratio<1||i.resistance_lowers_target&&s.ratio>1)){rt=o((rt-60)/s.ratio)+60,ot=o((ot-60)/s.ratio)+60;var ut=o((at-60)/s.ratio)+60;at===(ut=Math.max(80,ut))?process.stderr.write("target_bg unchanged: "+n(ut,i)+"; "):process.stderr.write("target_bg from "+n(ut,i)+" to "+n(ut,i)+"; "),at=ut}var ct=n(at,i);at!=f&&(ct=0!==b&&b!==at?n(f,i)+"→"+n(b,i)+"→"+n(at,i):n(f,i)+"→"+n(at,i));var gt=200,ht=200,pt=200;if(e.noise>=2){var vt=Math.max(1.1,i.noisyCGMTargetMultiplier);Math.min(250,i.maxRaw);gt=o(Math.min(200,rt*vt)),ht=o(Math.min(200,at*vt)),pt=o(Math.min(200,ot*vt)),process.stderr.write("Raising target_bg for noisy / raw CGM data, from "+n(ut,i)+" to "+n(ht,i)+"; "),rt=gt,at=ht,ot=pt}var ft=rt-.5*(rt-40),bt=i.threshold_setting;bt>ft&&bt<=120&&bt>=65?(console.error("Threshold changed in settings from "+n(ft,i)+" to "+n(bt,i)+". "),ft=bt):console.error("Current threshold: "+n(ft,i));var Bt="",Mt=(o(z,1),z);if(void 0!==s&&s&&((Mt=o(Mt=z/sensitivityRatio,1))!==z?process.stderr.write("ISF from "+n(z,i)+" to "+n(Mt,i)):process.stderr.write("ISF unchanged: "+n(Mt,i)),Bt+="Autosens ratio: "+o(sensitivityRatio,2)+", ISF: "+n(z,i)+"→"+n(Mt,i)),console.error("CR:"+N),void 0===a)return ze.error="Error: iob_data undefined. ",ze;var _t,yt=a;if(a.length,a.length>1&&(a=yt[0]),void 0===a.activity||void 0===a.iob)return ze.error="Error: iob_data missing some property. ",ze;var xt=((_t=void 0!==a.lastTemp?o((new Date($e).getTime()-a.lastTemp.date)/6e4):0)+t.duration)%30;if(console.error("currenttemp:"+t.rate+" lastTempAge:"+_t+"m, tempModulus:"+xt+"m"),ze.temp="absolute",ze.deliverAt=Ne,d&&t&&a.lastTemp&&t.rate!==a.lastTemp.rate&&_t>10&&t.duration)return ze.reason="Warning: currenttemp rate "+t.rate+" != lastTemp rate "+a.lastTemp.rate+" from pumphistory; canceling temp",m.setTempBasal(0,0,i,ze,t);if(t&&a.lastTemp&&t.duration>0){var wt=_t-a.lastTemp.duration;if(wt>5&&_t>10)return ze.reason="Warning: currenttemp running but lastTemp from pumphistory ended "+wt+"m ago; canceling temp",m.setTempBasal(0,0,i,ze,t)}var Dt=o(-a.activity*Mt*5,2),St=o(6*(Ye-Dt));St<0&&(St=o(6*(et-Dt)))<0&&(St=o(6*(e.long_avgdelta-Dt)));var Tt=Ve,Ct=(Tt=a.iob>0?o(Ve-a.iob*Mt):o(Ve-a.iob*Math.min(Mt,z)))+St;if(void 0===Ct||isNaN(Ct))return ze.error="Error: could not calculate eventualBG. Sensitivity: "+Mt+" Deviation: "+St,ze;var Ut=function(e,t,a){return o(a+(e-t)/24,1)}(at,Ct,Dt);ze={temp:"absolute",bg:Ve,tick:Je,eventualBG:Ct,insulinReq:0,reservoir:u,deliverAt:Ne,sensitivityRatio,TDD:de,insulin:ue,current_target:at};var Gt=[],Ot=[],Rt=[],At=[];Gt.push(Ve),Ot.push(Ve),At.push(Ve),Rt.push(Ve);var It=function(e,t,a,r,o,i){return t?!e.allowSMB_with_high_temptarget&&e.temptargetSet&&o>100?(console.error("SMB disabled due to high temptarget of "+o),!1):!0===a.bwFound&&!1===e.A52_risk_enable?(console.error("SMB disabled due to Bolus Wizard activity in the last 6 hours."),!1):!0===e.enableSMB_always?(a.bwFound?console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled due to enableSMB_always"),!0):!0===e.enableSMB_with_COB&&a.mealCOB?(a.bwCarbs?console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for COB of "+a.mealCOB),!0):!0===e.enableSMB_after_carbs&&a.carbs?(a.bwCarbs?console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for 6h after carb entry"),!0):!0===e.enableSMB_with_temptarget&&e.temptargetSet&&o<100?(a.bwFound?console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for temptarget of "+n(o,e)),!0):!0===e.enableSMB_high_bg&&null!==i&&r>=i?(console.error("Checking BG to see if High for SMB enablement."),console.error("Current BG",r," | High BG ",i),a.bwFound?console.error("Warning: High BG SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("High BG detected. Enabling SMB."),!0):(console.error("SMB disabled (no enableSMB preferences active or no condition satisfied)"),!1):(console.error("SMB disabled (!microBolusAllowed)"),!1)}(i,d,l,Ve,at,nt);if(B)if(w){let e=c.getHours();e>=D&&e<=S&&(console.error("SMB disabled by schedule (a Profile is active with SMBs disabled)"),It=!1)}else console.error("SMBs are disabled (a Profile is active with SMBs disabled)"),It=!1;var jt=i.enableUAM,Ft=0,Pt=0;Ft=o(Ye-Dt,1);var Et=o(Ye-Dt,1);csf=Mt/N,console.error("profile.sens:"+n(z,i)+", sens:"+n(Mt,i)+", CSF:"+o(csf,1));var qt=o(30*csf*5/60,1);Ft>qt&&(console.error("Limiting carb impact from "+Ft+" to "+qt+"mg/dL/5m (30g/h)"),Ft=qt);var Wt=3;sensitivityRatio&&(Wt/=sensitivityRatio);var kt=Wt;if(l.carbs){Wt=Math.max(Wt,l.mealCOB/20);var Lt=o((new Date($e).getTime()-l.lastCarbTime)/6e4),zt=(l.carbs-l.mealCOB)/l.carbs;kt=o(kt=Wt+1.5*Lt/60,1),console.error("Last carbs "+Lt+" minutes ago; remainingCATime:"+kt+"hours; "+o(100*zt,1)+"% carbs absorbed")}var Nt=Math.max(0,Ft/5*60*kt/2)/csf,Ht=90,Zt=1;i.remainingCarbsCap&&(Ht=Math.min(90,i.remainingCarbsCap)),i.remainingCarbsFraction&&(Zt=Math.min(1,i.remainingCarbsFraction));var $t=1-Zt,Jt=Math.max(0,l.mealCOB-Nt-l.carbs*$t),Kt=(Jt=Math.min(Ht,Jt))*csf*5/60/(kt/2),Qt=o(l.slopeFromMaxDeviation,2),Vt=o(l.slopeFromMinDeviation,2),Xt=Math.min(Qt,-Vt/3);Pt=0===Ft?0:Math.min(60*kt/5/2,Math.max(0,l.mealCOB*csf/Ft)),console.error("Carb Impact:"+Ft+"mg/dL per 5m; CI Duration:"+o(5*Pt/60*2,1)+"hours; remaining CI ("+kt/2+"h peak):"+o(Kt,1)+"mg/dL per 5m");var Yt,ea,ta,aa,ra,oa=999,na=999,ia=999,sa=Ve,la=999,ma=999,da=999,ua=999,ca=Ct,ga=Ve,ha=Ve,pa=0,va=[],fa=[];try{yt.forEach((function(e){var t=o(-e.activity*Mt*5,2),a=o(-e.iobWithZeroTemp.activity*Mt*5,2),r=Tt,n=Ft*(1-Math.min(1,Ot.length/12));if(!0===(ge&&!Ae))ca=Ot[Ot.length-1]+o(-e.activity*(1800/(F*fe*Math.log(Math.max(Ot[Ot.length-1],39)/Oe+1)))*5,2)+n,r=At[At.length-1]+o(-e.iobWithZeroTemp.activity*(1800/(F*fe*Math.log(Math.max(At[At.length-1],39)/Oe+1)))*5,2),console.log("Dynamic ISF (Logarithmic Formula) )adjusted predictions for IOB and ZT: IOBpredBG: "+o(ca,2)+" , ZTpredBG: "+o(r,2));else ca=Ot[Ot.length-1]+t+n,r=At[At.length-1]+a;var i=Math.max(0,Math.max(0,Ft)*(1-Gt.length/Math.max(2*Pt,1))),s=Math.min(Gt.length,12*kt-Gt.length),l=Math.max(0,s/(kt/2*12)*Kt);i+l,va.push(o(l,0)),fa.push(o(i,0)),COBpredBG=Gt[Gt.length-1]+t+Math.min(0,n)+i+l;var m=Math.max(0,Et+Rt.length*Xt),d=Math.max(0,Et*(1-Rt.length/Math.max(36,1))),u=Math.min(m,d);if(u>0&&(pa=o(5*(Rt.length+1)/60,1)),!0===(ge&&!Ae))UAMpredBG=Rt[Rt.length-1]+o(-e.activity*(1800/(F*fe*Math.log(Math.max(Rt[Rt.length-1],39)/Oe+1)))*5,2)+Math.min(0,n)+u,console.log("Dynamic ISF (Logarithmic Formula) adjusted prediction for UAM: UAMpredBG: "+o(UAMpredBG,2));else UAMpredBG=Rt[Rt.length-1]+t+Math.min(0,n)+u;Ot.length<48&&Ot.push(ca),Gt.length<48&&Gt.push(COBpredBG),Rt.length<48&&Rt.push(UAMpredBG),At.length<48&&At.push(r),COBpredBG18&&caga&&(ga=ca),(Pt||Kt>0)&&Gt.length>18&&COBpredBG0)&&COBpredBG>ga&&(ha=COBpredBG),jt&&Rt.length>12&&UAMpredBGga&&UAMpredBG}))}catch(e){console.error("Problem with iobArray. Optional feature Advanced Meal Assist disabled")}l.mealCOB&&(console.error("predCIs (mg/dL/5m):"+fa.join(" ")),console.error("remainingCIs: "+va.join(" "))),ze.predBGs={},Ot.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))}));for(var ba=Ot.length-1;ba>12&&Ot[ba-1]===Ot[ba];ba--)Ot.pop();for(ze.predBGs.IOB=Ot,ta=o(Ot[Ot.length-1]),At.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),ba=At.length-1;ba>6&&!(At[ba-1]>=At[ba]||At[ba]<=at);ba--)At.pop();if(ze.predBGs.ZT=At,o(At[At.length-1]),l.mealCOB>0&&(Ft>0||Kt>0)){for(Gt.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),ba=Gt.length-1;ba>12&&Gt[ba-1]===Gt[ba];ba--)Gt.pop();ze.predBGs.COB=Gt,aa=o(Gt[Gt.length-1]),Ct=Math.max(Ct,o(Gt[Gt.length-1]))}if(Ft>0||Kt>0){if(jt){for(Rt.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),ba=Rt.length-1;ba>12&&Rt[ba-1]===Rt[ba];ba--)Rt.pop();ze.predBGs.UAM=Rt,ra=o(Rt[Rt.length-1]),Rt[Rt.length-1]&&(Ct=Math.max(Ct,o(Rt[Rt.length-1])))}ze.eventualBG=Ct}console.error("UAM Impact:"+Et+"mg/dL per 5m; UAM Duration:"+pa+"hours"),oa=Math.max(39,oa),na=Math.max(39,na),ia=Math.max(39,ia),Yt=o(oa);var Ba=l.mealCOB/l.carbs;ea=o(ia<999&&na<999?(1-Ba)*UAMpredBG+Ba*COBpredBG:na<999?(ca+COBpredBG)/2:ia<999?(ca+UAMpredBG)/2:ca),ua>ea&&(ea=ua),sa=o(sa=Pt||Kt>0?jt?Ba*la+(1-Ba)*ma:la:jt?ma:da);var Ma=ia;if(uaia&&(Ma=(ia+ua)/2);if(Ma=o(Ma),l.carbs)if(!jt&&na<999)Yt=o(Math.max(oa,na));else if(na<999){var ya=Ba*na+(1-Ba)*Ma;Yt=o(Math.max(oa,na,ya))}else Yt=jt?Ma:sa;else jt&&(Yt=o(Math.max(oa,Ma)));Yt=Math.min(Yt,ea),process.stderr.write("minPredBG: "+Yt+" minIOBPredBG: "+oa+" minZTGuardBG: "+ua),na<999&&process.stderr.write(" minCOBPredBG: "+na),ia<999&&process.stderr.write(" minUAMPredBG: "+ia),console.error(" avgPredBG:"+ea+" COB/Carbs:"+l.mealCOB+"/"+l.carbs),ha>Ve&&(Yt=Math.min(Yt,ha)),ze.COB=l.mealCOB,ze.IOB=a.iob,ze.BGI=n(Dt,i),ze.deviation=n(St,i),ze.ISF=n(Mt,i),ze.CR=o(N,1),ze.target_bg=n(at,i),ze.TDD=o(de,2),ze.current_target=o(at,0);var xa=ze.CR;qe!=ze.CR&&(xa=qe+"→"+ze.CR),ze.reason=Bt+", COB: "+ze.COB+", Dev: "+ze.deviation+", BGI: "+ze.BGI+", CR: "+xa+", Target: "+ct+", minPredBG "+n(Yt,i)+", minGuardBG "+n(sa,i)+", IOBpredBG "+n(ta,i),aa>0&&(ze.reason+=", COBpredBG "+n(aa,i)),ra>0&&(ze.reason+=", UAMpredBG "+n(ra,i)),ze.reason+=tddReason,ze.reason+="; ";var wa=Tt;wa<40&&(wa=Math.min(sa,wa));var Da,Sa=ft-wa,Ta=240,Ca=240;if(l.mealCOB>0&&(Ft>0||Kt>0)){for(ba=0;baDa*Ve&&(console.error("maxDelta "+n(tt,i)+" > "+100*Da+"% of BG "+n(Ve,i)+" - disabling SMB"),ze.reason+="maxDelta "+n(tt,i)+" > "+100*Da+"% of BG "+n(Ve,i)+" - SMB disabled!, ",It=!1),console.error("BG projected to remain above "+n(rt,i)+" for "+Ta+"minutes"),(Ca<240||Ta<60)&&console.error("BG projected to remain above "+n(ft,i)+" for "+Ca+"minutes");var Ua=Ca,Ga=i.current_basal*L*Mt*Ua/60,Oa=Math.max(0,l.mealCOB-.25*l.carbs),Ra=(Sa-Ga)/csf-Oa;Ga=o(Ga),Ra=o(Ra),console.error("naive_eventualBG:",Tt,"bgUndershoot:",Sa,"zeroTempDuration:",Ua,"zeroTempEffect:",Ga,"carbsReq:",Ra),"Could not parse clock data"==l.reason?console.error("carbsReq unknown: Could not parse clock data"):Ra>=i.carbsReqThreshold&&Ca<=45&&(ze.carbsReq=Ra,ze.reason+=Ra+" add'l carbs req w/in "+Ca+"m; ");var Aa=0;if(Ve0&&Ye>Ut)ze.reason+="IOB "+a.iob+" < "+o(-i.current_basal*L*20/60,2),ze.reason+=" and minDelta "+n(Ye,i)+" > expectedDelta "+n(Ut,i)+"; ";else if(Ve=55)return ze.reason+="; Canceling temp at "+ze.deliverAt.getMinutes()+"m past the hour. ",m.setTempBasal(0,0,i,ze,t);var Ia=0,ja=Ze;if(CtUt&&Ye>0&&!Ra)return Tt<40?(ze.reason+=", naive_eventualBG < 40. ",m.setTempBasal(0,30,i,ze,t)):(e.delta>Ye?ze.reason+=", but Delta "+n(Je,i)+" > expectedDelta "+n(Ut,i):ze.reason+=", but Min. Delta "+Ye.toFixed(2)+" > Exp. Delta "+n(Ut,i),t.duration>15&&r(Ze,i)===r(t.rate,i)?(ze.reason+=", temp "+t.rate+" ~ req "+Ze+"U/hr. ",ze):(ze.reason+="; setting current basal of "+Ze+" as temp. ",m.setTempBasal(Ze,30,i,ze,t)));Ia=o(Ia=2*Math.min(0,(Ct-at)/Mt),2);var Fa=Math.min(0,(Tt-at)/Mt);if(Fa=o(Fa,2),Ye<0&&Ye>Ut)Ia=o(Ia*(Ye/Ut),2);if(ja=r(ja=Ze+2*Ia,i),t.duration*(t.rate-Ze)/605&&ja>=.8*t.rate)return ze.reason+=", temp "+t.rate+" ~< req "+ja+"U/hr. ",ze;if(ja<=0){if((Aa=o(60*((Sa=at-Tt)/Mt)/i.current_basal*L))<0?Aa=0:(Aa=30*o(Aa/30),Aa=Math.min(120,Math.max(0,Aa))),Aa>0)return ze.reason+=", setting "+Aa+"m zero temp. ",m.setTempBasal(ja,Aa,i,ze,t)}else ze.reason+=", setting "+ja+"U/hr. ";return m.setTempBasal(ja,30,i,ze,t)}if(Ye "+n(rt,i)+" but Delta "+n(Je,i)+" < Exp. Delta "+n(Ut,i):ze.reason+="Eventual BG "+n(Ct,i)+" > "+n(rt,i)+" but Min. Delta "+Ye.toFixed(2)+" < Exp. Delta "+n(Ut,i),t.duration>15&&r(Ze,i)===r(t.rate,i)?(ze.reason+=", temp "+t.rate+" ~ req "+Ze+"U/hr. ",ze):(ze.reason+="; setting current basal of "+Ze+" as temp. ",m.setTempBasal(Ze,30,i,ze,t));if(Math.min(Ct,Yt)15&&r(Ze,i)===r(t.rate,i)?(ze.reason+=", temp "+t.rate+" ~ req "+Ze+"U/hr. ",ze):(ze.reason+="; setting current basal of "+Ze+" as temp. ",m.setTempBasal(Ze,30,i,ze,t));if(Ct>=ot&&(ze.reason+="Eventual BG "+n(Ct,i)+" >= "+n(ot,i)+", "),a.iob>it)return ze.reason+="IOB "+o(a.iob,2)+" > max_iob "+it,t.duration>15&&r(Ze,i)===r(t.rate,i)?(ze.reason+=", temp "+t.rate+" ~ req "+Ze+"U/hr. ",ze):(ze.reason+="; setting current basal of "+Ze+" as temp. ",m.setTempBasal(Ze,30,i,ze,t));(Ia=o((Math.min(Yt,Ct)-at)/Mt,2))>it-a.iob?(console.error("SMB limited by maxIOB: "+it-a.iob+" (. insulinReq: "+Ia+" U)"),ze.reason+="max_iob "+it+", ",Ia=it-a.iob):console.error("SMB not limited by maxIOB ( insulinReq: "+Ia+" U)."),ja=r(ja=Ze+2*Ia,i),Ia=o(Ia,3),ze.insulinReq=Ia;var Pa=o((new Date($e).getTime()-a.lastBolusTime)/6e4,1);if(d&&It&&Ve>ft){var Ea=30;void 0!==i.maxSMBBasalMinutes&&(Ea=i.maxSMBBasalMinutes);var qa=30;void 0!==i.maxUAMSMBBasalMinutes&&(qa=i.maxUAMSMBBasalMinutes),v.useOverride&&M&&T!==Ea&&(console.error("SMB Max Minutes - setting overriden from "+Ea+" to "+T),Ea=T),v.useOverride&&M&&C!==qa&&(console.error("UAM Max Minutes - setting overriden from "+qa+" to "+C),qa=C);var Wa=o(l.mealCOB/N,3),ka=0;void 0===Ea?(ka=o(i.current_basal*L*30/60,1),console.error("smbMinutesSetting undefined: defaulting to 30m"),Ia>ka&&console.error("SMB limited by maxBolus: "+ka+" ( "+Ia+" U)")):a.iob>Wa&&a.iob>0?(console.error("IOB"+a.iob+"> COB"+l.mealCOB+"; mealInsulinReq ="+Wa),qa?(console.error("maxUAMSMBBasalMinutes: "+qa+", profile.current_basal: "+i.current_basal*L),ka=o(i.current_basal*L*qa/60,1)):(console.error("maxUAMSMBBasalMinutes undefined: defaulting to 30m"),ka=o(i.current_basal*L*30/60,1)),Ia>ka?console.error("SMB limited by maxUAMSMBBasalMinutes [ "+qa+"m ]: "+ka+"U ( "+Ia+"U )"):console.error("SMB is not limited by maxUAMSMBBasalMinutes. ( insulinReq: "+Ia+"U )")):(console.error(".maxSMBBasalMinutes: "+Ea+", profile.current_basal: "+i.current_basal*L),Ia>(ka=o(i.current_basal*Ea/60,1))?console.error("SMB limited by maxSMBBasalMinutes: "+Ea+"m ]: "+ka+"U ( insulinReq: "+Ia+"U )"):console.error("SMB is not limited by maxSMBBasalMinutes. ( insulinReq: "+Ia+"U )"));var La=i.bolus_increment,za=1/La,Na=i.smb_delivery_ratio;Na>.5&&console.error("SMB Delivery Ratio increased from default 0.5 to "+o(Na,2));var Ha=Math.min(Ia*Na,ka);Ha=Math.floor(Ha*za)/za,Aa=o(60*((at-(Tt+oa)/2)/Mt)/i.current_basal*L),Ia>0&&Ha=30?(Aa=30*o(Aa/30),Aa=Math.min(60,Math.max(0,Aa))):(Za=o(Ze*Aa/30,2),Aa=30),ze.reason+=" insulinReq "+Ia,Ha>=ka&&(ze.reason+="; maxBolus "+ka),Aa>0&&(ze.reason+="; setting "+Aa+"m low temp of "+Za+"U/h"),ze.reason+=". ";var $a=3;i.SMBInterval&&($a=Math.min(10,Math.max(1,i.SMBInterval)));var Ja=o($a-Pa,0),Ka=o(60*($a-Pa),0)%60;if(console.error("naive_eventualBG "+Tt+","+Aa+"m "+Za+"U/h temp needed; last bolus "+Pa+"m ago; maxBolus: "+ka),Pa>$a?Ha>0&&(ze.units=Ha,ze.reason+="Microbolusing "+Ha+"U. "):ze.reason+="Waiting "+Ja+"m "+Ka+"s to microbolus again. ",Aa>0)return ze.rate=Za,ze.duration=Aa,ze}var Qa=m.getMaxSafeBasal(i);return ja>Qa&&(ze.reason+="adj. req. rate: "+ja+" to maxSafeBasal: "+o(Qa,2)+", ",ja=r(Qa,i)),t.duration*(t.rate-Ze)/60>=2*Ia?(ze.reason+=t.duration+"m@"+t.rate.toFixed(2)+" > 2 * insulinReq. Setting temp basal of "+ja+"U/hr. ",m.setTempBasal(ja,30,i,ze,t)):void 0===t.duration||0===t.duration?(ze.reason+="no temp, setting "+ja+"U/hr. ",m.setTempBasal(ja,30,i,ze,t)):t.duration>5&&r(ja,i)<=r(t.rate,i)?(ze.reason+="temp "+t.rate+" >~ req "+ja+"U/hr. ",ze):(ze.reason+="temp "+t.rate+"<"+ja+"U/hr. ",m.setTempBasal(ja,30,i,ze,t))}},6880:(e,t,a)=>{var r=a(6654);e.exports=function(e,t){var a=20;void 0!==t&&"string"==typeof t.model&&(r(t.model,"54")||r(t.model,"23"))&&(a=40);return e<1?Math.round(e*a)/a:e<10?Math.round(20*e)/20:Math.round(10*e)/10}},2705:(e,t,a)=>{var r=a(5639).Symbol;e.exports=r},9932:e=>{e.exports=function(e,t){for(var a=-1,r=null==e?0:e.length,o=Array(r);++a{e.exports=function(e,t,a){return e==e&&(void 0!==a&&(e=e<=a?e:a),void 0!==t&&(e=e>=t?e:t)),e}},4239:(e,t,a)=>{var r=a(2705),o=a(9607),n=a(2333),i=r?r.toStringTag:void 0;e.exports=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":i&&i in Object(e)?o(e):n(e)}},531:(e,t,a)=>{var r=a(2705),o=a(9932),n=a(1469),i=a(3448),s=r?r.prototype:void 0,l=s?s.toString:void 0;e.exports=function e(t){if("string"==typeof t)return t;if(n(t))return o(t,e)+"";if(i(t))return l?l.call(t):"";var a=t+"";return"0"==a&&1/t==-Infinity?"-0":a}},7561:(e,t,a)=>{var r=a(7990),o=/^\s+/;e.exports=function(e){return e?e.slice(0,r(e)+1).replace(o,""):e}},1957:(e,t,a)=>{var r="object"==typeof a.g&&a.g&&a.g.Object===Object&&a.g;e.exports=r},9607:(e,t,a)=>{var r=a(2705),o=Object.prototype,n=o.hasOwnProperty,i=o.toString,s=r?r.toStringTag:void 0;e.exports=function(e){var t=n.call(e,s),a=e[s];try{e[s]=void 0;var r=!0}catch(e){}var o=i.call(e);return r&&(t?e[s]=a:delete e[s]),o}},2333:e=>{var t=Object.prototype.toString;e.exports=function(e){return t.call(e)}},5639:(e,t,a)=>{var r=a(1957),o="object"==typeof self&&self&&self.Object===Object&&self,n=r||o||Function("return this")();e.exports=n},7990:e=>{var t=/\s/;e.exports=function(e){for(var a=e.length;a--&&t.test(e.charAt(a)););return a}},6654:(e,t,a)=>{var r=a(9750),o=a(531),n=a(554),i=a(9833);e.exports=function(e,t,a){e=i(e),t=o(t);var s=e.length,l=a=void 0===a?s:r(n(a),0,s);return(a-=t.length)>=0&&e.slice(a,l)==t}},1469:e=>{var t=Array.isArray;e.exports=t},3218:e=>{e.exports=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}},7005:e=>{e.exports=function(e){return null!=e&&"object"==typeof e}},3448:(e,t,a)=>{var r=a(4239),o=a(7005);e.exports=function(e){return"symbol"==typeof e||o(e)&&"[object Symbol]"==r(e)}},8601:(e,t,a)=>{var r=a(4841),o=1/0;e.exports=function(e){return e?(e=r(e))===o||e===-1/0?17976931348623157e292*(e<0?-1:1):e==e?e:0:0===e?e:0}},554:(e,t,a)=>{var r=a(8601);e.exports=function(e){var t=r(e),a=t%1;return t==t?a?t-a:t:0}},4841:(e,t,a)=>{var r=a(7561),o=a(3218),n=a(3448),i=/^[-+]0x[0-9a-f]+$/i,s=/^0b[01]+$/i,l=/^0o[0-7]+$/i,m=parseInt;e.exports=function(e){if("number"==typeof e)return e;if(n(e))return NaN;if(o(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=o(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=r(e);var a=s.test(e);return a||l.test(e)?m(e.slice(2),a?2:8):i.test(e)?NaN:+e}},9833:(e,t,a)=>{var r=a(531);e.exports=function(e){return null==e?"":r(e)}}},t={};function a(r){var o=t[r];if(void 0!==o)return o.exports;var n=t[r]={exports:{}};return e[r](n,n.exports,a),n.exports}a.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}();var r=a(5546);freeaps_determineBasal=r})(); \ No newline at end of file From 551be37995beca8cda252a9a0d0fa4a63f0ced55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Sun, 4 Jun 2023 15:38:40 +0200 Subject: [PATCH 12/45] Display scheduled basal dots UI bug fix for issue nr 60: https://github.com/Artificial-Pancreas/iAPS/issues/60 (cherry picked from commit ffecddaba70b6c2ed7494f4189a3269e03275119) --- FreeAPS/Sources/Modules/Home/View/Chart/MainChartView.swift | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/FreeAPS/Sources/Modules/Home/View/Chart/MainChartView.swift b/FreeAPS/Sources/Modules/Home/View/Chart/MainChartView.swift index a0fc24a099..dc70707ee8 100644 --- a/FreeAPS/Sources/Modules/Home/View/Chart/MainChartView.swift +++ b/FreeAPS/Sources/Modules/Home/View/Chart/MainChartView.swift @@ -667,8 +667,9 @@ extension MainChartView { path.addLine(to: CGPoint(x: lastPoint.x, y: Config.basalHeight)) path.addLine(to: CGPoint(x: 0, y: Config.basalHeight)) } - - let endDateTime = dayAgoTime + min(max(screenHours, 2), 24).hours.timeInterval + min(max(screenHours, 2), 24).hours + let adjustForOptionalExtraHours = screenHours > 12 ? screenHours - 12 : 0 + let endDateTime = dayAgoTime + min(max(screenHours - adjustForOptionalExtraHours, 12), 24).hours + .timeInterval + min(max(screenHours - adjustForOptionalExtraHours, 12), 24).hours .timeInterval let autotunedBasalPoints = findRegularBasalPoints( timeBegin: dayAgoTime, From 2e8b5bc140a99268945e70c314d1ce62b9f5ef93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Sun, 4 Jun 2023 15:39:28 +0200 Subject: [PATCH 13/45] Improve logging dynamic CR (cherry picked from commit 162734a1001d65c9b9c6ed2aa450a0bd9e5640c7) --- FreeAPS/Resources/javascript/bundle/determine-basal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FreeAPS/Resources/javascript/bundle/determine-basal.js b/FreeAPS/Resources/javascript/bundle/determine-basal.js index 358340d7fe..6367dbacba 100644 --- a/FreeAPS/Resources/javascript/bundle/determine-basal.js +++ b/FreeAPS/Resources/javascript/bundle/determine-basal.js @@ -1 +1 @@ -var freeaps_determineBasal;(()=>{var e={5546:(e,t,a)=>{var r=a(6880);function o(e,t){t||(t=0);var a=Math.pow(10,t);return Math.round(e*a)/a}function n(e,t){return"mmol/L"===t.out_units?o(.0555*e,1):Math.round(e)}e.exports=function(e,t,a,i,s,l,m,d,u,c,g,h,p,v){var f=i.min_bg,b=v.overrideTarget;const B=v.smbIsOff,M=v.advancedSettings,_=v.isfAndCr,y=v.isf,x=v.cr,w=v.smbIsAlwaysOff,D=v.start,S=v.end,T=v.smbMinutes,C=v.uamMinutes;var U=0,G="",O="",R="",A="",I="",j=0,F=0,P=0,E=0,q=0,W=0;const k=v.weightedAverage;var L=1,z=i.sens,N=i.carb_ratio;v.useOverride&&(L=v.overridePercentage/100,_?(z/=L,N/=L):(x&&(N/=L),y&&(z/=L)));const H=i.weightPercentage,Z=v.average_total_data;function $(e,t){var a=e.getTime();return new Date(a+36e5*t)}function J(e){var t=i.bolus_increment;.025!=t&&(t=.05);var a=e/t;return a>=1?o(Math.floor(a)*t,5):0}function K(e){function t(e){return e<10&&(e="0"+e),e}return t(e.getHours())+":"+t(e.getMinutes())+":00"}function Q(e,t){var a=new Date("1/1/1999 "+e),r=new Date("1/1/1999 "+t);return(a.getTime()-r.getTime())/36e5}function V(e,t){var a=0,r=t,o=(e-t)/36e5,n=0,i=o,s=0;do{if(o>0){var l=K(r),m=p[0].rate;for(let e=0;e=(s=Q(p[e+1].start,p[e].start))?n=s:o=s?n=s:od)if(e+1=(s=Q(u,l))?n=s:o=(s=Q("23:59:59",l))?n=s:o0&&o21)q=V(X,(ee=24-U,te=X.getTime(),new Date(te-36e5*ee))),A="24 hours of data is required for an accurate tdd calculation. Currently only "+U.toPrecision(3)+" hours of pump history data are available. Using your pump scheduled basals to fill in the missing hours. Scheduled basals added: "+q.toPrecision(5)+" U. ";else U<21?(ge=!1,enableDynamicCR=!1):A=""}else console.log("Pumphistory is empty!"),ge=!1,enableDynamicCR=!1;var ee,te;for(let e=0;e0){j=e,W=g[e].rate;var ae=g[e-1]["duration (min)"]/60,re=ae,oe=new Date(g[e-1].timestamp),ne=oe,ie=0;do{if(e--,0==e){ne=new Date;break}if("TempBasal"==g[e]._type||"PumpSuspend"==g[e]._type){ne=new Date(g[e].timestamp);break}var se=e-2;if(se>=0&&"Rewind"==g[se]._type){let e=g[se].timestamp;for(;se-1>=0&&"Prime"==g[se-=1]._type;)ie=(g[se].timestamp-e)/36e5;ie>=ae&&(ne=e,ie=0)}}while(e>0);var le=(ne-oe)/36e5;le0&&(--r,"TempBasal"==g[r]._type)){a=new Date(g[r].timestamp);break}}while(r>0);(a-t)/36e5>0&&(q+=V(a,t))}for(let e=g.length-1;e>0;e--)if("TempBasalDuration"==g[e]._type){let t=g[e]["duration (min)"]/60,a=new Date(g[e].timestamp);var me=a;let r=e;do{if(--r,r>=0&&("TempBasal"==g[r]._type||"PumpSuspend"==g[r]._type)){me=new Date(g[r].timestamp);break}}while(r>0);if(0==e&&"TempBasalDuration"==g[0]._type&&(me=new Date,t=g[e]["duration (min)"]/60),(me-a)/36e5-t>0){q+=V(me,$(a,t))}}var de,ue={TDD:o(F=E+P+q,5),bolus:o(E,5),temp_basal:o(P,5),scheduled_basal:o(q,5)};U>21?(O=". Bolus insulin: "+E.toPrecision(5)+" U",R=". Temporary basal insulin: "+P.toPrecision(5)+" U",G=". Insulin with scheduled basal rate: "+q.toPrecision(5)+" U",I=A+(" TDD past 24h is: "+F.toPrecision(5)+" U")+O+R+G,tddReason=", Total insulin: "+o(F,2)+" U, "+o(E/F*100,0)+"% Bolus "+o((P+q)/F*100,0)+"% Basal"):tddReason=", TDD: Not enough pumpData (< 21h)";const ce=e.glucose;var ge=h.useNewFormula;const he=h.enableDynamicCR,pe=Math.min(i.autosens_min,i.autosens_max),ve=Math.max(i.autosens_min,i.autosens_max);(ve==pe||ve<1||pe>1)&&(ge=!1,console.log("Dynamic ISF disabled due to current autosens settings"));const fe=h.adjustmentFactor,be=i.min_bg;var Be=!1,Me="",_e=1,ye="";Z>0&&(_e=k/Z),ye=_e>1?"Basal adjustment with a 24 hour to total average (up to 14 days of data) TDD ratio (limited by Autosens max setting). Basal Ratio: "+(_e=o(_e=Math.min(_e,i.autosens_max),2))+". Upper limit = Autosens max ("+i.autosens_max+")":_e<1?"Basal adjustment with a 24 hour to to total average (up to 14 days of data) TDD ratio (limited by Autosens min setting). Basal Ratio: "+(_e=o(_e=Math.max(_e,i.autosens_min),2))+". Lower limit = Autosens min ("+i.autosens_min+")":"Basal adjusted with a 24 hour to total average (up to 14 days of data) TDD ratio: "+_e,ye=", Basal ratio: "+_e,(i.high_temptarget_raises_sensitivity||i.exercise_mode||v.isEnabled)&&(Be=!0),be>=118&&Be&&(ge=!1,Me="Dynamic ISF temporarily off due to a high temp target/exercising. Current min target: "+be);var xe=", Dynamic ratios log: ",we=", AF: "+fe,De="BG: "+ce+" mg/dl ("+(.0555*ce).toPrecision(2)+" mmol/l)",Se="",Te="";const Ce=h.curve,Ue=h.insulinPeakTime,Ge=h.useCustomPeakTime;var Oe=55,Re=65;switch(Ce){case"rapid-acting":Re=65;break;case"ultra-rapid":Re=50}Ge?(Oe=120-Ue,console.log("Custom insulinpeakTime set to :"+Ue+", insulinFactor: "+Oe)):(Oe=120-Re,console.log("insulinFactor set to : "+Oe)),de=F,H<1&&k>0&&(F=k,console.log("Using weighted TDD average: "+o(F,2)+" U, instead of past 24 h ("+o(de,2)+" U), weight: "+H),Te=", Weighted TDD: "+o(F,2)+" U");const Ae=h.sigmoid;var Ie="";if(ge){var je=z*fe*F*Math.log(ce/Oe+1)/1800;Se=", Logarithmic formula"}if(ge&&Ae){const e=pe,t=ve-e,a=.0555*(ce-i.min_bg);var Fe=_e,Pe=ve-1;1==ve&&(Pe=ve+.01-1);const r=Math.log10(1/Pe-e/Pe)/Math.log10(Math.E),o=a*fe*Fe+r;je=t/(1+Math.exp(-o))+e,Se=", Sigmoid function"}var Ee=N;const qe=o(N,1);var We="",ke="";if(ge&&F>0){if(We=", Dynamic ISF/CR: On/",je>ve?(Me=", Dynamic ISF limited by autosens_max setting: "+ve+" ("+o(je,2)+"), ",ke=", Autosens/Dynamic Limit: "+ve+" ("+o(je,2)+")",je=ve):je-.5?"+"+o(e.delta,0):o(e.delta,0);var Ye=Math.min(e.delta,e.short_avgdelta),et=Math.min(e.short_avgdelta,e.long_avgdelta),tt=Math.max(e.delta,e.short_avgdelta,e.long_avgdelta);(Ve<=10||38===Ve||Xe>=3)&&(ze.reason="CGM is calibrating, in ??? state, or noise is high");if(Ve>60&&0==e.delta&&e.short_avgdelta>-1&&e.short_avgdelta<1&&e.long_avgdelta>-1&&e.long_avgdelta<1&&("fakecgm"==e.device?(console.error("CGM data is unchanged ("+n(Ve,i)+"+"+n(e.delta,i)+") for 5m w/ "+n(e.short_avgdelta,i)+" mg/dL ~15m change & "+n(e.long_avgdelta,2)+" mg/dL ~45m change"),console.error("Simulator mode detected ("+e.device+"): continuing anyway")):!0),Qe>12||Qe<-5?ze.reason="If current system time "+$e+" is correct, then BG data is too old. The last BG data was read "+Qe+"m ago at "+Ke:0===e.short_avgdelta&&0===e.long_avgdelta&&(e.last_cal&&e.last_cal<3?ze.reason="CGM was just calibrated":ze.reason="CGM data is unchanged ("+n(Ve,i)+"+"+n(e.delta,i)+") for 5m w/ "+n(e.short_avgdelta,i)+" mg/dL ~15m change & "+n(e.long_avgdelta,i)+" mg/dL ~45m change"),Ve<=10||38===Ve||Xe>=3||Qe>12||Qe<-5||0===e.short_avgdelta&&0===e.long_avgdelta)return t.rate>=Ze?(ze.reason+=". Canceling high temp basal of "+t.rate,ze.deliverAt=Ne,ze.temp="absolute",ze.duration=0,ze.rate=0,ze):0===t.rate&&t.duration>30?(ze.reason+=". Shortening "+t.duration+"m long zero temp to 30m. ",ze.deliverAt=Ne,ze.temp="absolute",ze.duration=30,ze.rate=0,ze):(ze.reason+=". Temp "+t.rate+" <= current basal "+Ze+"U/hr; doing nothing. ",ze);var at,rt,ot,nt,it=i.max_iob;if(void 0!==i.min_bg&&(rt=i.min_bg),void 0!==i.max_bg&&(ot=i.max_bg),void 0!==i.enableSMB_high_bg_target&&(nt=i.enableSMB_high_bg_target),void 0===i.min_bg||void 0===i.max_bg)return ze.error="Error: could not determine target_bg. ",ze;at=(i.min_bg+i.max_bg)/2;var st=i.exercise_mode||i.high_temptarget_raises_sensitivity||v.isEnabled,lt=100,mt=160;if(mt=i.half_basal_exercise_target,v.isEnabled){const e=v.hbt;console.log("Half Basal Target used: "+n(e,i)+" "+i.out_units),mt=e}else console.log("Default Half Basal Target used: "+n(mt,i)+" "+i.out_units);if(st&&i.temptargetSet&&at>lt||i.low_temptarget_lowers_sensitivity&&i.temptargetSet&&at=at&&sensitivityRatio0&&(process.stderr.write("TDD-adjustment of basals activated, using tdd24h_14d_Ratio "+o(_e,2)+", TDD 24h = "+o(de,2)+"U, Weighted average TDD = "+o(k,2)+"U, (Weight percentage = "+H+"), Total data of TDDs (up to 14 days) average = "+o(Z,2)+"U. "),Ze!==He*L?process.stderr.write("Adjusting basal from "+He*L+" U/h to "+Ze+" U/h; "):process.stderr.write("Basal unchanged: "+Ze+" U/h; "))),i.temptargetSet);else if(void 0!==s&&s&&(i.sensitivity_raises_target&&s.ratio<1||i.resistance_lowers_target&&s.ratio>1)){rt=o((rt-60)/s.ratio)+60,ot=o((ot-60)/s.ratio)+60;var ut=o((at-60)/s.ratio)+60;at===(ut=Math.max(80,ut))?process.stderr.write("target_bg unchanged: "+n(ut,i)+"; "):process.stderr.write("target_bg from "+n(ut,i)+" to "+n(ut,i)+"; "),at=ut}var ct=n(at,i);at!=f&&(ct=0!==b&&b!==at?n(f,i)+"→"+n(b,i)+"→"+n(at,i):n(f,i)+"→"+n(at,i));var gt=200,ht=200,pt=200;if(e.noise>=2){var vt=Math.max(1.1,i.noisyCGMTargetMultiplier);Math.min(250,i.maxRaw);gt=o(Math.min(200,rt*vt)),ht=o(Math.min(200,at*vt)),pt=o(Math.min(200,ot*vt)),process.stderr.write("Raising target_bg for noisy / raw CGM data, from "+n(ut,i)+" to "+n(ht,i)+"; "),rt=gt,at=ht,ot=pt}var ft=rt-.5*(rt-40),bt=i.threshold_setting;bt>ft&&bt<=120&&bt>=65?(console.error("Threshold changed in settings from "+n(ft,i)+" to "+n(bt,i)+". "),ft=bt):console.error("Current threshold: "+n(ft,i));var Bt="",Mt=(o(z,1),z);if(void 0!==s&&s&&((Mt=o(Mt=z/sensitivityRatio,1))!==z?process.stderr.write("ISF from "+n(z,i)+" to "+n(Mt,i)):process.stderr.write("ISF unchanged: "+n(Mt,i)),Bt+="Autosens ratio: "+o(sensitivityRatio,2)+", ISF: "+n(z,i)+"→"+n(Mt,i)),console.error("CR:"+N),void 0===a)return ze.error="Error: iob_data undefined. ",ze;var _t,yt=a;if(a.length,a.length>1&&(a=yt[0]),void 0===a.activity||void 0===a.iob)return ze.error="Error: iob_data missing some property. ",ze;var xt=((_t=void 0!==a.lastTemp?o((new Date($e).getTime()-a.lastTemp.date)/6e4):0)+t.duration)%30;if(console.error("currenttemp:"+t.rate+" lastTempAge:"+_t+"m, tempModulus:"+xt+"m"),ze.temp="absolute",ze.deliverAt=Ne,d&&t&&a.lastTemp&&t.rate!==a.lastTemp.rate&&_t>10&&t.duration)return ze.reason="Warning: currenttemp rate "+t.rate+" != lastTemp rate "+a.lastTemp.rate+" from pumphistory; canceling temp",m.setTempBasal(0,0,i,ze,t);if(t&&a.lastTemp&&t.duration>0){var wt=_t-a.lastTemp.duration;if(wt>5&&_t>10)return ze.reason="Warning: currenttemp running but lastTemp from pumphistory ended "+wt+"m ago; canceling temp",m.setTempBasal(0,0,i,ze,t)}var Dt=o(-a.activity*Mt*5,2),St=o(6*(Ye-Dt));St<0&&(St=o(6*(et-Dt)))<0&&(St=o(6*(e.long_avgdelta-Dt)));var Tt=Ve,Ct=(Tt=a.iob>0?o(Ve-a.iob*Mt):o(Ve-a.iob*Math.min(Mt,z)))+St;if(void 0===Ct||isNaN(Ct))return ze.error="Error: could not calculate eventualBG. Sensitivity: "+Mt+" Deviation: "+St,ze;var Ut=function(e,t,a){return o(a+(e-t)/24,1)}(at,Ct,Dt);ze={temp:"absolute",bg:Ve,tick:Je,eventualBG:Ct,insulinReq:0,reservoir:u,deliverAt:Ne,sensitivityRatio,TDD:de,insulin:ue,current_target:at};var Gt=[],Ot=[],Rt=[],At=[];Gt.push(Ve),Ot.push(Ve),At.push(Ve),Rt.push(Ve);var It=function(e,t,a,r,o,i){return t?!e.allowSMB_with_high_temptarget&&e.temptargetSet&&o>100?(console.error("SMB disabled due to high temptarget of "+o),!1):!0===a.bwFound&&!1===e.A52_risk_enable?(console.error("SMB disabled due to Bolus Wizard activity in the last 6 hours."),!1):!0===e.enableSMB_always?(a.bwFound?console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled due to enableSMB_always"),!0):!0===e.enableSMB_with_COB&&a.mealCOB?(a.bwCarbs?console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for COB of "+a.mealCOB),!0):!0===e.enableSMB_after_carbs&&a.carbs?(a.bwCarbs?console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for 6h after carb entry"),!0):!0===e.enableSMB_with_temptarget&&e.temptargetSet&&o<100?(a.bwFound?console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for temptarget of "+n(o,e)),!0):!0===e.enableSMB_high_bg&&null!==i&&r>=i?(console.error("Checking BG to see if High for SMB enablement."),console.error("Current BG",r," | High BG ",i),a.bwFound?console.error("Warning: High BG SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("High BG detected. Enabling SMB."),!0):(console.error("SMB disabled (no enableSMB preferences active or no condition satisfied)"),!1):(console.error("SMB disabled (!microBolusAllowed)"),!1)}(i,d,l,Ve,at,nt);if(B)if(w){let e=c.getHours();e>=D&&e<=S&&(console.error("SMB disabled by schedule (a Profile is active with SMBs disabled)"),It=!1)}else console.error("SMBs are disabled (a Profile is active with SMBs disabled)"),It=!1;var jt=i.enableUAM,Ft=0,Pt=0;Ft=o(Ye-Dt,1);var Et=o(Ye-Dt,1);csf=Mt/N,console.error("profile.sens:"+n(z,i)+", sens:"+n(Mt,i)+", CSF:"+o(csf,1));var qt=o(30*csf*5/60,1);Ft>qt&&(console.error("Limiting carb impact from "+Ft+" to "+qt+"mg/dL/5m (30g/h)"),Ft=qt);var Wt=3;sensitivityRatio&&(Wt/=sensitivityRatio);var kt=Wt;if(l.carbs){Wt=Math.max(Wt,l.mealCOB/20);var Lt=o((new Date($e).getTime()-l.lastCarbTime)/6e4),zt=(l.carbs-l.mealCOB)/l.carbs;kt=o(kt=Wt+1.5*Lt/60,1),console.error("Last carbs "+Lt+" minutes ago; remainingCATime:"+kt+"hours; "+o(100*zt,1)+"% carbs absorbed")}var Nt=Math.max(0,Ft/5*60*kt/2)/csf,Ht=90,Zt=1;i.remainingCarbsCap&&(Ht=Math.min(90,i.remainingCarbsCap)),i.remainingCarbsFraction&&(Zt=Math.min(1,i.remainingCarbsFraction));var $t=1-Zt,Jt=Math.max(0,l.mealCOB-Nt-l.carbs*$t),Kt=(Jt=Math.min(Ht,Jt))*csf*5/60/(kt/2),Qt=o(l.slopeFromMaxDeviation,2),Vt=o(l.slopeFromMinDeviation,2),Xt=Math.min(Qt,-Vt/3);Pt=0===Ft?0:Math.min(60*kt/5/2,Math.max(0,l.mealCOB*csf/Ft)),console.error("Carb Impact:"+Ft+"mg/dL per 5m; CI Duration:"+o(5*Pt/60*2,1)+"hours; remaining CI ("+kt/2+"h peak):"+o(Kt,1)+"mg/dL per 5m");var Yt,ea,ta,aa,ra,oa=999,na=999,ia=999,sa=Ve,la=999,ma=999,da=999,ua=999,ca=Ct,ga=Ve,ha=Ve,pa=0,va=[],fa=[];try{yt.forEach((function(e){var t=o(-e.activity*Mt*5,2),a=o(-e.iobWithZeroTemp.activity*Mt*5,2),r=Tt,n=Ft*(1-Math.min(1,Ot.length/12));if(!0===(ge&&!Ae))ca=Ot[Ot.length-1]+o(-e.activity*(1800/(F*fe*Math.log(Math.max(Ot[Ot.length-1],39)/Oe+1)))*5,2)+n,r=At[At.length-1]+o(-e.iobWithZeroTemp.activity*(1800/(F*fe*Math.log(Math.max(At[At.length-1],39)/Oe+1)))*5,2),console.log("Dynamic ISF (Logarithmic Formula) )adjusted predictions for IOB and ZT: IOBpredBG: "+o(ca,2)+" , ZTpredBG: "+o(r,2));else ca=Ot[Ot.length-1]+t+n,r=At[At.length-1]+a;var i=Math.max(0,Math.max(0,Ft)*(1-Gt.length/Math.max(2*Pt,1))),s=Math.min(Gt.length,12*kt-Gt.length),l=Math.max(0,s/(kt/2*12)*Kt);i+l,va.push(o(l,0)),fa.push(o(i,0)),COBpredBG=Gt[Gt.length-1]+t+Math.min(0,n)+i+l;var m=Math.max(0,Et+Rt.length*Xt),d=Math.max(0,Et*(1-Rt.length/Math.max(36,1))),u=Math.min(m,d);if(u>0&&(pa=o(5*(Rt.length+1)/60,1)),!0===(ge&&!Ae))UAMpredBG=Rt[Rt.length-1]+o(-e.activity*(1800/(F*fe*Math.log(Math.max(Rt[Rt.length-1],39)/Oe+1)))*5,2)+Math.min(0,n)+u,console.log("Dynamic ISF (Logarithmic Formula) adjusted prediction for UAM: UAMpredBG: "+o(UAMpredBG,2));else UAMpredBG=Rt[Rt.length-1]+t+Math.min(0,n)+u;Ot.length<48&&Ot.push(ca),Gt.length<48&&Gt.push(COBpredBG),Rt.length<48&&Rt.push(UAMpredBG),At.length<48&&At.push(r),COBpredBG18&&caga&&(ga=ca),(Pt||Kt>0)&&Gt.length>18&&COBpredBG0)&&COBpredBG>ga&&(ha=COBpredBG),jt&&Rt.length>12&&UAMpredBGga&&UAMpredBG}))}catch(e){console.error("Problem with iobArray. Optional feature Advanced Meal Assist disabled")}l.mealCOB&&(console.error("predCIs (mg/dL/5m):"+fa.join(" ")),console.error("remainingCIs: "+va.join(" "))),ze.predBGs={},Ot.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))}));for(var ba=Ot.length-1;ba>12&&Ot[ba-1]===Ot[ba];ba--)Ot.pop();for(ze.predBGs.IOB=Ot,ta=o(Ot[Ot.length-1]),At.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),ba=At.length-1;ba>6&&!(At[ba-1]>=At[ba]||At[ba]<=at);ba--)At.pop();if(ze.predBGs.ZT=At,o(At[At.length-1]),l.mealCOB>0&&(Ft>0||Kt>0)){for(Gt.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),ba=Gt.length-1;ba>12&&Gt[ba-1]===Gt[ba];ba--)Gt.pop();ze.predBGs.COB=Gt,aa=o(Gt[Gt.length-1]),Ct=Math.max(Ct,o(Gt[Gt.length-1]))}if(Ft>0||Kt>0){if(jt){for(Rt.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),ba=Rt.length-1;ba>12&&Rt[ba-1]===Rt[ba];ba--)Rt.pop();ze.predBGs.UAM=Rt,ra=o(Rt[Rt.length-1]),Rt[Rt.length-1]&&(Ct=Math.max(Ct,o(Rt[Rt.length-1])))}ze.eventualBG=Ct}console.error("UAM Impact:"+Et+"mg/dL per 5m; UAM Duration:"+pa+"hours"),oa=Math.max(39,oa),na=Math.max(39,na),ia=Math.max(39,ia),Yt=o(oa);var Ba=l.mealCOB/l.carbs;ea=o(ia<999&&na<999?(1-Ba)*UAMpredBG+Ba*COBpredBG:na<999?(ca+COBpredBG)/2:ia<999?(ca+UAMpredBG)/2:ca),ua>ea&&(ea=ua),sa=o(sa=Pt||Kt>0?jt?Ba*la+(1-Ba)*ma:la:jt?ma:da);var Ma=ia;if(uaia&&(Ma=(ia+ua)/2);if(Ma=o(Ma),l.carbs)if(!jt&&na<999)Yt=o(Math.max(oa,na));else if(na<999){var ya=Ba*na+(1-Ba)*Ma;Yt=o(Math.max(oa,na,ya))}else Yt=jt?Ma:sa;else jt&&(Yt=o(Math.max(oa,Ma)));Yt=Math.min(Yt,ea),process.stderr.write("minPredBG: "+Yt+" minIOBPredBG: "+oa+" minZTGuardBG: "+ua),na<999&&process.stderr.write(" minCOBPredBG: "+na),ia<999&&process.stderr.write(" minUAMPredBG: "+ia),console.error(" avgPredBG:"+ea+" COB/Carbs:"+l.mealCOB+"/"+l.carbs),ha>Ve&&(Yt=Math.min(Yt,ha)),ze.COB=l.mealCOB,ze.IOB=a.iob,ze.BGI=n(Dt,i),ze.deviation=n(St,i),ze.ISF=n(Mt,i),ze.CR=o(N,1),ze.target_bg=n(at,i),ze.TDD=o(de,2),ze.current_target=o(at,0);var xa=ze.CR;qe!=ze.CR&&(xa=qe+"→"+ze.CR),ze.reason=Bt+", COB: "+ze.COB+", Dev: "+ze.deviation+", BGI: "+ze.BGI+", CR: "+xa+", Target: "+ct+", minPredBG "+n(Yt,i)+", minGuardBG "+n(sa,i)+", IOBpredBG "+n(ta,i),aa>0&&(ze.reason+=", COBpredBG "+n(aa,i)),ra>0&&(ze.reason+=", UAMpredBG "+n(ra,i)),ze.reason+=tddReason,ze.reason+="; ";var wa=Tt;wa<40&&(wa=Math.min(sa,wa));var Da,Sa=ft-wa,Ta=240,Ca=240;if(l.mealCOB>0&&(Ft>0||Kt>0)){for(ba=0;baDa*Ve&&(console.error("maxDelta "+n(tt,i)+" > "+100*Da+"% of BG "+n(Ve,i)+" - disabling SMB"),ze.reason+="maxDelta "+n(tt,i)+" > "+100*Da+"% of BG "+n(Ve,i)+" - SMB disabled!, ",It=!1),console.error("BG projected to remain above "+n(rt,i)+" for "+Ta+"minutes"),(Ca<240||Ta<60)&&console.error("BG projected to remain above "+n(ft,i)+" for "+Ca+"minutes");var Ua=Ca,Ga=i.current_basal*L*Mt*Ua/60,Oa=Math.max(0,l.mealCOB-.25*l.carbs),Ra=(Sa-Ga)/csf-Oa;Ga=o(Ga),Ra=o(Ra),console.error("naive_eventualBG:",Tt,"bgUndershoot:",Sa,"zeroTempDuration:",Ua,"zeroTempEffect:",Ga,"carbsReq:",Ra),"Could not parse clock data"==l.reason?console.error("carbsReq unknown: Could not parse clock data"):Ra>=i.carbsReqThreshold&&Ca<=45&&(ze.carbsReq=Ra,ze.reason+=Ra+" add'l carbs req w/in "+Ca+"m; ");var Aa=0;if(Ve0&&Ye>Ut)ze.reason+="IOB "+a.iob+" < "+o(-i.current_basal*L*20/60,2),ze.reason+=" and minDelta "+n(Ye,i)+" > expectedDelta "+n(Ut,i)+"; ";else if(Ve=55)return ze.reason+="; Canceling temp at "+ze.deliverAt.getMinutes()+"m past the hour. ",m.setTempBasal(0,0,i,ze,t);var Ia=0,ja=Ze;if(CtUt&&Ye>0&&!Ra)return Tt<40?(ze.reason+=", naive_eventualBG < 40. ",m.setTempBasal(0,30,i,ze,t)):(e.delta>Ye?ze.reason+=", but Delta "+n(Je,i)+" > expectedDelta "+n(Ut,i):ze.reason+=", but Min. Delta "+Ye.toFixed(2)+" > Exp. Delta "+n(Ut,i),t.duration>15&&r(Ze,i)===r(t.rate,i)?(ze.reason+=", temp "+t.rate+" ~ req "+Ze+"U/hr. ",ze):(ze.reason+="; setting current basal of "+Ze+" as temp. ",m.setTempBasal(Ze,30,i,ze,t)));Ia=o(Ia=2*Math.min(0,(Ct-at)/Mt),2);var Fa=Math.min(0,(Tt-at)/Mt);if(Fa=o(Fa,2),Ye<0&&Ye>Ut)Ia=o(Ia*(Ye/Ut),2);if(ja=r(ja=Ze+2*Ia,i),t.duration*(t.rate-Ze)/605&&ja>=.8*t.rate)return ze.reason+=", temp "+t.rate+" ~< req "+ja+"U/hr. ",ze;if(ja<=0){if((Aa=o(60*((Sa=at-Tt)/Mt)/i.current_basal*L))<0?Aa=0:(Aa=30*o(Aa/30),Aa=Math.min(120,Math.max(0,Aa))),Aa>0)return ze.reason+=", setting "+Aa+"m zero temp. ",m.setTempBasal(ja,Aa,i,ze,t)}else ze.reason+=", setting "+ja+"U/hr. ";return m.setTempBasal(ja,30,i,ze,t)}if(Ye "+n(rt,i)+" but Delta "+n(Je,i)+" < Exp. Delta "+n(Ut,i):ze.reason+="Eventual BG "+n(Ct,i)+" > "+n(rt,i)+" but Min. Delta "+Ye.toFixed(2)+" < Exp. Delta "+n(Ut,i),t.duration>15&&r(Ze,i)===r(t.rate,i)?(ze.reason+=", temp "+t.rate+" ~ req "+Ze+"U/hr. ",ze):(ze.reason+="; setting current basal of "+Ze+" as temp. ",m.setTempBasal(Ze,30,i,ze,t));if(Math.min(Ct,Yt)15&&r(Ze,i)===r(t.rate,i)?(ze.reason+=", temp "+t.rate+" ~ req "+Ze+"U/hr. ",ze):(ze.reason+="; setting current basal of "+Ze+" as temp. ",m.setTempBasal(Ze,30,i,ze,t));if(Ct>=ot&&(ze.reason+="Eventual BG "+n(Ct,i)+" >= "+n(ot,i)+", "),a.iob>it)return ze.reason+="IOB "+o(a.iob,2)+" > max_iob "+it,t.duration>15&&r(Ze,i)===r(t.rate,i)?(ze.reason+=", temp "+t.rate+" ~ req "+Ze+"U/hr. ",ze):(ze.reason+="; setting current basal of "+Ze+" as temp. ",m.setTempBasal(Ze,30,i,ze,t));(Ia=o((Math.min(Yt,Ct)-at)/Mt,2))>it-a.iob?(console.error("SMB limited by maxIOB: "+it-a.iob+" (. insulinReq: "+Ia+" U)"),ze.reason+="max_iob "+it+", ",Ia=it-a.iob):console.error("SMB not limited by maxIOB ( insulinReq: "+Ia+" U)."),ja=r(ja=Ze+2*Ia,i),Ia=o(Ia,3),ze.insulinReq=Ia;var Pa=o((new Date($e).getTime()-a.lastBolusTime)/6e4,1);if(d&&It&&Ve>ft){var Ea=30;void 0!==i.maxSMBBasalMinutes&&(Ea=i.maxSMBBasalMinutes);var qa=30;void 0!==i.maxUAMSMBBasalMinutes&&(qa=i.maxUAMSMBBasalMinutes),v.useOverride&&M&&T!==Ea&&(console.error("SMB Max Minutes - setting overriden from "+Ea+" to "+T),Ea=T),v.useOverride&&M&&C!==qa&&(console.error("UAM Max Minutes - setting overriden from "+qa+" to "+C),qa=C);var Wa=o(l.mealCOB/N,3),ka=0;void 0===Ea?(ka=o(i.current_basal*L*30/60,1),console.error("smbMinutesSetting undefined: defaulting to 30m"),Ia>ka&&console.error("SMB limited by maxBolus: "+ka+" ( "+Ia+" U)")):a.iob>Wa&&a.iob>0?(console.error("IOB"+a.iob+"> COB"+l.mealCOB+"; mealInsulinReq ="+Wa),qa?(console.error("maxUAMSMBBasalMinutes: "+qa+", profile.current_basal: "+i.current_basal*L),ka=o(i.current_basal*L*qa/60,1)):(console.error("maxUAMSMBBasalMinutes undefined: defaulting to 30m"),ka=o(i.current_basal*L*30/60,1)),Ia>ka?console.error("SMB limited by maxUAMSMBBasalMinutes [ "+qa+"m ]: "+ka+"U ( "+Ia+"U )"):console.error("SMB is not limited by maxUAMSMBBasalMinutes. ( insulinReq: "+Ia+"U )")):(console.error(".maxSMBBasalMinutes: "+Ea+", profile.current_basal: "+i.current_basal*L),Ia>(ka=o(i.current_basal*Ea/60,1))?console.error("SMB limited by maxSMBBasalMinutes: "+Ea+"m ]: "+ka+"U ( insulinReq: "+Ia+"U )"):console.error("SMB is not limited by maxSMBBasalMinutes. ( insulinReq: "+Ia+"U )"));var La=i.bolus_increment,za=1/La,Na=i.smb_delivery_ratio;Na>.5&&console.error("SMB Delivery Ratio increased from default 0.5 to "+o(Na,2));var Ha=Math.min(Ia*Na,ka);Ha=Math.floor(Ha*za)/za,Aa=o(60*((at-(Tt+oa)/2)/Mt)/i.current_basal*L),Ia>0&&Ha=30?(Aa=30*o(Aa/30),Aa=Math.min(60,Math.max(0,Aa))):(Za=o(Ze*Aa/30,2),Aa=30),ze.reason+=" insulinReq "+Ia,Ha>=ka&&(ze.reason+="; maxBolus "+ka),Aa>0&&(ze.reason+="; setting "+Aa+"m low temp of "+Za+"U/h"),ze.reason+=". ";var $a=3;i.SMBInterval&&($a=Math.min(10,Math.max(1,i.SMBInterval)));var Ja=o($a-Pa,0),Ka=o(60*($a-Pa),0)%60;if(console.error("naive_eventualBG "+Tt+","+Aa+"m "+Za+"U/h temp needed; last bolus "+Pa+"m ago; maxBolus: "+ka),Pa>$a?Ha>0&&(ze.units=Ha,ze.reason+="Microbolusing "+Ha+"U. "):ze.reason+="Waiting "+Ja+"m "+Ka+"s to microbolus again. ",Aa>0)return ze.rate=Za,ze.duration=Aa,ze}var Qa=m.getMaxSafeBasal(i);return ja>Qa&&(ze.reason+="adj. req. rate: "+ja+" to maxSafeBasal: "+o(Qa,2)+", ",ja=r(Qa,i)),t.duration*(t.rate-Ze)/60>=2*Ia?(ze.reason+=t.duration+"m@"+t.rate.toFixed(2)+" > 2 * insulinReq. Setting temp basal of "+ja+"U/hr. ",m.setTempBasal(ja,30,i,ze,t)):void 0===t.duration||0===t.duration?(ze.reason+="no temp, setting "+ja+"U/hr. ",m.setTempBasal(ja,30,i,ze,t)):t.duration>5&&r(ja,i)<=r(t.rate,i)?(ze.reason+="temp "+t.rate+" >~ req "+ja+"U/hr. ",ze):(ze.reason+="temp "+t.rate+"<"+ja+"U/hr. ",m.setTempBasal(ja,30,i,ze,t))}},6880:(e,t,a)=>{var r=a(6654);e.exports=function(e,t){var a=20;void 0!==t&&"string"==typeof t.model&&(r(t.model,"54")||r(t.model,"23"))&&(a=40);return e<1?Math.round(e*a)/a:e<10?Math.round(20*e)/20:Math.round(10*e)/10}},2705:(e,t,a)=>{var r=a(5639).Symbol;e.exports=r},9932:e=>{e.exports=function(e,t){for(var a=-1,r=null==e?0:e.length,o=Array(r);++a{e.exports=function(e,t,a){return e==e&&(void 0!==a&&(e=e<=a?e:a),void 0!==t&&(e=e>=t?e:t)),e}},4239:(e,t,a)=>{var r=a(2705),o=a(9607),n=a(2333),i=r?r.toStringTag:void 0;e.exports=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":i&&i in Object(e)?o(e):n(e)}},531:(e,t,a)=>{var r=a(2705),o=a(9932),n=a(1469),i=a(3448),s=r?r.prototype:void 0,l=s?s.toString:void 0;e.exports=function e(t){if("string"==typeof t)return t;if(n(t))return o(t,e)+"";if(i(t))return l?l.call(t):"";var a=t+"";return"0"==a&&1/t==-Infinity?"-0":a}},7561:(e,t,a)=>{var r=a(7990),o=/^\s+/;e.exports=function(e){return e?e.slice(0,r(e)+1).replace(o,""):e}},1957:(e,t,a)=>{var r="object"==typeof a.g&&a.g&&a.g.Object===Object&&a.g;e.exports=r},9607:(e,t,a)=>{var r=a(2705),o=Object.prototype,n=o.hasOwnProperty,i=o.toString,s=r?r.toStringTag:void 0;e.exports=function(e){var t=n.call(e,s),a=e[s];try{e[s]=void 0;var r=!0}catch(e){}var o=i.call(e);return r&&(t?e[s]=a:delete e[s]),o}},2333:e=>{var t=Object.prototype.toString;e.exports=function(e){return t.call(e)}},5639:(e,t,a)=>{var r=a(1957),o="object"==typeof self&&self&&self.Object===Object&&self,n=r||o||Function("return this")();e.exports=n},7990:e=>{var t=/\s/;e.exports=function(e){for(var a=e.length;a--&&t.test(e.charAt(a)););return a}},6654:(e,t,a)=>{var r=a(9750),o=a(531),n=a(554),i=a(9833);e.exports=function(e,t,a){e=i(e),t=o(t);var s=e.length,l=a=void 0===a?s:r(n(a),0,s);return(a-=t.length)>=0&&e.slice(a,l)==t}},1469:e=>{var t=Array.isArray;e.exports=t},3218:e=>{e.exports=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}},7005:e=>{e.exports=function(e){return null!=e&&"object"==typeof e}},3448:(e,t,a)=>{var r=a(4239),o=a(7005);e.exports=function(e){return"symbol"==typeof e||o(e)&&"[object Symbol]"==r(e)}},8601:(e,t,a)=>{var r=a(4841),o=1/0;e.exports=function(e){return e?(e=r(e))===o||e===-1/0?17976931348623157e292*(e<0?-1:1):e==e?e:0:0===e?e:0}},554:(e,t,a)=>{var r=a(8601);e.exports=function(e){var t=r(e),a=t%1;return t==t?a?t-a:t:0}},4841:(e,t,a)=>{var r=a(7561),o=a(3218),n=a(3448),i=/^[-+]0x[0-9a-f]+$/i,s=/^0b[01]+$/i,l=/^0o[0-7]+$/i,m=parseInt;e.exports=function(e){if("number"==typeof e)return e;if(n(e))return NaN;if(o(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=o(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=r(e);var a=s.test(e);return a||l.test(e)?m(e.slice(2),a?2:8):i.test(e)?NaN:+e}},9833:(e,t,a)=>{var r=a(531);e.exports=function(e){return null==e?"":r(e)}}},t={};function a(r){var o=t[r];if(void 0!==o)return o.exports;var n=t[r]={exports:{}};return e[r](n,n.exports,a),n.exports}a.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}();var r=a(5546);freeaps_determineBasal=r})(); \ No newline at end of file +var freeaps_determineBasal;(()=>{var e={5546:(e,t,a)=>{var r=a(6880);function o(e,t){t||(t=0);var a=Math.pow(10,t);return Math.round(e*a)/a}function n(e,t){return"mmol/L"===t.out_units?o(.0555*e,1):Math.round(e)}e.exports=function(e,t,a,i,s,l,m,d,u,c,g,h,p,v){var f=i.min_bg,b=v.overrideTarget;const B=v.smbIsOff,M=v.advancedSettings,_=v.isfAndCr,y=v.isf,x=v.cr,w=v.smbIsAlwaysOff,D=v.start,S=v.end,T=v.smbMinutes,C=v.uamMinutes;var U=0,G="",O="",R="",A="",I="",j=0,F=0,P=0,E=0,q=0,W=0;const k=v.weightedAverage;var L=1,z=i.sens,N=i.carb_ratio;v.useOverride&&(L=v.overridePercentage/100,_?(z/=L,N/=L):(x&&(N/=L),y&&(z/=L)));const H=i.weightPercentage,Z=v.average_total_data;function $(e,t){var a=e.getTime();return new Date(a+36e5*t)}function J(e){var t=i.bolus_increment;.025!=t&&(t=.05);var a=e/t;return a>=1?o(Math.floor(a)*t,5):0}function K(e){function t(e){return e<10&&(e="0"+e),e}return t(e.getHours())+":"+t(e.getMinutes())+":00"}function Q(e,t){var a=new Date("1/1/1999 "+e),r=new Date("1/1/1999 "+t);return(a.getTime()-r.getTime())/36e5}function V(e,t){var a=0,r=t,o=(e-t)/36e5,n=0,i=o,s=0;do{if(o>0){var l=K(r),m=p[0].rate;for(let e=0;e=(s=Q(p[e+1].start,p[e].start))?n=s:o=s?n=s:od)if(e+1=(s=Q(u,l))?n=s:o=(s=Q("23:59:59",l))?n=s:o0&&o21)q=V(X,(ee=24-U,te=X.getTime(),new Date(te-36e5*ee))),A="24 hours of data is required for an accurate tdd calculation. Currently only "+U.toPrecision(3)+" hours of pump history data are available. Using your pump scheduled basals to fill in the missing hours. Scheduled basals added: "+q.toPrecision(5)+" U. ";else U<21?(ge=!1,enableDynamicCR=!1):A=""}else console.log("Pumphistory is empty!"),ge=!1,enableDynamicCR=!1;var ee,te;for(let e=0;e0){j=e,W=g[e].rate;var ae=g[e-1]["duration (min)"]/60,re=ae,oe=new Date(g[e-1].timestamp),ne=oe,ie=0;do{if(e--,0==e){ne=new Date;break}if("TempBasal"==g[e]._type||"PumpSuspend"==g[e]._type){ne=new Date(g[e].timestamp);break}var se=e-2;if(se>=0&&"Rewind"==g[se]._type){let e=g[se].timestamp;for(;se-1>=0&&"Prime"==g[se-=1]._type;)ie=(g[se].timestamp-e)/36e5;ie>=ae&&(ne=e,ie=0)}}while(e>0);var le=(ne-oe)/36e5;le0&&(--r,"TempBasal"==g[r]._type)){a=new Date(g[r].timestamp);break}}while(r>0);(a-t)/36e5>0&&(q+=V(a,t))}for(let e=g.length-1;e>0;e--)if("TempBasalDuration"==g[e]._type){let t=g[e]["duration (min)"]/60,a=new Date(g[e].timestamp);var me=a;let r=e;do{if(--r,r>=0&&("TempBasal"==g[r]._type||"PumpSuspend"==g[r]._type)){me=new Date(g[r].timestamp);break}}while(r>0);if(0==e&&"TempBasalDuration"==g[0]._type&&(me=new Date,t=g[e]["duration (min)"]/60),(me-a)/36e5-t>0){q+=V(me,$(a,t))}}var de,ue={TDD:o(F=E+P+q,5),bolus:o(E,5),temp_basal:o(P,5),scheduled_basal:o(q,5)};U>21?(O=". Bolus insulin: "+E.toPrecision(5)+" U",R=". Temporary basal insulin: "+P.toPrecision(5)+" U",G=". Insulin with scheduled basal rate: "+q.toPrecision(5)+" U",I=A+(" TDD past 24h is: "+F.toPrecision(5)+" U")+O+R+G,tddReason=", Total insulin: "+o(F,2)+" U, "+o(E/F*100,0)+"% Bolus "+o((P+q)/F*100,0)+"% Basal"):tddReason=", TDD: Not enough pumpData (< 21h)";const ce=e.glucose;var ge=h.useNewFormula;const he=h.enableDynamicCR,pe=Math.min(i.autosens_min,i.autosens_max),ve=Math.max(i.autosens_min,i.autosens_max);(ve==pe||ve<1||pe>1)&&(ge=!1,console.log("Dynamic ISF disabled due to current autosens settings"));const fe=h.adjustmentFactor,be=i.min_bg;var Be=!1,Me="",_e=1,ye="";Z>0&&(_e=k/Z),ye=_e>1?"Basal adjustment with a 24 hour to total average (up to 14 days of data) TDD ratio (limited by Autosens max setting). Basal Ratio: "+(_e=o(_e=Math.min(_e,i.autosens_max),2))+". Upper limit = Autosens max ("+i.autosens_max+")":_e<1?"Basal adjustment with a 24 hour to to total average (up to 14 days of data) TDD ratio (limited by Autosens min setting). Basal Ratio: "+(_e=o(_e=Math.max(_e,i.autosens_min),2))+". Lower limit = Autosens min ("+i.autosens_min+")":"Basal adjusted with a 24 hour to total average (up to 14 days of data) TDD ratio: "+_e,ye=", Basal ratio: "+_e,(i.high_temptarget_raises_sensitivity||i.exercise_mode||v.isEnabled)&&(Be=!0),be>=118&&Be&&(ge=!1,Me="Dynamic ISF temporarily off due to a high temp target/exercising. Current min target: "+be);var xe=", Dynamic ratios log: ",we=", AF: "+fe,De="BG: "+ce+" mg/dl ("+(.0555*ce).toPrecision(2)+" mmol/l)",Se="",Te="";const Ce=h.curve,Ue=h.insulinPeakTime,Ge=h.useCustomPeakTime;var Oe=55,Re=65;switch(Ce){case"rapid-acting":Re=65;break;case"ultra-rapid":Re=50}Ge?(Oe=120-Ue,console.log("Custom insulinpeakTime set to :"+Ue+", insulinFactor: "+Oe)):(Oe=120-Re,console.log("insulinFactor set to : "+Oe)),de=F,H<1&&k>0&&(F=k,console.log("Using weighted TDD average: "+o(F,2)+" U, instead of past 24 h ("+o(de,2)+" U), weight: "+H),Te=", Weighted TDD: "+o(F,2)+" U");const Ae=h.sigmoid;var Ie="";if(ge){var je=z*fe*F*Math.log(ce/Oe+1)/1800;Se=", Logarithmic formula"}if(ge&&Ae){const e=pe,t=ve-e,a=.0555*(ce-i.min_bg);var Fe=_e,Pe=ve-1;1==ve&&(Pe=ve+.01-1);const r=Math.log10(1/Pe-e/Pe)/Math.log10(Math.E),o=a*fe*Fe+r;je=t/(1+Math.exp(-o))+e,Se=", Sigmoid function"}var Ee=N;const qe=o(N,1);var We="",ke="";if(ge&&F>0){if(We=", Dynamic ISF/CR: On/",je>ve?(Me=", Dynamic ISF limited by autosens_max setting: "+ve+" ("+o(je,2)+"), ",ke=", Autosens/Dynamic Limit: "+ve+" ("+o(je,2)+")",je=ve):je-.5?"+"+o(e.delta,0):o(e.delta,0);var Ye=Math.min(e.delta,e.short_avgdelta),et=Math.min(e.short_avgdelta,e.long_avgdelta),tt=Math.max(e.delta,e.short_avgdelta,e.long_avgdelta);(Ve<=10||38===Ve||Xe>=3)&&(ze.reason="CGM is calibrating, in ??? state, or noise is high");if(Ve>60&&0==e.delta&&e.short_avgdelta>-1&&e.short_avgdelta<1&&e.long_avgdelta>-1&&e.long_avgdelta<1&&("fakecgm"==e.device?(console.error("CGM data is unchanged ("+n(Ve,i)+"+"+n(e.delta,i)+") for 5m w/ "+n(e.short_avgdelta,i)+" mg/dL ~15m change & "+n(e.long_avgdelta,2)+" mg/dL ~45m change"),console.error("Simulator mode detected ("+e.device+"): continuing anyway")):!0),Qe>12||Qe<-5?ze.reason="If current system time "+$e+" is correct, then BG data is too old. The last BG data was read "+Qe+"m ago at "+Ke:0===e.short_avgdelta&&0===e.long_avgdelta&&(e.last_cal&&e.last_cal<3?ze.reason="CGM was just calibrated":ze.reason="CGM data is unchanged ("+n(Ve,i)+"+"+n(e.delta,i)+") for 5m w/ "+n(e.short_avgdelta,i)+" mg/dL ~15m change & "+n(e.long_avgdelta,i)+" mg/dL ~45m change"),Ve<=10||38===Ve||Xe>=3||Qe>12||Qe<-5||0===e.short_avgdelta&&0===e.long_avgdelta)return t.rate>=Ze?(ze.reason+=". Canceling high temp basal of "+t.rate,ze.deliverAt=Ne,ze.temp="absolute",ze.duration=0,ze.rate=0,ze):0===t.rate&&t.duration>30?(ze.reason+=". Shortening "+t.duration+"m long zero temp to 30m. ",ze.deliverAt=Ne,ze.temp="absolute",ze.duration=30,ze.rate=0,ze):(ze.reason+=". Temp "+t.rate+" <= current basal "+Ze+"U/hr; doing nothing. ",ze);var at,rt,ot,nt,it=i.max_iob;if(void 0!==i.min_bg&&(rt=i.min_bg),void 0!==i.max_bg&&(ot=i.max_bg),void 0!==i.enableSMB_high_bg_target&&(nt=i.enableSMB_high_bg_target),void 0===i.min_bg||void 0===i.max_bg)return ze.error="Error: could not determine target_bg. ",ze;at=(i.min_bg+i.max_bg)/2;var st=i.exercise_mode||i.high_temptarget_raises_sensitivity||v.isEnabled,lt=100,mt=160;if(mt=i.half_basal_exercise_target,v.isEnabled){const e=v.hbt;console.log("Half Basal Target used: "+n(e,i)+" "+i.out_units),mt=e}else console.log("Default Half Basal Target used: "+n(mt,i)+" "+i.out_units);if(st&&i.temptargetSet&&at>lt||i.low_temptarget_lowers_sensitivity&&i.temptargetSet&&at=at&&sensitivityRatio0&&(process.stderr.write("TDD-adjustment of basals activated, using tdd24h_14d_Ratio "+o(_e,2)+", TDD 24h = "+o(de,2)+"U, Weighted average TDD = "+o(k,2)+"U, (Weight percentage = "+H+"), Total data of TDDs (up to 14 days) average = "+o(Z,2)+"U. "),Ze!==He*L?process.stderr.write("Adjusting basal from "+He*L+" U/h to "+Ze+" U/h; "):process.stderr.write("Basal unchanged: "+Ze+" U/h; "))),i.temptargetSet);else if(void 0!==s&&s&&(i.sensitivity_raises_target&&s.ratio<1||i.resistance_lowers_target&&s.ratio>1)){rt=o((rt-60)/s.ratio)+60,ot=o((ot-60)/s.ratio)+60;var ut=o((at-60)/s.ratio)+60;at===(ut=Math.max(80,ut))?process.stderr.write("target_bg unchanged: "+n(ut,i)+"; "):process.stderr.write("target_bg from "+n(ut,i)+" to "+n(ut,i)+"; "),at=ut}var ct=n(at,i);at!=f&&(ct=0!==b&&b!==at?n(f,i)+"→"+n(b,i)+"→"+n(at,i):n(f,i)+"→"+n(at,i));var gt=200,ht=200,pt=200;if(e.noise>=2){var vt=Math.max(1.1,i.noisyCGMTargetMultiplier);Math.min(250,i.maxRaw);gt=o(Math.min(200,rt*vt)),ht=o(Math.min(200,at*vt)),pt=o(Math.min(200,ot*vt)),process.stderr.write("Raising target_bg for noisy / raw CGM data, from "+n(ut,i)+" to "+n(ht,i)+"; "),rt=gt,at=ht,ot=pt}var ft=rt-.5*(rt-40),bt=i.threshold_setting;bt>ft&&bt<=120&&bt>=65?(console.error("Threshold changed in settings from "+n(ft,i)+" to "+n(bt,i)+". "),ft=bt):console.error("Current threshold: "+n(ft,i));var Bt="",Mt=(o(z,1),z);if(void 0!==s&&s&&((Mt=o(Mt=z/sensitivityRatio,1))!==z?process.stderr.write("ISF from "+n(z,i)+" to "+n(Mt,i)):process.stderr.write("ISF unchanged: "+n(Mt,i)),Bt+="Autosens ratio: "+o(sensitivityRatio,2)+", ISF: "+n(z,i)+"→"+n(Mt,i)),console.error("CR:"+N),void 0===a)return ze.error="Error: iob_data undefined. ",ze;var _t,yt=a;if(a.length,a.length>1&&(a=yt[0]),void 0===a.activity||void 0===a.iob)return ze.error="Error: iob_data missing some property. ",ze;var xt=((_t=void 0!==a.lastTemp?o((new Date($e).getTime()-a.lastTemp.date)/6e4):0)+t.duration)%30;if(console.error("currenttemp:"+t.rate+" lastTempAge:"+_t+"m, tempModulus:"+xt+"m"),ze.temp="absolute",ze.deliverAt=Ne,d&&t&&a.lastTemp&&t.rate!==a.lastTemp.rate&&_t>10&&t.duration)return ze.reason="Warning: currenttemp rate "+t.rate+" != lastTemp rate "+a.lastTemp.rate+" from pumphistory; canceling temp",m.setTempBasal(0,0,i,ze,t);if(t&&a.lastTemp&&t.duration>0){var wt=_t-a.lastTemp.duration;if(wt>5&&_t>10)return ze.reason="Warning: currenttemp running but lastTemp from pumphistory ended "+wt+"m ago; canceling temp",m.setTempBasal(0,0,i,ze,t)}var Dt=o(-a.activity*Mt*5,2),St=o(6*(Ye-Dt));St<0&&(St=o(6*(et-Dt)))<0&&(St=o(6*(e.long_avgdelta-Dt)));var Tt=Ve,Ct=(Tt=a.iob>0?o(Ve-a.iob*Mt):o(Ve-a.iob*Math.min(Mt,z)))+St;if(void 0===Ct||isNaN(Ct))return ze.error="Error: could not calculate eventualBG. Sensitivity: "+Mt+" Deviation: "+St,ze;var Ut=function(e,t,a){return o(a+(e-t)/24,1)}(at,Ct,Dt);ze={temp:"absolute",bg:Ve,tick:Je,eventualBG:Ct,insulinReq:0,reservoir:u,deliverAt:Ne,sensitivityRatio,TDD:de,insulin:ue,current_target:at};var Gt=[],Ot=[],Rt=[],At=[];Gt.push(Ve),Ot.push(Ve),At.push(Ve),Rt.push(Ve);var It=function(e,t,a,r,o,i){return t?!e.allowSMB_with_high_temptarget&&e.temptargetSet&&o>100?(console.error("SMB disabled due to high temptarget of "+o),!1):!0===a.bwFound&&!1===e.A52_risk_enable?(console.error("SMB disabled due to Bolus Wizard activity in the last 6 hours."),!1):!0===e.enableSMB_always?(a.bwFound?console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled due to enableSMB_always"),!0):!0===e.enableSMB_with_COB&&a.mealCOB?(a.bwCarbs?console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for COB of "+a.mealCOB),!0):!0===e.enableSMB_after_carbs&&a.carbs?(a.bwCarbs?console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for 6h after carb entry"),!0):!0===e.enableSMB_with_temptarget&&e.temptargetSet&&o<100?(a.bwFound?console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for temptarget of "+n(o,e)),!0):!0===e.enableSMB_high_bg&&null!==i&&r>=i?(console.error("Checking BG to see if High for SMB enablement."),console.error("Current BG",r," | High BG ",i),a.bwFound?console.error("Warning: High BG SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("High BG detected. Enabling SMB."),!0):(console.error("SMB disabled (no enableSMB preferences active or no condition satisfied)"),!1):(console.error("SMB disabled (!microBolusAllowed)"),!1)}(i,d,l,Ve,at,nt);if(B)if(w){let e=c.getHours();e>=D&&e<=S&&(console.error("SMB disabled by schedule (a Profile is active with SMBs disabled)"),It=!1)}else console.error("SMBs are disabled (a Profile is active with SMBs disabled)"),It=!1;var jt=i.enableUAM,Ft=0,Pt=0;Ft=o(Ye-Dt,1);var Et=o(Ye-Dt,1);csf=Mt/N,console.error("profile.sens:"+n(z,i)+", sens:"+n(Mt,i)+", CSF:"+o(csf,1));var qt=o(30*csf*5/60,1);Ft>qt&&(console.error("Limiting carb impact from "+Ft+" to "+qt+"mg/dL/5m (30g/h)"),Ft=qt);var Wt=3;sensitivityRatio&&(Wt/=sensitivityRatio);var kt=Wt;if(l.carbs){Wt=Math.max(Wt,l.mealCOB/20);var Lt=o((new Date($e).getTime()-l.lastCarbTime)/6e4),zt=(l.carbs-l.mealCOB)/l.carbs;kt=o(kt=Wt+1.5*Lt/60,1),console.error("Last carbs "+Lt+" minutes ago; remainingCATime:"+kt+"hours; "+o(100*zt,1)+"% carbs absorbed")}var Nt=Math.max(0,Ft/5*60*kt/2)/csf,Ht=90,Zt=1;i.remainingCarbsCap&&(Ht=Math.min(90,i.remainingCarbsCap)),i.remainingCarbsFraction&&(Zt=Math.min(1,i.remainingCarbsFraction));var $t=1-Zt,Jt=Math.max(0,l.mealCOB-Nt-l.carbs*$t),Kt=(Jt=Math.min(Ht,Jt))*csf*5/60/(kt/2),Qt=o(l.slopeFromMaxDeviation,2),Vt=o(l.slopeFromMinDeviation,2),Xt=Math.min(Qt,-Vt/3);Pt=0===Ft?0:Math.min(60*kt/5/2,Math.max(0,l.mealCOB*csf/Ft)),console.error("Carb Impact:"+Ft+"mg/dL per 5m; CI Duration:"+o(5*Pt/60*2,1)+"hours; remaining CI ("+kt/2+"h peak):"+o(Kt,1)+"mg/dL per 5m");var Yt,ea,ta,aa,ra,oa=999,na=999,ia=999,sa=Ve,la=999,ma=999,da=999,ua=999,ca=Ct,ga=Ve,ha=Ve,pa=0,va=[],fa=[];try{yt.forEach((function(e){var t=o(-e.activity*Mt*5,2),a=o(-e.iobWithZeroTemp.activity*Mt*5,2),r=Tt,n=Ft*(1-Math.min(1,Ot.length/12));if(!0===(ge&&!Ae))ca=Ot[Ot.length-1]+o(-e.activity*(1800/(F*fe*Math.log(Math.max(Ot[Ot.length-1],39)/Oe+1)))*5,2)+n,r=At[At.length-1]+o(-e.iobWithZeroTemp.activity*(1800/(F*fe*Math.log(Math.max(At[At.length-1],39)/Oe+1)))*5,2),console.log("Dynamic ISF (Logarithmic Formula) )adjusted predictions for IOB and ZT: IOBpredBG: "+o(ca,2)+" , ZTpredBG: "+o(r,2));else ca=Ot[Ot.length-1]+t+n,r=At[At.length-1]+a;var i=Math.max(0,Math.max(0,Ft)*(1-Gt.length/Math.max(2*Pt,1))),s=Math.min(Gt.length,12*kt-Gt.length),l=Math.max(0,s/(kt/2*12)*Kt);i+l,va.push(o(l,0)),fa.push(o(i,0)),COBpredBG=Gt[Gt.length-1]+t+Math.min(0,n)+i+l;var m=Math.max(0,Et+Rt.length*Xt),d=Math.max(0,Et*(1-Rt.length/Math.max(36,1))),u=Math.min(m,d);if(u>0&&(pa=o(5*(Rt.length+1)/60,1)),!0===(ge&&!Ae))UAMpredBG=Rt[Rt.length-1]+o(-e.activity*(1800/(F*fe*Math.log(Math.max(Rt[Rt.length-1],39)/Oe+1)))*5,2)+Math.min(0,n)+u,console.log("Dynamic ISF (Logarithmic Formula) adjusted prediction for UAM: UAMpredBG: "+o(UAMpredBG,2));else UAMpredBG=Rt[Rt.length-1]+t+Math.min(0,n)+u;Ot.length<48&&Ot.push(ca),Gt.length<48&&Gt.push(COBpredBG),Rt.length<48&&Rt.push(UAMpredBG),At.length<48&&At.push(r),COBpredBG18&&caga&&(ga=ca),(Pt||Kt>0)&&Gt.length>18&&COBpredBG0)&&COBpredBG>ga&&(ha=COBpredBG),jt&&Rt.length>12&&UAMpredBGga&&UAMpredBG}))}catch(e){console.error("Problem with iobArray. Optional feature Advanced Meal Assist disabled")}l.mealCOB&&(console.error("predCIs (mg/dL/5m):"+fa.join(" ")),console.error("remainingCIs: "+va.join(" "))),ze.predBGs={},Ot.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))}));for(var ba=Ot.length-1;ba>12&&Ot[ba-1]===Ot[ba];ba--)Ot.pop();for(ze.predBGs.IOB=Ot,ta=o(Ot[Ot.length-1]),At.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),ba=At.length-1;ba>6&&!(At[ba-1]>=At[ba]||At[ba]<=at);ba--)At.pop();if(ze.predBGs.ZT=At,o(At[At.length-1]),l.mealCOB>0&&(Ft>0||Kt>0)){for(Gt.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),ba=Gt.length-1;ba>12&&Gt[ba-1]===Gt[ba];ba--)Gt.pop();ze.predBGs.COB=Gt,aa=o(Gt[Gt.length-1]),Ct=Math.max(Ct,o(Gt[Gt.length-1]))}if(Ft>0||Kt>0){if(jt){for(Rt.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),ba=Rt.length-1;ba>12&&Rt[ba-1]===Rt[ba];ba--)Rt.pop();ze.predBGs.UAM=Rt,ra=o(Rt[Rt.length-1]),Rt[Rt.length-1]&&(Ct=Math.max(Ct,o(Rt[Rt.length-1])))}ze.eventualBG=Ct}console.error("UAM Impact:"+Et+"mg/dL per 5m; UAM Duration:"+pa+"hours"),oa=Math.max(39,oa),na=Math.max(39,na),ia=Math.max(39,ia),Yt=o(oa);var Ba=l.mealCOB/l.carbs;ea=o(ia<999&&na<999?(1-Ba)*UAMpredBG+Ba*COBpredBG:na<999?(ca+COBpredBG)/2:ia<999?(ca+UAMpredBG)/2:ca),ua>ea&&(ea=ua),sa=o(sa=Pt||Kt>0?jt?Ba*la+(1-Ba)*ma:la:jt?ma:da);var Ma=ia;if(uaia&&(Ma=(ia+ua)/2);if(Ma=o(Ma),l.carbs)if(!jt&&na<999)Yt=o(Math.max(oa,na));else if(na<999){var ya=Ba*na+(1-Ba)*Ma;Yt=o(Math.max(oa,na,ya))}else Yt=jt?Ma:sa;else jt&&(Yt=o(Math.max(oa,Ma)));Yt=Math.min(Yt,ea),process.stderr.write("minPredBG: "+Yt+" minIOBPredBG: "+oa+" minZTGuardBG: "+ua),na<999&&process.stderr.write(" minCOBPredBG: "+na),ia<999&&process.stderr.write(" minUAMPredBG: "+ia),console.error(" avgPredBG:"+ea+" COB/Carbs:"+l.mealCOB+"/"+l.carbs),ha>Ve&&(Yt=Math.min(Yt,ha)),ze.COB=l.mealCOB,ze.IOB=a.iob,ze.BGI=n(Dt,i),ze.deviation=n(St,i),ze.ISF=n(Mt,i),ze.CR=o(N,1),ze.target_bg=n(at,i),ze.TDD=o(de,2),ze.current_target=o(at,0);var xa=ze.CR;qe!=ze.CR&&(xa=qe+"→"+ze.CR),ze.reason=Bt+", COB: "+ze.COB+", Dev: "+ze.deviation+", BGI: "+ze.BGI+", CR: "+xa+", Target: "+ct+", minPredBG "+n(Yt,i)+", minGuardBG "+n(sa,i)+", IOBpredBG "+n(ta,i),aa>0&&(ze.reason+=", COBpredBG "+n(aa,i)),ra>0&&(ze.reason+=", UAMpredBG "+n(ra,i)),ze.reason+=tddReason,ze.reason+="; ";var wa=Tt;wa<40&&(wa=Math.min(sa,wa));var Da,Sa=ft-wa,Ta=240,Ca=240;if(l.mealCOB>0&&(Ft>0||Kt>0)){for(ba=0;baDa*Ve&&(console.error("maxDelta "+n(tt,i)+" > "+100*Da+"% of BG "+n(Ve,i)+" - disabling SMB"),ze.reason+="maxDelta "+n(tt,i)+" > "+100*Da+"% of BG "+n(Ve,i)+" - SMB disabled!, ",It=!1),console.error("BG projected to remain above "+n(rt,i)+" for "+Ta+"minutes"),(Ca<240||Ta<60)&&console.error("BG projected to remain above "+n(ft,i)+" for "+Ca+"minutes");var Ua=Ca,Ga=i.current_basal*L*Mt*Ua/60,Oa=Math.max(0,l.mealCOB-.25*l.carbs),Ra=(Sa-Ga)/csf-Oa;Ga=o(Ga),Ra=o(Ra),console.error("naive_eventualBG:",Tt,"bgUndershoot:",Sa,"zeroTempDuration:",Ua,"zeroTempEffect:",Ga,"carbsReq:",Ra),"Could not parse clock data"==l.reason?console.error("carbsReq unknown: Could not parse clock data"):Ra>=i.carbsReqThreshold&&Ca<=45&&(ze.carbsReq=Ra,ze.reason+=Ra+" add'l carbs req w/in "+Ca+"m; ");var Aa=0;if(Ve0&&Ye>Ut)ze.reason+="IOB "+a.iob+" < "+o(-i.current_basal*L*20/60,2),ze.reason+=" and minDelta "+n(Ye,i)+" > expectedDelta "+n(Ut,i)+"; ";else if(Ve=55)return ze.reason+="; Canceling temp at "+ze.deliverAt.getMinutes()+"m past the hour. ",m.setTempBasal(0,0,i,ze,t);var Ia=0,ja=Ze;if(CtUt&&Ye>0&&!Ra)return Tt<40?(ze.reason+=", naive_eventualBG < 40. ",m.setTempBasal(0,30,i,ze,t)):(e.delta>Ye?ze.reason+=", but Delta "+n(Je,i)+" > expectedDelta "+n(Ut,i):ze.reason+=", but Min. Delta "+Ye.toFixed(2)+" > Exp. Delta "+n(Ut,i),t.duration>15&&r(Ze,i)===r(t.rate,i)?(ze.reason+=", temp "+t.rate+" ~ req "+Ze+"U/hr. ",ze):(ze.reason+="; setting current basal of "+Ze+" as temp. ",m.setTempBasal(Ze,30,i,ze,t)));Ia=o(Ia=2*Math.min(0,(Ct-at)/Mt),2);var Fa=Math.min(0,(Tt-at)/Mt);if(Fa=o(Fa,2),Ye<0&&Ye>Ut)Ia=o(Ia*(Ye/Ut),2);if(ja=r(ja=Ze+2*Ia,i),t.duration*(t.rate-Ze)/605&&ja>=.8*t.rate)return ze.reason+=", temp "+t.rate+" ~< req "+ja+"U/hr. ",ze;if(ja<=0){if((Aa=o(60*((Sa=at-Tt)/Mt)/i.current_basal*L))<0?Aa=0:(Aa=30*o(Aa/30),Aa=Math.min(120,Math.max(0,Aa))),Aa>0)return ze.reason+=", setting "+Aa+"m zero temp. ",m.setTempBasal(ja,Aa,i,ze,t)}else ze.reason+=", setting "+ja+"U/hr. ";return m.setTempBasal(ja,30,i,ze,t)}if(Ye "+n(rt,i)+" but Delta "+n(Je,i)+" < Exp. Delta "+n(Ut,i):ze.reason+="Eventual BG "+n(Ct,i)+" > "+n(rt,i)+" but Min. Delta "+Ye.toFixed(2)+" < Exp. Delta "+n(Ut,i),t.duration>15&&r(Ze,i)===r(t.rate,i)?(ze.reason+=", temp "+t.rate+" ~ req "+Ze+"U/hr. ",ze):(ze.reason+="; setting current basal of "+Ze+" as temp. ",m.setTempBasal(Ze,30,i,ze,t));if(Math.min(Ct,Yt)15&&r(Ze,i)===r(t.rate,i)?(ze.reason+=", temp "+t.rate+" ~ req "+Ze+"U/hr. ",ze):(ze.reason+="; setting current basal of "+Ze+" as temp. ",m.setTempBasal(Ze,30,i,ze,t));if(Ct>=ot&&(ze.reason+="Eventual BG "+n(Ct,i)+" >= "+n(ot,i)+", "),a.iob>it)return ze.reason+="IOB "+o(a.iob,2)+" > max_iob "+it,t.duration>15&&r(Ze,i)===r(t.rate,i)?(ze.reason+=", temp "+t.rate+" ~ req "+Ze+"U/hr. ",ze):(ze.reason+="; setting current basal of "+Ze+" as temp. ",m.setTempBasal(Ze,30,i,ze,t));(Ia=o((Math.min(Yt,Ct)-at)/Mt,2))>it-a.iob?(console.error("SMB limited by maxIOB: "+it-a.iob+" (. insulinReq: "+Ia+" U)"),ze.reason+="max_iob "+it+", ",Ia=it-a.iob):console.error("SMB not limited by maxIOB ( insulinReq: "+Ia+" U)."),ja=r(ja=Ze+2*Ia,i),Ia=o(Ia,3),ze.insulinReq=Ia;var Pa=o((new Date($e).getTime()-a.lastBolusTime)/6e4,1);if(d&&It&&Ve>ft){var Ea=30;void 0!==i.maxSMBBasalMinutes&&(Ea=i.maxSMBBasalMinutes);var qa=30;void 0!==i.maxUAMSMBBasalMinutes&&(qa=i.maxUAMSMBBasalMinutes),v.useOverride&&M&&T!==Ea&&(console.error("SMB Max Minutes - setting overriden from "+Ea+" to "+T),Ea=T),v.useOverride&&M&&C!==qa&&(console.error("UAM Max Minutes - setting overriden from "+qa+" to "+C),qa=C);var Wa=o(l.mealCOB/N,3),ka=0;void 0===Ea?(ka=o(i.current_basal*L*30/60,1),console.error("smbMinutesSetting undefined: defaulting to 30m"),Ia>ka&&console.error("SMB limited by maxBolus: "+ka+" ( "+Ia+" U)")):a.iob>Wa&&a.iob>0?(console.error("IOB"+a.iob+"> COB"+l.mealCOB+"; mealInsulinReq ="+Wa),qa?(console.error("maxUAMSMBBasalMinutes: "+qa+", profile.current_basal: "+i.current_basal*L),ka=o(i.current_basal*L*qa/60,1)):(console.error("maxUAMSMBBasalMinutes undefined: defaulting to 30m"),ka=o(i.current_basal*L*30/60,1)),Ia>ka?console.error("SMB limited by maxUAMSMBBasalMinutes [ "+qa+"m ]: "+ka+"U ( "+Ia+"U )"):console.error("SMB is not limited by maxUAMSMBBasalMinutes. ( insulinReq: "+Ia+"U )")):(console.error(".maxSMBBasalMinutes: "+Ea+", profile.current_basal: "+i.current_basal*L),Ia>(ka=o(i.current_basal*Ea/60,1))?console.error("SMB limited by maxSMBBasalMinutes: "+Ea+"m ]: "+ka+"U ( insulinReq: "+Ia+"U )"):console.error("SMB is not limited by maxSMBBasalMinutes. ( insulinReq: "+Ia+"U )"));var La=i.bolus_increment,za=1/La,Na=i.smb_delivery_ratio;Na>.5&&console.error("SMB Delivery Ratio increased from default 0.5 to "+o(Na,2));var Ha=Math.min(Ia*Na,ka);Ha=Math.floor(Ha*za)/za,Aa=o(60*((at-(Tt+oa)/2)/Mt)/i.current_basal*L),Ia>0&&Ha=30?(Aa=30*o(Aa/30),Aa=Math.min(60,Math.max(0,Aa))):(Za=o(Ze*Aa/30,2),Aa=30),ze.reason+=" insulinReq "+Ia,Ha>=ka&&(ze.reason+="; maxBolus "+ka),Aa>0&&(ze.reason+="; setting "+Aa+"m low temp of "+Za+"U/h"),ze.reason+=". ";var $a=3;i.SMBInterval&&($a=Math.min(10,Math.max(1,i.SMBInterval)));var Ja=o($a-Pa,0),Ka=o(60*($a-Pa),0)%60;if(console.error("naive_eventualBG "+Tt+","+Aa+"m "+Za+"U/h temp needed; last bolus "+Pa+"m ago; maxBolus: "+ka),Pa>$a?Ha>0&&(ze.units=Ha,ze.reason+="Microbolusing "+Ha+"U. "):ze.reason+="Waiting "+Ja+"m "+Ka+"s to microbolus again. ",Aa>0)return ze.rate=Za,ze.duration=Aa,ze}var Qa=m.getMaxSafeBasal(i);return ja>Qa&&(ze.reason+="adj. req. rate: "+ja+" to maxSafeBasal: "+o(Qa,2)+", ",ja=r(Qa,i)),t.duration*(t.rate-Ze)/60>=2*Ia?(ze.reason+=t.duration+"m@"+t.rate.toFixed(2)+" > 2 * insulinReq. Setting temp basal of "+ja+"U/hr. ",m.setTempBasal(ja,30,i,ze,t)):void 0===t.duration||0===t.duration?(ze.reason+="no temp, setting "+ja+"U/hr. ",m.setTempBasal(ja,30,i,ze,t)):t.duration>5&&r(ja,i)<=r(t.rate,i)?(ze.reason+="temp "+t.rate+" >~ req "+ja+"U/hr. ",ze):(ze.reason+="temp "+t.rate+"<"+ja+"U/hr. ",m.setTempBasal(ja,30,i,ze,t))}},6880:(e,t,a)=>{var r=a(6654);e.exports=function(e,t){var a=20;void 0!==t&&"string"==typeof t.model&&(r(t.model,"54")||r(t.model,"23"))&&(a=40);return e<1?Math.round(e*a)/a:e<10?Math.round(20*e)/20:Math.round(10*e)/10}},2705:(e,t,a)=>{var r=a(5639).Symbol;e.exports=r},9932:e=>{e.exports=function(e,t){for(var a=-1,r=null==e?0:e.length,o=Array(r);++a{e.exports=function(e,t,a){return e==e&&(void 0!==a&&(e=e<=a?e:a),void 0!==t&&(e=e>=t?e:t)),e}},4239:(e,t,a)=>{var r=a(2705),o=a(9607),n=a(2333),i=r?r.toStringTag:void 0;e.exports=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":i&&i in Object(e)?o(e):n(e)}},531:(e,t,a)=>{var r=a(2705),o=a(9932),n=a(1469),i=a(3448),s=r?r.prototype:void 0,l=s?s.toString:void 0;e.exports=function e(t){if("string"==typeof t)return t;if(n(t))return o(t,e)+"";if(i(t))return l?l.call(t):"";var a=t+"";return"0"==a&&1/t==-Infinity?"-0":a}},7561:(e,t,a)=>{var r=a(7990),o=/^\s+/;e.exports=function(e){return e?e.slice(0,r(e)+1).replace(o,""):e}},1957:(e,t,a)=>{var r="object"==typeof a.g&&a.g&&a.g.Object===Object&&a.g;e.exports=r},9607:(e,t,a)=>{var r=a(2705),o=Object.prototype,n=o.hasOwnProperty,i=o.toString,s=r?r.toStringTag:void 0;e.exports=function(e){var t=n.call(e,s),a=e[s];try{e[s]=void 0;var r=!0}catch(e){}var o=i.call(e);return r&&(t?e[s]=a:delete e[s]),o}},2333:e=>{var t=Object.prototype.toString;e.exports=function(e){return t.call(e)}},5639:(e,t,a)=>{var r=a(1957),o="object"==typeof self&&self&&self.Object===Object&&self,n=r||o||Function("return this")();e.exports=n},7990:e=>{var t=/\s/;e.exports=function(e){for(var a=e.length;a--&&t.test(e.charAt(a)););return a}},6654:(e,t,a)=>{var r=a(9750),o=a(531),n=a(554),i=a(9833);e.exports=function(e,t,a){e=i(e),t=o(t);var s=e.length,l=a=void 0===a?s:r(n(a),0,s);return(a-=t.length)>=0&&e.slice(a,l)==t}},1469:e=>{var t=Array.isArray;e.exports=t},3218:e=>{e.exports=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}},7005:e=>{e.exports=function(e){return null!=e&&"object"==typeof e}},3448:(e,t,a)=>{var r=a(4239),o=a(7005);e.exports=function(e){return"symbol"==typeof e||o(e)&&"[object Symbol]"==r(e)}},8601:(e,t,a)=>{var r=a(4841),o=1/0;e.exports=function(e){return e?(e=r(e))===o||e===-1/0?17976931348623157e292*(e<0?-1:1):e==e?e:0:0===e?e:0}},554:(e,t,a)=>{var r=a(8601);e.exports=function(e){var t=r(e),a=t%1;return t==t?a?t-a:t:0}},4841:(e,t,a)=>{var r=a(7561),o=a(3218),n=a(3448),i=/^[-+]0x[0-9a-f]+$/i,s=/^0b[01]+$/i,l=/^0o[0-7]+$/i,m=parseInt;e.exports=function(e){if("number"==typeof e)return e;if(n(e))return NaN;if(o(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=o(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=r(e);var a=s.test(e);return a||l.test(e)?m(e.slice(2),a?2:8):i.test(e)?NaN:+e}},9833:(e,t,a)=>{var r=a(531);e.exports=function(e){return null==e?"":r(e)}}},t={};function a(r){var o=t[r];if(void 0!==o)return o.exports;var n=t[r]={exports:{}};return e[r](n,n.exports,a),n.exports}a.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}();var r=a(5546);freeaps_determineBasal=r})(); \ No newline at end of file From c5ae091afcc137745a1632d0592a1e705c33898e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20B=20M=C3=A5rtensson?= <53905247+Jon-b-m@users.noreply.github.com> Date: Sun, 4 Jun 2023 16:01:10 +0200 Subject: [PATCH 14/45] Bump version.xcconfig --- Config.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config.xcconfig b/Config.xcconfig index dea375d616..af6e47f8d4 100644 --- a/Config.xcconfig +++ b/Config.xcconfig @@ -1,5 +1,5 @@ APP_DISPLAY_NAME = iAPS -APP_VERSION = 2.1.0 +APP_VERSION = 2.1.5 APP_BUILD_NUMBER = 1 COPYRIGHT_NOTICE = DEVELOPER_TEAM = ##TEAM_ID## From f44fd2bb6e8714550d86f1e7f71e64d8f912facd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Sun, 4 Jun 2023 16:25:21 +0200 Subject: [PATCH 15/45] Add euglucemic range. Formatting. --- .../Modules/Stat/View/ChartsView.swift | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/FreeAPS/Sources/Modules/Stat/View/ChartsView.swift b/FreeAPS/Sources/Modules/Stat/View/ChartsView.swift index 6382c859ab..6b18601995 100644 --- a/FreeAPS/Sources/Modules/Stat/View/ChartsView.swift +++ b/FreeAPS/Sources/Modules/Stat/View/ChartsView.swift @@ -208,19 +208,30 @@ struct ChartsView: View { let mapGlucose = glucose.compactMap({ each in each.glucose }) let mapGlucoseAcuteLow = mapGlucose.filter({ $0 < Int16(3.3 / 0.0555) }) let mapGlucoseHigh = mapGlucose.filter({ $0 > Int16(11 / 0.0555) }) + let mapGlucoseNormal = mapGlucose.filter({ $0 > Int16(3.8 / 0.0555) && $0 < Int16(7.9 / 0.0555) }) HStack { let value = Double(mapGlucoseHigh.count * 100 / mapGlucose.count) if value != 0 { - Text(units == .mmolL ? "> 11" : "> 200").foregroundColor(.secondary) + Text(units == .mmolL ? "> 11 " : "> 200 ").foregroundColor(.secondary) Text(value.formatted()).foregroundColor(.orange) Text("%").foregroundColor(.secondary) } }.font(.caption) + + HStack { + let value = Double(mapGlucoseNormal.count * 100 / mapGlucose.count) + if value != 0 { + Text(units == .mmolL ? "3.9-7.8" : "70-140").foregroundColor(.secondary) + Text(value.formatted()).foregroundColor(.green) + Text("%").foregroundColor(.secondary) + } + }.font(.caption) + HStack { let value = Double(mapGlucoseAcuteLow.count * 100 / mapGlucose.count) if value != 0 { - Text(units == .mmolL ? "< 3.3" : "< 59").foregroundColor(.secondary) + Text(units == .mmolL ? "< 3.3 " : "< 59 ").foregroundColor(.secondary) Text(value.formatted()).foregroundColor(.red) Text("%").foregroundColor(.secondary) } @@ -236,7 +247,7 @@ struct ChartsView: View { let mapGlucoseLow = mapGlucose.filter({ $0 < Int16(3.3 / 0.0555) }) let mapGlucoseAcuteLow = mapGlucose.filter({ $0 < Int16(2.6 / 0.0555) }) - let mapGlucoseHigh = mapGlucose.filter({ $0 > Int(8.5 / 0.0555) }) + let mapGlucoseHigh = mapGlucose.filter({ $0 > Int(7.8 / 0.0555) }) let mapGlucoseAcuteHigh = mapGlucose.filter({ $0 > Int16(11 / 0.0555) }) HStack { @@ -259,7 +270,7 @@ struct ChartsView: View { HStack { let value = Double(mapGlucoseHigh.count * 100 / mapGlucose.count) if value != 0 { - Text(units == .mmolL ? "> 8.5" : "> 144").font(.caption).foregroundColor(.secondary) + Text(units == .mmolL ? "> 7.8" : "> 140").font(.caption).foregroundColor(.secondary) Text(value.formatted()).font(.caption).foregroundColor(value == 0 ? .green : .orange) Text("%").font(.caption) } From 9f95d6bb7fafb4b7454becd0d2db476b72a1a984 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Sun, 4 Jun 2023 16:25:21 +0200 Subject: [PATCH 16/45] Add euglucemic range. Formatting. (cherry picked from commit f44fd2bb6e8714550d86f1e7f71e64d8f912facd) (cherry picked from commit 4a9db1560ff1381fbb63a28b09f6c34eabce8ec6) --- .../Modules/Stat/View/ChartsView.swift | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/FreeAPS/Sources/Modules/Stat/View/ChartsView.swift b/FreeAPS/Sources/Modules/Stat/View/ChartsView.swift index 6382c859ab..6b18601995 100644 --- a/FreeAPS/Sources/Modules/Stat/View/ChartsView.swift +++ b/FreeAPS/Sources/Modules/Stat/View/ChartsView.swift @@ -208,19 +208,30 @@ struct ChartsView: View { let mapGlucose = glucose.compactMap({ each in each.glucose }) let mapGlucoseAcuteLow = mapGlucose.filter({ $0 < Int16(3.3 / 0.0555) }) let mapGlucoseHigh = mapGlucose.filter({ $0 > Int16(11 / 0.0555) }) + let mapGlucoseNormal = mapGlucose.filter({ $0 > Int16(3.8 / 0.0555) && $0 < Int16(7.9 / 0.0555) }) HStack { let value = Double(mapGlucoseHigh.count * 100 / mapGlucose.count) if value != 0 { - Text(units == .mmolL ? "> 11" : "> 200").foregroundColor(.secondary) + Text(units == .mmolL ? "> 11 " : "> 200 ").foregroundColor(.secondary) Text(value.formatted()).foregroundColor(.orange) Text("%").foregroundColor(.secondary) } }.font(.caption) + + HStack { + let value = Double(mapGlucoseNormal.count * 100 / mapGlucose.count) + if value != 0 { + Text(units == .mmolL ? "3.9-7.8" : "70-140").foregroundColor(.secondary) + Text(value.formatted()).foregroundColor(.green) + Text("%").foregroundColor(.secondary) + } + }.font(.caption) + HStack { let value = Double(mapGlucoseAcuteLow.count * 100 / mapGlucose.count) if value != 0 { - Text(units == .mmolL ? "< 3.3" : "< 59").foregroundColor(.secondary) + Text(units == .mmolL ? "< 3.3 " : "< 59 ").foregroundColor(.secondary) Text(value.formatted()).foregroundColor(.red) Text("%").foregroundColor(.secondary) } @@ -236,7 +247,7 @@ struct ChartsView: View { let mapGlucoseLow = mapGlucose.filter({ $0 < Int16(3.3 / 0.0555) }) let mapGlucoseAcuteLow = mapGlucose.filter({ $0 < Int16(2.6 / 0.0555) }) - let mapGlucoseHigh = mapGlucose.filter({ $0 > Int(8.5 / 0.0555) }) + let mapGlucoseHigh = mapGlucose.filter({ $0 > Int(7.8 / 0.0555) }) let mapGlucoseAcuteHigh = mapGlucose.filter({ $0 > Int16(11 / 0.0555) }) HStack { @@ -259,7 +270,7 @@ struct ChartsView: View { HStack { let value = Double(mapGlucoseHigh.count * 100 / mapGlucose.count) if value != 0 { - Text(units == .mmolL ? "> 8.5" : "> 144").font(.caption).foregroundColor(.secondary) + Text(units == .mmolL ? "> 7.8" : "> 140").font(.caption).foregroundColor(.secondary) Text(value.formatted()).font(.caption).foregroundColor(value == 0 ? .green : .orange) Text("%").font(.caption) } From ff7c4a765f99b71080a448dacf65381513b2385b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Mon, 5 Jun 2023 01:42:56 +0200 Subject: [PATCH 17/45] Format TIR Chart. Check for empty loops --- .../Modules/Stat/View/ChartsView.swift | 23 +++-- .../Sources/Modules/Stat/View/StatsView.swift | 95 ++++++++++--------- 2 files changed, 64 insertions(+), 54 deletions(-) diff --git a/FreeAPS/Sources/Modules/Stat/View/ChartsView.swift b/FreeAPS/Sources/Modules/Stat/View/ChartsView.swift index 6b18601995..bcfa59d5fb 100644 --- a/FreeAPS/Sources/Modules/Stat/View/ChartsView.swift +++ b/FreeAPS/Sources/Modules/Stat/View/ChartsView.swift @@ -161,20 +161,24 @@ struct ChartsView: View { let fetched = tir() let low = lowLimit * (units == .mmolL ? Decimal(conversionFactor) : 1) let high = highLimit * (units == .mmolL ? Decimal(conversionFactor) : 1) + let fraction = units == .mmolL ? 1 : 0 let data: [ShapeModel] = [ .init( type: NSLocalizedString( "Low", comment: "" - ) + " (≤ \(low.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1)))))", + ) + " (≤ \(low.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1))))", percent: fetched[0].decimal ), - .init(type: NSLocalizedString("In Range", comment: ""), percent: fetched[1].decimal), + .init( + type: "> \(low.formatted(.number.precision(.fractionLength(fraction)))) - < \(high.formatted(.number.precision(.fractionLength(fraction))))", + percent: fetched[1].decimal + ), .init( type: NSLocalizedString( "High", comment: "" - ) + " (≥ \(high.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1)))))", + ) + " (≥ \(high.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1))))", percent: fetched[2].decimal ) ] @@ -184,21 +188,26 @@ struct ChartsView: View { y: .value("Percentage", shape.percent) ) .foregroundStyle(by: .value("Group", shape.type)) - .annotation(position: .automatic, alignment: .center) { + .annotation(position: shape.percent > 19 ? .overlay : .automatic, alignment: .center) { Text(shape.percent == 0 ? "" : "\(shape.percent, format: .number.precision(.fractionLength(0)))") } } .chartXAxis(.hidden) + .chartYAxis { + AxisMarks( + format: Decimal.FormatStyle.Percent.percent.scale(1) + ) + } .chartForegroundStyleScale([ NSLocalizedString( "Low", comment: "" - ) + " (≤ \(low.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1)))))": .red, - NSLocalizedString("In Range", comment: ""): .green, + ) + " (≤ \(low.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1))))": .red, + "> \(low.formatted(.number.precision(.fractionLength(fraction)))) - < \(high.formatted(.number.precision(.fractionLength(fraction))))": .green, NSLocalizedString( "High", comment: "" - ) + " (≥ \(high.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1)))))": .orange + ) + " (≥ \(high.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1))))": .orange ]) } diff --git a/FreeAPS/Sources/Modules/Stat/View/StatsView.swift b/FreeAPS/Sources/Modules/Stat/View/StatsView.swift index 861cb9f9e7..b88bd2f0d6 100644 --- a/FreeAPS/Sources/Modules/Stat/View/StatsView.swift +++ b/FreeAPS/Sources/Modules/Stat/View/StatsView.swift @@ -57,53 +57,54 @@ struct StatsView: View { var loops: some View { VStack(spacing: 10) { let loops = fetchRequest - - // First date - let previous = loops.last?.end ?? Date() - // Last date (recent) - let current = loops.first?.start ?? Date() - - // Total time in days - let totalTime = (current - previous).timeInterval / 8.64E4 - - let durationArray = loops.compactMap({ each in each.duration }) - let durationArrayCount = durationArray.count - // var durationAverage = durationArray.reduce(0, +) / Double(durationArrayCount) - let medianDuration = medianCalculationDouble(array: durationArray) - let successsNR = loops.compactMap({ each in each.loopStatus }).filter({ each in each!.contains("Success") }) - .count - let errorNR = durationArrayCount - successsNR - let successRate: Double? = (Double(successsNR) / Double(successsNR + errorNR)) * 100 - - let loopNr = totalTime <= 1 ? Double(successsNR + errorNR) : round(Double(successsNR + errorNR) / totalTime) - - let intervalArray = loops.compactMap({ each in each.interval as Double }) - let intervalAverage = intervalArray.reduce(0, +) / Double(intervalArray.count) - // let maximumInterval = intervalArray.max() - // let minimumInterval = intervalArray.min() - - HStack(spacing: 35) { - VStack(spacing: 5) { - Text("Loops").font(.subheadline).foregroundColor(headline) - Text(loopNr.formatted()) - } - VStack(spacing: 5) { - Text("Interval").font(.subheadline).foregroundColor(headline) - Text(intervalAverage.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1))) + " min") - } - VStack(spacing: 5) { - Text("Duration").font(.subheadline).foregroundColor(headline) - Text( - (medianDuration * 60) - .formatted(.number.grouping(.never).rounded().precision(.fractionLength(1))) + " s" - ) - } - VStack(spacing: 5) { - Text("Sucess").font(.subheadline).foregroundColor(headline) - Text( - ((successRate ?? 100) / 100) - .formatted(.percent.grouping(.never).rounded().precision(.fractionLength(1))) - ) + if !loops.isEmpty { + // First date + let previous = loops.last?.end ?? Date() + // Last date (recent) + let current = loops.first?.start ?? Date() + + // Total time in days + let totalTime = (current - previous).timeInterval / 8.64E4 + + let durationArray = loops.compactMap({ each in each.duration }) + let durationArrayCount = durationArray.count + // var durationAverage = durationArray.reduce(0, +) / Double(durationArrayCount) + let medianDuration = medianCalculationDouble(array: durationArray) + let successsNR = loops.compactMap({ each in each.loopStatus }).filter({ each in each!.contains("Success") }) + .count + let errorNR = durationArrayCount - successsNR + let successRate: Double? = (Double(successsNR) / Double(successsNR + errorNR)) * 100 + + let loopNr = totalTime <= 1 ? Double(successsNR + errorNR) : round(Double(successsNR + errorNR) / totalTime) + + let intervalArray = loops.compactMap({ each in each.interval as Double }) + let intervalAverage = intervalArray.reduce(0, +) / Double(intervalArray.count) + // let maximumInterval = intervalArray.max() + // let minimumInterval = intervalArray.min() + + HStack(spacing: 35) { + VStack(spacing: 5) { + Text("Loops").font(.subheadline).foregroundColor(headline) + Text(loopNr.formatted()) + } + VStack(spacing: 5) { + Text("Interval").font(.subheadline).foregroundColor(headline) + Text(intervalAverage.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1))) + " min") + } + VStack(spacing: 5) { + Text("Duration").font(.subheadline).foregroundColor(headline) + Text( + (medianDuration * 60) + .formatted(.number.grouping(.never).rounded().precision(.fractionLength(1))) + " s" + ) + } + VStack(spacing: 5) { + Text("Sucess").font(.subheadline).foregroundColor(headline) + Text( + ((successRate ?? 100) / 100) + .formatted(.percent.grouping(.never).rounded().precision(.fractionLength(1))) + ) + } } } } From fe174f05e786d950e760a2583f46359623c14de9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Mon, 5 Jun 2023 01:51:10 +0200 Subject: [PATCH 18/45] More formatting --- FreeAPS/Sources/Modules/Stat/View/ChartsView.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/FreeAPS/Sources/Modules/Stat/View/ChartsView.swift b/FreeAPS/Sources/Modules/Stat/View/ChartsView.swift index bcfa59d5fb..7803f9be00 100644 --- a/FreeAPS/Sources/Modules/Stat/View/ChartsView.swift +++ b/FreeAPS/Sources/Modules/Stat/View/ChartsView.swift @@ -167,7 +167,7 @@ struct ChartsView: View { type: NSLocalizedString( "Low", comment: "" - ) + " (≤ \(low.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1))))", + ) + " (≤ \(low.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1)))))", percent: fetched[0].decimal ), .init( @@ -178,7 +178,7 @@ struct ChartsView: View { type: NSLocalizedString( "High", comment: "" - ) + " (≥ \(high.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1))))", + ) + " (≥ \(high.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1)))))", percent: fetched[2].decimal ) ] @@ -202,12 +202,12 @@ struct ChartsView: View { NSLocalizedString( "Low", comment: "" - ) + " (≤ \(low.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1))))": .red, + ) + " (≤ \(low.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1)))))": .red, "> \(low.formatted(.number.precision(.fractionLength(fraction)))) - < \(high.formatted(.number.precision(.fractionLength(fraction))))": .green, NSLocalizedString( "High", comment: "" - ) + " (≥ \(high.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1))))": .orange + ) + " (≥ \(high.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1)))))": .orange ]) } From c15a7157ef856ad1c332be7f60928a3598a3ac21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20B=20M=C3=A5rtensson?= <53905247+Jon-b-m@users.noreply.github.com> Date: Tue, 6 Jun 2023 01:00:57 +0200 Subject: [PATCH 19/45] Update Config.xcconfig --- Config.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config.xcconfig b/Config.xcconfig index af6e47f8d4..3463088bd4 100644 --- a/Config.xcconfig +++ b/Config.xcconfig @@ -1,5 +1,5 @@ APP_DISPLAY_NAME = iAPS -APP_VERSION = 2.1.5 +APP_VERSION = 2.1.6 APP_BUILD_NUMBER = 1 COPYRIGHT_NOTICE = DEVELOPER_TEAM = ##TEAM_ID## From 421793cb4ba154e5df70647d8c1371885c8dd380 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Tue, 6 Jun 2023 16:10:46 +0200 Subject: [PATCH 20/45] Bug fix for empty glucose data (cherry picked from commit c74ab7c24148ab55351c3709528f6f3ce01dcbd6) --- .../Modules/Stat/View/ChartsView.swift | 127 +++++++++--------- 1 file changed, 65 insertions(+), 62 deletions(-) diff --git a/FreeAPS/Sources/Modules/Stat/View/ChartsView.swift b/FreeAPS/Sources/Modules/Stat/View/ChartsView.swift index 7803f9be00..219ba281bc 100644 --- a/FreeAPS/Sources/Modules/Stat/View/ChartsView.swift +++ b/FreeAPS/Sources/Modules/Stat/View/ChartsView.swift @@ -215,81 +215,84 @@ struct ChartsView: View { VStack(alignment: .leading, spacing: 20) { let glucose = fetchRequest let mapGlucose = glucose.compactMap({ each in each.glucose }) - let mapGlucoseAcuteLow = mapGlucose.filter({ $0 < Int16(3.3 / 0.0555) }) - let mapGlucoseHigh = mapGlucose.filter({ $0 > Int16(11 / 0.0555) }) - let mapGlucoseNormal = mapGlucose.filter({ $0 > Int16(3.8 / 0.0555) && $0 < Int16(7.9 / 0.0555) }) + if !mapGlucose.isEmpty { + let mapGlucoseAcuteLow = mapGlucose.filter({ $0 < Int16(3.3 / 0.0555) }) + let mapGlucoseHigh = mapGlucose.filter({ $0 > Int16(11 / 0.0555) }) + let mapGlucoseNormal = mapGlucose.filter({ $0 > Int16(3.8 / 0.0555) && $0 < Int16(7.9 / 0.0555) }) - HStack { - let value = Double(mapGlucoseHigh.count * 100 / mapGlucose.count) - if value != 0 { - Text(units == .mmolL ? "> 11 " : "> 200 ").foregroundColor(.secondary) - Text(value.formatted()).foregroundColor(.orange) - Text("%").foregroundColor(.secondary) - } - }.font(.caption) + HStack { + let value = Double(mapGlucoseHigh.count * 100 / mapGlucose.count) + if value != 0 { + Text(units == .mmolL ? "> 11 " : "> 200 ").foregroundColor(.secondary) + Text(value.formatted()).foregroundColor(.orange) + Text("%").foregroundColor(.secondary) + } + }.font(.caption) - HStack { - let value = Double(mapGlucoseNormal.count * 100 / mapGlucose.count) - if value != 0 { - Text(units == .mmolL ? "3.9-7.8" : "70-140").foregroundColor(.secondary) - Text(value.formatted()).foregroundColor(.green) - Text("%").foregroundColor(.secondary) - } - }.font(.caption) + HStack { + let value = Double(mapGlucoseNormal.count * 100 / mapGlucose.count) + if value != 0 { + Text(units == .mmolL ? "3.9-7.8" : "70-140").foregroundColor(.secondary) + Text(value.formatted()).foregroundColor(.green) + Text("%").foregroundColor(.secondary) + } + }.font(.caption) - HStack { - let value = Double(mapGlucoseAcuteLow.count * 100 / mapGlucose.count) - if value != 0 { - Text(units == .mmolL ? "< 3.3 " : "< 59 ").foregroundColor(.secondary) - Text(value.formatted()).foregroundColor(.red) - Text("%").foregroundColor(.secondary) - } - }.font(.caption) + HStack { + let value = Double(mapGlucoseAcuteLow.count * 100 / mapGlucose.count) + if value != 0 { + Text(units == .mmolL ? "< 3.3 " : "< 59 ").foregroundColor(.secondary) + Text(value.formatted()).foregroundColor(.red) + Text("%").foregroundColor(.secondary) + } + }.font(.caption) + } } } var groupedGlucoseStatsLaying: some View { HStack { let glucose = fetchRequest - let mapGlucose = glucose.compactMap({ each in each.glucose }) - let mapGlucoseLow = mapGlucose.filter({ $0 < Int16(3.3 / 0.0555) }) - let mapGlucoseAcuteLow = mapGlucose.filter({ $0 < Int16(2.6 / 0.0555) }) + if !mapGlucose.isEmpty { + let mapGlucoseLow = mapGlucose.filter({ $0 < Int16(3.3 / 0.0555) }) + let mapGlucoseAcuteLow = mapGlucose.filter({ $0 < Int16(2.6 / 0.0555) }) - let mapGlucoseHigh = mapGlucose.filter({ $0 > Int(7.8 / 0.0555) }) - let mapGlucoseAcuteHigh = mapGlucose.filter({ $0 > Int16(11 / 0.0555) }) + let mapGlucoseHigh = mapGlucose.filter({ $0 > Int(7.8 / 0.0555) }) + let mapGlucoseAcuteHigh = mapGlucose.filter({ $0 > Int16(11 / 0.0555) }) - HStack { - let value = Double(mapGlucoseAcuteLow.count * 100 / mapGlucose.count) - if value != 0 { - Text(units == .mmolL ? "< 2.6" : "< 47").font(.caption2).foregroundColor(.secondary) - Text(value.formatted()).font(.caption).foregroundColor(value == 0 ? .green : .red) - Text("%").font(.caption) - } - }.padding(.horizontal, 10) - HStack { - let value = Double(mapGlucoseLow.count * 100 / mapGlucose.count) - if value != 0 { - Text(units == .mmolL ? "< 3.3" : "< 59").font(.caption2).foregroundColor(.secondary) - Text(value.formatted()).font(.caption).foregroundColor(value == 0 ? .green : .orange) - Text("%").font(.caption) - } - } - Spacer() - HStack { - let value = Double(mapGlucoseHigh.count * 100 / mapGlucose.count) - if value != 0 { - Text(units == .mmolL ? "> 7.8" : "> 140").font(.caption).foregroundColor(.secondary) - Text(value.formatted()).font(.caption).foregroundColor(value == 0 ? .green : .orange) - Text("%").font(.caption) + HStack { + let value = Double(mapGlucoseAcuteLow.count * 100 / mapGlucose.count) + if value != 0 { + Text(units == .mmolL ? "< 2.6" : "< 47").font(.caption2).foregroundColor(.secondary) + Text(value.formatted()).font(.caption).foregroundColor(value == 0 ? .green : .red) + Text("%").font(.caption) + } + }.padding(.horizontal, 10) + HStack { + let value = Double(mapGlucoseLow.count * 100 / mapGlucose.count) + if value != 0 { + Text(units == .mmolL ? "< 3.3" : "< 59").font(.caption2).foregroundColor(.secondary) + Text(value.formatted()).font(.caption).foregroundColor(value == 0 ? .green : .orange) + Text("%").font(.caption) + } } - }.padding(.horizontal, 10) - HStack { - let value = Double(mapGlucoseAcuteHigh.count * 100 / mapGlucose.count) - if value != 0 { - Text(units == .mmolL ? "> 11.0" : "> 216").font(.caption).foregroundColor(.secondary) - Text(value.formatted()).font(.caption).foregroundColor(value == 0 ? .green : .red) - Text("%").font(.caption) + Spacer() + HStack { + let value = Double(mapGlucoseHigh.count * 100 / mapGlucose.count) + if value != 0 { + Text(units == .mmolL ? "> 7.8" : "> 140").font(.caption).foregroundColor(.secondary) + Text(value.formatted()).font(.caption).foregroundColor(value == 0 ? .green : .orange) + Text("%").font(.caption) + } + }.padding(.horizontal, 10) + HStack { + let value = Double(mapGlucoseAcuteHigh.count * 100 / mapGlucose.count) + if value != 0 { + Text(units == .mmolL ? "> 11.0" : "> 216").font(.caption).foregroundColor(.secondary) + Text(value.formatted()).font(.caption).foregroundColor(value == 0 ? .green : .red) + Text("%").font(.caption) + } } } } From 561cf1c8bf6097edd2036dc1e5de8f400b56ef30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Wed, 7 Jun 2023 22:05:05 +0200 Subject: [PATCH 21/45] Add Manual Glucose. Test Co (cherry picked from commit 113018be2c1d3274f2a1ed4b910a98296d17b006) --- .../Core_Data.xcdatamodel/contents | 3 +- .../Sources/APS/Storage/GlucoseStorage.swift | 5 +- .../DataTable/DataTableStateModel.swift | 56 +++++++++++++++++++ .../DataTable/View/DataTableRootView.swift | 36 +++++++++++- 4 files changed, 97 insertions(+), 3 deletions(-) diff --git a/Core_Data.xcdatamodeld/Core_Data.xcdatamodel/contents b/Core_Data.xcdatamodeld/Core_Data.xcdatamodel/contents index 7f007e3b2e..f83f1b8e2c 100644 --- a/Core_Data.xcdatamodeld/Core_Data.xcdatamodel/contents +++ b/Core_Data.xcdatamodeld/Core_Data.xcdatamodel/contents @@ -1,5 +1,5 @@ - + @@ -92,6 +92,7 @@ + diff --git a/FreeAPS/Sources/APS/Storage/GlucoseStorage.swift b/FreeAPS/Sources/APS/Storage/GlucoseStorage.swift index 22abf73725..0748f9dc14 100644 --- a/FreeAPS/Sources/APS/Storage/GlucoseStorage.swift +++ b/FreeAPS/Sources/APS/Storage/GlucoseStorage.swift @@ -56,14 +56,16 @@ final class BaseGlucoseStorage: GlucoseStorage, Injectable { } } - // MARK: Save to CoreData. TEST + // MARK: Save to CoreData. var bg_ = 0 var bgDate = Date() + var id = "" if glucose.isNotEmpty { bg_ = glucose[0].glucose ?? 0 bgDate = glucose[0].dateString + id = glucose[0].id } if bg_ != 0 { @@ -72,6 +74,7 @@ final class BaseGlucoseStorage: GlucoseStorage, Injectable { dataForForStats.date = bgDate dataForForStats.glucose = Int16(bg_) + dataForForStats.id = id try? self.coredataContext.save() } diff --git a/FreeAPS/Sources/Modules/DataTable/DataTableStateModel.swift b/FreeAPS/Sources/Modules/DataTable/DataTableStateModel.swift index d17d9e342f..738bc4687c 100644 --- a/FreeAPS/Sources/Modules/DataTable/DataTableStateModel.swift +++ b/FreeAPS/Sources/Modules/DataTable/DataTableStateModel.swift @@ -1,13 +1,19 @@ +import CoreData import SwiftUI extension DataTable { final class StateModel: BaseStateModel { @Injected() var broadcaster: Broadcaster! @Injected() var unlockmanager: UnlockManager! + @Injected() private var storage: FileStorage! + + let coredataContext = CoreDataStack.shared.persistentContainer.viewContext @Published var mode: Mode = .treatments @Published var treatments: [Treatment] = [] @Published var glucose: [Glucose] = [] + @Published var manualGlcuose: Decimal = 0 + var units: GlucoseUnits = .mmolL override func subscribe() { @@ -132,6 +138,56 @@ extension DataTable { func deleteGlucose(at index: Int) { let id = glucose[index].id provider.deleteGlucose(id: id) + + let fetchRequest: NSFetchRequest + fetchRequest = NSFetchRequest(entityName: "Readings") + fetchRequest.predicate = NSPredicate(format: "id == %@", id) + + let deleteRequest = NSBatchDeleteRequest( + fetchRequest: fetchRequest + ) + deleteRequest.resultType = .resultTypeObjectIDs + do { + let deleteResult = try coredataContext.execute(deleteRequest) as? NSBatchDeleteResult + if let objectIDs = deleteResult?.result as? [NSManagedObjectID] { + NSManagedObjectContext.mergeChanges( + fromRemoteContextSave: [NSDeletedObjectsKey: objectIDs], + into: [coredataContext] + ) + } + } catch { + // To do: handle any thrown errors. + } + try? coredataContext.save() + } + + func addManualGlucose() { + let glucose = units == .mmolL ? manualGlcuose.asMgdL : manualGlcuose + let now = Date() + let id = UUID().uuidString + + let saveToJSON = BloodGlucose( + _id: id, + direction: nil, + date: Decimal(now.timeIntervalSince1970) * 1000, + dateString: now, + unfiltered: nil, + filtered: nil, + noise: nil, + glucose: Int(glucose), + type: "Manual" + ) + provider.glucoseStorage.storeGlucose([saveToJSON]) + debug(.default, "Manual Glucose saved to glucose.json") + + coredataContext.perform { + let saveToCoreData = Readings(context: self.coredataContext) + saveToCoreData.date = now + saveToCoreData.glucose = Int16(Int(glucose)) + saveToCoreData.id = id + try? self.coredataContext.save() + debug(.default, "Manual Glucose saved to CoreData") + } } } } diff --git a/FreeAPS/Sources/Modules/DataTable/View/DataTableRootView.swift b/FreeAPS/Sources/Modules/DataTable/View/DataTableRootView.swift index af2af1f7bb..38ce4d79db 100644 --- a/FreeAPS/Sources/Modules/DataTable/View/DataTableRootView.swift +++ b/FreeAPS/Sources/Modules/DataTable/View/DataTableRootView.swift @@ -1,3 +1,4 @@ +import CoreData import SwiftUI import Swinject @@ -8,9 +9,11 @@ extension DataTable { @State private var isRemoveCarbsAlertPresented = false @State private var removeCarbsAlert: Alert? - @State private var isRemoveInsulinAlertPresented = false @State private var removeInsulinAlert: Alert? + @State private var newGlucose = false + + @Environment(\.colorScheme) var colorScheme private var glucoseFormatter: NumberFormatter { let formatter = NumberFormatter() @@ -54,6 +57,33 @@ extension DataTable { leading: Button("Close", action: state.hideModal), trailing: state.mode == .glucose ? EditButton().asAny() : EmptyView().asAny() ) + .popup(isPresented: newGlucose, alignment: .top, direction: .bottom) { + VStack(spacing: 20) { + HStack { + Text("New Glucose") + DecimalTextField(" ... ", value: $state.manualGlcuose, formatter: glucoseFormatter) + Text(state.units.rawValue) + }.padding(.horizontal, 20) + HStack { + Button { newGlucose = false } + label: { Text("Cancel") }.frame(maxWidth: .infinity, alignment: .leading) + + Button { + state.addManualGlucose() + newGlucose = false + } + label: { Text("Save") } + .frame(maxWidth: .infinity, alignment: .trailing) + .disabled(state.manualGlcuose < 2.2 || state.manualGlcuose > 22) + + }.padding(20) + } + .frame(maxHeight: 140) + .background( + RoundedRectangle(cornerRadius: 8, style: .continuous) + .fill(Color(colorScheme == .dark ? UIColor.systemGray2 : UIColor.systemGray6)) + ) + } } private var treatmentsList: some View { @@ -66,6 +96,10 @@ extension DataTable { private var glucoseList: some View { List { + Button { newGlucose = true } + label: { Text("Add") }.frame(maxWidth: .infinity, alignment: .trailing) + .padding(.trailing, 20) + ForEach(state.glucose) { item in glucoseView(item) }.onDelete(perform: deleteGlucose) From d8ae953d378a5019189adce85e29148d865b3b6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Wed, 7 Jun 2023 22:10:07 +0200 Subject: [PATCH 22/45] Clean up (cherry picked from commit dfed5264919622b1af9c52a7dbdd0847acecb627) --- .../Modules/AddTempTarget/AddTempTargetStateModel.swift | 1 - .../Modules/AddTempTarget/View/AddTempTargetRootView.swift | 3 +-- FreeAPS/Sources/Modules/Stat/View/StatsView.swift | 5 ----- 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/FreeAPS/Sources/Modules/AddTempTarget/AddTempTargetStateModel.swift b/FreeAPS/Sources/Modules/AddTempTarget/AddTempTargetStateModel.swift index 00cc0ff175..84370d45bf 100644 --- a/FreeAPS/Sources/Modules/AddTempTarget/AddTempTargetStateModel.swift +++ b/FreeAPS/Sources/Modules/AddTempTarget/AddTempTargetStateModel.swift @@ -7,7 +7,6 @@ extension AddTempTarget { @Injected() var apsManager: APSManager! let coredataContext = CoreDataStack.shared.persistentContainer.viewContext - @Environment(\.managedObjectContext) var moc @Published var low: Decimal = 0 // @Published var target: Decimal = 0 diff --git a/FreeAPS/Sources/Modules/AddTempTarget/View/AddTempTargetRootView.swift b/FreeAPS/Sources/Modules/AddTempTarget/View/AddTempTargetRootView.swift index f7f1c83cc6..41f759a189 100644 --- a/FreeAPS/Sources/Modules/AddTempTarget/View/AddTempTargetRootView.swift +++ b/FreeAPS/Sources/Modules/AddTempTarget/View/AddTempTargetRootView.swift @@ -16,8 +16,6 @@ extension AddTempTarget { sortDescriptors: [NSSortDescriptor(key: "date", ascending: false)] ) var isEnabledArray: FetchedResults - @Environment(\.managedObjectContext) var moc - private var formatter: NumberFormatter { let formatter = NumberFormatter() formatter.numberStyle = .decimal @@ -116,6 +114,7 @@ extension AddTempTarget { DatePicker("Date", selection: $state.date) Button { isPromtPresented = true } label: { Text("Save as preset") } + .disabled(state.duration == 0) } } diff --git a/FreeAPS/Sources/Modules/Stat/View/StatsView.swift b/FreeAPS/Sources/Modules/Stat/View/StatsView.swift index b88bd2f0d6..16c0e2f25f 100644 --- a/FreeAPS/Sources/Modules/Stat/View/StatsView.swift +++ b/FreeAPS/Sources/Modules/Stat/View/StatsView.swift @@ -62,10 +62,8 @@ struct StatsView: View { let previous = loops.last?.end ?? Date() // Last date (recent) let current = loops.first?.start ?? Date() - // Total time in days let totalTime = (current - previous).timeInterval / 8.64E4 - let durationArray = loops.compactMap({ each in each.duration }) let durationArrayCount = durationArray.count // var durationAverage = durationArray.reduce(0, +) / Double(durationArrayCount) @@ -74,14 +72,11 @@ struct StatsView: View { .count let errorNR = durationArrayCount - successsNR let successRate: Double? = (Double(successsNR) / Double(successsNR + errorNR)) * 100 - let loopNr = totalTime <= 1 ? Double(successsNR + errorNR) : round(Double(successsNR + errorNR) / totalTime) - let intervalArray = loops.compactMap({ each in each.interval as Double }) let intervalAverage = intervalArray.reduce(0, +) / Double(intervalArray.count) // let maximumInterval = intervalArray.max() // let minimumInterval = intervalArray.min() - HStack(spacing: 35) { VStack(spacing: 5) { Text("Loops").font(.subheadline).foregroundColor(headline) From 99f9b50d38a755510718afefcb0940bc490a7279 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Wed, 7 Jun 2023 22:24:25 +0200 Subject: [PATCH 23/45] Bump version --- Config.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config.xcconfig b/Config.xcconfig index 3463088bd4..dfa0eddc11 100644 --- a/Config.xcconfig +++ b/Config.xcconfig @@ -1,5 +1,5 @@ APP_DISPLAY_NAME = iAPS -APP_VERSION = 2.1.6 +APP_VERSION = 2.1.7 APP_BUILD_NUMBER = 1 COPYRIGHT_NOTICE = DEVELOPER_TEAM = ##TEAM_ID## From 3e39fad777017ab3289aaa715debb04bee019958 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Wed, 7 Jun 2023 23:19:34 +0200 Subject: [PATCH 24/45] Prevent Xcode build error for some users? --- .../Sources/Modules/Stat/View/StatsView.swift | 90 +++++++++---------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/FreeAPS/Sources/Modules/Stat/View/StatsView.swift b/FreeAPS/Sources/Modules/Stat/View/StatsView.swift index 16c0e2f25f..7cbd1c1d86 100644 --- a/FreeAPS/Sources/Modules/Stat/View/StatsView.swift +++ b/FreeAPS/Sources/Modules/Stat/View/StatsView.swift @@ -55,51 +55,51 @@ struct StatsView: View { } var loops: some View { - VStack(spacing: 10) { - let loops = fetchRequest - if !loops.isEmpty { - // First date - let previous = loops.last?.end ?? Date() - // Last date (recent) - let current = loops.first?.start ?? Date() - // Total time in days - let totalTime = (current - previous).timeInterval / 8.64E4 - let durationArray = loops.compactMap({ each in each.duration }) - let durationArrayCount = durationArray.count - // var durationAverage = durationArray.reduce(0, +) / Double(durationArrayCount) - let medianDuration = medianCalculationDouble(array: durationArray) - let successsNR = loops.compactMap({ each in each.loopStatus }).filter({ each in each!.contains("Success") }) - .count - let errorNR = durationArrayCount - successsNR - let successRate: Double? = (Double(successsNR) / Double(successsNR + errorNR)) * 100 - let loopNr = totalTime <= 1 ? Double(successsNR + errorNR) : round(Double(successsNR + errorNR) / totalTime) - let intervalArray = loops.compactMap({ each in each.interval as Double }) - let intervalAverage = intervalArray.reduce(0, +) / Double(intervalArray.count) - // let maximumInterval = intervalArray.max() - // let minimumInterval = intervalArray.min() - HStack(spacing: 35) { - VStack(spacing: 5) { - Text("Loops").font(.subheadline).foregroundColor(headline) - Text(loopNr.formatted()) - } - VStack(spacing: 5) { - Text("Interval").font(.subheadline).foregroundColor(headline) - Text(intervalAverage.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1))) + " min") - } - VStack(spacing: 5) { - Text("Duration").font(.subheadline).foregroundColor(headline) - Text( - (medianDuration * 60) - .formatted(.number.grouping(.never).rounded().precision(.fractionLength(1))) + " s" - ) - } - VStack(spacing: 5) { - Text("Sucess").font(.subheadline).foregroundColor(headline) - Text( - ((successRate ?? 100) / 100) - .formatted(.percent.grouping(.never).rounded().precision(.fractionLength(1))) - ) - } + let loops = fetchRequest + // First date + let previous = loops.last?.end ?? Date() + // Last date (recent) + let current = loops.first?.start ?? Date() + // Total time in days + let totalTime = (current - previous).timeInterval / 8.64E4 + let durationArray = loops.compactMap({ each in each.duration }) + let durationArrayCount = durationArray.count + // var durationAverage = durationArray.reduce(0, +) / Double(durationArrayCount) + let medianDuration = medianCalculationDouble(array: durationArray) + let successsNR = loops.compactMap({ each in each.loopStatus }).filter({ each in each!.contains("Success") }).count + let errorNR = durationArrayCount - successsNR + let total = Double(successsNR + errorNR) == 0 ? 1 : Double(successsNR + errorNR) + let successRate: Double? = (Double(successsNR) / total) * 100 + let loopNr = totalTime <= 1 ? Double(successsNR + errorNR) : + round(Double(successsNR + errorNR) / totalTime != 0 ? totalTime : 1) + let intervalArray = loops.compactMap({ each in each.interval as Double }) + let count = intervalArray.count != 0 ? intervalArray.count : 1 + let intervalAverage = intervalArray.reduce(0, +) / Double(count) + // let maximumInterval = intervalArray.max() + // let minimumInterval = intervalArray.min() + return VStack(spacing: 10) { + HStack(spacing: 35) { + VStack(spacing: 5) { + Text("Loops").font(.subheadline).foregroundColor(headline) + Text(loopNr.formatted()) + } + VStack(spacing: 5) { + Text("Interval").font(.subheadline).foregroundColor(headline) + Text(intervalAverage.formatted(.number.grouping(.never).rounded().precision(.fractionLength(1))) + " min") + } + VStack(spacing: 5) { + Text("Duration").font(.subheadline).foregroundColor(headline) + Text( + (medianDuration * 60) + .formatted(.number.grouping(.never).rounded().precision(.fractionLength(1))) + " s" + ) + } + VStack(spacing: 5) { + Text("Sucess").font(.subheadline).foregroundColor(headline) + Text( + ((successRate ?? 100) / 100) + .formatted(.percent.grouping(.never).rounded().precision(.fractionLength(1))) + ) } } } From 91f79c225f4c32acf9b0e0f2d8bf839859efeaa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Thu, 8 Jun 2023 01:26:09 +0200 Subject: [PATCH 25/45] Avoid double saving (cherry picked from commit ce6081e2c282346715bf7c5813e2d070e138a9dc) --- FreeAPS/Sources/APS/Storage/GlucoseStorage.swift | 2 -- .../Modules/DataTable/DataTableStateModel.swift | 12 +----------- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/FreeAPS/Sources/APS/Storage/GlucoseStorage.swift b/FreeAPS/Sources/APS/Storage/GlucoseStorage.swift index 0748f9dc14..d9a8de5508 100644 --- a/FreeAPS/Sources/APS/Storage/GlucoseStorage.swift +++ b/FreeAPS/Sources/APS/Storage/GlucoseStorage.swift @@ -71,11 +71,9 @@ final class BaseGlucoseStorage: GlucoseStorage, Injectable { if bg_ != 0 { self.coredataContext.perform { let dataForForStats = Readings(context: self.coredataContext) - dataForForStats.date = bgDate dataForForStats.glucose = Int16(bg_) dataForForStats.id = id - try? self.coredataContext.save() } } diff --git a/FreeAPS/Sources/Modules/DataTable/DataTableStateModel.swift b/FreeAPS/Sources/Modules/DataTable/DataTableStateModel.swift index 738bc4687c..e62bead00c 100644 --- a/FreeAPS/Sources/Modules/DataTable/DataTableStateModel.swift +++ b/FreeAPS/Sources/Modules/DataTable/DataTableStateModel.swift @@ -142,7 +142,6 @@ extension DataTable { let fetchRequest: NSFetchRequest fetchRequest = NSFetchRequest(entityName: "Readings") fetchRequest.predicate = NSPredicate(format: "id == %@", id) - let deleteRequest = NSBatchDeleteRequest( fetchRequest: fetchRequest ) @@ -158,7 +157,7 @@ extension DataTable { } catch { // To do: handle any thrown errors. } - try? coredataContext.save() + // try? coredataContext.save() } func addManualGlucose() { @@ -179,15 +178,6 @@ extension DataTable { ) provider.glucoseStorage.storeGlucose([saveToJSON]) debug(.default, "Manual Glucose saved to glucose.json") - - coredataContext.perform { - let saveToCoreData = Readings(context: self.coredataContext) - saveToCoreData.date = now - saveToCoreData.glucose = Int16(Int(glucose)) - saveToCoreData.id = id - try? self.coredataContext.save() - debug(.default, "Manual Glucose saved to CoreData") - } } } } From ceedda2c82651c4070009119629cdc000709c227 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Thu, 8 Jun 2023 02:27:31 +0200 Subject: [PATCH 26/45] Correction (cherry picked from commit b6f1490f3f73d599a62b46209092d8f321fbb3e8) --- FreeAPS/Sources/Modules/Stat/View/StatsView.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FreeAPS/Sources/Modules/Stat/View/StatsView.swift b/FreeAPS/Sources/Modules/Stat/View/StatsView.swift index 7cbd1c1d86..297a5bcc07 100644 --- a/FreeAPS/Sources/Modules/Stat/View/StatsView.swift +++ b/FreeAPS/Sources/Modules/Stat/View/StatsView.swift @@ -62,6 +62,7 @@ struct StatsView: View { let current = loops.first?.start ?? Date() // Total time in days let totalTime = (current - previous).timeInterval / 8.64E4 + let durationArray = loops.compactMap({ each in each.duration }) let durationArrayCount = durationArray.count // var durationAverage = durationArray.reduce(0, +) / Double(durationArrayCount) @@ -70,8 +71,7 @@ struct StatsView: View { let errorNR = durationArrayCount - successsNR let total = Double(successsNR + errorNR) == 0 ? 1 : Double(successsNR + errorNR) let successRate: Double? = (Double(successsNR) / total) * 100 - let loopNr = totalTime <= 1 ? Double(successsNR + errorNR) : - round(Double(successsNR + errorNR) / totalTime != 0 ? totalTime : 1) + let loopNr = totalTime <= 1 ? total : round(total / (totalTime != 0 ? totalTime : 1)) let intervalArray = loops.compactMap({ each in each.interval as Double }) let count = intervalArray.count != 0 ? intervalArray.count : 1 let intervalAverage = intervalArray.reduce(0, +) / Double(count) From 6edda045d379ee128e9254519f8d8aecba01c1ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20B=20M=C3=A5rtensson?= <53905247+Jon-b-m@users.noreply.github.com> Date: Thu, 8 Jun 2023 15:46:09 +0200 Subject: [PATCH 27/45] Improve the bolus calculator. (#98) When entering carbs and coming to the bolus recommendation screen, use the EventualBG instead of the minPredBG when computing recommended bolus. Only used when directly combined with carbs. If not everything else is as before. To not make things overly complicated I'm using this new bolus recommendation for Watch App also, but always, until I find a neat way of collecting the manual state from the BolusStateModel. For testing. Tested for about a week without any dramatic adverse effects, but needs more testing from more users. --- Config.xcconfig | 2 +- .../javascript/bundle/determine-basal.js | 3 +- FreeAPS/Sources/Models/Suggestion.swift | 2 + .../Modules/AddCarbs/AddCarbsStateModel.swift | 4 +- .../Modules/Bolus/BolusStateModel.swift | 24 ++++-- .../Modules/Bolus/View/BolusRootView.swift | 74 ++++++++++++------- .../Modules/Home/View/HomeRootView.swift | 2 +- .../Modules/Stat/View/ChartsView.swift | 6 -- .../Sources/Modules/Stat/View/StatsView.swift | 6 -- FreeAPS/Sources/Router/Screen.swift | 6 +- .../Services/WatchManager/WatchManager.swift | 10 ++- 11 files changed, 85 insertions(+), 54 deletions(-) diff --git a/Config.xcconfig b/Config.xcconfig index dfa0eddc11..5343d916ef 100644 --- a/Config.xcconfig +++ b/Config.xcconfig @@ -1,5 +1,5 @@ APP_DISPLAY_NAME = iAPS -APP_VERSION = 2.1.7 +APP_VERSION = 2.1.8 APP_BUILD_NUMBER = 1 COPYRIGHT_NOTICE = DEVELOPER_TEAM = ##TEAM_ID## diff --git a/FreeAPS/Resources/javascript/bundle/determine-basal.js b/FreeAPS/Resources/javascript/bundle/determine-basal.js index 3e80b19cf7..6144378639 100644 --- a/FreeAPS/Resources/javascript/bundle/determine-basal.js +++ b/FreeAPS/Resources/javascript/bundle/determine-basal.js @@ -1,2 +1 @@ - -var freeaps_determineBasal;(()=>{var e={5546:(e,t,a)=>{var r=a(6880);function o(e,t){t||(t=0);var a=Math.pow(10,t);return Math.round(e*a)/a}function n(e,t){return"mmol/L"===t.out_units?o(.0555*e,1):Math.round(e)}e.exports=function(e,t,a,i,s,l,m,d,u,c,g,h,p,v){var f=i.min_bg,b=v.overrideTarget;const B=v.smbIsOff,M=v.advancedSettings,_=v.isfAndCr,y=v.isf,x=v.cr,w=v.smbIsAlwaysOff,D=v.start,S=v.end,T=v.smbMinutes,C=v.uamMinutes;var U=0,G="",O="",R="",A="",I="",j=0,F=0,P=0,E=0,q=0,W=0;const k=v.weightedAverage;var L=1,z=i.sens,N=i.carb_ratio;v.useOverride&&(L=v.overridePercentage/100,_?(z/=L,N/=L):(x&&(N/=L),y&&(z/=L)));const H=i.weightPercentage,Z=v.average_total_data;function $(e,t){var a=e.getTime();return new Date(a+36e5*t)}function J(e){var t=i.bolus_increment;.025!=t&&(t=.05);var a=e/t;return a>=1?o(Math.floor(a)*t,5):0}function K(e){function t(e){return e<10&&(e="0"+e),e}return t(e.getHours())+":"+t(e.getMinutes())+":00"}function Q(e,t){var a=new Date("1/1/1999 "+e),r=new Date("1/1/1999 "+t);return(a.getTime()-r.getTime())/36e5}function V(e,t){var a=0,r=t,o=(e-t)/36e5,n=0,i=o,s=0;do{if(o>0){var l=K(r),m=p[0].rate;for(let e=0;e=(s=Q(p[e+1].start,p[e].start))?n=s:o=s?n=s:od)if(e+1=(s=Q(u,l))?n=s:o=(s=Q("23:59:59",l))?n=s:o0&&o21)q=V(X,(ee=24-U,te=X.getTime(),new Date(te-36e5*ee))),A="24 hours of data is required for an accurate tdd calculation. Currently only "+U.toPrecision(3)+" hours of pump history data are available. Using your pump scheduled basals to fill in the missing hours. Scheduled basals added: "+q.toPrecision(5)+" U. ";else U<21?(ge=!1,enableDynamicCR=!1):A=""}else console.log("Pumphistory is empty!"),ge=!1,enableDynamicCR=!1;var ee,te;for(let e=0;e0){j=e,W=g[e].rate;var ae=g[e-1]["duration (min)"]/60,re=ae,oe=new Date(g[e-1].timestamp),ne=oe,ie=0;do{if(e--,0==e){ne=new Date;break}if("TempBasal"==g[e]._type||"PumpSuspend"==g[e]._type){ne=new Date(g[e].timestamp);break}var se=e-2;if(se>=0&&"Rewind"==g[se]._type){let e=g[se].timestamp;for(;se-1>=0&&"Prime"==g[se-=1]._type;)ie=(g[se].timestamp-e)/36e5;ie>=ae&&(ne=e,ie=0)}}while(e>0);var le=(ne-oe)/36e5;le0&&(--r,"TempBasal"==g[r]._type)){a=new Date(g[r].timestamp);break}}while(r>0);(a-t)/36e5>0&&(q+=V(a,t))}for(let e=g.length-1;e>0;e--)if("TempBasalDuration"==g[e]._type){let t=g[e]["duration (min)"]/60,a=new Date(g[e].timestamp);var me=a;let r=e;do{if(--r,r>=0&&("TempBasal"==g[r]._type||"PumpSuspend"==g[r]._type)){me=new Date(g[r].timestamp);break}}while(r>0);if(0==e&&"TempBasalDuration"==g[0]._type&&(me=new Date,t=g[e]["duration (min)"]/60),(me-a)/36e5-t>0){q+=V(me,$(a,t))}}var de,ue={TDD:o(F=E+P+q,5),bolus:o(E,5),temp_basal:o(P,5),scheduled_basal:o(q,5)};U>21?(O=". Bolus insulin: "+E.toPrecision(5)+" U",R=". Temporary basal insulin: "+P.toPrecision(5)+" U",G=". Insulin with scheduled basal rate: "+q.toPrecision(5)+" U",I=A+(" TDD past 24h is: "+F.toPrecision(5)+" U")+O+R+G,tddReason=", Total insulin: "+o(F,2)+" U, "+o(E/F*100,0)+"% Bolus "+o((P+q)/F*100,0)+"% Basal"):tddReason=", TDD: Not enough pumpData (< 21h)";const ce=e.glucose;var ge=h.useNewFormula;const he=h.enableDynamicCR,pe=Math.min(i.autosens_min,i.autosens_max),ve=Math.max(i.autosens_min,i.autosens_max);(ve==pe||ve<1||pe>1)&&(ge=!1,console.log("Dynamic ISF disabled due to current autosens settings"));const fe=h.adjustmentFactor,be=i.min_bg;var Be=!1,Me="",_e=1,ye="";Z>0&&(_e=k/Z),ye=_e>1?"Basal adjustment with a 24 hour to total average (up to 14 days of data) TDD ratio (limited by Autosens max setting). Basal Ratio: "+(_e=o(_e=Math.min(_e,i.autosens_max),2))+". Upper limit = Autosens max ("+i.autosens_max+")":_e<1?"Basal adjustment with a 24 hour to to total average (up to 14 days of data) TDD ratio (limited by Autosens min setting). Basal Ratio: "+(_e=o(_e=Math.max(_e,i.autosens_min),2))+". Lower limit = Autosens min ("+i.autosens_min+")":"Basal adjusted with a 24 hour to total average (up to 14 days of data) TDD ratio: "+_e,ye=", Basal ratio: "+_e,(i.high_temptarget_raises_sensitivity||i.exercise_mode||v.isEnabled)&&(Be=!0),be>=118&&Be&&(ge=!1,Me="Dynamic ISF temporarily off due to a high temp target/exercising. Current min target: "+be);var xe=", Dynamic ratios log: ",we=", AF: "+fe,De="BG: "+ce+" mg/dl ("+(.0555*ce).toPrecision(2)+" mmol/l)",Se="",Te="";const Ce=h.curve,Ue=h.insulinPeakTime,Ge=h.useCustomPeakTime;var Oe=55,Re=65;switch(Ce){case"rapid-acting":Re=65;break;case"ultra-rapid":Re=50}Ge?(Oe=120-Ue,console.log("Custom insulinpeakTime set to :"+Ue+", insulinFactor: "+Oe)):(Oe=120-Re,console.log("insulinFactor set to : "+Oe)),de=F,H<1&&k>0&&(F=k,console.log("Using weighted TDD average: "+o(F,2)+" U, instead of past 24 h ("+o(de,2)+" U), weight: "+H),Te=", Weighted TDD: "+o(F,2)+" U");const Ae=h.sigmoid;var Ie="";if(ge){var je=z*fe*F*Math.log(ce/Oe+1)/1800;Se=", Logarithmic formula"}if(ge&&Ae){const e=pe,t=ve-e,a=.0555*(ce-i.min_bg);var Fe=_e,Pe=ve-1;1==ve&&(Pe=ve+.01-1);const r=Math.log10(1/Pe-e/Pe)/Math.log10(Math.E),o=a*fe*Fe+r;je=t/(1+Math.exp(-o))+e,Se=", Sigmoid function"}var Ee=N;const qe=o(N,1);var We="",ke="";if(ge&&F>0){if(We=", Dynamic ISF/CR: On/",je>ve?(Me=", Dynamic ISF limited by autosens_max setting: "+ve+" ("+o(je,2)+"), ",ke=", Autosens/Dynamic Limit: "+ve+" ("+o(je,2)+")",je=ve):je-.5?"+"+o(e.delta,0):o(e.delta,0);var Ye=Math.min(e.delta,e.short_avgdelta),et=Math.min(e.short_avgdelta,e.long_avgdelta),tt=Math.max(e.delta,e.short_avgdelta,e.long_avgdelta);(Ve<=10||38===Ve||Xe>=3)&&(ze.reason="CGM is calibrating, in ??? state, or noise is high");if(Ve>60&&0==e.delta&&e.short_avgdelta>-1&&e.short_avgdelta<1&&e.long_avgdelta>-1&&e.long_avgdelta<1&&("fakecgm"==e.device?(console.error("CGM data is unchanged ("+n(Ve,i)+"+"+n(e.delta,i)+") for 5m w/ "+n(e.short_avgdelta,i)+" mg/dL ~15m change & "+n(e.long_avgdelta,2)+" mg/dL ~45m change"),console.error("Simulator mode detected ("+e.device+"): continuing anyway")):!0),Qe>12||Qe<-5?ze.reason="If current system time "+$e+" is correct, then BG data is too old. The last BG data was read "+Qe+"m ago at "+Ke:0===e.short_avgdelta&&0===e.long_avgdelta&&(e.last_cal&&e.last_cal<3?ze.reason="CGM was just calibrated":ze.reason="CGM data is unchanged ("+n(Ve,i)+"+"+n(e.delta,i)+") for 5m w/ "+n(e.short_avgdelta,i)+" mg/dL ~15m change & "+n(e.long_avgdelta,i)+" mg/dL ~45m change"),Ve<=10||38===Ve||Xe>=3||Qe>12||Qe<-5||0===e.short_avgdelta&&0===e.long_avgdelta)return t.rate>=Ze?(ze.reason+=". Canceling high temp basal of "+t.rate,ze.deliverAt=Ne,ze.temp="absolute",ze.duration=0,ze.rate=0,ze):0===t.rate&&t.duration>30?(ze.reason+=". Shortening "+t.duration+"m long zero temp to 30m. ",ze.deliverAt=Ne,ze.temp="absolute",ze.duration=30,ze.rate=0,ze):(ze.reason+=". Temp "+t.rate+" <= current basal "+Ze+"U/hr; doing nothing. ",ze);var at,rt,ot,nt,it=i.max_iob;if(void 0!==i.min_bg&&(rt=i.min_bg),void 0!==i.max_bg&&(ot=i.max_bg),void 0!==i.enableSMB_high_bg_target&&(nt=i.enableSMB_high_bg_target),void 0===i.min_bg||void 0===i.max_bg)return ze.error="Error: could not determine target_bg. ",ze;at=(i.min_bg+i.max_bg)/2;var st=i.exercise_mode||i.high_temptarget_raises_sensitivity||v.isEnabled,lt=100,mt=160;if(mt=i.half_basal_exercise_target,v.isEnabled){const e=v.hbt;console.log("Half Basal Target used: "+n(e,i)+" "+i.out_units),mt=e}else console.log("Default Half Basal Target used: "+n(mt,i)+" "+i.out_units);if(st&&i.temptargetSet&&at>lt||i.low_temptarget_lowers_sensitivity&&i.temptargetSet&&at=at&&sensitivityRatio0&&(process.stderr.write("TDD-adjustment of basals activated, using tdd24h_14d_Ratio "+o(_e,2)+", TDD 24h = "+o(de,2)+"U, Weighted average TDD = "+o(k,2)+"U, (Weight percentage = "+H+"), Total data of TDDs (up to 14 days) average = "+o(Z,2)+"U. "),Ze!==He*L?process.stderr.write("Adjusting basal from "+He*L+" U/h to "+Ze+" U/h; "):process.stderr.write("Basal unchanged: "+Ze+" U/h; "))),i.temptargetSet);else if(void 0!==s&&s&&(i.sensitivity_raises_target&&s.ratio<1||i.resistance_lowers_target&&s.ratio>1)){rt=o((rt-60)/s.ratio)+60,ot=o((ot-60)/s.ratio)+60;var ut=o((at-60)/s.ratio)+60;at===(ut=Math.max(80,ut))?process.stderr.write("target_bg unchanged: "+n(ut,i)+"; "):process.stderr.write("target_bg from "+n(ut,i)+" to "+n(ut,i)+"; "),at=ut}var ct=n(at,i);at!=f&&(ct=0!==b&&b!==at?n(f,i)+"→"+n(b,i)+"→"+n(at,i):n(f,i)+"→"+n(at,i));var gt=200,ht=200,pt=200;if(e.noise>=2){var vt=Math.max(1.1,i.noisyCGMTargetMultiplier);Math.min(250,i.maxRaw);gt=o(Math.min(200,rt*vt)),ht=o(Math.min(200,at*vt)),pt=o(Math.min(200,ot*vt)),process.stderr.write("Raising target_bg for noisy / raw CGM data, from "+n(ut,i)+" to "+n(ht,i)+"; "),rt=gt,at=ht,ot=pt}var ft=rt-.5*(rt-40),bt=i.threshold_setting;bt>ft&&bt<=120&&bt>=65?(console.error("Threshold changed in settings from "+n(ft,i)+" to "+n(bt,i)+". "),ft=bt):console.error("Current threshold: "+n(ft,i));var Bt="",Mt=(o(z,1),z);if(void 0!==s&&s&&((Mt=o(Mt=z/sensitivityRatio,1))!==z?process.stderr.write("ISF from "+n(z,i)+" to "+n(Mt,i)):process.stderr.write("ISF unchanged: "+n(Mt,i)),Bt+="Autosens ratio: "+o(sensitivityRatio,2)+", ISF: "+n(z,i)+"→"+n(Mt,i)),console.error("CR:"+N),void 0===a)return ze.error="Error: iob_data undefined. ",ze;var _t,yt=a;if(a.length,a.length>1&&(a=yt[0]),void 0===a.activity||void 0===a.iob)return ze.error="Error: iob_data missing some property. ",ze;var xt=((_t=void 0!==a.lastTemp?o((new Date($e).getTime()-a.lastTemp.date)/6e4):0)+t.duration)%30;if(console.error("currenttemp:"+t.rate+" lastTempAge:"+_t+"m, tempModulus:"+xt+"m"),ze.temp="absolute",ze.deliverAt=Ne,d&&t&&a.lastTemp&&t.rate!==a.lastTemp.rate&&_t>10&&t.duration)return ze.reason="Warning: currenttemp rate "+t.rate+" != lastTemp rate "+a.lastTemp.rate+" from pumphistory; canceling temp",m.setTempBasal(0,0,i,ze,t);if(t&&a.lastTemp&&t.duration>0){var wt=_t-a.lastTemp.duration;if(wt>5&&_t>10)return ze.reason="Warning: currenttemp running but lastTemp from pumphistory ended "+wt+"m ago; canceling temp",m.setTempBasal(0,0,i,ze,t)}var Dt=o(-a.activity*Mt*5,2),St=o(6*(Ye-Dt));St<0&&(St=o(6*(et-Dt)))<0&&(St=o(6*(e.long_avgdelta-Dt)));var Tt=Ve,Ct=(Tt=a.iob>0?o(Ve-a.iob*Mt):o(Ve-a.iob*Math.min(Mt,z)))+St;if(void 0===Ct||isNaN(Ct))return ze.error="Error: could not calculate eventualBG. Sensitivity: "+Mt+" Deviation: "+St,ze;var Ut=function(e,t,a){return o(a+(e-t)/24,1)}(at,Ct,Dt);ze={temp:"absolute",bg:Ve,tick:Je,eventualBG:Ct,insulinReq:0,reservoir:u,deliverAt:Ne,sensitivityRatio,TDD:de,insulin:ue,current_target:at};var Gt=[],Ot=[],Rt=[],At=[];Gt.push(Ve),Ot.push(Ve),At.push(Ve),Rt.push(Ve);var It=function(e,t,a,r,o,i){return t?!e.allowSMB_with_high_temptarget&&e.temptargetSet&&o>100?(console.error("SMB disabled due to high temptarget of "+o),!1):!0===a.bwFound&&!1===e.A52_risk_enable?(console.error("SMB disabled due to Bolus Wizard activity in the last 6 hours."),!1):!0===e.enableSMB_always?(a.bwFound?console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled due to enableSMB_always"),!0):!0===e.enableSMB_with_COB&&a.mealCOB?(a.bwCarbs?console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for COB of "+a.mealCOB),!0):!0===e.enableSMB_after_carbs&&a.carbs?(a.bwCarbs?console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for 6h after carb entry"),!0):!0===e.enableSMB_with_temptarget&&e.temptargetSet&&o<100?(a.bwFound?console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for temptarget of "+n(o,e)),!0):!0===e.enableSMB_high_bg&&null!==i&&r>=i?(console.error("Checking BG to see if High for SMB enablement."),console.error("Current BG",r," | High BG ",i),a.bwFound?console.error("Warning: High BG SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("High BG detected. Enabling SMB."),!0):(console.error("SMB disabled (no enableSMB preferences active or no condition satisfied)"),!1):(console.error("SMB disabled (!microBolusAllowed)"),!1)}(i,d,l,Ve,at,nt);if(B)if(w){let e=c.getHours();e>=D&&e<=S&&(console.error("SMB disabled by schedule (a Profile is active with SMBs disabled)"),It=!1)}else console.error("SMBs are disabled (a Profile is active with SMBs disabled)"),It=!1;var jt=i.enableUAM,Ft=0,Pt=0;Ft=o(Ye-Dt,1);var Et=o(Ye-Dt,1);csf=Mt/N,console.error("profile.sens:"+n(z,i)+", sens:"+n(Mt,i)+", CSF:"+o(csf,1));var qt=o(30*csf*5/60,1);Ft>qt&&(console.error("Limiting carb impact from "+Ft+" to "+qt+"mg/dL/5m (30g/h)"),Ft=qt);var Wt=3;sensitivityRatio&&(Wt/=sensitivityRatio);var kt=Wt;if(l.carbs){Wt=Math.max(Wt,l.mealCOB/20);var Lt=o((new Date($e).getTime()-l.lastCarbTime)/6e4),zt=(l.carbs-l.mealCOB)/l.carbs;kt=o(kt=Wt+1.5*Lt/60,1),console.error("Last carbs "+Lt+" minutes ago; remainingCATime:"+kt+"hours; "+o(100*zt,1)+"% carbs absorbed")}var Nt=Math.max(0,Ft/5*60*kt/2)/csf,Ht=90,Zt=1;i.remainingCarbsCap&&(Ht=Math.min(90,i.remainingCarbsCap)),i.remainingCarbsFraction&&(Zt=Math.min(1,i.remainingCarbsFraction));var $t=1-Zt,Jt=Math.max(0,l.mealCOB-Nt-l.carbs*$t),Kt=(Jt=Math.min(Ht,Jt))*csf*5/60/(kt/2),Qt=o(l.slopeFromMaxDeviation,2),Vt=o(l.slopeFromMinDeviation,2),Xt=Math.min(Qt,-Vt/3);Pt=0===Ft?0:Math.min(60*kt/5/2,Math.max(0,l.mealCOB*csf/Ft)),console.error("Carb Impact:"+Ft+"mg/dL per 5m; CI Duration:"+o(5*Pt/60*2,1)+"hours; remaining CI ("+kt/2+"h peak):"+o(Kt,1)+"mg/dL per 5m");var Yt,ea,ta,aa,ra,oa=999,na=999,ia=999,sa=Ve,la=999,ma=999,da=999,ua=999,ca=Ct,ga=Ve,ha=Ve,pa=0,va=[],fa=[];try{yt.forEach((function(e){var t=o(-e.activity*Mt*5,2),a=o(-e.iobWithZeroTemp.activity*Mt*5,2),r=Tt,n=Ft*(1-Math.min(1,Ot.length/12));if(!0===(ge&&!Ae))ca=Ot[Ot.length-1]+o(-e.activity*(1800/(F*fe*Math.log(Math.max(Ot[Ot.length-1],39)/Oe+1)))*5,2)+n,r=At[At.length-1]+o(-e.iobWithZeroTemp.activity*(1800/(F*fe*Math.log(Math.max(At[At.length-1],39)/Oe+1)))*5,2),console.log("Dynamic ISF (Logarithmic Formula) )adjusted predictions for IOB and ZT: IOBpredBG: "+o(ca,2)+" , ZTpredBG: "+o(r,2));else ca=Ot[Ot.length-1]+t+n,r=At[At.length-1]+a;var i=Math.max(0,Math.max(0,Ft)*(1-Gt.length/Math.max(2*Pt,1))),s=Math.min(Gt.length,12*kt-Gt.length),l=Math.max(0,s/(kt/2*12)*Kt);i+l,va.push(o(l,0)),fa.push(o(i,0)),COBpredBG=Gt[Gt.length-1]+t+Math.min(0,n)+i+l;var m=Math.max(0,Et+Rt.length*Xt),d=Math.max(0,Et*(1-Rt.length/Math.max(36,1))),u=Math.min(m,d);if(u>0&&(pa=o(5*(Rt.length+1)/60,1)),!0===(ge&&!Ae))UAMpredBG=Rt[Rt.length-1]+o(-e.activity*(1800/(F*fe*Math.log(Math.max(Rt[Rt.length-1],39)/Oe+1)))*5,2)+Math.min(0,n)+u,console.log("Dynamic ISF (Logarithmic Formula) adjusted prediction for UAM: UAMpredBG: "+o(UAMpredBG,2));else UAMpredBG=Rt[Rt.length-1]+t+Math.min(0,n)+u;Ot.length<48&&Ot.push(ca),Gt.length<48&&Gt.push(COBpredBG),Rt.length<48&&Rt.push(UAMpredBG),At.length<48&&At.push(r),COBpredBG18&&caga&&(ga=ca),(Pt||Kt>0)&&Gt.length>18&&COBpredBG0)&&COBpredBG>ga&&(ha=COBpredBG),jt&&Rt.length>12&&UAMpredBGga&&UAMpredBG}))}catch(e){console.error("Problem with iobArray. Optional feature Advanced Meal Assist disabled")}l.mealCOB&&(console.error("predCIs (mg/dL/5m):"+fa.join(" ")),console.error("remainingCIs: "+va.join(" "))),ze.predBGs={},Ot.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))}));for(var ba=Ot.length-1;ba>12&&Ot[ba-1]===Ot[ba];ba--)Ot.pop();for(ze.predBGs.IOB=Ot,ta=o(Ot[Ot.length-1]),At.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),ba=At.length-1;ba>6&&!(At[ba-1]>=At[ba]||At[ba]<=at);ba--)At.pop();if(ze.predBGs.ZT=At,o(At[At.length-1]),l.mealCOB>0&&(Ft>0||Kt>0)){for(Gt.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),ba=Gt.length-1;ba>12&&Gt[ba-1]===Gt[ba];ba--)Gt.pop();ze.predBGs.COB=Gt,aa=o(Gt[Gt.length-1]),Ct=Math.max(Ct,o(Gt[Gt.length-1]))}if(Ft>0||Kt>0){if(jt){for(Rt.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),ba=Rt.length-1;ba>12&&Rt[ba-1]===Rt[ba];ba--)Rt.pop();ze.predBGs.UAM=Rt,ra=o(Rt[Rt.length-1]),Rt[Rt.length-1]&&(Ct=Math.max(Ct,o(Rt[Rt.length-1])))}ze.eventualBG=Ct}console.error("UAM Impact:"+Et+"mg/dL per 5m; UAM Duration:"+pa+"hours"),oa=Math.max(39,oa),na=Math.max(39,na),ia=Math.max(39,ia),Yt=o(oa);var Ba=l.mealCOB/l.carbs;ea=o(ia<999&&na<999?(1-Ba)*UAMpredBG+Ba*COBpredBG:na<999?(ca+COBpredBG)/2:ia<999?(ca+UAMpredBG)/2:ca),ua>ea&&(ea=ua),sa=o(sa=Pt||Kt>0?jt?Ba*la+(1-Ba)*ma:la:jt?ma:da);var Ma=ia;if(uaia&&(Ma=(ia+ua)/2);if(Ma=o(Ma),l.carbs)if(!jt&&na<999)Yt=o(Math.max(oa,na));else if(na<999){var ya=Ba*na+(1-Ba)*Ma;Yt=o(Math.max(oa,na,ya))}else Yt=jt?Ma:sa;else jt&&(Yt=o(Math.max(oa,Ma)));Yt=Math.min(Yt,ea),process.stderr.write("minPredBG: "+Yt+" minIOBPredBG: "+oa+" minZTGuardBG: "+ua),na<999&&process.stderr.write(" minCOBPredBG: "+na),ia<999&&process.stderr.write(" minUAMPredBG: "+ia),console.error(" avgPredBG:"+ea+" COB/Carbs:"+l.mealCOB+"/"+l.carbs),ha>Ve&&(Yt=Math.min(Yt,ha)),ze.COB=l.mealCOB,ze.IOB=a.iob,ze.BGI=n(Dt,i),ze.deviation=n(St,i),ze.ISF=n(Mt,i),ze.CR=o(N,1),ze.target_bg=n(at,i),ze.TDD=o(de,2),ze.current_target=o(at,0);var xa=ze.CR;qe!=ze.CR&&(xa=qe+"→"+ze.CR),ze.reason=Bt+", COB: "+ze.COB+", Dev: "+ze.deviation+", BGI: "+ze.BGI+", CR: "+xa+", Target: "+ct+", minPredBG "+n(Yt,i)+", minGuardBG "+n(sa,i)+", IOBpredBG "+n(ta,i),aa>0&&(ze.reason+=", COBpredBG "+n(aa,i)),ra>0&&(ze.reason+=", UAMpredBG "+n(ra,i)),ze.reason+=tddReason,ze.reason+="; ";var wa=Tt;wa<40&&(wa=Math.min(sa,wa));var Da,Sa=ft-wa,Ta=240,Ca=240;if(l.mealCOB>0&&(Ft>0||Kt>0)){for(ba=0;baDa*Ve&&(console.error("maxDelta "+n(tt,i)+" > "+100*Da+"% of BG "+n(Ve,i)+" - disabling SMB"),ze.reason+="maxDelta "+n(tt,i)+" > "+100*Da+"% of BG "+n(Ve,i)+" - SMB disabled!, ",It=!1),console.error("BG projected to remain above "+n(rt,i)+" for "+Ta+"minutes"),(Ca<240||Ta<60)&&console.error("BG projected to remain above "+n(ft,i)+" for "+Ca+"minutes");var Ua=Ca,Ga=i.current_basal*L*Mt*Ua/60,Oa=Math.max(0,l.mealCOB-.25*l.carbs),Ra=(Sa-Ga)/csf-Oa;Ga=o(Ga),Ra=o(Ra),console.error("naive_eventualBG:",Tt,"bgUndershoot:",Sa,"zeroTempDuration:",Ua,"zeroTempEffect:",Ga,"carbsReq:",Ra),"Could not parse clock data"==l.reason?console.error("carbsReq unknown: Could not parse clock data"):Ra>=i.carbsReqThreshold&&Ca<=45&&(ze.carbsReq=Ra,ze.reason+=Ra+" add'l carbs req w/in "+Ca+"m; ");var Aa=0;if(Ve0&&Ye>Ut)ze.reason+="IOB "+a.iob+" < "+o(-i.current_basal*L*20/60,2),ze.reason+=" and minDelta "+n(Ye,i)+" > expectedDelta "+n(Ut,i)+"; ";else if(Ve=55)return ze.reason+="; Canceling temp at "+ze.deliverAt.getMinutes()+"m past the hour. ",m.setTempBasal(0,0,i,ze,t);var Ia=0,ja=Ze;if(CtUt&&Ye>0&&!Ra)return Tt<40?(ze.reason+=", naive_eventualBG < 40. ",m.setTempBasal(0,30,i,ze,t)):(e.delta>Ye?ze.reason+=", but Delta "+n(Je,i)+" > expectedDelta "+n(Ut,i):ze.reason+=", but Min. Delta "+Ye.toFixed(2)+" > Exp. Delta "+n(Ut,i),t.duration>15&&r(Ze,i)===r(t.rate,i)?(ze.reason+=", temp "+t.rate+" ~ req "+Ze+"U/hr. ",ze):(ze.reason+="; setting current basal of "+Ze+" as temp. ",m.setTempBasal(Ze,30,i,ze,t)));Ia=o(Ia=2*Math.min(0,(Ct-at)/Mt),2);var Fa=Math.min(0,(Tt-at)/Mt);if(Fa=o(Fa,2),Ye<0&&Ye>Ut)Ia=o(Ia*(Ye/Ut),2);if(ja=r(ja=Ze+2*Ia,i),t.duration*(t.rate-Ze)/605&&ja>=.8*t.rate)return ze.reason+=", temp "+t.rate+" ~< req "+ja+"U/hr. ",ze;if(ja<=0){if((Aa=o(60*((Sa=at-Tt)/Mt)/i.current_basal*L))<0?Aa=0:(Aa=30*o(Aa/30),Aa=Math.min(120,Math.max(0,Aa))),Aa>0)return ze.reason+=", setting "+Aa+"m zero temp. ",m.setTempBasal(ja,Aa,i,ze,t)}else ze.reason+=", setting "+ja+"U/hr. ";return m.setTempBasal(ja,30,i,ze,t)}if(Ye "+n(rt,i)+" but Delta "+n(Je,i)+" < Exp. Delta "+n(Ut,i):ze.reason+="Eventual BG "+n(Ct,i)+" > "+n(rt,i)+" but Min. Delta "+Ye.toFixed(2)+" < Exp. Delta "+n(Ut,i),t.duration>15&&r(Ze,i)===r(t.rate,i)?(ze.reason+=", temp "+t.rate+" ~ req "+Ze+"U/hr. ",ze):(ze.reason+="; setting current basal of "+Ze+" as temp. ",m.setTempBasal(Ze,30,i,ze,t));if(Math.min(Ct,Yt)15&&r(Ze,i)===r(t.rate,i)?(ze.reason+=", temp "+t.rate+" ~ req "+Ze+"U/hr. ",ze):(ze.reason+="; setting current basal of "+Ze+" as temp. ",m.setTempBasal(Ze,30,i,ze,t));if(Ct>=ot&&(ze.reason+="Eventual BG "+n(Ct,i)+" >= "+n(ot,i)+", "),a.iob>it)return ze.reason+="IOB "+o(a.iob,2)+" > max_iob "+it,t.duration>15&&r(Ze,i)===r(t.rate,i)?(ze.reason+=", temp "+t.rate+" ~ req "+Ze+"U/hr. ",ze):(ze.reason+="; setting current basal of "+Ze+" as temp. ",m.setTempBasal(Ze,30,i,ze,t));(Ia=o((Math.min(Yt,Ct)-at)/Mt,2))>it-a.iob?(console.error("SMB limited by maxIOB: "+it-a.iob+" (. insulinReq: "+Ia+" U)"),ze.reason+="max_iob "+it+", ",Ia=it-a.iob):console.error("SMB not limited by maxIOB ( insulinReq: "+Ia+" U)."),ja=r(ja=Ze+2*Ia,i),Ia=o(Ia,3),ze.insulinReq=Ia;var Pa=o((new Date($e).getTime()-a.lastBolusTime)/6e4,1);if(d&&It&&Ve>ft){var Ea=30;void 0!==i.maxSMBBasalMinutes&&(Ea=i.maxSMBBasalMinutes);var qa=30;void 0!==i.maxUAMSMBBasalMinutes&&(qa=i.maxUAMSMBBasalMinutes),v.useOverride&&M&&T!==Ea&&(console.error("SMB Max Minutes - setting overriden from "+Ea+" to "+T),Ea=T),v.useOverride&&M&&C!==qa&&(console.error("UAM Max Minutes - setting overriden from "+qa+" to "+C),qa=C);var Wa=o(l.mealCOB/N,3),ka=0;void 0===Ea?(ka=o(i.current_basal*L*30/60,1),console.error("smbMinutesSetting undefined: defaulting to 30m"),Ia>ka&&console.error("SMB limited by maxBolus: "+ka+" ( "+Ia+" U)")):a.iob>Wa&&a.iob>0?(console.error("IOB"+a.iob+"> COB"+l.mealCOB+"; mealInsulinReq ="+Wa),qa?(console.error("maxUAMSMBBasalMinutes: "+qa+", profile.current_basal: "+i.current_basal*L),ka=o(i.current_basal*L*qa/60,1)):(console.error("maxUAMSMBBasalMinutes undefined: defaulting to 30m"),ka=o(i.current_basal*L*30/60,1)),Ia>ka?console.error("SMB limited by maxUAMSMBBasalMinutes [ "+qa+"m ]: "+ka+"U ( "+Ia+"U )"):console.error("SMB is not limited by maxUAMSMBBasalMinutes. ( insulinReq: "+Ia+"U )")):(console.error(".maxSMBBasalMinutes: "+Ea+", profile.current_basal: "+i.current_basal*L),Ia>(ka=o(i.current_basal*Ea/60,1))?console.error("SMB limited by maxSMBBasalMinutes: "+Ea+"m ]: "+ka+"U ( insulinReq: "+Ia+"U )"):console.error("SMB is not limited by maxSMBBasalMinutes. ( insulinReq: "+Ia+"U )"));var La=i.bolus_increment,za=1/La,Na=i.smb_delivery_ratio;Na>.5&&console.error("SMB Delivery Ratio increased from default 0.5 to "+o(Na,2));var Ha=Math.min(Ia*Na,ka);Ha=Math.floor(Ha*za)/za,Aa=o(60*((at-(Tt+oa)/2)/Mt)/i.current_basal*L),Ia>0&&Ha=30?(Aa=30*o(Aa/30),Aa=Math.min(60,Math.max(0,Aa))):(Za=o(Ze*Aa/30,2),Aa=30),ze.reason+=" insulinReq "+Ia,Ha>=ka&&(ze.reason+="; maxBolus "+ka),Aa>0&&(ze.reason+="; setting "+Aa+"m low temp of "+Za+"U/h"),ze.reason+=". ";var $a=3;i.SMBInterval&&($a=Math.min(10,Math.max(1,i.SMBInterval)));var Ja=o($a-Pa,0),Ka=o(60*($a-Pa),0)%60;if(console.error("naive_eventualBG "+Tt+","+Aa+"m "+Za+"U/h temp needed; last bolus "+Pa+"m ago; maxBolus: "+ka),Pa>$a?Ha>0&&(ze.units=Ha,ze.reason+="Microbolusing "+Ha+"U. "):ze.reason+="Waiting "+Ja+"m "+Ka+"s to microbolus again. ",Aa>0)return ze.rate=Za,ze.duration=Aa,ze}var Qa=m.getMaxSafeBasal(i);return ja>Qa&&(ze.reason+="adj. req. rate: "+ja+" to maxSafeBasal: "+o(Qa,2)+", ",ja=r(Qa,i)),t.duration*(t.rate-Ze)/60>=2*Ia?(ze.reason+=t.duration+"m@"+t.rate.toFixed(2)+" > 2 * insulinReq. Setting temp basal of "+ja+"U/hr. ",m.setTempBasal(ja,30,i,ze,t)):void 0===t.duration||0===t.duration?(ze.reason+="no temp, setting "+ja+"U/hr. ",m.setTempBasal(ja,30,i,ze,t)):t.duration>5&&r(ja,i)<=r(t.rate,i)?(ze.reason+="temp "+t.rate+" >~ req "+ja+"U/hr. ",ze):(ze.reason+="temp "+t.rate+"<"+ja+"U/hr. ",m.setTempBasal(ja,30,i,ze,t))}},6880:(e,t,a)=>{var r=a(6654);e.exports=function(e,t){var a=20;void 0!==t&&"string"==typeof t.model&&(r(t.model,"54")||r(t.model,"23"))&&(a=40);return e<1?Math.round(e*a)/a:e<10?Math.round(20*e)/20:Math.round(10*e)/10}},2705:(e,t,a)=>{var r=a(5639).Symbol;e.exports=r},9932:e=>{e.exports=function(e,t){for(var a=-1,r=null==e?0:e.length,o=Array(r);++a{e.exports=function(e,t,a){return e==e&&(void 0!==a&&(e=e<=a?e:a),void 0!==t&&(e=e>=t?e:t)),e}},4239:(e,t,a)=>{var r=a(2705),o=a(9607),n=a(2333),i=r?r.toStringTag:void 0;e.exports=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":i&&i in Object(e)?o(e):n(e)}},531:(e,t,a)=>{var r=a(2705),o=a(9932),n=a(1469),i=a(3448),s=r?r.prototype:void 0,l=s?s.toString:void 0;e.exports=function e(t){if("string"==typeof t)return t;if(n(t))return o(t,e)+"";if(i(t))return l?l.call(t):"";var a=t+"";return"0"==a&&1/t==-Infinity?"-0":a}},7561:(e,t,a)=>{var r=a(7990),o=/^\s+/;e.exports=function(e){return e?e.slice(0,r(e)+1).replace(o,""):e}},1957:(e,t,a)=>{var r="object"==typeof a.g&&a.g&&a.g.Object===Object&&a.g;e.exports=r},9607:(e,t,a)=>{var r=a(2705),o=Object.prototype,n=o.hasOwnProperty,i=o.toString,s=r?r.toStringTag:void 0;e.exports=function(e){var t=n.call(e,s),a=e[s];try{e[s]=void 0;var r=!0}catch(e){}var o=i.call(e);return r&&(t?e[s]=a:delete e[s]),o}},2333:e=>{var t=Object.prototype.toString;e.exports=function(e){return t.call(e)}},5639:(e,t,a)=>{var r=a(1957),o="object"==typeof self&&self&&self.Object===Object&&self,n=r||o||Function("return this")();e.exports=n},7990:e=>{var t=/\s/;e.exports=function(e){for(var a=e.length;a--&&t.test(e.charAt(a)););return a}},6654:(e,t,a)=>{var r=a(9750),o=a(531),n=a(554),i=a(9833);e.exports=function(e,t,a){e=i(e),t=o(t);var s=e.length,l=a=void 0===a?s:r(n(a),0,s);return(a-=t.length)>=0&&e.slice(a,l)==t}},1469:e=>{var t=Array.isArray;e.exports=t},3218:e=>{e.exports=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}},7005:e=>{e.exports=function(e){return null!=e&&"object"==typeof e}},3448:(e,t,a)=>{var r=a(4239),o=a(7005);e.exports=function(e){return"symbol"==typeof e||o(e)&&"[object Symbol]"==r(e)}},8601:(e,t,a)=>{var r=a(4841),o=1/0;e.exports=function(e){return e?(e=r(e))===o||e===-1/0?17976931348623157e292*(e<0?-1:1):e==e?e:0:0===e?e:0}},554:(e,t,a)=>{var r=a(8601);e.exports=function(e){var t=r(e),a=t%1;return t==t?a?t-a:t:0}},4841:(e,t,a)=>{var r=a(7561),o=a(3218),n=a(3448),i=/^[-+]0x[0-9a-f]+$/i,s=/^0b[01]+$/i,l=/^0o[0-7]+$/i,m=parseInt;e.exports=function(e){if("number"==typeof e)return e;if(n(e))return NaN;if(o(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=o(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=r(e);var a=s.test(e);return a||l.test(e)?m(e.slice(2),a?2:8):i.test(e)?NaN:+e}},9833:(e,t,a)=>{var r=a(531);e.exports=function(e){return null==e?"":r(e)}}},t={};function a(r){var o=t[r];if(void 0!==o)return o.exports;var n=t[r]={exports:{}};return e[r](n,n.exports,a),n.exports}a.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}();var r=a(5546);freeaps_determineBasal=r})(); \ No newline at end of file +var freeaps_determineBasal;(()=>{var e={5546:(e,t,a)=>{var r=a(6880);function o(e,t){t||(t=0);var a=Math.pow(10,t);return Math.round(e*a)/a}function n(e,t){return"mmol/L"===t.out_units?o(.0555*e,1):Math.round(e)}e.exports=function(e,t,a,i,s,l,m,u,d,c,g,h,p,v){var f=i.min_bg,b=v.overrideTarget;const B=v.smbIsOff,M=v.advancedSettings,_=v.isfAndCr,y=v.isf,x=v.cr,w=v.smbIsAlwaysOff,D=v.start,S=v.end,T=v.smbMinutes,C=v.uamMinutes;var U=0,G="",O="",R="",A="",I="",F=0,j=0,P=0,E=0,q=0,W=0;const k=v.weightedAverage;var L=1,z=i.sens,N=i.carb_ratio;v.useOverride&&(L=v.overridePercentage/100,_?(z/=L,N/=L):(x&&(N/=L),y&&(z/=L)));const H=i.weightPercentage,Z=v.average_total_data;function $(e,t){var a=e.getTime();return new Date(a+36e5*t)}function J(e){var t=i.bolus_increment;.025!=t&&(t=.05);var a=e/t;return a>=1?o(Math.floor(a)*t,5):0}function K(e){function t(e){return e<10&&(e="0"+e),e}return t(e.getHours())+":"+t(e.getMinutes())+":00"}function Q(e,t){var a=new Date("1/1/1999 "+e),r=new Date("1/1/1999 "+t);return(a.getTime()-r.getTime())/36e5}function V(e,t){var a=0,r=t,o=(e-t)/36e5,n=0,i=o,s=0;do{if(o>0){var l=K(r),m=p[0].rate;for(let e=0;e=(s=Q(p[e+1].start,p[e].start))?n=s:o=s?n=s:ou)if(e+1=(s=Q(d,l))?n=s:o=(s=Q("23:59:59",l))?n=s:o0&&o21)q=V(X,(ee=24-U,te=X.getTime(),new Date(te-36e5*ee))),A="24 hours of data is required for an accurate tdd calculation. Currently only "+U.toPrecision(3)+" hours of pump history data are available. Using your pump scheduled basals to fill in the missing hours. Scheduled basals added: "+q.toPrecision(5)+" U. ";else U<21?(ge=!1,enableDynamicCR=!1):A=""}else console.log("Pumphistory is empty!"),ge=!1,enableDynamicCR=!1;var ee,te;for(let e=0;e0){F=e,W=g[e].rate;var ae=g[e-1]["duration (min)"]/60,re=ae,oe=new Date(g[e-1].timestamp),ne=oe,ie=0;do{if(e--,0==e){ne=new Date;break}if("TempBasal"==g[e]._type||"PumpSuspend"==g[e]._type){ne=new Date(g[e].timestamp);break}var se=e-2;if(se>=0&&"Rewind"==g[se]._type){let e=g[se].timestamp;for(;se-1>=0&&"Prime"==g[se-=1]._type;)ie=(g[se].timestamp-e)/36e5;ie>=ae&&(ne=e,ie=0)}}while(e>0);var le=(ne-oe)/36e5;le0&&(--r,"TempBasal"==g[r]._type)){a=new Date(g[r].timestamp);break}}while(r>0);(a-t)/36e5>0&&(q+=V(a,t))}for(let e=g.length-1;e>0;e--)if("TempBasalDuration"==g[e]._type){let t=g[e]["duration (min)"]/60,a=new Date(g[e].timestamp);var me=a;let r=e;do{if(--r,r>=0&&("TempBasal"==g[r]._type||"PumpSuspend"==g[r]._type)){me=new Date(g[r].timestamp);break}}while(r>0);if(0==e&&"TempBasalDuration"==g[0]._type&&(me=new Date,t=g[e]["duration (min)"]/60),(me-a)/36e5-t>0){q+=V(me,$(a,t))}}var ue,de={TDD:o(j=E+P+q,5),bolus:o(E,5),temp_basal:o(P,5),scheduled_basal:o(q,5)};U>21?(O=". Bolus insulin: "+E.toPrecision(5)+" U",R=". Temporary basal insulin: "+P.toPrecision(5)+" U",G=". Insulin with scheduled basal rate: "+q.toPrecision(5)+" U",I=A+(" TDD past 24h is: "+j.toPrecision(5)+" U")+O+R+G,tddReason=", Total insulin: "+o(j,2)+" U, "+o(E/j*100,0)+"% Bolus "+o((P+q)/j*100,0)+"% Basal"):tddReason=", TDD: Not enough pumpData (< 21h)";const ce=e.glucose;var ge=h.useNewFormula;const he=h.enableDynamicCR,pe=Math.min(i.autosens_min,i.autosens_max),ve=Math.max(i.autosens_min,i.autosens_max);(ve==pe||ve<1||pe>1)&&(ge=!1,console.log("Dynamic ISF disabled due to current autosens settings"));const fe=h.adjustmentFactor,be=i.min_bg;var Be=!1,Me="",_e=1,ye="";Z>0&&(_e=k/Z),ye=_e>1?"Basal adjustment with a 24 hour to total average (up to 14 days of data) TDD ratio (limited by Autosens max setting). Basal Ratio: "+(_e=o(_e=Math.min(_e,i.autosens_max),2))+". Upper limit = Autosens max ("+i.autosens_max+")":_e<1?"Basal adjustment with a 24 hour to to total average (up to 14 days of data) TDD ratio (limited by Autosens min setting). Basal Ratio: "+(_e=o(_e=Math.max(_e,i.autosens_min),2))+". Lower limit = Autosens min ("+i.autosens_min+")":"Basal adjusted with a 24 hour to total average (up to 14 days of data) TDD ratio: "+_e,ye=", Basal ratio: "+_e,(i.high_temptarget_raises_sensitivity||i.exercise_mode||v.isEnabled)&&(Be=!0),be>=118&&Be&&(ge=!1,Me="Dynamic ISF temporarily off due to a high temp target/exercising. Current min target: "+be);var xe=", Dynamic ratios log: ",we=", AF: "+fe,De="BG: "+ce+" mg/dl ("+(.0555*ce).toPrecision(2)+" mmol/l)",Se="",Te="";const Ce=h.curve,Ue=h.insulinPeakTime,Ge=h.useCustomPeakTime;var Oe=55,Re=65;switch(Ce){case"rapid-acting":Re=65;break;case"ultra-rapid":Re=50}Ge?(Oe=120-Ue,console.log("Custom insulinpeakTime set to :"+Ue+", insulinFactor: "+Oe)):(Oe=120-Re,console.log("insulinFactor set to : "+Oe)),ue=j,H<1&&k>0&&(j=k,console.log("Using weighted TDD average: "+o(j,2)+" U, instead of past 24 h ("+o(ue,2)+" U), weight: "+H),Te=", Weighted TDD: "+o(j,2)+" U");const Ae=h.sigmoid;var Ie="";if(ge){var Fe=z*fe*j*Math.log(ce/Oe+1)/1800;Se=", Logarithmic formula"}if(ge&&Ae){const e=pe,t=ve-e,a=.0555*(ce-i.min_bg);var je=_e,Pe=ve-1;1==ve&&(Pe=ve+.01-1);const r=Math.log10(1/Pe-e/Pe)/Math.log10(Math.E),o=a*fe*je+r;Fe=t/(1+Math.exp(-o))+e,Se=", Sigmoid function"}var Ee=N;const qe=o(N,1);var We="",ke="";if(ge&&j>0){if(We=", Dynamic ISF/CR: On/",Fe>ve?(Me=", Dynamic ISF limited by autosens_max setting: "+ve+" ("+o(Fe,2)+"), ",ke=", Autosens/Dynamic Limit: "+ve+" ("+o(Fe,2)+")",Fe=ve):Fe-.5?"+"+o(e.delta,0):o(e.delta,0);var Ye=Math.min(e.delta,e.short_avgdelta),et=Math.min(e.short_avgdelta,e.long_avgdelta),tt=Math.max(e.delta,e.short_avgdelta,e.long_avgdelta);(Ve<=10||38===Ve||Xe>=3)&&(ze.reason="CGM is calibrating, in ??? state, or noise is high");if(Ve>60&&0==e.delta&&e.short_avgdelta>-1&&e.short_avgdelta<1&&e.long_avgdelta>-1&&e.long_avgdelta<1&&("fakecgm"==e.device?(console.error("CGM data is unchanged ("+n(Ve,i)+"+"+n(e.delta,i)+") for 5m w/ "+n(e.short_avgdelta,i)+" mg/dL ~15m change & "+n(e.long_avgdelta,2)+" mg/dL ~45m change"),console.error("Simulator mode detected ("+e.device+"): continuing anyway")):!0),Qe>12||Qe<-5?ze.reason="If current system time "+$e+" is correct, then BG data is too old. The last BG data was read "+Qe+"m ago at "+Ke:0===e.short_avgdelta&&0===e.long_avgdelta&&(e.last_cal&&e.last_cal<3?ze.reason="CGM was just calibrated":ze.reason="CGM data is unchanged ("+n(Ve,i)+"+"+n(e.delta,i)+") for 5m w/ "+n(e.short_avgdelta,i)+" mg/dL ~15m change & "+n(e.long_avgdelta,i)+" mg/dL ~45m change"),Ve<=10||38===Ve||Xe>=3||Qe>12||Qe<-5||0===e.short_avgdelta&&0===e.long_avgdelta)return t.rate>=Ze?(ze.reason+=". Canceling high temp basal of "+t.rate,ze.deliverAt=Ne,ze.temp="absolute",ze.duration=0,ze.rate=0,ze):0===t.rate&&t.duration>30?(ze.reason+=". Shortening "+t.duration+"m long zero temp to 30m. ",ze.deliverAt=Ne,ze.temp="absolute",ze.duration=30,ze.rate=0,ze):(ze.reason+=". Temp "+t.rate+" <= current basal "+Ze+"U/hr; doing nothing. ",ze);var at,rt,ot,nt,it=i.max_iob;if(void 0!==i.min_bg&&(rt=i.min_bg),void 0!==i.max_bg&&(ot=i.max_bg),void 0!==i.enableSMB_high_bg_target&&(nt=i.enableSMB_high_bg_target),void 0===i.min_bg||void 0===i.max_bg)return ze.error="Error: could not determine target_bg. ",ze;at=(i.min_bg+i.max_bg)/2;var st=i.exercise_mode||i.high_temptarget_raises_sensitivity||v.isEnabled,lt=100,mt=160;if(mt=i.half_basal_exercise_target,v.isEnabled){const e=v.hbt;console.log("Half Basal Target used: "+n(e,i)+" "+i.out_units),mt=e}else console.log("Default Half Basal Target used: "+n(mt,i)+" "+i.out_units);if(st&&i.temptargetSet&&at>lt||i.low_temptarget_lowers_sensitivity&&i.temptargetSet&&at=at&&sensitivityRatio0&&(process.stderr.write("TDD-adjustment of basals activated, using tdd24h_14d_Ratio "+o(_e,2)+", TDD 24h = "+o(ue,2)+"U, Weighted average TDD = "+o(k,2)+"U, (Weight percentage = "+H+"), Total data of TDDs (up to 14 days) average = "+o(Z,2)+"U. "),Ze!==He*L?process.stderr.write("Adjusting basal from "+He*L+" U/h to "+Ze+" U/h; "):process.stderr.write("Basal unchanged: "+Ze+" U/h; "))),i.temptargetSet);else if(void 0!==s&&s&&(i.sensitivity_raises_target&&s.ratio<1||i.resistance_lowers_target&&s.ratio>1)){rt=o((rt-60)/s.ratio)+60,ot=o((ot-60)/s.ratio)+60;var dt=o((at-60)/s.ratio)+60;at===(dt=Math.max(80,dt))?process.stderr.write("target_bg unchanged: "+n(dt,i)+"; "):process.stderr.write("target_bg from "+n(dt,i)+" to "+n(dt,i)+"; "),at=dt}var ct=n(at,i);at!=f&&(ct=0!==b&&b!==at?n(f,i)+"→"+n(b,i)+"→"+n(at,i):n(f,i)+"→"+n(at,i));var gt=200,ht=200,pt=200;if(e.noise>=2){var vt=Math.max(1.1,i.noisyCGMTargetMultiplier);Math.min(250,i.maxRaw);gt=o(Math.min(200,rt*vt)),ht=o(Math.min(200,at*vt)),pt=o(Math.min(200,ot*vt)),process.stderr.write("Raising target_bg for noisy / raw CGM data, from "+n(dt,i)+" to "+n(ht,i)+"; "),rt=gt,at=ht,ot=pt}var ft=rt-.5*(rt-40),bt=i.threshold_setting;bt>ft&&bt<=120&&bt>=65?(console.error("Threshold changed in settings from "+n(ft,i)+" to "+n(bt,i)+". "),ft=bt):console.error("Current threshold: "+n(ft,i));var Bt="",Mt=(o(z,1),z);if(void 0!==s&&s&&((Mt=o(Mt=z/sensitivityRatio,1))!==z?process.stderr.write("ISF from "+n(z,i)+" to "+n(Mt,i)):process.stderr.write("ISF unchanged: "+n(Mt,i)),Bt+="Autosens ratio: "+o(sensitivityRatio,2)+", ISF: "+n(z,i)+"→"+n(Mt,i)),console.error("CR:"+N),void 0===a)return ze.error="Error: iob_data undefined. ",ze;var _t,yt=a;if(a.length,a.length>1&&(a=yt[0]),void 0===a.activity||void 0===a.iob)return ze.error="Error: iob_data missing some property. ",ze;var xt=((_t=void 0!==a.lastTemp?o((new Date($e).getTime()-a.lastTemp.date)/6e4):0)+t.duration)%30;if(console.error("currenttemp:"+t.rate+" lastTempAge:"+_t+"m, tempModulus:"+xt+"m"),ze.temp="absolute",ze.deliverAt=Ne,u&&t&&a.lastTemp&&t.rate!==a.lastTemp.rate&&_t>10&&t.duration)return ze.reason="Warning: currenttemp rate "+t.rate+" != lastTemp rate "+a.lastTemp.rate+" from pumphistory; canceling temp",m.setTempBasal(0,0,i,ze,t);if(t&&a.lastTemp&&t.duration>0){var wt=_t-a.lastTemp.duration;if(wt>5&&_t>10)return ze.reason="Warning: currenttemp running but lastTemp from pumphistory ended "+wt+"m ago; canceling temp",m.setTempBasal(0,0,i,ze,t)}var Dt=o(-a.activity*Mt*5,2),St=o(6*(Ye-Dt));St<0&&(St=o(6*(et-Dt)))<0&&(St=o(6*(e.long_avgdelta-Dt)));var Tt=Ve,Ct=(Tt=a.iob>0?o(Ve-a.iob*Mt):o(Ve-a.iob*Math.min(Mt,z)))+St;if(void 0===Ct||isNaN(Ct))return ze.error="Error: could not calculate eventualBG. Sensitivity: "+Mt+" Deviation: "+St,ze;var Ut=function(e,t,a){return o(a+(e-t)/24,1)}(at,Ct,Dt);ze={temp:"absolute",bg:Ve,tick:Je,eventualBG:Ct,insulinReq:0,reservoir:d,deliverAt:Ne,sensitivityRatio,TDD:ue,insulin:de,current_target:at,insulinForManualBolus:Fa};var Gt=[],Ot=[],Rt=[],At=[];Gt.push(Ve),Ot.push(Ve),At.push(Ve),Rt.push(Ve);var It=function(e,t,a,r,o,i){return t?!e.allowSMB_with_high_temptarget&&e.temptargetSet&&o>100?(console.error("SMB disabled due to high temptarget of "+o),!1):!0===a.bwFound&&!1===e.A52_risk_enable?(console.error("SMB disabled due to Bolus Wizard activity in the last 6 hours."),!1):!0===e.enableSMB_always?(a.bwFound?console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled due to enableSMB_always"),!0):!0===e.enableSMB_with_COB&&a.mealCOB?(a.bwCarbs?console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for COB of "+a.mealCOB),!0):!0===e.enableSMB_after_carbs&&a.carbs?(a.bwCarbs?console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for 6h after carb entry"),!0):!0===e.enableSMB_with_temptarget&&e.temptargetSet&&o<100?(a.bwFound?console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for temptarget of "+n(o,e)),!0):!0===e.enableSMB_high_bg&&null!==i&&r>=i?(console.error("Checking BG to see if High for SMB enablement."),console.error("Current BG",r," | High BG ",i),a.bwFound?console.error("Warning: High BG SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("High BG detected. Enabling SMB."),!0):(console.error("SMB disabled (no enableSMB preferences active or no condition satisfied)"),!1):(console.error("SMB disabled (!microBolusAllowed)"),!1)}(i,u,l,Ve,at,nt);if(B)if(w){let e=c.getHours();e>=D&&e<=S&&(console.error("SMB disabled by schedule (a Profile is active with SMBs disabled)"),It=!1)}else console.error("SMBs are disabled (a Profile is active with SMBs disabled)"),It=!1;var Ft=i.enableUAM,jt=0,Pt=0;jt=o(Ye-Dt,1);var Et=o(Ye-Dt,1);csf=Mt/N,console.error("profile.sens:"+n(z,i)+", sens:"+n(Mt,i)+", CSF:"+o(csf,1));var qt=o(30*csf*5/60,1);jt>qt&&(console.error("Limiting carb impact from "+jt+" to "+qt+"mg/dL/5m (30g/h)"),jt=qt);var Wt=3;sensitivityRatio&&(Wt/=sensitivityRatio);var kt=Wt;if(l.carbs){Wt=Math.max(Wt,l.mealCOB/20);var Lt=o((new Date($e).getTime()-l.lastCarbTime)/6e4),zt=(l.carbs-l.mealCOB)/l.carbs;kt=o(kt=Wt+1.5*Lt/60,1),console.error("Last carbs "+Lt+" minutes ago; remainingCATime:"+kt+"hours; "+o(100*zt,1)+"% carbs absorbed")}var Nt=Math.max(0,jt/5*60*kt/2)/csf,Ht=90,Zt=1;i.remainingCarbsCap&&(Ht=Math.min(90,i.remainingCarbsCap)),i.remainingCarbsFraction&&(Zt=Math.min(1,i.remainingCarbsFraction));var $t=1-Zt,Jt=Math.max(0,l.mealCOB-Nt-l.carbs*$t),Kt=(Jt=Math.min(Ht,Jt))*csf*5/60/(kt/2),Qt=o(l.slopeFromMaxDeviation,2),Vt=o(l.slopeFromMinDeviation,2),Xt=Math.min(Qt,-Vt/3);Pt=0===jt?0:Math.min(60*kt/5/2,Math.max(0,l.mealCOB*csf/jt)),console.error("Carb Impact:"+jt+"mg/dL per 5m; CI Duration:"+o(5*Pt/60*2,1)+"hours; remaining CI ("+kt/2+"h peak):"+o(Kt,1)+"mg/dL per 5m");var Yt,ea,ta,aa,ra,oa=999,na=999,ia=999,sa=Ve,la=999,ma=999,ua=999,da=999,ca=Ct,ga=Ve,ha=Ve,pa=0,va=[],fa=[];try{yt.forEach((function(e){var t=o(-e.activity*Mt*5,2),a=o(-e.iobWithZeroTemp.activity*Mt*5,2),r=Tt,n=jt*(1-Math.min(1,Ot.length/12));if(!0===(ge&&!Ae))ca=Ot[Ot.length-1]+o(-e.activity*(1800/(j*fe*Math.log(Math.max(Ot[Ot.length-1],39)/Oe+1)))*5,2)+n,r=At[At.length-1]+o(-e.iobWithZeroTemp.activity*(1800/(j*fe*Math.log(Math.max(At[At.length-1],39)/Oe+1)))*5,2),console.log("Dynamic ISF (Logarithmic Formula) )adjusted predictions for IOB and ZT: IOBpredBG: "+o(ca,2)+" , ZTpredBG: "+o(r,2));else ca=Ot[Ot.length-1]+t+n,r=At[At.length-1]+a;var i=Math.max(0,Math.max(0,jt)*(1-Gt.length/Math.max(2*Pt,1))),s=Math.min(Gt.length,12*kt-Gt.length),l=Math.max(0,s/(kt/2*12)*Kt);i+l,va.push(o(l,0)),fa.push(o(i,0)),COBpredBG=Gt[Gt.length-1]+t+Math.min(0,n)+i+l;var m=Math.max(0,Et+Rt.length*Xt),u=Math.max(0,Et*(1-Rt.length/Math.max(36,1))),d=Math.min(m,u);if(d>0&&(pa=o(5*(Rt.length+1)/60,1)),!0===(ge&&!Ae))UAMpredBG=Rt[Rt.length-1]+o(-e.activity*(1800/(j*fe*Math.log(Math.max(Rt[Rt.length-1],39)/Oe+1)))*5,2)+Math.min(0,n)+d,console.log("Dynamic ISF (Logarithmic Formula) adjusted prediction for UAM: UAMpredBG: "+o(UAMpredBG,2));else UAMpredBG=Rt[Rt.length-1]+t+Math.min(0,n)+d;Ot.length<48&&Ot.push(ca),Gt.length<48&&Gt.push(COBpredBG),Rt.length<48&&Rt.push(UAMpredBG),At.length<48&&At.push(r),COBpredBG18&&caga&&(ga=ca),(Pt||Kt>0)&&Gt.length>18&&COBpredBG0)&&COBpredBG>ga&&(ha=COBpredBG),Ft&&Rt.length>12&&UAMpredBGga&&UAMpredBG}))}catch(e){console.error("Problem with iobArray. Optional feature Advanced Meal Assist disabled")}l.mealCOB&&(console.error("predCIs (mg/dL/5m):"+fa.join(" ")),console.error("remainingCIs: "+va.join(" "))),ze.predBGs={},Ot.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))}));for(var ba=Ot.length-1;ba>12&&Ot[ba-1]===Ot[ba];ba--)Ot.pop();for(ze.predBGs.IOB=Ot,ta=o(Ot[Ot.length-1]),At.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),ba=At.length-1;ba>6&&!(At[ba-1]>=At[ba]||At[ba]<=at);ba--)At.pop();if(ze.predBGs.ZT=At,o(At[At.length-1]),l.mealCOB>0&&(jt>0||Kt>0)){for(Gt.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),ba=Gt.length-1;ba>12&&Gt[ba-1]===Gt[ba];ba--)Gt.pop();ze.predBGs.COB=Gt,aa=o(Gt[Gt.length-1]),Ct=Math.max(Ct,o(Gt[Gt.length-1]))}if(jt>0||Kt>0){if(Ft){for(Rt.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),ba=Rt.length-1;ba>12&&Rt[ba-1]===Rt[ba];ba--)Rt.pop();ze.predBGs.UAM=Rt,ra=o(Rt[Rt.length-1]),Rt[Rt.length-1]&&(Ct=Math.max(Ct,o(Rt[Rt.length-1])))}ze.eventualBG=Ct}console.error("UAM Impact:"+Et+"mg/dL per 5m; UAM Duration:"+pa+"hours"),oa=Math.max(39,oa),na=Math.max(39,na),ia=Math.max(39,ia),Yt=o(oa);var Ba=l.mealCOB/l.carbs;ea=o(ia<999&&na<999?(1-Ba)*UAMpredBG+Ba*COBpredBG:na<999?(ca+COBpredBG)/2:ia<999?(ca+UAMpredBG)/2:ca),da>ea&&(ea=da),sa=o(sa=Pt||Kt>0?Ft?Ba*la+(1-Ba)*ma:la:Ft?ma:ua);var Ma=ia;if(daia&&(Ma=(ia+da)/2);if(Ma=o(Ma),l.carbs)if(!Ft&&na<999)Yt=o(Math.max(oa,na));else if(na<999){var ya=Ba*na+(1-Ba)*Ma;Yt=o(Math.max(oa,na,ya))}else Yt=Ft?Ma:sa;else Ft&&(Yt=o(Math.max(oa,Ma)));Yt=Math.min(Yt,ea),process.stderr.write("minPredBG: "+Yt+" minIOBPredBG: "+oa+" minZTGuardBG: "+da),na<999&&process.stderr.write(" minCOBPredBG: "+na),ia<999&&process.stderr.write(" minUAMPredBG: "+ia),console.error(" avgPredBG:"+ea+" COB/Carbs:"+l.mealCOB+"/"+l.carbs),ha>Ve&&(Yt=Math.min(Yt,ha)),ze.COB=l.mealCOB,ze.IOB=a.iob,ze.BGI=n(Dt,i),ze.deviation=n(St,i),ze.ISF=n(Mt,i),ze.CR=o(N,1),ze.target_bg=n(at,i),ze.TDD=o(ue,2),ze.current_target=o(at,0);var xa=ze.CR;qe!=ze.CR&&(xa=qe+"→"+ze.CR),ze.reason=Bt+", COB: "+ze.COB+", Dev: "+ze.deviation+", BGI: "+ze.BGI+", CR: "+xa+", Target: "+ct+", minPredBG "+n(Yt,i)+", minGuardBG "+n(sa,i)+", IOBpredBG "+n(ta,i),aa>0&&(ze.reason+=", COBpredBG "+n(aa,i)),ra>0&&(ze.reason+=", UAMpredBG "+n(ra,i)),ze.reason+=tddReason,ze.reason+="; ";var wa=Tt;wa<40&&(wa=Math.min(sa,wa));var Da,Sa=ft-wa,Ta=240,Ca=240;if(l.mealCOB>0&&(jt>0||Kt>0)){for(ba=0;baDa*Ve&&(console.error("maxDelta "+n(tt,i)+" > "+100*Da+"% of BG "+n(Ve,i)+" - disabling SMB"),ze.reason+="maxDelta "+n(tt,i)+" > "+100*Da+"% of BG "+n(Ve,i)+" - SMB disabled!, ",It=!1),console.error("BG projected to remain above "+n(rt,i)+" for "+Ta+"minutes"),(Ca<240||Ta<60)&&console.error("BG projected to remain above "+n(ft,i)+" for "+Ca+"minutes");var Ua=Ca,Ga=i.current_basal*L*Mt*Ua/60,Oa=Math.max(0,l.mealCOB-.25*l.carbs),Ra=(Sa-Ga)/csf-Oa;Ga=o(Ga),Ra=o(Ra),console.error("naive_eventualBG:",Tt,"bgUndershoot:",Sa,"zeroTempDuration:",Ua,"zeroTempEffect:",Ga,"carbsReq:",Ra),"Could not parse clock data"==l.reason?console.error("carbsReq unknown: Could not parse clock data"):Ra>=i.carbsReqThreshold&&Ca<=45&&(ze.carbsReq=Ra,ze.reason+=Ra+" add'l carbs req w/in "+Ca+"m; ");var Aa=0;if(Ve0&&Ye>Ut)ze.reason+="IOB "+a.iob+" < "+o(-i.current_basal*L*20/60,2),ze.reason+=" and minDelta "+n(Ye,i)+" > expectedDelta "+n(Ut,i)+"; ";else if(Ve=55)return ze.reason+="; Canceling temp at "+ze.deliverAt.getMinutes()+"m past the hour. ",m.setTempBasal(0,0,i,ze,t);var Ia=0,Fa=0,ja=Ze,Pa=0;if(CtUt&&Ye>0&&!Ra)return Tt<40?(ze.reason+=", naive_eventualBG < 40. ",m.setTempBasal(0,30,i,ze,t)):(e.delta>Ye?ze.reason+=", but Delta "+n(Je,i)+" > expectedDelta "+n(Ut,i):ze.reason+=", but Min. Delta "+Ye.toFixed(2)+" > Exp. Delta "+n(Ut,i),t.duration>15&&r(Ze,i)===r(t.rate,i)?(ze.reason+=", temp "+t.rate+" ~ req "+Ze+"U/hr. ",ze):(ze.reason+="; setting current basal of "+Ze+" as temp. ",m.setTempBasal(Ze,30,i,ze,t)));Ia=o(Ia=2*Math.min(0,(Ct-at)/Mt),2);var Ea=Math.min(0,(Tt-at)/Mt);if(Ea=o(Ea,2),Ye<0&&Ye>Ut)Ia=o(Ia*(Ye/Ut),2);ja=r(ja=Ze+2*Ia,i),Pa=t.duration*(t.rate-Ze)/60;var qa=Math.min(Ia,Ea);if(console.log("naiveInsulinReq:"+Ea),Pa5&&ja>=.8*t.rate)return ze.reason+=", temp "+t.rate+" ~< req "+ja+"U/hr. ",ze;if(ja<=0){if((Aa=o(60*((Sa=at-Tt)/Mt)/i.current_basal*L))<0?Aa=0:(Aa=30*o(Aa/30),Aa=Math.min(120,Math.max(0,Aa))),Aa>0)return ze.reason+=", setting "+Aa+"m zero temp. ",m.setTempBasal(ja,Aa,i,ze,t)}else ze.reason+=", setting "+ja+"U/hr. ";return m.setTempBasal(ja,30,i,ze,t)}if(Ye "+n(rt,i)+" but Delta "+n(Je,i)+" < Exp. Delta "+n(Ut,i):ze.reason+="Eventual BG "+n(Ct,i)+" > "+n(rt,i)+" but Min. Delta "+Ye.toFixed(2)+" < Exp. Delta "+n(Ut,i),t.duration>15&&r(Ze,i)===r(t.rate,i)?(ze.reason+=", temp "+t.rate+" ~ req "+Ze+"U/hr. ",ze):(ze.reason+="; setting current basal of "+Ze+" as temp. ",m.setTempBasal(Ze,30,i,ze,t));if(Math.min(Ct,Yt)15&&r(Ze,i)===r(t.rate,i)?(ze.reason+=", temp "+t.rate+" ~ req "+Ze+"U/hr. ",ze):(ze.reason+="; setting current basal of "+Ze+" as temp. ",m.setTempBasal(Ze,30,i,ze,t));if(Ct>=ot&&(ze.reason+="Eventual BG "+n(Ct,i)+" >= "+n(ot,i)+", "),a.iob>it)return ze.reason+="IOB "+o(a.iob,2)+" > max_iob "+it,t.duration>15&&r(Ze,i)===r(t.rate,i)?(ze.reason+=", temp "+t.rate+" ~ req "+Ze+"U/hr. ",ze):(ze.reason+="; setting current basal of "+Ze+" as temp. ",m.setTempBasal(Ze,30,i,ze,t));Ia=o((Math.min(Yt,Ct)-at)/Mt,2),Fa=o((Ct-at)/Mt,2),Ia>it-a.iob?(console.error("SMB limited by maxIOB: "+it-a.iob+" (. insulinReq: "+Ia+" U)"),ze.reason+="max_iob "+it+", ",Ia=it-a.iob):console.error("SMB not limited by maxIOB ( insulinReq: "+Ia+" U)."),Fa>it-a.iob?(console.error("Ev. Bolus would not be limited by maxIOB: "+it-a.iob+" (. insulinForManualBolus: "+Fa+" U)"),ze.reason+="max_iob "+it+", ",Fa=it-a.iob):console.error("Ev. Bolus would not be limited by maxIOB ( insulinForManualBolus: "+Fa+" U)."),ja=r(ja=Ze+2*Ia,i),Ia=o(Ia,3),ze.insulinReq=Ia,ze.insulinForManualBolus=o(Fa,3);var Wa=o((new Date($e).getTime()-a.lastBolusTime)/6e4,1);if(u&&It&&Ve>ft){var ka=30;void 0!==i.maxSMBBasalMinutes&&(ka=i.maxSMBBasalMinutes);var La=30;void 0!==i.maxUAMSMBBasalMinutes&&(La=i.maxUAMSMBBasalMinutes),v.useOverride&&M&&T!==ka&&(console.error("SMB Max Minutes - setting overriden from "+ka+" to "+T),ka=T),v.useOverride&&M&&C!==La&&(console.error("UAM Max Minutes - setting overriden from "+La+" to "+C),La=C);var za=o(l.mealCOB/N,3),Na=0;void 0===ka?(Na=o(i.current_basal*L*30/60,1),console.error("smbMinutesSetting undefined: defaulting to 30m"),Ia>Na&&console.error("SMB limited by maxBolus: "+Na+" ( "+Ia+" U)")):a.iob>za&&a.iob>0?(console.error("IOB"+a.iob+"> COB"+l.mealCOB+"; mealInsulinReq ="+za),La?(console.error("maxUAMSMBBasalMinutes: "+La+", profile.current_basal: "+i.current_basal*L),Na=o(i.current_basal*L*La/60,1)):(console.error("maxUAMSMBBasalMinutes undefined: defaulting to 30m"),Na=o(i.current_basal*L*30/60,1)),Ia>Na?console.error("SMB limited by maxUAMSMBBasalMinutes [ "+La+"m ]: "+Na+"U ( "+Ia+"U )"):console.error("SMB is not limited by maxUAMSMBBasalMinutes. ( insulinReq: "+Ia+"U )")):(console.error(".maxSMBBasalMinutes: "+ka+", profile.current_basal: "+i.current_basal*L),Ia>(Na=o(i.current_basal*ka/60,1))?console.error("SMB limited by maxSMBBasalMinutes: "+ka+"m ]: "+Na+"U ( insulinReq: "+Ia+"U )"):console.error("SMB is not limited by maxSMBBasalMinutes. ( insulinReq: "+Ia+"U )"));var Ha=i.bolus_increment,Za=1/Ha,$a=i.smb_delivery_ratio;$a>.5&&console.error("SMB Delivery Ratio increased from default 0.5 to "+o($a,2));var Ja=Math.min(Ia*$a,Na);Ja=Math.floor(Ja*Za)/Za,Aa=o(60*((at-(Tt+oa)/2)/Mt)/i.current_basal*L),Ia>0&&Ja=30?(Aa=30*o(Aa/30),Aa=Math.min(60,Math.max(0,Aa))):(Ka=o(Ze*Aa/30,2),Aa=30),ze.reason+=" insulinReq "+Ia,Ja>=Na&&(ze.reason+="; maxBolus "+Na),Aa>0&&(ze.reason+="; setting "+Aa+"m low temp of "+Ka+"U/h"),ze.reason+=". ";var Qa=3;i.SMBInterval&&(Qa=Math.min(10,Math.max(1,i.SMBInterval)));var Va=o(Qa-Wa,0),Xa=o(60*(Qa-Wa),0)%60;if(console.error("naive_eventualBG "+Tt+","+Aa+"m "+Ka+"U/h temp needed; last bolus "+Wa+"m ago; maxBolus: "+Na),Wa>Qa?Ja>0&&(ze.units=Ja,ze.reason+="Microbolusing "+Ja+"U. "):ze.reason+="Waiting "+Va+"m "+Xa+"s to microbolus again. ",Aa>0)return ze.rate=Ka,ze.duration=Aa,ze}var Ya=m.getMaxSafeBasal(i);return ja>Ya&&(ze.reason+="adj. req. rate: "+ja+" to maxSafeBasal: "+o(Ya,2)+", ",ja=r(Ya,i)),(Pa=t.duration*(t.rate-Ze)/60)>=2*Ia?(ze.reason+=t.duration+"m@"+t.rate.toFixed(2)+" > 2 * insulinReq. Setting temp basal of "+ja+"U/hr. ",m.setTempBasal(ja,30,i,ze,t)):void 0===t.duration||0===t.duration?(ze.reason+="no temp, setting "+ja+"U/hr. ",m.setTempBasal(ja,30,i,ze,t)):t.duration>5&&r(ja,i)<=r(t.rate,i)?(ze.reason+="temp "+t.rate+" >~ req "+ja+"U/hr. ",ze):(ze.reason+="temp "+t.rate+"<"+ja+"U/hr. ",m.setTempBasal(ja,30,i,ze,t))}},6880:(e,t,a)=>{var r=a(6654);e.exports=function(e,t){var a=20;void 0!==t&&"string"==typeof t.model&&(r(t.model,"54")||r(t.model,"23"))&&(a=40);return e<1?Math.round(e*a)/a:e<10?Math.round(20*e)/20:Math.round(10*e)/10}},2705:(e,t,a)=>{var r=a(5639).Symbol;e.exports=r},9932:e=>{e.exports=function(e,t){for(var a=-1,r=null==e?0:e.length,o=Array(r);++a{e.exports=function(e,t,a){return e==e&&(void 0!==a&&(e=e<=a?e:a),void 0!==t&&(e=e>=t?e:t)),e}},4239:(e,t,a)=>{var r=a(2705),o=a(9607),n=a(2333),i=r?r.toStringTag:void 0;e.exports=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":i&&i in Object(e)?o(e):n(e)}},531:(e,t,a)=>{var r=a(2705),o=a(9932),n=a(1469),i=a(3448),s=r?r.prototype:void 0,l=s?s.toString:void 0;e.exports=function e(t){if("string"==typeof t)return t;if(n(t))return o(t,e)+"";if(i(t))return l?l.call(t):"";var a=t+"";return"0"==a&&1/t==-Infinity?"-0":a}},7561:(e,t,a)=>{var r=a(7990),o=/^\s+/;e.exports=function(e){return e?e.slice(0,r(e)+1).replace(o,""):e}},1957:(e,t,a)=>{var r="object"==typeof a.g&&a.g&&a.g.Object===Object&&a.g;e.exports=r},9607:(e,t,a)=>{var r=a(2705),o=Object.prototype,n=o.hasOwnProperty,i=o.toString,s=r?r.toStringTag:void 0;e.exports=function(e){var t=n.call(e,s),a=e[s];try{e[s]=void 0;var r=!0}catch(e){}var o=i.call(e);return r&&(t?e[s]=a:delete e[s]),o}},2333:e=>{var t=Object.prototype.toString;e.exports=function(e){return t.call(e)}},5639:(e,t,a)=>{var r=a(1957),o="object"==typeof self&&self&&self.Object===Object&&self,n=r||o||Function("return this")();e.exports=n},7990:e=>{var t=/\s/;e.exports=function(e){for(var a=e.length;a--&&t.test(e.charAt(a)););return a}},6654:(e,t,a)=>{var r=a(9750),o=a(531),n=a(554),i=a(9833);e.exports=function(e,t,a){e=i(e),t=o(t);var s=e.length,l=a=void 0===a?s:r(n(a),0,s);return(a-=t.length)>=0&&e.slice(a,l)==t}},1469:e=>{var t=Array.isArray;e.exports=t},3218:e=>{e.exports=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}},7005:e=>{e.exports=function(e){return null!=e&&"object"==typeof e}},3448:(e,t,a)=>{var r=a(4239),o=a(7005);e.exports=function(e){return"symbol"==typeof e||o(e)&&"[object Symbol]"==r(e)}},8601:(e,t,a)=>{var r=a(4841),o=1/0;e.exports=function(e){return e?(e=r(e))===o||e===-1/0?17976931348623157e292*(e<0?-1:1):e==e?e:0:0===e?e:0}},554:(e,t,a)=>{var r=a(8601);e.exports=function(e){var t=r(e),a=t%1;return t==t?a?t-a:t:0}},4841:(e,t,a)=>{var r=a(7561),o=a(3218),n=a(3448),i=/^[-+]0x[0-9a-f]+$/i,s=/^0b[01]+$/i,l=/^0o[0-7]+$/i,m=parseInt;e.exports=function(e){if("number"==typeof e)return e;if(n(e))return NaN;if(o(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=o(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=r(e);var a=s.test(e);return a||l.test(e)?m(e.slice(2),a?2:8):i.test(e)?NaN:+e}},9833:(e,t,a)=>{var r=a(531);e.exports=function(e){return null==e?"":r(e)}}},t={};function a(r){var o=t[r];if(void 0!==o)return o.exports;var n=t[r]={exports:{}};return e[r](n,n.exports,a),n.exports}a.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}();var r=a(5546);freeaps_determineBasal=r})(); diff --git a/FreeAPS/Sources/Models/Suggestion.swift b/FreeAPS/Sources/Models/Suggestion.swift index 184cf82d53..c75ee7f252 100644 --- a/FreeAPS/Sources/Models/Suggestion.swift +++ b/FreeAPS/Sources/Models/Suggestion.swift @@ -22,6 +22,7 @@ struct Suggestion: JSON, Equatable { let tdd: Decimal? let insulin: Insulin? let current_target: Decimal? + let insulinForManualBolus: Decimal? } struct Predictions: JSON, Equatable { @@ -61,6 +62,7 @@ extension Suggestion { case tdd = "TDD" case insulin case current_target + case insulinForManualBolus } } diff --git a/FreeAPS/Sources/Modules/AddCarbs/AddCarbsStateModel.swift b/FreeAPS/Sources/Modules/AddCarbs/AddCarbsStateModel.swift index a18f8417b0..bff66a5723 100644 --- a/FreeAPS/Sources/Modules/AddCarbs/AddCarbsStateModel.swift +++ b/FreeAPS/Sources/Modules/AddCarbs/AddCarbsStateModel.swift @@ -16,6 +16,7 @@ extension AddCarbs { @Published var dish: String = "" @Published var selection: Presets? @Published var summation: [String] = [] + @Published var manualBolus: Bool = false let coredataContext = CoreDataStack.shared.persistentContainer.viewContext @@ -108,7 +109,8 @@ extension AddCarbs { apsManager.determineBasalSync() showModal(for: nil) } else { - showModal(for: .bolus(waitForSuggestion: true)) + manualBolus.toggle() + showModal(for: .bolus(waitForSuggestion: true, manualBolus: manualBolus)) } } diff --git a/FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift b/FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift index e4fe0e78c4..16c78ba200 100644 --- a/FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift +++ b/FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift @@ -11,6 +11,8 @@ extension Bolus { @Published var insulinRecommended: Decimal = 0 @Published var insulinRequired: Decimal = 0 @Published var waitForSuggestion: Bool = false + @Published var manual: Bool = false + var waitForSuggestionInitial: Bool = false override func subscribe() { @@ -74,12 +76,24 @@ extension Bolus { func setupInsulinRequired() { DispatchQueue.main.async { - self.insulinRequired = self.provider.suggestion?.insulinReq ?? 0 + // Manual Bolus recommendation screen after a carb entry (normally) yields a higher amount than the insulin reqiured amount computed for SMBs (auto boluses). Carbs combined with a manual bolus threfore now (test) uses the Eventual BG for glucose prediction, whereas the insulinReg for SMBs (and for manual boluses not combined with a carb entry) uses the minPredBG for glucose prediction (typically lower than Eventual BG). + + if self.manual { + self.insulinRequired = self.provider.suggestion?.insulinForManualBolus ?? 0 + + if self.settingsManager.settings.insulinReqPercentage != 100 { + self.insulinRecommended = self + .insulinRequired * (self.settingsManager.settings.insulinReqPercentage / 100) + } else { self.insulinRecommended = self.insulinRequired } + + } else { + self.insulinRequired = self.provider.suggestion?.insulinReq ?? 0 + self.insulinRecommended = self + .insulinRequired * (self.settingsManager.settings.insulinReqPercentage / 100) * 2 + } + self.insulinRecommended = self.apsManager - .roundBolus(amount: max( - self.insulinRequired * (self.settingsManager.settings.insulinReqPercentage / 100) * 2, - 0 - )) + .roundBolus(amount: max(self.insulinRecommended, 0)) } } } diff --git a/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift b/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift index f093bc6797..df14c69766 100644 --- a/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift +++ b/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift @@ -5,6 +5,7 @@ extension Bolus { struct RootView: BaseView { let resolver: Resolver let waitForSuggestion: Bool + let manualBolus: Bool @StateObject var state = StateModel() @State private var isAddInsulinAlertPresented = false @@ -17,7 +18,7 @@ extension Bolus { var body: some View { Form { - Section(header: Text("Recommendation")) { + Section { if state.waitForSuggestion { HStack { Text("Wait please").foregroundColor(.secondary) @@ -25,35 +26,52 @@ extension Bolus { ActivityIndicator(isAnimating: .constant(true), style: .medium) // fix iOS 15 bug } } else { - HStack { - Text("Insulin required").foregroundColor(.secondary) - Spacer() - Text( - formatter - .string(from: state.insulinRequired as NSNumber)! + - NSLocalizedString(" U", comment: "Insulin unit") - ).foregroundColor(.secondary) - }.contentShape(Rectangle()) - .onTapGesture { - state.amount = state.insulinRequired - } - HStack { - Text("Insulin recommended") - Spacer() - Text( - formatter - .string(from: state.insulinRecommended as NSNumber)! + - NSLocalizedString(" U", comment: "Insulin unit") - ).foregroundColor(.secondary) - }.contentShape(Rectangle()) - .onTapGesture { - state.amount = state.insulinRecommended - } + if state.manual { + HStack { + Text("Insulin recommended") + Spacer() + Text( + formatter + .string(from: state.insulinRecommended as NSNumber)! + + NSLocalizedString(" U", comment: "Insulin unit") + ).foregroundColor(.secondary) + }.contentShape(Rectangle()) + .onTapGesture { + state.amount = state.insulinRecommended + } + } else { + HStack { + Text("Insulin required").foregroundColor(.secondary) + Spacer() + Text( + formatter + .string(from: state.insulinRequired as NSNumber)! + + NSLocalizedString(" U", comment: "Insulin unit") + ).foregroundColor(.secondary) + }.contentShape(Rectangle()) + .onTapGesture { + state.amount = state.insulinRequired + } + + HStack { + Text("Insulin recommended") + Spacer() + Text( + formatter + .string(from: state.insulinRecommended as NSNumber)! + + NSLocalizedString(" U", comment: "Insulin unit") + ).foregroundColor(.secondary) + }.contentShape(Rectangle()) + .onTapGesture { + state.amount = state.insulinRecommended + } + } } } - + header: { Text("Recommendation") } + if !state.waitForSuggestion { - Section(header: Text("Bolus")) { + Section { HStack { Text("Amount") Spacer() @@ -67,6 +85,7 @@ extension Bolus { Text("U").foregroundColor(.secondary) } } + header: { Text("Bolus") } Section { Button { state.add() } @@ -103,6 +122,7 @@ extension Bolus { configureView { state.waitForSuggestionInitial = waitForSuggestion state.waitForSuggestion = waitForSuggestion + state.manual = manualBolus } } .navigationTitle("Enact Bolus") diff --git a/FreeAPS/Sources/Modules/Home/View/HomeRootView.swift b/FreeAPS/Sources/Modules/Home/View/HomeRootView.swift index 60806f8fab..b6912144e4 100644 --- a/FreeAPS/Sources/Modules/Home/View/HomeRootView.swift +++ b/FreeAPS/Sources/Modules/Home/View/HomeRootView.swift @@ -502,7 +502,7 @@ extension Home { .padding(8) }.foregroundColor(.loopGreen) Spacer() - Button { state.showModal(for: .bolus(waitForSuggestion: false)) } + Button { state.showModal(for: .bolus(waitForSuggestion: false, manualBolus: false)) } label: { Image("bolus") .renderingMode(.template) diff --git a/FreeAPS/Sources/Modules/Stat/View/ChartsView.swift b/FreeAPS/Sources/Modules/Stat/View/ChartsView.swift index 219ba281bc..22c1898c36 100644 --- a/FreeAPS/Sources/Modules/Stat/View/ChartsView.swift +++ b/FreeAPS/Sources/Modules/Stat/View/ChartsView.swift @@ -1,9 +1,3 @@ -// -// FilteredLoopsView.swift -// FreeAPS -// -// Created by Jon Mårtensson on 2023-05-29. -// import Charts import CoreData import SwiftDate diff --git a/FreeAPS/Sources/Modules/Stat/View/StatsView.swift b/FreeAPS/Sources/Modules/Stat/View/StatsView.swift index 297a5bcc07..cf82cb66c9 100644 --- a/FreeAPS/Sources/Modules/Stat/View/StatsView.swift +++ b/FreeAPS/Sources/Modules/Stat/View/StatsView.swift @@ -1,9 +1,3 @@ -// -// FilteredLoopsView.swift -// FreeAPS -// -// Created by Jon Mårtensson on 2023-05-29. -// import CoreData import SwiftDate import SwiftUI diff --git a/FreeAPS/Sources/Router/Screen.swift b/FreeAPS/Sources/Router/Screen.swift index af152733c9..76fb42131e 100644 --- a/FreeAPS/Sources/Router/Screen.swift +++ b/FreeAPS/Sources/Router/Screen.swift @@ -16,7 +16,7 @@ enum Screen: Identifiable, Hashable { case preferencesEditor case addCarbs case addTempTarget - case bolus(waitForSuggestion: Bool) + case bolus(waitForSuggestion: Bool, manualBolus: Bool) case manualTempBasal case autotuneConfig case dataTable @@ -67,8 +67,8 @@ extension Screen { AddCarbs.RootView(resolver: resolver) case .addTempTarget: AddTempTarget.RootView(resolver: resolver) - case let .bolus(waitForSuggestion): - Bolus.RootView(resolver: resolver, waitForSuggestion: waitForSuggestion) + case let .bolus(waitForSuggestion, manualBolus): + Bolus.RootView(resolver: resolver, waitForSuggestion: waitForSuggestion, manualBolus: manualBolus) case .manualTempBasal: ManualTempBasal.RootView(resolver: resolver) case .autotuneConfig: diff --git a/FreeAPS/Sources/Services/WatchManager/WatchManager.swift b/FreeAPS/Sources/Services/WatchManager/WatchManager.swift index 3e68d2b05d..fd0685713c 100644 --- a/FreeAPS/Sources/Services/WatchManager/WatchManager.swift +++ b/FreeAPS/Sources/Services/WatchManager/WatchManager.swift @@ -75,9 +75,15 @@ final class BaseWatchManager: NSObject, WatchManager, Injectable { self.state.maxBolus = self.settingsManager.pumpSettings.maxBolus self.state.carbsRequired = self.suggestion?.carbsReq - let insulinRequired = self.suggestion?.insulinReq ?? 0 + var insulinRequired = self.suggestion?.insulinReq ?? 0 + var double: Decimal = 2 + if (self.suggestion?.cob ?? 0) > 0 { + insulinRequired = self.suggestion?.insulinForManualBolus ?? 0 + double = 1 + } + self.state.bolusRecommended = self.apsManager - .roundBolus(amount: max(insulinRequired * (self.settingsManager.settings.insulinReqPercentage / 100) * 2, 0)) + .roundBolus(amount: max(insulinRequired * (self.settingsManager.settings.insulinReqPercentage / 100) * double, 0)) self.state.iob = self.suggestion?.iob self.state.cob = self.suggestion?.cob From 9361bca0eb00fa36cb6d344c2dbad376251d6d19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Thu, 8 Jun 2023 17:47:21 +0200 Subject: [PATCH 28/45] Add euglycemic range also to laying grouped glucose in laying TIR chart in stat view. (cherry picked from commit 3d89a5bee3b8feecdccec1444a56152bc6b4ce9d) --- .../Modules/Bolus/View/BolusRootView.swift | 2 +- .../Modules/Stat/View/ChartsView.swift | 27 +++++++------------ 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift b/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift index df14c69766..778011dab2 100644 --- a/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift +++ b/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift @@ -69,7 +69,7 @@ extension Bolus { } } header: { Text("Recommendation") } - + if !state.waitForSuggestion { Section { HStack { diff --git a/FreeAPS/Sources/Modules/Stat/View/ChartsView.swift b/FreeAPS/Sources/Modules/Stat/View/ChartsView.swift index 22c1898c36..b0188a8c29 100644 --- a/FreeAPS/Sources/Modules/Stat/View/ChartsView.swift +++ b/FreeAPS/Sources/Modules/Stat/View/ChartsView.swift @@ -250,41 +250,32 @@ struct ChartsView: View { let mapGlucose = glucose.compactMap({ each in each.glucose }) if !mapGlucose.isEmpty { let mapGlucoseLow = mapGlucose.filter({ $0 < Int16(3.3 / 0.0555) }) - let mapGlucoseAcuteLow = mapGlucose.filter({ $0 < Int16(2.6 / 0.0555) }) - - let mapGlucoseHigh = mapGlucose.filter({ $0 > Int(7.8 / 0.0555) }) + let mapGlucoseNormal = mapGlucose.filter({ $0 > Int16(3.8 / 0.0555) && $0 < Int16(7.9 / 0.0555) }) let mapGlucoseAcuteHigh = mapGlucose.filter({ $0 > Int16(11 / 0.0555) }) - HStack { - let value = Double(mapGlucoseAcuteLow.count * 100 / mapGlucose.count) - if value != 0 { - Text(units == .mmolL ? "< 2.6" : "< 47").font(.caption2).foregroundColor(.secondary) - Text(value.formatted()).font(.caption).foregroundColor(value == 0 ? .green : .red) - Text("%").font(.caption) - } - }.padding(.horizontal, 10) HStack { let value = Double(mapGlucoseLow.count * 100 / mapGlucose.count) if value != 0 { Text(units == .mmolL ? "< 3.3" : "< 59").font(.caption2).foregroundColor(.secondary) - Text(value.formatted()).font(.caption).foregroundColor(value == 0 ? .green : .orange) + Text(value.formatted()).font(.caption).foregroundColor(value == 0 ? .green : .red) Text("%").font(.caption) } } Spacer() HStack { - let value = Double(mapGlucoseHigh.count * 100 / mapGlucose.count) + let value = Double(mapGlucoseNormal.count * 100 / mapGlucose.count) if value != 0 { - Text(units == .mmolL ? "> 7.8" : "> 140").font(.caption).foregroundColor(.secondary) - Text(value.formatted()).font(.caption).foregroundColor(value == 0 ? .green : .orange) - Text("%").font(.caption) + Text(units == .mmolL ? "3.9-7.8" : "70-140").foregroundColor(.secondary) + Text(value.formatted()).foregroundColor(.green) + Text("%").foregroundColor(.secondary) } - }.padding(.horizontal, 10) + }.font(.caption) + Spacer() HStack { let value = Double(mapGlucoseAcuteHigh.count * 100 / mapGlucose.count) if value != 0 { Text(units == .mmolL ? "> 11.0" : "> 216").font(.caption).foregroundColor(.secondary) - Text(value.formatted()).font(.caption).foregroundColor(value == 0 ? .green : .red) + Text(value.formatted()).font(.caption).foregroundColor(value == 0 ? .green : .orange) Text("%").font(.caption) } } From af03c7ff116ccca7be24bb8e71b1ee6af7af324e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Fri, 9 Jun 2023 11:20:18 +0200 Subject: [PATCH 29/45] Bug fix. Glucose conversion (cherry picked from commit 63559998071db8c59390efa685e5e71827b22050) --- .../Sources/Modules/DataTable/View/DataTableRootView.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/FreeAPS/Sources/Modules/DataTable/View/DataTableRootView.swift b/FreeAPS/Sources/Modules/DataTable/View/DataTableRootView.swift index 38ce4d79db..cba7eed7b1 100644 --- a/FreeAPS/Sources/Modules/DataTable/View/DataTableRootView.swift +++ b/FreeAPS/Sources/Modules/DataTable/View/DataTableRootView.swift @@ -65,6 +65,8 @@ extension DataTable { Text(state.units.rawValue) }.padding(.horizontal, 20) HStack { + let limitLow: Decimal = state.units == .mmolL ? 2.2 : 40 + let limitHigh: Decimal = state.units == .mmolL ? 21 : 380 Button { newGlucose = false } label: { Text("Cancel") }.frame(maxWidth: .infinity, alignment: .leading) @@ -74,7 +76,7 @@ extension DataTable { } label: { Text("Save") } .frame(maxWidth: .infinity, alignment: .trailing) - .disabled(state.manualGlcuose < 2.2 || state.manualGlcuose > 22) + .disabled(state.manualGlcuose < limitLow || state.manualGlcuose > limitHigh) }.padding(20) } From ac066ccfd9c189108d346b99444d1f842ee2a808 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20B=20M=C3=A5rtensson?= <53905247+Jon-b-m@users.noreply.github.com> Date: Sun, 11 Jun 2023 20:51:12 +0200 Subject: [PATCH 30/45] Bolus calculator (#101) Refactored the new bolus calculator. Now just using one formula (using two was too confusing). Removed many of the restrictions ad replaced those with warnings and alerts instead, making it possible to bolus even when BG is falling or glucose predicted below target. The Eventual BG still needs to be over target for a recommendations. This limit is not removed. Added logging and error strings from oref0 to iAPS. New bolus pop-up and new bolus alerts. To do: UI polish. --- Config.xcconfig | 2 +- .../javascript/bundle/determine-basal.js | 2 +- .../Main/en.lproj/Localizable.strings | 29 +++ .../Main/sv.lproj/Localizable.strings | 29 +++ FreeAPS/Sources/Models/Suggestion.swift | 2 + .../Modules/Bolus/BolusStateModel.swift | 36 ++-- .../Modules/Bolus/View/BolusRootView.swift | 175 ++++++++++++++---- 7 files changed, 222 insertions(+), 53 deletions(-) diff --git a/Config.xcconfig b/Config.xcconfig index 5343d916ef..dac9d7f72d 100644 --- a/Config.xcconfig +++ b/Config.xcconfig @@ -1,5 +1,5 @@ APP_DISPLAY_NAME = iAPS -APP_VERSION = 2.1.8 +APP_VERSION = 2.1.9 APP_BUILD_NUMBER = 1 COPYRIGHT_NOTICE = DEVELOPER_TEAM = ##TEAM_ID## diff --git a/FreeAPS/Resources/javascript/bundle/determine-basal.js b/FreeAPS/Resources/javascript/bundle/determine-basal.js index 6144378639..644ce39391 100644 --- a/FreeAPS/Resources/javascript/bundle/determine-basal.js +++ b/FreeAPS/Resources/javascript/bundle/determine-basal.js @@ -1 +1 @@ -var freeaps_determineBasal;(()=>{var e={5546:(e,t,a)=>{var r=a(6880);function o(e,t){t||(t=0);var a=Math.pow(10,t);return Math.round(e*a)/a}function n(e,t){return"mmol/L"===t.out_units?o(.0555*e,1):Math.round(e)}e.exports=function(e,t,a,i,s,l,m,u,d,c,g,h,p,v){var f=i.min_bg,b=v.overrideTarget;const B=v.smbIsOff,M=v.advancedSettings,_=v.isfAndCr,y=v.isf,x=v.cr,w=v.smbIsAlwaysOff,D=v.start,S=v.end,T=v.smbMinutes,C=v.uamMinutes;var U=0,G="",O="",R="",A="",I="",F=0,j=0,P=0,E=0,q=0,W=0;const k=v.weightedAverage;var L=1,z=i.sens,N=i.carb_ratio;v.useOverride&&(L=v.overridePercentage/100,_?(z/=L,N/=L):(x&&(N/=L),y&&(z/=L)));const H=i.weightPercentage,Z=v.average_total_data;function $(e,t){var a=e.getTime();return new Date(a+36e5*t)}function J(e){var t=i.bolus_increment;.025!=t&&(t=.05);var a=e/t;return a>=1?o(Math.floor(a)*t,5):0}function K(e){function t(e){return e<10&&(e="0"+e),e}return t(e.getHours())+":"+t(e.getMinutes())+":00"}function Q(e,t){var a=new Date("1/1/1999 "+e),r=new Date("1/1/1999 "+t);return(a.getTime()-r.getTime())/36e5}function V(e,t){var a=0,r=t,o=(e-t)/36e5,n=0,i=o,s=0;do{if(o>0){var l=K(r),m=p[0].rate;for(let e=0;e=(s=Q(p[e+1].start,p[e].start))?n=s:o=s?n=s:ou)if(e+1=(s=Q(d,l))?n=s:o=(s=Q("23:59:59",l))?n=s:o0&&o21)q=V(X,(ee=24-U,te=X.getTime(),new Date(te-36e5*ee))),A="24 hours of data is required for an accurate tdd calculation. Currently only "+U.toPrecision(3)+" hours of pump history data are available. Using your pump scheduled basals to fill in the missing hours. Scheduled basals added: "+q.toPrecision(5)+" U. ";else U<21?(ge=!1,enableDynamicCR=!1):A=""}else console.log("Pumphistory is empty!"),ge=!1,enableDynamicCR=!1;var ee,te;for(let e=0;e0){F=e,W=g[e].rate;var ae=g[e-1]["duration (min)"]/60,re=ae,oe=new Date(g[e-1].timestamp),ne=oe,ie=0;do{if(e--,0==e){ne=new Date;break}if("TempBasal"==g[e]._type||"PumpSuspend"==g[e]._type){ne=new Date(g[e].timestamp);break}var se=e-2;if(se>=0&&"Rewind"==g[se]._type){let e=g[se].timestamp;for(;se-1>=0&&"Prime"==g[se-=1]._type;)ie=(g[se].timestamp-e)/36e5;ie>=ae&&(ne=e,ie=0)}}while(e>0);var le=(ne-oe)/36e5;le0&&(--r,"TempBasal"==g[r]._type)){a=new Date(g[r].timestamp);break}}while(r>0);(a-t)/36e5>0&&(q+=V(a,t))}for(let e=g.length-1;e>0;e--)if("TempBasalDuration"==g[e]._type){let t=g[e]["duration (min)"]/60,a=new Date(g[e].timestamp);var me=a;let r=e;do{if(--r,r>=0&&("TempBasal"==g[r]._type||"PumpSuspend"==g[r]._type)){me=new Date(g[r].timestamp);break}}while(r>0);if(0==e&&"TempBasalDuration"==g[0]._type&&(me=new Date,t=g[e]["duration (min)"]/60),(me-a)/36e5-t>0){q+=V(me,$(a,t))}}var ue,de={TDD:o(j=E+P+q,5),bolus:o(E,5),temp_basal:o(P,5),scheduled_basal:o(q,5)};U>21?(O=". Bolus insulin: "+E.toPrecision(5)+" U",R=". Temporary basal insulin: "+P.toPrecision(5)+" U",G=". Insulin with scheduled basal rate: "+q.toPrecision(5)+" U",I=A+(" TDD past 24h is: "+j.toPrecision(5)+" U")+O+R+G,tddReason=", Total insulin: "+o(j,2)+" U, "+o(E/j*100,0)+"% Bolus "+o((P+q)/j*100,0)+"% Basal"):tddReason=", TDD: Not enough pumpData (< 21h)";const ce=e.glucose;var ge=h.useNewFormula;const he=h.enableDynamicCR,pe=Math.min(i.autosens_min,i.autosens_max),ve=Math.max(i.autosens_min,i.autosens_max);(ve==pe||ve<1||pe>1)&&(ge=!1,console.log("Dynamic ISF disabled due to current autosens settings"));const fe=h.adjustmentFactor,be=i.min_bg;var Be=!1,Me="",_e=1,ye="";Z>0&&(_e=k/Z),ye=_e>1?"Basal adjustment with a 24 hour to total average (up to 14 days of data) TDD ratio (limited by Autosens max setting). Basal Ratio: "+(_e=o(_e=Math.min(_e,i.autosens_max),2))+". Upper limit = Autosens max ("+i.autosens_max+")":_e<1?"Basal adjustment with a 24 hour to to total average (up to 14 days of data) TDD ratio (limited by Autosens min setting). Basal Ratio: "+(_e=o(_e=Math.max(_e,i.autosens_min),2))+". Lower limit = Autosens min ("+i.autosens_min+")":"Basal adjusted with a 24 hour to total average (up to 14 days of data) TDD ratio: "+_e,ye=", Basal ratio: "+_e,(i.high_temptarget_raises_sensitivity||i.exercise_mode||v.isEnabled)&&(Be=!0),be>=118&&Be&&(ge=!1,Me="Dynamic ISF temporarily off due to a high temp target/exercising. Current min target: "+be);var xe=", Dynamic ratios log: ",we=", AF: "+fe,De="BG: "+ce+" mg/dl ("+(.0555*ce).toPrecision(2)+" mmol/l)",Se="",Te="";const Ce=h.curve,Ue=h.insulinPeakTime,Ge=h.useCustomPeakTime;var Oe=55,Re=65;switch(Ce){case"rapid-acting":Re=65;break;case"ultra-rapid":Re=50}Ge?(Oe=120-Ue,console.log("Custom insulinpeakTime set to :"+Ue+", insulinFactor: "+Oe)):(Oe=120-Re,console.log("insulinFactor set to : "+Oe)),ue=j,H<1&&k>0&&(j=k,console.log("Using weighted TDD average: "+o(j,2)+" U, instead of past 24 h ("+o(ue,2)+" U), weight: "+H),Te=", Weighted TDD: "+o(j,2)+" U");const Ae=h.sigmoid;var Ie="";if(ge){var Fe=z*fe*j*Math.log(ce/Oe+1)/1800;Se=", Logarithmic formula"}if(ge&&Ae){const e=pe,t=ve-e,a=.0555*(ce-i.min_bg);var je=_e,Pe=ve-1;1==ve&&(Pe=ve+.01-1);const r=Math.log10(1/Pe-e/Pe)/Math.log10(Math.E),o=a*fe*je+r;Fe=t/(1+Math.exp(-o))+e,Se=", Sigmoid function"}var Ee=N;const qe=o(N,1);var We="",ke="";if(ge&&j>0){if(We=", Dynamic ISF/CR: On/",Fe>ve?(Me=", Dynamic ISF limited by autosens_max setting: "+ve+" ("+o(Fe,2)+"), ",ke=", Autosens/Dynamic Limit: "+ve+" ("+o(Fe,2)+")",Fe=ve):Fe-.5?"+"+o(e.delta,0):o(e.delta,0);var Ye=Math.min(e.delta,e.short_avgdelta),et=Math.min(e.short_avgdelta,e.long_avgdelta),tt=Math.max(e.delta,e.short_avgdelta,e.long_avgdelta);(Ve<=10||38===Ve||Xe>=3)&&(ze.reason="CGM is calibrating, in ??? state, or noise is high");if(Ve>60&&0==e.delta&&e.short_avgdelta>-1&&e.short_avgdelta<1&&e.long_avgdelta>-1&&e.long_avgdelta<1&&("fakecgm"==e.device?(console.error("CGM data is unchanged ("+n(Ve,i)+"+"+n(e.delta,i)+") for 5m w/ "+n(e.short_avgdelta,i)+" mg/dL ~15m change & "+n(e.long_avgdelta,2)+" mg/dL ~45m change"),console.error("Simulator mode detected ("+e.device+"): continuing anyway")):!0),Qe>12||Qe<-5?ze.reason="If current system time "+$e+" is correct, then BG data is too old. The last BG data was read "+Qe+"m ago at "+Ke:0===e.short_avgdelta&&0===e.long_avgdelta&&(e.last_cal&&e.last_cal<3?ze.reason="CGM was just calibrated":ze.reason="CGM data is unchanged ("+n(Ve,i)+"+"+n(e.delta,i)+") for 5m w/ "+n(e.short_avgdelta,i)+" mg/dL ~15m change & "+n(e.long_avgdelta,i)+" mg/dL ~45m change"),Ve<=10||38===Ve||Xe>=3||Qe>12||Qe<-5||0===e.short_avgdelta&&0===e.long_avgdelta)return t.rate>=Ze?(ze.reason+=". Canceling high temp basal of "+t.rate,ze.deliverAt=Ne,ze.temp="absolute",ze.duration=0,ze.rate=0,ze):0===t.rate&&t.duration>30?(ze.reason+=". Shortening "+t.duration+"m long zero temp to 30m. ",ze.deliverAt=Ne,ze.temp="absolute",ze.duration=30,ze.rate=0,ze):(ze.reason+=". Temp "+t.rate+" <= current basal "+Ze+"U/hr; doing nothing. ",ze);var at,rt,ot,nt,it=i.max_iob;if(void 0!==i.min_bg&&(rt=i.min_bg),void 0!==i.max_bg&&(ot=i.max_bg),void 0!==i.enableSMB_high_bg_target&&(nt=i.enableSMB_high_bg_target),void 0===i.min_bg||void 0===i.max_bg)return ze.error="Error: could not determine target_bg. ",ze;at=(i.min_bg+i.max_bg)/2;var st=i.exercise_mode||i.high_temptarget_raises_sensitivity||v.isEnabled,lt=100,mt=160;if(mt=i.half_basal_exercise_target,v.isEnabled){const e=v.hbt;console.log("Half Basal Target used: "+n(e,i)+" "+i.out_units),mt=e}else console.log("Default Half Basal Target used: "+n(mt,i)+" "+i.out_units);if(st&&i.temptargetSet&&at>lt||i.low_temptarget_lowers_sensitivity&&i.temptargetSet&&at=at&&sensitivityRatio0&&(process.stderr.write("TDD-adjustment of basals activated, using tdd24h_14d_Ratio "+o(_e,2)+", TDD 24h = "+o(ue,2)+"U, Weighted average TDD = "+o(k,2)+"U, (Weight percentage = "+H+"), Total data of TDDs (up to 14 days) average = "+o(Z,2)+"U. "),Ze!==He*L?process.stderr.write("Adjusting basal from "+He*L+" U/h to "+Ze+" U/h; "):process.stderr.write("Basal unchanged: "+Ze+" U/h; "))),i.temptargetSet);else if(void 0!==s&&s&&(i.sensitivity_raises_target&&s.ratio<1||i.resistance_lowers_target&&s.ratio>1)){rt=o((rt-60)/s.ratio)+60,ot=o((ot-60)/s.ratio)+60;var dt=o((at-60)/s.ratio)+60;at===(dt=Math.max(80,dt))?process.stderr.write("target_bg unchanged: "+n(dt,i)+"; "):process.stderr.write("target_bg from "+n(dt,i)+" to "+n(dt,i)+"; "),at=dt}var ct=n(at,i);at!=f&&(ct=0!==b&&b!==at?n(f,i)+"→"+n(b,i)+"→"+n(at,i):n(f,i)+"→"+n(at,i));var gt=200,ht=200,pt=200;if(e.noise>=2){var vt=Math.max(1.1,i.noisyCGMTargetMultiplier);Math.min(250,i.maxRaw);gt=o(Math.min(200,rt*vt)),ht=o(Math.min(200,at*vt)),pt=o(Math.min(200,ot*vt)),process.stderr.write("Raising target_bg for noisy / raw CGM data, from "+n(dt,i)+" to "+n(ht,i)+"; "),rt=gt,at=ht,ot=pt}var ft=rt-.5*(rt-40),bt=i.threshold_setting;bt>ft&&bt<=120&&bt>=65?(console.error("Threshold changed in settings from "+n(ft,i)+" to "+n(bt,i)+". "),ft=bt):console.error("Current threshold: "+n(ft,i));var Bt="",Mt=(o(z,1),z);if(void 0!==s&&s&&((Mt=o(Mt=z/sensitivityRatio,1))!==z?process.stderr.write("ISF from "+n(z,i)+" to "+n(Mt,i)):process.stderr.write("ISF unchanged: "+n(Mt,i)),Bt+="Autosens ratio: "+o(sensitivityRatio,2)+", ISF: "+n(z,i)+"→"+n(Mt,i)),console.error("CR:"+N),void 0===a)return ze.error="Error: iob_data undefined. ",ze;var _t,yt=a;if(a.length,a.length>1&&(a=yt[0]),void 0===a.activity||void 0===a.iob)return ze.error="Error: iob_data missing some property. ",ze;var xt=((_t=void 0!==a.lastTemp?o((new Date($e).getTime()-a.lastTemp.date)/6e4):0)+t.duration)%30;if(console.error("currenttemp:"+t.rate+" lastTempAge:"+_t+"m, tempModulus:"+xt+"m"),ze.temp="absolute",ze.deliverAt=Ne,u&&t&&a.lastTemp&&t.rate!==a.lastTemp.rate&&_t>10&&t.duration)return ze.reason="Warning: currenttemp rate "+t.rate+" != lastTemp rate "+a.lastTemp.rate+" from pumphistory; canceling temp",m.setTempBasal(0,0,i,ze,t);if(t&&a.lastTemp&&t.duration>0){var wt=_t-a.lastTemp.duration;if(wt>5&&_t>10)return ze.reason="Warning: currenttemp running but lastTemp from pumphistory ended "+wt+"m ago; canceling temp",m.setTempBasal(0,0,i,ze,t)}var Dt=o(-a.activity*Mt*5,2),St=o(6*(Ye-Dt));St<0&&(St=o(6*(et-Dt)))<0&&(St=o(6*(e.long_avgdelta-Dt)));var Tt=Ve,Ct=(Tt=a.iob>0?o(Ve-a.iob*Mt):o(Ve-a.iob*Math.min(Mt,z)))+St;if(void 0===Ct||isNaN(Ct))return ze.error="Error: could not calculate eventualBG. Sensitivity: "+Mt+" Deviation: "+St,ze;var Ut=function(e,t,a){return o(a+(e-t)/24,1)}(at,Ct,Dt);ze={temp:"absolute",bg:Ve,tick:Je,eventualBG:Ct,insulinReq:0,reservoir:d,deliverAt:Ne,sensitivityRatio,TDD:ue,insulin:de,current_target:at,insulinForManualBolus:Fa};var Gt=[],Ot=[],Rt=[],At=[];Gt.push(Ve),Ot.push(Ve),At.push(Ve),Rt.push(Ve);var It=function(e,t,a,r,o,i){return t?!e.allowSMB_with_high_temptarget&&e.temptargetSet&&o>100?(console.error("SMB disabled due to high temptarget of "+o),!1):!0===a.bwFound&&!1===e.A52_risk_enable?(console.error("SMB disabled due to Bolus Wizard activity in the last 6 hours."),!1):!0===e.enableSMB_always?(a.bwFound?console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled due to enableSMB_always"),!0):!0===e.enableSMB_with_COB&&a.mealCOB?(a.bwCarbs?console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for COB of "+a.mealCOB),!0):!0===e.enableSMB_after_carbs&&a.carbs?(a.bwCarbs?console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for 6h after carb entry"),!0):!0===e.enableSMB_with_temptarget&&e.temptargetSet&&o<100?(a.bwFound?console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for temptarget of "+n(o,e)),!0):!0===e.enableSMB_high_bg&&null!==i&&r>=i?(console.error("Checking BG to see if High for SMB enablement."),console.error("Current BG",r," | High BG ",i),a.bwFound?console.error("Warning: High BG SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("High BG detected. Enabling SMB."),!0):(console.error("SMB disabled (no enableSMB preferences active or no condition satisfied)"),!1):(console.error("SMB disabled (!microBolusAllowed)"),!1)}(i,u,l,Ve,at,nt);if(B)if(w){let e=c.getHours();e>=D&&e<=S&&(console.error("SMB disabled by schedule (a Profile is active with SMBs disabled)"),It=!1)}else console.error("SMBs are disabled (a Profile is active with SMBs disabled)"),It=!1;var Ft=i.enableUAM,jt=0,Pt=0;jt=o(Ye-Dt,1);var Et=o(Ye-Dt,1);csf=Mt/N,console.error("profile.sens:"+n(z,i)+", sens:"+n(Mt,i)+", CSF:"+o(csf,1));var qt=o(30*csf*5/60,1);jt>qt&&(console.error("Limiting carb impact from "+jt+" to "+qt+"mg/dL/5m (30g/h)"),jt=qt);var Wt=3;sensitivityRatio&&(Wt/=sensitivityRatio);var kt=Wt;if(l.carbs){Wt=Math.max(Wt,l.mealCOB/20);var Lt=o((new Date($e).getTime()-l.lastCarbTime)/6e4),zt=(l.carbs-l.mealCOB)/l.carbs;kt=o(kt=Wt+1.5*Lt/60,1),console.error("Last carbs "+Lt+" minutes ago; remainingCATime:"+kt+"hours; "+o(100*zt,1)+"% carbs absorbed")}var Nt=Math.max(0,jt/5*60*kt/2)/csf,Ht=90,Zt=1;i.remainingCarbsCap&&(Ht=Math.min(90,i.remainingCarbsCap)),i.remainingCarbsFraction&&(Zt=Math.min(1,i.remainingCarbsFraction));var $t=1-Zt,Jt=Math.max(0,l.mealCOB-Nt-l.carbs*$t),Kt=(Jt=Math.min(Ht,Jt))*csf*5/60/(kt/2),Qt=o(l.slopeFromMaxDeviation,2),Vt=o(l.slopeFromMinDeviation,2),Xt=Math.min(Qt,-Vt/3);Pt=0===jt?0:Math.min(60*kt/5/2,Math.max(0,l.mealCOB*csf/jt)),console.error("Carb Impact:"+jt+"mg/dL per 5m; CI Duration:"+o(5*Pt/60*2,1)+"hours; remaining CI ("+kt/2+"h peak):"+o(Kt,1)+"mg/dL per 5m");var Yt,ea,ta,aa,ra,oa=999,na=999,ia=999,sa=Ve,la=999,ma=999,ua=999,da=999,ca=Ct,ga=Ve,ha=Ve,pa=0,va=[],fa=[];try{yt.forEach((function(e){var t=o(-e.activity*Mt*5,2),a=o(-e.iobWithZeroTemp.activity*Mt*5,2),r=Tt,n=jt*(1-Math.min(1,Ot.length/12));if(!0===(ge&&!Ae))ca=Ot[Ot.length-1]+o(-e.activity*(1800/(j*fe*Math.log(Math.max(Ot[Ot.length-1],39)/Oe+1)))*5,2)+n,r=At[At.length-1]+o(-e.iobWithZeroTemp.activity*(1800/(j*fe*Math.log(Math.max(At[At.length-1],39)/Oe+1)))*5,2),console.log("Dynamic ISF (Logarithmic Formula) )adjusted predictions for IOB and ZT: IOBpredBG: "+o(ca,2)+" , ZTpredBG: "+o(r,2));else ca=Ot[Ot.length-1]+t+n,r=At[At.length-1]+a;var i=Math.max(0,Math.max(0,jt)*(1-Gt.length/Math.max(2*Pt,1))),s=Math.min(Gt.length,12*kt-Gt.length),l=Math.max(0,s/(kt/2*12)*Kt);i+l,va.push(o(l,0)),fa.push(o(i,0)),COBpredBG=Gt[Gt.length-1]+t+Math.min(0,n)+i+l;var m=Math.max(0,Et+Rt.length*Xt),u=Math.max(0,Et*(1-Rt.length/Math.max(36,1))),d=Math.min(m,u);if(d>0&&(pa=o(5*(Rt.length+1)/60,1)),!0===(ge&&!Ae))UAMpredBG=Rt[Rt.length-1]+o(-e.activity*(1800/(j*fe*Math.log(Math.max(Rt[Rt.length-1],39)/Oe+1)))*5,2)+Math.min(0,n)+d,console.log("Dynamic ISF (Logarithmic Formula) adjusted prediction for UAM: UAMpredBG: "+o(UAMpredBG,2));else UAMpredBG=Rt[Rt.length-1]+t+Math.min(0,n)+d;Ot.length<48&&Ot.push(ca),Gt.length<48&&Gt.push(COBpredBG),Rt.length<48&&Rt.push(UAMpredBG),At.length<48&&At.push(r),COBpredBG18&&caga&&(ga=ca),(Pt||Kt>0)&&Gt.length>18&&COBpredBG0)&&COBpredBG>ga&&(ha=COBpredBG),Ft&&Rt.length>12&&UAMpredBGga&&UAMpredBG}))}catch(e){console.error("Problem with iobArray. Optional feature Advanced Meal Assist disabled")}l.mealCOB&&(console.error("predCIs (mg/dL/5m):"+fa.join(" ")),console.error("remainingCIs: "+va.join(" "))),ze.predBGs={},Ot.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))}));for(var ba=Ot.length-1;ba>12&&Ot[ba-1]===Ot[ba];ba--)Ot.pop();for(ze.predBGs.IOB=Ot,ta=o(Ot[Ot.length-1]),At.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),ba=At.length-1;ba>6&&!(At[ba-1]>=At[ba]||At[ba]<=at);ba--)At.pop();if(ze.predBGs.ZT=At,o(At[At.length-1]),l.mealCOB>0&&(jt>0||Kt>0)){for(Gt.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),ba=Gt.length-1;ba>12&&Gt[ba-1]===Gt[ba];ba--)Gt.pop();ze.predBGs.COB=Gt,aa=o(Gt[Gt.length-1]),Ct=Math.max(Ct,o(Gt[Gt.length-1]))}if(jt>0||Kt>0){if(Ft){for(Rt.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),ba=Rt.length-1;ba>12&&Rt[ba-1]===Rt[ba];ba--)Rt.pop();ze.predBGs.UAM=Rt,ra=o(Rt[Rt.length-1]),Rt[Rt.length-1]&&(Ct=Math.max(Ct,o(Rt[Rt.length-1])))}ze.eventualBG=Ct}console.error("UAM Impact:"+Et+"mg/dL per 5m; UAM Duration:"+pa+"hours"),oa=Math.max(39,oa),na=Math.max(39,na),ia=Math.max(39,ia),Yt=o(oa);var Ba=l.mealCOB/l.carbs;ea=o(ia<999&&na<999?(1-Ba)*UAMpredBG+Ba*COBpredBG:na<999?(ca+COBpredBG)/2:ia<999?(ca+UAMpredBG)/2:ca),da>ea&&(ea=da),sa=o(sa=Pt||Kt>0?Ft?Ba*la+(1-Ba)*ma:la:Ft?ma:ua);var Ma=ia;if(daia&&(Ma=(ia+da)/2);if(Ma=o(Ma),l.carbs)if(!Ft&&na<999)Yt=o(Math.max(oa,na));else if(na<999){var ya=Ba*na+(1-Ba)*Ma;Yt=o(Math.max(oa,na,ya))}else Yt=Ft?Ma:sa;else Ft&&(Yt=o(Math.max(oa,Ma)));Yt=Math.min(Yt,ea),process.stderr.write("minPredBG: "+Yt+" minIOBPredBG: "+oa+" minZTGuardBG: "+da),na<999&&process.stderr.write(" minCOBPredBG: "+na),ia<999&&process.stderr.write(" minUAMPredBG: "+ia),console.error(" avgPredBG:"+ea+" COB/Carbs:"+l.mealCOB+"/"+l.carbs),ha>Ve&&(Yt=Math.min(Yt,ha)),ze.COB=l.mealCOB,ze.IOB=a.iob,ze.BGI=n(Dt,i),ze.deviation=n(St,i),ze.ISF=n(Mt,i),ze.CR=o(N,1),ze.target_bg=n(at,i),ze.TDD=o(ue,2),ze.current_target=o(at,0);var xa=ze.CR;qe!=ze.CR&&(xa=qe+"→"+ze.CR),ze.reason=Bt+", COB: "+ze.COB+", Dev: "+ze.deviation+", BGI: "+ze.BGI+", CR: "+xa+", Target: "+ct+", minPredBG "+n(Yt,i)+", minGuardBG "+n(sa,i)+", IOBpredBG "+n(ta,i),aa>0&&(ze.reason+=", COBpredBG "+n(aa,i)),ra>0&&(ze.reason+=", UAMpredBG "+n(ra,i)),ze.reason+=tddReason,ze.reason+="; ";var wa=Tt;wa<40&&(wa=Math.min(sa,wa));var Da,Sa=ft-wa,Ta=240,Ca=240;if(l.mealCOB>0&&(jt>0||Kt>0)){for(ba=0;baDa*Ve&&(console.error("maxDelta "+n(tt,i)+" > "+100*Da+"% of BG "+n(Ve,i)+" - disabling SMB"),ze.reason+="maxDelta "+n(tt,i)+" > "+100*Da+"% of BG "+n(Ve,i)+" - SMB disabled!, ",It=!1),console.error("BG projected to remain above "+n(rt,i)+" for "+Ta+"minutes"),(Ca<240||Ta<60)&&console.error("BG projected to remain above "+n(ft,i)+" for "+Ca+"minutes");var Ua=Ca,Ga=i.current_basal*L*Mt*Ua/60,Oa=Math.max(0,l.mealCOB-.25*l.carbs),Ra=(Sa-Ga)/csf-Oa;Ga=o(Ga),Ra=o(Ra),console.error("naive_eventualBG:",Tt,"bgUndershoot:",Sa,"zeroTempDuration:",Ua,"zeroTempEffect:",Ga,"carbsReq:",Ra),"Could not parse clock data"==l.reason?console.error("carbsReq unknown: Could not parse clock data"):Ra>=i.carbsReqThreshold&&Ca<=45&&(ze.carbsReq=Ra,ze.reason+=Ra+" add'l carbs req w/in "+Ca+"m; ");var Aa=0;if(Ve0&&Ye>Ut)ze.reason+="IOB "+a.iob+" < "+o(-i.current_basal*L*20/60,2),ze.reason+=" and minDelta "+n(Ye,i)+" > expectedDelta "+n(Ut,i)+"; ";else if(Ve=55)return ze.reason+="; Canceling temp at "+ze.deliverAt.getMinutes()+"m past the hour. ",m.setTempBasal(0,0,i,ze,t);var Ia=0,Fa=0,ja=Ze,Pa=0;if(CtUt&&Ye>0&&!Ra)return Tt<40?(ze.reason+=", naive_eventualBG < 40. ",m.setTempBasal(0,30,i,ze,t)):(e.delta>Ye?ze.reason+=", but Delta "+n(Je,i)+" > expectedDelta "+n(Ut,i):ze.reason+=", but Min. Delta "+Ye.toFixed(2)+" > Exp. Delta "+n(Ut,i),t.duration>15&&r(Ze,i)===r(t.rate,i)?(ze.reason+=", temp "+t.rate+" ~ req "+Ze+"U/hr. ",ze):(ze.reason+="; setting current basal of "+Ze+" as temp. ",m.setTempBasal(Ze,30,i,ze,t)));Ia=o(Ia=2*Math.min(0,(Ct-at)/Mt),2);var Ea=Math.min(0,(Tt-at)/Mt);if(Ea=o(Ea,2),Ye<0&&Ye>Ut)Ia=o(Ia*(Ye/Ut),2);ja=r(ja=Ze+2*Ia,i),Pa=t.duration*(t.rate-Ze)/60;var qa=Math.min(Ia,Ea);if(console.log("naiveInsulinReq:"+Ea),Pa5&&ja>=.8*t.rate)return ze.reason+=", temp "+t.rate+" ~< req "+ja+"U/hr. ",ze;if(ja<=0){if((Aa=o(60*((Sa=at-Tt)/Mt)/i.current_basal*L))<0?Aa=0:(Aa=30*o(Aa/30),Aa=Math.min(120,Math.max(0,Aa))),Aa>0)return ze.reason+=", setting "+Aa+"m zero temp. ",m.setTempBasal(ja,Aa,i,ze,t)}else ze.reason+=", setting "+ja+"U/hr. ";return m.setTempBasal(ja,30,i,ze,t)}if(Ye "+n(rt,i)+" but Delta "+n(Je,i)+" < Exp. Delta "+n(Ut,i):ze.reason+="Eventual BG "+n(Ct,i)+" > "+n(rt,i)+" but Min. Delta "+Ye.toFixed(2)+" < Exp. Delta "+n(Ut,i),t.duration>15&&r(Ze,i)===r(t.rate,i)?(ze.reason+=", temp "+t.rate+" ~ req "+Ze+"U/hr. ",ze):(ze.reason+="; setting current basal of "+Ze+" as temp. ",m.setTempBasal(Ze,30,i,ze,t));if(Math.min(Ct,Yt)15&&r(Ze,i)===r(t.rate,i)?(ze.reason+=", temp "+t.rate+" ~ req "+Ze+"U/hr. ",ze):(ze.reason+="; setting current basal of "+Ze+" as temp. ",m.setTempBasal(Ze,30,i,ze,t));if(Ct>=ot&&(ze.reason+="Eventual BG "+n(Ct,i)+" >= "+n(ot,i)+", "),a.iob>it)return ze.reason+="IOB "+o(a.iob,2)+" > max_iob "+it,t.duration>15&&r(Ze,i)===r(t.rate,i)?(ze.reason+=", temp "+t.rate+" ~ req "+Ze+"U/hr. ",ze):(ze.reason+="; setting current basal of "+Ze+" as temp. ",m.setTempBasal(Ze,30,i,ze,t));Ia=o((Math.min(Yt,Ct)-at)/Mt,2),Fa=o((Ct-at)/Mt,2),Ia>it-a.iob?(console.error("SMB limited by maxIOB: "+it-a.iob+" (. insulinReq: "+Ia+" U)"),ze.reason+="max_iob "+it+", ",Ia=it-a.iob):console.error("SMB not limited by maxIOB ( insulinReq: "+Ia+" U)."),Fa>it-a.iob?(console.error("Ev. Bolus would not be limited by maxIOB: "+it-a.iob+" (. insulinForManualBolus: "+Fa+" U)"),ze.reason+="max_iob "+it+", ",Fa=it-a.iob):console.error("Ev. Bolus would not be limited by maxIOB ( insulinForManualBolus: "+Fa+" U)."),ja=r(ja=Ze+2*Ia,i),Ia=o(Ia,3),ze.insulinReq=Ia,ze.insulinForManualBolus=o(Fa,3);var Wa=o((new Date($e).getTime()-a.lastBolusTime)/6e4,1);if(u&&It&&Ve>ft){var ka=30;void 0!==i.maxSMBBasalMinutes&&(ka=i.maxSMBBasalMinutes);var La=30;void 0!==i.maxUAMSMBBasalMinutes&&(La=i.maxUAMSMBBasalMinutes),v.useOverride&&M&&T!==ka&&(console.error("SMB Max Minutes - setting overriden from "+ka+" to "+T),ka=T),v.useOverride&&M&&C!==La&&(console.error("UAM Max Minutes - setting overriden from "+La+" to "+C),La=C);var za=o(l.mealCOB/N,3),Na=0;void 0===ka?(Na=o(i.current_basal*L*30/60,1),console.error("smbMinutesSetting undefined: defaulting to 30m"),Ia>Na&&console.error("SMB limited by maxBolus: "+Na+" ( "+Ia+" U)")):a.iob>za&&a.iob>0?(console.error("IOB"+a.iob+"> COB"+l.mealCOB+"; mealInsulinReq ="+za),La?(console.error("maxUAMSMBBasalMinutes: "+La+", profile.current_basal: "+i.current_basal*L),Na=o(i.current_basal*L*La/60,1)):(console.error("maxUAMSMBBasalMinutes undefined: defaulting to 30m"),Na=o(i.current_basal*L*30/60,1)),Ia>Na?console.error("SMB limited by maxUAMSMBBasalMinutes [ "+La+"m ]: "+Na+"U ( "+Ia+"U )"):console.error("SMB is not limited by maxUAMSMBBasalMinutes. ( insulinReq: "+Ia+"U )")):(console.error(".maxSMBBasalMinutes: "+ka+", profile.current_basal: "+i.current_basal*L),Ia>(Na=o(i.current_basal*ka/60,1))?console.error("SMB limited by maxSMBBasalMinutes: "+ka+"m ]: "+Na+"U ( insulinReq: "+Ia+"U )"):console.error("SMB is not limited by maxSMBBasalMinutes. ( insulinReq: "+Ia+"U )"));var Ha=i.bolus_increment,Za=1/Ha,$a=i.smb_delivery_ratio;$a>.5&&console.error("SMB Delivery Ratio increased from default 0.5 to "+o($a,2));var Ja=Math.min(Ia*$a,Na);Ja=Math.floor(Ja*Za)/Za,Aa=o(60*((at-(Tt+oa)/2)/Mt)/i.current_basal*L),Ia>0&&Ja=30?(Aa=30*o(Aa/30),Aa=Math.min(60,Math.max(0,Aa))):(Ka=o(Ze*Aa/30,2),Aa=30),ze.reason+=" insulinReq "+Ia,Ja>=Na&&(ze.reason+="; maxBolus "+Na),Aa>0&&(ze.reason+="; setting "+Aa+"m low temp of "+Ka+"U/h"),ze.reason+=". ";var Qa=3;i.SMBInterval&&(Qa=Math.min(10,Math.max(1,i.SMBInterval)));var Va=o(Qa-Wa,0),Xa=o(60*(Qa-Wa),0)%60;if(console.error("naive_eventualBG "+Tt+","+Aa+"m "+Ka+"U/h temp needed; last bolus "+Wa+"m ago; maxBolus: "+Na),Wa>Qa?Ja>0&&(ze.units=Ja,ze.reason+="Microbolusing "+Ja+"U. "):ze.reason+="Waiting "+Va+"m "+Xa+"s to microbolus again. ",Aa>0)return ze.rate=Ka,ze.duration=Aa,ze}var Ya=m.getMaxSafeBasal(i);return ja>Ya&&(ze.reason+="adj. req. rate: "+ja+" to maxSafeBasal: "+o(Ya,2)+", ",ja=r(Ya,i)),(Pa=t.duration*(t.rate-Ze)/60)>=2*Ia?(ze.reason+=t.duration+"m@"+t.rate.toFixed(2)+" > 2 * insulinReq. Setting temp basal of "+ja+"U/hr. ",m.setTempBasal(ja,30,i,ze,t)):void 0===t.duration||0===t.duration?(ze.reason+="no temp, setting "+ja+"U/hr. ",m.setTempBasal(ja,30,i,ze,t)):t.duration>5&&r(ja,i)<=r(t.rate,i)?(ze.reason+="temp "+t.rate+" >~ req "+ja+"U/hr. ",ze):(ze.reason+="temp "+t.rate+"<"+ja+"U/hr. ",m.setTempBasal(ja,30,i,ze,t))}},6880:(e,t,a)=>{var r=a(6654);e.exports=function(e,t){var a=20;void 0!==t&&"string"==typeof t.model&&(r(t.model,"54")||r(t.model,"23"))&&(a=40);return e<1?Math.round(e*a)/a:e<10?Math.round(20*e)/20:Math.round(10*e)/10}},2705:(e,t,a)=>{var r=a(5639).Symbol;e.exports=r},9932:e=>{e.exports=function(e,t){for(var a=-1,r=null==e?0:e.length,o=Array(r);++a{e.exports=function(e,t,a){return e==e&&(void 0!==a&&(e=e<=a?e:a),void 0!==t&&(e=e>=t?e:t)),e}},4239:(e,t,a)=>{var r=a(2705),o=a(9607),n=a(2333),i=r?r.toStringTag:void 0;e.exports=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":i&&i in Object(e)?o(e):n(e)}},531:(e,t,a)=>{var r=a(2705),o=a(9932),n=a(1469),i=a(3448),s=r?r.prototype:void 0,l=s?s.toString:void 0;e.exports=function e(t){if("string"==typeof t)return t;if(n(t))return o(t,e)+"";if(i(t))return l?l.call(t):"";var a=t+"";return"0"==a&&1/t==-Infinity?"-0":a}},7561:(e,t,a)=>{var r=a(7990),o=/^\s+/;e.exports=function(e){return e?e.slice(0,r(e)+1).replace(o,""):e}},1957:(e,t,a)=>{var r="object"==typeof a.g&&a.g&&a.g.Object===Object&&a.g;e.exports=r},9607:(e,t,a)=>{var r=a(2705),o=Object.prototype,n=o.hasOwnProperty,i=o.toString,s=r?r.toStringTag:void 0;e.exports=function(e){var t=n.call(e,s),a=e[s];try{e[s]=void 0;var r=!0}catch(e){}var o=i.call(e);return r&&(t?e[s]=a:delete e[s]),o}},2333:e=>{var t=Object.prototype.toString;e.exports=function(e){return t.call(e)}},5639:(e,t,a)=>{var r=a(1957),o="object"==typeof self&&self&&self.Object===Object&&self,n=r||o||Function("return this")();e.exports=n},7990:e=>{var t=/\s/;e.exports=function(e){for(var a=e.length;a--&&t.test(e.charAt(a)););return a}},6654:(e,t,a)=>{var r=a(9750),o=a(531),n=a(554),i=a(9833);e.exports=function(e,t,a){e=i(e),t=o(t);var s=e.length,l=a=void 0===a?s:r(n(a),0,s);return(a-=t.length)>=0&&e.slice(a,l)==t}},1469:e=>{var t=Array.isArray;e.exports=t},3218:e=>{e.exports=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}},7005:e=>{e.exports=function(e){return null!=e&&"object"==typeof e}},3448:(e,t,a)=>{var r=a(4239),o=a(7005);e.exports=function(e){return"symbol"==typeof e||o(e)&&"[object Symbol]"==r(e)}},8601:(e,t,a)=>{var r=a(4841),o=1/0;e.exports=function(e){return e?(e=r(e))===o||e===-1/0?17976931348623157e292*(e<0?-1:1):e==e?e:0:0===e?e:0}},554:(e,t,a)=>{var r=a(8601);e.exports=function(e){var t=r(e),a=t%1;return t==t?a?t-a:t:0}},4841:(e,t,a)=>{var r=a(7561),o=a(3218),n=a(3448),i=/^[-+]0x[0-9a-f]+$/i,s=/^0b[01]+$/i,l=/^0o[0-7]+$/i,m=parseInt;e.exports=function(e){if("number"==typeof e)return e;if(n(e))return NaN;if(o(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=o(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=r(e);var a=s.test(e);return a||l.test(e)?m(e.slice(2),a?2:8):i.test(e)?NaN:+e}},9833:(e,t,a)=>{var r=a(531);e.exports=function(e){return null==e?"":r(e)}}},t={};function a(r){var o=t[r];if(void 0!==o)return o.exports;var n=t[r]={exports:{}};return e[r](n,n.exports,a),n.exports}a.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}();var r=a(5546);freeaps_determineBasal=r})(); +var freeaps_determineBasal;(()=>{var e={5546:(e,t,a)=>{var r=a(6880);function o(e,t){t||(t=0);var a=Math.pow(10,t);return Math.round(e*a)/a}function n(e,t){return"mmol/L"===t.out_units?o(.0555*e,1):Math.round(e)}e.exports=function(e,t,a,i,s,l,u,m,d,c,g,h,p,v){var f=i.min_bg,b=v.overrideTarget;const B=v.smbIsOff,M=v.advancedSettings,_=v.isfAndCr,y=v.isf,x=v.cr,S=v.smbIsAlwaysOff,w=v.start,D=v.end,T=v.smbMinutes,G=v.uamMinutes;var C=0,U=0,O="",R="",A="",I="",F="",j=0,P=0,E=0,q=0,W=0,k=0;const L=v.weightedAverage;var z=1,N=i.sens,H=i.carb_ratio;v.useOverride&&(z=v.overridePercentage/100,_?(N/=z,H/=z):(x&&(H/=z),y&&(N/=z)));const Z=i.weightPercentage,$=v.average_total_data;function J(e,t){var a=e.getTime();return new Date(a+36e5*t)}function K(e){var t=i.bolus_increment;.025!=t&&(t=.05);var a=e/t;return a>=1?o(Math.floor(a)*t,5):0}function Q(e){function t(e){return e<10&&(e="0"+e),e}return t(e.getHours())+":"+t(e.getMinutes())+":00"}function V(e,t){var a=new Date("1/1/1999 "+e),r=new Date("1/1/1999 "+t);return(a.getTime()-r.getTime())/36e5}function X(e,t){var a=0,r=t,o=(e-t)/36e5,n=0,i=o,s=0;do{if(o>0){var l=Q(r),u=p[0].rate;for(let e=0;e=(s=V(p[e+1].start,p[e].start))?n=s:o=s?n=s:om)if(e+1=(s=V(d,l))?n=s:o=(s=V("23:59:59",l))?n=s:o0&&o21)W=X(Y,(te=24-U,ae=Y.getTime(),new Date(ae-36e5*te))),I="24 hours of data is required for an accurate tdd calculation. Currently only "+U.toPrecision(3)+" hours of pump history data are available. Using your pump scheduled basals to fill in the missing hours. Scheduled basals added: "+W.toPrecision(5)+" U. ";else U<21?(he=!1,enableDynamicCR=!1):I=""}else console.log("Pumphistory is empty!"),he=!1,enableDynamicCR=!1;var te,ae;for(let e=0;e0){j=e,k=g[e].rate;var re=g[e-1]["duration (min)"]/60,oe=re,ne=new Date(g[e-1].timestamp),ie=ne,se=0;do{if(e--,0==e){ie=new Date;break}if("TempBasal"==g[e]._type||"PumpSuspend"==g[e]._type){ie=new Date(g[e].timestamp);break}var le=e-2;if(le>=0&&"Rewind"==g[le]._type){let e=g[le].timestamp;for(;le-1>=0&&"Prime"==g[le-=1]._type;)se=(g[le].timestamp-e)/36e5;se>=re&&(ie=e,se=0)}}while(e>0);var ue=(ie-ne)/36e5;ue0&&(--r,"TempBasal"==g[r]._type)){a=new Date(g[r].timestamp);break}}while(r>0);(a-t)/36e5>0&&(W+=X(a,t))}for(let e=g.length-1;e>0;e--)if("TempBasalDuration"==g[e]._type){let t=g[e]["duration (min)"]/60,a=new Date(g[e].timestamp);var me=a;let r=e;do{if(--r,r>=0&&("TempBasal"==g[r]._type||"PumpSuspend"==g[r]._type)){me=new Date(g[r].timestamp);break}}while(r>0);if(0==e&&"TempBasalDuration"==g[0]._type&&(me=new Date,t=g[e]["duration (min)"]/60),(me-a)/36e5-t>0){W+=X(me,J(a,t))}}var de,ce={TDD:o(P=q+E+W,5),bolus:o(q,5),temp_basal:o(E,5),scheduled_basal:o(W,5)};U>21?(R=". Bolus insulin: "+q.toPrecision(5)+" U",A=". Temporary basal insulin: "+E.toPrecision(5)+" U",O=". Insulin with scheduled basal rate: "+W.toPrecision(5)+" U",F=I+(" TDD past 24h is: "+P.toPrecision(5)+" U")+R+A+O,tddReason=", Total insulin: "+o(P,2)+" U, "+o(q/P*100,0)+"% Bolus "+o((E+W)/P*100,0)+"% Basal"):tddReason=", TDD: Not enough pumpData (< 21h)";const ge=e.glucose;var he=h.useNewFormula;const pe=h.enableDynamicCR,ve=Math.min(i.autosens_min,i.autosens_max),fe=Math.max(i.autosens_min,i.autosens_max);(fe==ve||fe<1||ve>1)&&(he=!1,console.log("Dynamic ISF disabled due to current autosens settings"));const be=h.adjustmentFactor,Be=i.min_bg;var Me=!1,_e="",ye=1,xe="";$>0&&(ye=L/$),xe=ye>1?"Basal adjustment with a 24 hour to total average (up to 14 days of data) TDD ratio (limited by Autosens max setting). Basal Ratio: "+(ye=o(ye=Math.min(ye,i.autosens_max),2))+". Upper limit = Autosens max ("+i.autosens_max+")":ye<1?"Basal adjustment with a 24 hour to to total average (up to 14 days of data) TDD ratio (limited by Autosens min setting). Basal Ratio: "+(ye=o(ye=Math.max(ye,i.autosens_min),2))+". Lower limit = Autosens min ("+i.autosens_min+")":"Basal adjusted with a 24 hour to total average (up to 14 days of data) TDD ratio: "+ye,xe=", Basal ratio: "+ye,(i.high_temptarget_raises_sensitivity||i.exercise_mode||v.isEnabled)&&(Me=!0),Be>=118&&Me&&(he=!1,_e="Dynamic ISF temporarily off due to a high temp target/exercising. Current min target: "+Be);var Se=", Dynamic ratios log: ",we=", AF: "+be,De="BG: "+ge+" mg/dl ("+(.0555*ge).toPrecision(2)+" mmol/l)",Te="",Ge="";const Ce=h.curve,Ue=h.insulinPeakTime,Oe=h.useCustomPeakTime;var Re=55,Ae=65;switch(Ce){case"rapid-acting":Ae=65;break;case"ultra-rapid":Ae=50}Oe?(Re=120-Ue,console.log("Custom insulinpeakTime set to :"+Ue+", insulinFactor: "+Re)):(Re=120-Ae,console.log("insulinFactor set to : "+Re)),de=P,Z<1&&L>0&&(P=L,console.log("Using weighted TDD average: "+o(P,2)+" U, instead of past 24 h ("+o(de,2)+" U), weight: "+Z),Ge=", Weighted TDD: "+o(P,2)+" U");const Ie=h.sigmoid;var Fe="";if(he){var je=N*be*P*Math.log(ge/Re+1)/1800;Te=", Logarithmic formula"}if(he&&Ie){const e=ve,t=fe-e,a=.0555*(ge-i.min_bg);var Pe=ye,Ee=fe-1;1==fe&&(Ee=fe+.01-1);const r=Math.log10(1/Ee-e/Ee)/Math.log10(Math.E),o=a*be*Pe+r;je=t/(1+Math.exp(-o))+e,Te=", Sigmoid function"}var qe=H;const We=o(H,1);var ke="",Le="";if(he&&P>0){if(ke=", Dynamic ISF/CR: On/",je>fe?(_e=", Dynamic ISF limited by autosens_max setting: "+fe+" ("+o(je,2)+"), ",Le=", Autosens/Dynamic Limit: "+fe+" ("+o(je,2)+")",je=fe):je-.5?"+"+o(e.delta,0):o(e.delta,0);var et=Math.min(e.delta,e.short_avgdelta),tt=Math.min(e.short_avgdelta,e.long_avgdelta),at=Math.max(e.delta,e.short_avgdelta,e.long_avgdelta);(Xe<=10||38===Xe||Ye>=3)&&(Ne.reason="CGM is calibrating, in ??? state, or noise is high");if(Xe>60&&0==e.delta&&e.short_avgdelta>-1&&e.short_avgdelta<1&&e.long_avgdelta>-1&&e.long_avgdelta<1&&("fakecgm"==e.device?(console.error("CGM data is unchanged ("+n(Xe,i)+"+"+n(e.delta,i)+") for 5m w/ "+n(e.short_avgdelta,i)+" mg/dL ~15m change & "+n(e.long_avgdelta,2)+" mg/dL ~45m change"),console.error("Simulator mode detected ("+e.device+"): continuing anyway")):!0),Ve>12||Ve<-5?Ne.reason="If current system time "+Je+" is correct, then BG data is too old. The last BG data was read "+Ve+"m ago at "+Qe:0===e.short_avgdelta&&0===e.long_avgdelta&&(e.last_cal&&e.last_cal<3?Ne.reason="CGM was just calibrated":Ne.reason="CGM data is unchanged ("+n(Xe,i)+"+"+n(e.delta,i)+") for 5m w/ "+n(e.short_avgdelta,i)+" mg/dL ~15m change & "+n(e.long_avgdelta,i)+" mg/dL ~45m change"),Xe<=10||38===Xe||Ye>=3||Ve>12||Ve<-5||0===e.short_avgdelta&&0===e.long_avgdelta)return t.rate>=$e?(Ne.reason+=". Canceling high temp basal of "+t.rate,Ne.deliverAt=He,Ne.temp="absolute",Ne.duration=0,Ne.rate=0,Ne):0===t.rate&&t.duration>30?(Ne.reason+=". Shortening "+t.duration+"m long zero temp to 30m. ",Ne.deliverAt=He,Ne.temp="absolute",Ne.duration=30,Ne.rate=0,Ne):(Ne.reason+=". Temp "+t.rate+" <= current basal "+$e+"U/hr; doing nothing. ",Ne);var rt,ot,nt,it,st=i.max_iob;if(void 0!==i.min_bg&&(ot=i.min_bg),void 0!==i.max_bg&&(nt=i.max_bg),void 0!==i.enableSMB_high_bg_target&&(it=i.enableSMB_high_bg_target),void 0===i.min_bg||void 0===i.max_bg)return Ne.error="Error: could not determine target_bg. ",Ne;rt=(i.min_bg+i.max_bg)/2;var lt=i.exercise_mode||i.high_temptarget_raises_sensitivity||v.isEnabled,ut=100,mt=160;if(mt=i.half_basal_exercise_target,v.isEnabled){const e=v.hbt;console.log("Half Basal Target used: "+n(e,i)+" "+i.out_units),mt=e}else console.log("Default Half Basal Target used: "+n(mt,i)+" "+i.out_units);if(lt&&i.temptargetSet&&rt>ut||i.low_temptarget_lowers_sensitivity&&i.temptargetSet&&rt=rt&&sensitivityRatio0&&(process.stderr.write("TDD-adjustment of basals activated, using tdd24h_14d_Ratio "+o(ye,2)+", TDD 24h = "+o(de,2)+"U, Weighted average TDD = "+o(L,2)+"U, (Weight percentage = "+Z+"), Total data of TDDs (up to 14 days) average = "+o($,2)+"U. "),$e!==Ze*z?process.stderr.write("Adjusting basal from "+Ze*z+" U/h to "+$e+" U/h; "):process.stderr.write("Basal unchanged: "+$e+" U/h; "))),i.temptargetSet);else if(void 0!==s&&s&&(i.sensitivity_raises_target&&s.ratio<1||i.resistance_lowers_target&&s.ratio>1)){ot=o((ot-60)/s.ratio)+60,nt=o((nt-60)/s.ratio)+60;var ct=o((rt-60)/s.ratio)+60;rt===(ct=Math.max(80,ct))?process.stderr.write("target_bg unchanged: "+n(ct,i)+"; "):process.stderr.write("target_bg from "+n(ct,i)+" to "+n(ct,i)+"; "),rt=ct}var gt=n(rt,i);rt!=f&&(gt=0!==b&&b!==rt?n(f,i)+"→"+n(b,i)+"→"+n(rt,i):n(f,i)+"→"+n(rt,i));var ht=200,pt=200,vt=200;if(e.noise>=2){var ft=Math.max(1.1,i.noisyCGMTargetMultiplier);Math.min(250,i.maxRaw);ht=o(Math.min(200,ot*ft)),pt=o(Math.min(200,rt*ft)),vt=o(Math.min(200,nt*ft)),process.stderr.write("Raising target_bg for noisy / raw CGM data, from "+n(ct,i)+" to "+n(pt,i)+"; "),ot=ht,rt=pt,nt=vt}var bt=ot-.5*(ot-40),Bt=i.threshold_setting;Bt>bt&&Bt<=120&&Bt>=65?(console.error("Threshold changed in settings from "+n(bt,i)+" to "+n(Bt,i)+". "),bt=Bt):console.error("Current threshold: "+n(bt,i));var Mt="",_t=(o(N,1),N);if(void 0!==s&&s&&((_t=o(_t=N/sensitivityRatio,1))!==N?process.stderr.write("ISF from "+n(N,i)+" to "+n(_t,i)):process.stderr.write("ISF unchanged: "+n(_t,i)),Mt+="Autosens ratio: "+o(sensitivityRatio,2)+", ISF: "+n(N,i)+"→"+n(_t,i)),console.error("CR:"+H),void 0===a)return Ne.error="Error: iob_data undefined. ",Ne;var yt,xt=a;if(a.length,a.length>1&&(a=xt[0]),void 0===a.activity||void 0===a.iob)return Ne.error="Error: iob_data missing some property. ",Ne;var St=((yt=void 0!==a.lastTemp?o((new Date(Je).getTime()-a.lastTemp.date)/6e4):0)+t.duration)%30;if(console.error("currenttemp:"+t.rate+" lastTempAge:"+yt+"m, tempModulus:"+St+"m"),Ne.temp="absolute",Ne.deliverAt=He,m&&t&&a.lastTemp&&t.rate!==a.lastTemp.rate&&yt>10&&t.duration)return Ne.reason="Warning: currenttemp rate "+t.rate+" != lastTemp rate "+a.lastTemp.rate+" from pumphistory; canceling temp",u.setTempBasal(0,0,i,Ne,t);if(t&&a.lastTemp&&t.duration>0){var wt=yt-a.lastTemp.duration;if(wt>5&&yt>10)return Ne.reason="Warning: currenttemp running but lastTemp from pumphistory ended "+wt+"m ago; canceling temp",u.setTempBasal(0,0,i,Ne,t)}var Dt=o(-a.activity*_t*5,2),Tt=o(6*(et-Dt));Tt<0&&(Tt=o(6*(tt-Dt)))<0&&(Tt=o(6*(e.long_avgdelta-Dt)));var Gt=Xe,Ct=(Gt=a.iob>0?o(Xe-a.iob*_t):o(Xe-a.iob*Math.min(_t,N)))+Tt;if(void 0===Ct||isNaN(Ct))return Ne.error="Error: could not calculate eventualBG. Sensitivity: "+_t+" Deviation: "+Tt,Ne;var Ut=function(e,t,a){return o(a+(e-t)/24,1)}(rt,Ct,Dt);Ne={temp:"absolute",bg:Xe,tick:Ke,eventualBG:Ct,insulinReq:0,reservoir:d,deliverAt:He,sensitivityRatio,TDD:de,insulin:ce,current_target:rt,insulinForManualBolus:C,manualBolusErrorString:""};var Ot=[],Rt=[],At=[],It=[];Ot.push(Xe),Rt.push(Xe),It.push(Xe),At.push(Xe);var Ft=function(e,t,a,r,o,i){return t?!e.allowSMB_with_high_temptarget&&e.temptargetSet&&o>100?(console.error("SMB disabled due to high temptarget of "+o),!1):!0===a.bwFound&&!1===e.A52_risk_enable?(console.error("SMB disabled due to Bolus Wizard activity in the last 6 hours."),!1):!0===e.enableSMB_always?(a.bwFound?console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled due to enableSMB_always"),!0):!0===e.enableSMB_with_COB&&a.mealCOB?(a.bwCarbs?console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for COB of "+a.mealCOB),!0):!0===e.enableSMB_after_carbs&&a.carbs?(a.bwCarbs?console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for 6h after carb entry"),!0):!0===e.enableSMB_with_temptarget&&e.temptargetSet&&o<100?(a.bwFound?console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for temptarget of "+n(o,e)),!0):!0===e.enableSMB_high_bg&&null!==i&&r>=i?(console.error("Checking BG to see if High for SMB enablement."),console.error("Current BG",r," | High BG ",i),a.bwFound?console.error("Warning: High BG SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("High BG detected. Enabling SMB."),!0):(console.error("SMB disabled (no enableSMB preferences active or no condition satisfied)"),!1):(console.error("SMB disabled (!microBolusAllowed)"),!1)}(i,m,l,Xe,rt,it);if(B)if(S){let e=c.getHours();e>=w&&e<=D&&(console.error("SMB disabled by schedule (a Profile is active with SMBs disabled)"),Ft=!1)}else console.error("SMBs are disabled (a Profile is active with SMBs disabled)"),Ft=!1;var jt=i.enableUAM,Pt=0,Et=0;Pt=o(et-Dt,1);var qt=o(et-Dt,1);csf=_t/H,console.error("profile.sens:"+n(N,i)+", sens:"+n(_t,i)+", CSF:"+o(csf,1));var Wt=o(30*csf*5/60,1);Pt>Wt&&(console.error("Limiting carb impact from "+Pt+" to "+Wt+"mg/dL/5m (30g/h)"),Pt=Wt);var kt=3;sensitivityRatio&&(kt/=sensitivityRatio);var Lt=kt;if(l.carbs){kt=Math.max(kt,l.mealCOB/20);var zt=o((new Date(Je).getTime()-l.lastCarbTime)/6e4),Nt=(l.carbs-l.mealCOB)/l.carbs;Lt=o(Lt=kt+1.5*zt/60,1),console.error("Last carbs "+zt+" minutes ago; remainingCATime:"+Lt+"hours; "+o(100*Nt,1)+"% carbs absorbed")}var Ht=Math.max(0,Pt/5*60*Lt/2)/csf,Zt=90,$t=1;i.remainingCarbsCap&&(Zt=Math.min(90,i.remainingCarbsCap)),i.remainingCarbsFraction&&($t=Math.min(1,i.remainingCarbsFraction));var Jt=1-$t,Kt=Math.max(0,l.mealCOB-Ht-l.carbs*Jt),Qt=(Kt=Math.min(Zt,Kt))*csf*5/60/(Lt/2),Vt=o(l.slopeFromMaxDeviation,2),Xt=o(l.slopeFromMinDeviation,2),Yt=Math.min(Vt,-Xt/3);Et=0===Pt?0:Math.min(60*Lt/5/2,Math.max(0,l.mealCOB*csf/Pt)),console.error("Carb Impact:"+Pt+"mg/dL per 5m; CI Duration:"+o(5*Et/60*2,1)+"hours; remaining CI ("+Lt/2+"h peak):"+o(Qt,1)+"mg/dL per 5m");var ea,ta,aa,ra,oa,na=999,ia=999,sa=999,la=Xe,ua=999,ma=999,da=999,ca=999,ga=Ct,ha=Xe,pa=Xe,va=0,fa=[],ba=[];try{xt.forEach((function(e){var t=o(-e.activity*_t*5,2),a=o(-e.iobWithZeroTemp.activity*_t*5,2),r=Gt,n=Pt*(1-Math.min(1,Rt.length/12));if(!0===(he&&!Ie))ga=Rt[Rt.length-1]+o(-e.activity*(1800/(P*be*Math.log(Math.max(Rt[Rt.length-1],39)/Re+1)))*5,2)+n,r=It[It.length-1]+o(-e.iobWithZeroTemp.activity*(1800/(P*be*Math.log(Math.max(It[It.length-1],39)/Re+1)))*5,2),console.log("Dynamic ISF (Logarithmic Formula) )adjusted predictions for IOB and ZT: IOBpredBG: "+o(ga,2)+" , ZTpredBG: "+o(r,2));else ga=Rt[Rt.length-1]+t+n,r=It[It.length-1]+a;var i=Math.max(0,Math.max(0,Pt)*(1-Ot.length/Math.max(2*Et,1))),s=Math.min(Ot.length,12*Lt-Ot.length),l=Math.max(0,s/(Lt/2*12)*Qt);i+l,fa.push(o(l,0)),ba.push(o(i,0)),COBpredBG=Ot[Ot.length-1]+t+Math.min(0,n)+i+l;var u=Math.max(0,qt+At.length*Yt),m=Math.max(0,qt*(1-At.length/Math.max(36,1))),d=Math.min(u,m);if(d>0&&(va=o(5*(At.length+1)/60,1)),!0===(he&&!Ie))UAMpredBG=At[At.length-1]+o(-e.activity*(1800/(P*be*Math.log(Math.max(At[At.length-1],39)/Re+1)))*5,2)+Math.min(0,n)+d,console.log("Dynamic ISF (Logarithmic Formula) adjusted prediction for UAM: UAMpredBG: "+o(UAMpredBG,2));else UAMpredBG=At[At.length-1]+t+Math.min(0,n)+d;Rt.length<48&&Rt.push(ga),Ot.length<48&&Ot.push(COBpredBG),At.length<48&&At.push(UAMpredBG),It.length<48&&It.push(r),COBpredBG18&&gaha&&(ha=ga),(Et||Qt>0)&&Ot.length>18&&COBpredBG0)&&COBpredBG>ha&&(pa=COBpredBG),jt&&At.length>12&&UAMpredBGha&&UAMpredBG}))}catch(e){console.error("Problem with iobArray. Optional feature Advanced Meal Assist disabled")}l.mealCOB&&(console.error("predCIs (mg/dL/5m):"+ba.join(" ")),console.error("remainingCIs: "+fa.join(" "))),Ne.predBGs={},Rt.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))}));for(var Ba=Rt.length-1;Ba>12&&Rt[Ba-1]===Rt[Ba];Ba--)Rt.pop();for(Ne.predBGs.IOB=Rt,aa=o(Rt[Rt.length-1]),It.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),Ba=It.length-1;Ba>6&&!(It[Ba-1]>=It[Ba]||It[Ba]<=rt);Ba--)It.pop();if(Ne.predBGs.ZT=It,o(It[It.length-1]),l.mealCOB>0&&(Pt>0||Qt>0)){for(Ot.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),Ba=Ot.length-1;Ba>12&&Ot[Ba-1]===Ot[Ba];Ba--)Ot.pop();Ne.predBGs.COB=Ot,ra=o(Ot[Ot.length-1]),Ct=Math.max(Ct,o(Ot[Ot.length-1]))}if(Pt>0||Qt>0){if(jt){for(At.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),Ba=At.length-1;Ba>12&&At[Ba-1]===At[Ba];Ba--)At.pop();Ne.predBGs.UAM=At,oa=o(At[At.length-1]),At[At.length-1]&&(Ct=Math.max(Ct,o(At[At.length-1])))}Ne.eventualBG=Ct}console.error("UAM Impact:"+qt+"mg/dL per 5m; UAM Duration:"+va+"hours"),na=Math.max(39,na),ia=Math.max(39,ia),sa=Math.max(39,sa),ea=o(na);var Ma=l.mealCOB/l.carbs;ta=o(sa<999&&ia<999?(1-Ma)*UAMpredBG+Ma*COBpredBG:ia<999?(ga+COBpredBG)/2:sa<999?(ga+UAMpredBG)/2:ga),ca>ta&&(ta=ca),la=o(la=Et||Qt>0?jt?Ma*ua+(1-Ma)*ma:ua:jt?ma:da);var _a=sa;if(casa&&(_a=(sa+ca)/2);if(_a=o(_a),l.carbs)if(!jt&&ia<999)ea=o(Math.max(na,ia));else if(ia<999){var xa=Ma*ia+(1-Ma)*_a;ea=o(Math.max(na,ia,xa))}else ea=jt?_a:la;else jt&&(ea=o(Math.max(na,_a)));ea=Math.min(ea,ta),process.stderr.write("minPredBG: "+ea+" minIOBPredBG: "+na+" minZTGuardBG: "+ca),ia<999&&process.stderr.write(" minCOBPredBG: "+ia),sa<999&&process.stderr.write(" minUAMPredBG: "+sa),console.error(" avgPredBG:"+ta+" COB/Carbs:"+l.mealCOB+"/"+l.carbs),pa>Xe&&(ea=Math.min(ea,pa)),Ne.COB=l.mealCOB,Ne.IOB=a.iob,Ne.BGI=n(Dt,i),Ne.deviation=n(Tt,i),Ne.ISF=n(_t,i),Ne.CR=o(H,1),Ne.target_bg=n(rt,i),Ne.TDD=o(de,2),Ne.current_target=o(rt,0);var Sa=Ne.CR;We!=Ne.CR&&(Sa=We+"→"+Ne.CR),Ne.reason=Mt+", COB: "+Ne.COB+", Dev: "+Ne.deviation+", BGI: "+Ne.BGI+", CR: "+Sa+", Target: "+gt+", minPredBG "+n(ea,i)+", minGuardBG "+n(la,i)+", IOBpredBG "+n(aa,i),ra>0&&(Ne.reason+=", COBpredBG "+n(ra,i)),oa>0&&(Ne.reason+=", UAMpredBG "+n(oa,i)),Ne.reason+=tddReason,Ne.reason+="; ";var wa=Gt;wa<40&&(wa=Math.min(la,wa));var Da,Ta=bt-wa,Ga=240,Ca=240;if(l.mealCOB>0&&(Pt>0||Qt>0)){for(Ba=0;BaDa*Xe&&(console.error("maxDelta "+n(at,i)+" > "+100*Da+"% of BG "+n(Xe,i)+" - disabling SMB"),Ne.reason+="maxDelta "+n(at,i)+" > "+100*Da+"% of BG "+n(Xe,i)+" - SMB disabled!, ",Ft=!1),console.error("BG projected to remain above "+n(ot,i)+" for "+Ga+"minutes"),(Ca<240||Ga<60)&&console.error("BG projected to remain above "+n(bt,i)+" for "+Ca+"minutes");var Ua=Ca,Oa=i.current_basal*z*_t*Ua/60,Ra=Math.max(0,l.mealCOB-.25*l.carbs),Aa=(Ta-Oa)/csf-Ra;Oa=o(Oa),Aa=o(Aa),console.error("naive_eventualBG:",Gt,"bgUndershoot:",Ta,"zeroTempDuration:",Ua,"zeroTempEffect:",Oa,"carbsReq:",Aa),"Could not parse clock data"==l.reason?console.error("carbsReq unknown: Could not parse clock data"):Aa>=i.carbsReqThreshold&&Ca<=45&&(Ne.carbsReq=Aa,Ne.reason+=Aa+" add'l carbs req w/in "+Ca+"m; ");var Ia=0;if(Xe0&&et>Ut)Ne.reason+="IOB "+a.iob+" < "+o(-i.current_basal*z*20/60,2),Ne.reason+=" and minDelta "+n(et,i)+" > expectedDelta "+n(Ut,i)+"; ";else if(Xe=55)return Ne.reason+="; Canceling temp at "+Ne.deliverAt.getMinutes()+"m past the hour. ",u.setTempBasal(0,0,i,Ne,t);var Fa=0,ja=$e,Pa=0;if(CtUt&&et>0&&!Aa)return Gt<40?(Ne.reason+=", naive_eventualBG < 40. ",u.setTempBasal(0,30,i,Ne,t)):(e.delta>et?Ne.reason+=", but Delta "+n(Ke,i)+" > expectedDelta "+n(Ut,i):Ne.reason+=", but Min. Delta "+et.toFixed(2)+" > Exp. Delta "+n(Ut,i),t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",u.setTempBasal($e,30,i,Ne,t)));Fa=o(Fa=2*Math.min(0,(Ct-rt)/_t),2);var Ea=Math.min(0,(Gt-rt)/_t);if(Ea=o(Ea,2),et<0&&et>Ut)Fa=o(Fa*(et/Ut),2);ja=r(ja=$e+2*Fa,i),Pa=t.duration*(t.rate-$e)/60;var qa=Math.min(Fa,Ea);if(console.log("naiveInsulinReq:"+Ea),Pa5&&ja>=.8*t.rate)return Ne.reason+=", temp "+t.rate+" ~< req "+ja+"U/hr. ",Ne;if(ja<=0){if((Ia=o(60*((Ta=rt-Gt)/_t)/i.current_basal*z))<0?Ia=0:(Ia=30*o(Ia/30),Ia=Math.min(120,Math.max(0,Ia))),Ia>0)return Ne.reason+=", setting "+Ia+"m zero temp. ",u.setTempBasal(ja,Ia,i,Ne,t)}else Ne.reason+=", setting "+ja+"U/hr. ";return u.setTempBasal(ja,30,i,Ne,t)}if(et Target Glucose, but glucose is falling faster than expected. Expected: "+Ut+". Falling: "+et,Ne.insulinForManualBolus=o((Ne.eventualBG-Ne.target_bg)/_t,2),!m||!Ft))return e.delta "+n(ot,i)+" but Delta "+n(Ke,i)+" < Exp. Delta "+n(Ut,i):Ne.reason+="Eventual BG "+n(Ct,i)+" > "+n(ot,i)+" but Min. Delta "+et.toFixed(2)+" < Exp. Delta "+n(Ut,i),t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",u.setTempBasal($e,30,i,Ne,t));if(Math.min(Ct,ea)ot&&(Ne.manualBolusErrorString="Minimum predicted Glucose is "+n(ea,i)+" "+i.out_units,Ne.insulinForManualBolus=o((Ne.eventualBG-Ne.target_bg)/_t,2)),!m||!Ft))return Ne.reason+=n(Ct,i)+"-"+n(ea,i)+" in range: no temp required",t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",u.setTempBasal($e,30,i,Ne,t));if(Ct>=nt&&(Ne.reason+="Eventual BG "+n(Ct,i)+" >= "+n(nt,i)+", "),a.iob>st)return Ne.reason+="IOB "+o(a.iob,2)+" > max_iob "+st,t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",u.setTempBasal($e,30,i,Ne,t));Fa=o((Math.min(ea,Ct)-rt)/_t,2),C=o((Ct-rt)/_t,2),Fa>st-a.iob?(console.error("SMB limited by maxIOB: "+st-a.iob+" (. insulinReq: "+Fa+" U)"),Ne.reason+="max_iob "+st+", ",Fa=st-a.iob):console.error("SMB not limited by maxIOB ( insulinReq: "+Fa+" U)."),C>st-a.iob?(console.error("Ev. Bolus limited by maxIOB: "+st-a.iob+" (. insulinForManualBolus: "+C+" U)"),Ne.reason+="max_iob "+st+", ",C=st-a.iob):console.error("Ev. Bolus would not be limited by maxIOB ( insulinForManualBolus: "+C+" U)."),ja=r(ja=$e+2*Fa,i),Fa=o(Fa,3),Ne.insulinReq=Fa,Ne.insulinForManualBolus=o(C,3);var Wa=o((new Date(Je).getTime()-a.lastBolusTime)/6e4,1);if(m&&Ft&&Xe>bt){var ka=30;void 0!==i.maxSMBBasalMinutes&&(ka=i.maxSMBBasalMinutes);var La=30;void 0!==i.maxUAMSMBBasalMinutes&&(La=i.maxUAMSMBBasalMinutes),v.useOverride&&M&&T!==ka&&(console.error("SMB Max Minutes - setting overriden from "+ka+" to "+T),ka=T),v.useOverride&&M&&G!==La&&(console.error("UAM Max Minutes - setting overriden from "+La+" to "+G),La=G);var za=o(l.mealCOB/H,3),Na=0;void 0===ka?(Na=o(i.current_basal*z*30/60,1),console.error("smbMinutesSetting undefined: defaulting to 30m"),Fa>Na&&console.error("SMB limited by maxBolus: "+Na+" ( "+Fa+" U)")):a.iob>za&&a.iob>0?(console.error("IOB"+a.iob+"> COB"+l.mealCOB+"; mealInsulinReq ="+za),La?(console.error("maxUAMSMBBasalMinutes: "+La+", profile.current_basal: "+i.current_basal*z),Na=o(i.current_basal*z*La/60,1)):(console.error("maxUAMSMBBasalMinutes undefined: defaulting to 30m"),Na=o(i.current_basal*z*30/60,1)),Fa>Na?console.error("SMB limited by maxUAMSMBBasalMinutes [ "+La+"m ]: "+Na+"U ( "+Fa+"U )"):console.error("SMB is not limited by maxUAMSMBBasalMinutes. ( insulinReq: "+Fa+"U )")):(console.error(".maxSMBBasalMinutes: "+ka+", profile.current_basal: "+i.current_basal*z),Fa>(Na=o(i.current_basal*ka/60,1))?console.error("SMB limited by maxSMBBasalMinutes: "+ka+"m ]: "+Na+"U ( insulinReq: "+Fa+"U )"):console.error("SMB is not limited by maxSMBBasalMinutes. ( insulinReq: "+Fa+"U )"));var Ha=i.bolus_increment,Za=1/Ha,$a=i.smb_delivery_ratio;$a>.5&&console.error("SMB Delivery Ratio increased from default 0.5 to "+o($a,2));var Ja=Math.min(Fa*$a,Na);Ja=Math.floor(Ja*Za)/Za,Ia=o(60*((rt-(Gt+na)/2)/_t)/i.current_basal*z),Fa>0&&Ja=30?(Ia=30*o(Ia/30),Ia=Math.min(60,Math.max(0,Ia))):(Ka=o($e*Ia/30,2),Ia=30),Ne.reason+=" insulinReq "+Fa,Ja>=Na&&(Ne.reason+="; maxBolus "+Na),Ia>0&&(Ne.reason+="; setting "+Ia+"m low temp of "+Ka+"U/h"),Ne.reason+=". ";var Qa=3;i.SMBInterval&&(Qa=Math.min(10,Math.max(1,i.SMBInterval)));var Va=o(Qa-Wa,0),Xa=o(60*(Qa-Wa),0)%60;if(console.error("naive_eventualBG "+Gt+","+Ia+"m "+Ka+"U/h temp needed; last bolus "+Wa+"m ago; maxBolus: "+Na),Wa>Qa?Ja>0&&(Ne.units=Ja,Ne.reason+="Microbolusing "+Ja+"U. "):Ne.reason+="Waiting "+Va+"m "+Xa+"s to microbolus again. ",Ia>0)return Ne.rate=Ka,Ne.duration=Ia,Ne}var Ya=u.getMaxSafeBasal(i);return ja>Ya&&(Ne.reason+="adj. req. rate: "+ja+" to maxSafeBasal: "+o(Ya,2)+", ",ja=r(Ya,i)),(Pa=t.duration*(t.rate-$e)/60)>=2*Fa?(Ne.reason+=t.duration+"m@"+t.rate.toFixed(2)+" > 2 * insulinReq. Setting temp basal of "+ja+"U/hr. ",u.setTempBasal(ja,30,i,Ne,t)):void 0===t.duration||0===t.duration?(Ne.reason+="no temp, setting "+ja+"U/hr. ",u.setTempBasal(ja,30,i,Ne,t)):t.duration>5&&r(ja,i)<=r(t.rate,i)?(Ne.reason+="temp "+t.rate+" >~ req "+ja+"U/hr. ",Ne):(Ne.reason+="temp "+t.rate+"<"+ja+"U/hr. ",u.setTempBasal(ja,30,i,Ne,t))}},6880:(e,t,a)=>{var r=a(6654);e.exports=function(e,t){var a=20;void 0!==t&&"string"==typeof t.model&&(r(t.model,"54")||r(t.model,"23"))&&(a=40);return e<1?Math.round(e*a)/a:e<10?Math.round(20*e)/20:Math.round(10*e)/10}},2705:(e,t,a)=>{var r=a(5639).Symbol;e.exports=r},9932:e=>{e.exports=function(e,t){for(var a=-1,r=null==e?0:e.length,o=Array(r);++a{e.exports=function(e,t,a){return e==e&&(void 0!==a&&(e=e<=a?e:a),void 0!==t&&(e=e>=t?e:t)),e}},4239:(e,t,a)=>{var r=a(2705),o=a(9607),n=a(2333),i=r?r.toStringTag:void 0;e.exports=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":i&&i in Object(e)?o(e):n(e)}},531:(e,t,a)=>{var r=a(2705),o=a(9932),n=a(1469),i=a(3448),s=r?r.prototype:void 0,l=s?s.toString:void 0;e.exports=function e(t){if("string"==typeof t)return t;if(n(t))return o(t,e)+"";if(i(t))return l?l.call(t):"";var a=t+"";return"0"==a&&1/t==-Infinity?"-0":a}},7561:(e,t,a)=>{var r=a(7990),o=/^\s+/;e.exports=function(e){return e?e.slice(0,r(e)+1).replace(o,""):e}},1957:(e,t,a)=>{var r="object"==typeof a.g&&a.g&&a.g.Object===Object&&a.g;e.exports=r},9607:(e,t,a)=>{var r=a(2705),o=Object.prototype,n=o.hasOwnProperty,i=o.toString,s=r?r.toStringTag:void 0;e.exports=function(e){var t=n.call(e,s),a=e[s];try{e[s]=void 0;var r=!0}catch(e){}var o=i.call(e);return r&&(t?e[s]=a:delete e[s]),o}},2333:e=>{var t=Object.prototype.toString;e.exports=function(e){return t.call(e)}},5639:(e,t,a)=>{var r=a(1957),o="object"==typeof self&&self&&self.Object===Object&&self,n=r||o||Function("return this")();e.exports=n},7990:e=>{var t=/\s/;e.exports=function(e){for(var a=e.length;a--&&t.test(e.charAt(a)););return a}},6654:(e,t,a)=>{var r=a(9750),o=a(531),n=a(554),i=a(9833);e.exports=function(e,t,a){e=i(e),t=o(t);var s=e.length,l=a=void 0===a?s:r(n(a),0,s);return(a-=t.length)>=0&&e.slice(a,l)==t}},1469:e=>{var t=Array.isArray;e.exports=t},3218:e=>{e.exports=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}},7005:e=>{e.exports=function(e){return null!=e&&"object"==typeof e}},3448:(e,t,a)=>{var r=a(4239),o=a(7005);e.exports=function(e){return"symbol"==typeof e||o(e)&&"[object Symbol]"==r(e)}},8601:(e,t,a)=>{var r=a(4841),o=1/0;e.exports=function(e){return e?(e=r(e))===o||e===-1/0?17976931348623157e292*(e<0?-1:1):e==e?e:0:0===e?e:0}},554:(e,t,a)=>{var r=a(8601);e.exports=function(e){var t=r(e),a=t%1;return t==t?a?t-a:t:0}},4841:(e,t,a)=>{var r=a(7561),o=a(3218),n=a(3448),i=/^[-+]0x[0-9a-f]+$/i,s=/^0b[01]+$/i,l=/^0o[0-7]+$/i,u=parseInt;e.exports=function(e){if("number"==typeof e)return e;if(n(e))return NaN;if(o(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=o(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=r(e);var a=s.test(e);return a||l.test(e)?u(e.slice(2),a?2:8):i.test(e)?NaN:+e}},9833:(e,t,a)=>{var r=a(531);e.exports=function(e){return null==e?"":r(e)}}},t={};function a(r){var o=t[r];if(void 0!==o)return o.exports;var n=t[r]={exports:{}};return e[r](n,n.exports,a),n.exports}a.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}();var r=a(5546);freeaps_determineBasal=r})(); \ No newline at end of file diff --git a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings index c5ab5711d4..39f9f01924 100644 --- a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings @@ -1278,6 +1278,35 @@ Enact a temp Basal or a temp target */ /* */ "Save as Preset" = "Save as Preset"; +/* ----------------------- New Bolus Calculator ---------------------------*/ + +/* Warning about bolus recommendation. Title */ +"Warning!" = "Warning!"; + +/* Alert to confirm bolus amount to add */ +"\n\nTap 'Add' to continue with selected amount." = "\n\nTap 'Add' to continue with selected amount."; + +/* */ +"Eventual Glucose" = "Eventual Glucose"; + +/* */ +"Target Glucose" = "Target Glucose"; + +/* */ +"Percentage setting" = "Percentage setting"; + +/* */ +"Insulin Sensitivity" = "Insulin Sensitivity"; + +/* Formuala displayed in Bolus info pop-up*/ +"(Eventual Glucose - Target) / ISF =" = "(Eventual Glucose - Target) / ISF ="; + +/* Bolus pop-up footer */ +"Carbs and previous insulin are included in the glucose prediction, but if the Eventual Glucose is lower than the Target Glucose, a bolus will not be recommended." = "Carbs and previous insulin are included in the glucose prediction, but if the Eventual Glucose is lower than the Target Glucose, a bolus will not be recommended."; + +/* Hide pop-up */ +"Hide" = "Hide"; + /* ------------------------------------------------------------------------------------------- DASH strings */ diff --git a/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings index 586a798132..87e52d54f9 100644 --- a/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings @@ -1278,6 +1278,35 @@ Enact a temp Basal or a temp target */ /* */ "Save as Preset" = "Spara som förval"; +/* ----------------------- New Bolus Calculator ---------------------------*/ + +/* Warning about bolus recommendation. Title */ +"Warning!" = "Varning!"; + +/* Alert to confirm bolus amount to add */ +"\n\nTap 'Add' to continue with selected amount." = "\n\nTryck 'Lägg till' för att fylla i bolusmängd."; + +/* */ +"Eventual Glucose" = "Blodsockerprognos"; + +/* */ +"Target Glucose" = "Målvärde"; + +/* */ +"Percentage setting" = "Bolusprocentinställning"; + +/* */ +"Insulin Sensitivity" = "Insulinkänslighet"; + +/* Formuala displayed in Bolus info pop-up. Make translation short! */ +"(Eventual Glucose - Target) / ISF =" = "(Blodsockerprognos - Målvärde) / ISF ="; + +/* Bolus pop-up footer */ +"Carbs and previous insulin are included in the glucose prediction, but if the Eventual Glucose is lower than the Target Glucose, a bolus will not be recommended." = "Kolhydrater och tidigare insulin ingår i prognos, men om prognos är lägre än målvärde kommer ingen bolus att föreslås."; + +/* Hide pop-up */ +"Hide" = "Göm"; + /* ------------------------------------------------------------------------------------------- DASH strings */ diff --git a/FreeAPS/Sources/Models/Suggestion.swift b/FreeAPS/Sources/Models/Suggestion.swift index c75ee7f252..25d074a946 100644 --- a/FreeAPS/Sources/Models/Suggestion.swift +++ b/FreeAPS/Sources/Models/Suggestion.swift @@ -23,6 +23,7 @@ struct Suggestion: JSON, Equatable { let insulin: Insulin? let current_target: Decimal? let insulinForManualBolus: Decimal? + let manualBolusErrorString: String? } struct Predictions: JSON, Equatable { @@ -63,6 +64,7 @@ extension Suggestion { case insulin case current_target case insulinForManualBolus + case manualBolusErrorString } } diff --git a/FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift b/FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift index 16c78ba200..6491b121df 100644 --- a/FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift +++ b/FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift @@ -12,12 +12,24 @@ extension Bolus { @Published var insulinRequired: Decimal = 0 @Published var waitForSuggestion: Bool = false @Published var manual: Bool = false + @Published var error: Bool = false + @Published var errorString: String = "" + + @Published var evBG: Int = 0 + @Published var insulin: Decimal = 0 + @Published var target: Decimal = 0 + @Published var isf: Decimal = 0 + @Published var percentage: Decimal = 0 + + @Published var units: GlucoseUnits = .mmolL var waitForSuggestionInitial: Bool = false override func subscribe() { setupInsulinRequired() broadcaster.register(SuggestionObserver.self, observer: self) + units = settingsManager.settings.units + percentage = settingsManager.settings.insulinReqPercentage if waitForSuggestionInitial { apsManager.determineBasal() @@ -76,21 +88,21 @@ extension Bolus { func setupInsulinRequired() { DispatchQueue.main.async { - // Manual Bolus recommendation screen after a carb entry (normally) yields a higher amount than the insulin reqiured amount computed for SMBs (auto boluses). Carbs combined with a manual bolus threfore now (test) uses the Eventual BG for glucose prediction, whereas the insulinReg for SMBs (and for manual boluses not combined with a carb entry) uses the minPredBG for glucose prediction (typically lower than Eventual BG). + self.insulinRequired = self.provider.suggestion?.insulinReq ?? 0 - if self.manual { - self.insulinRequired = self.provider.suggestion?.insulinForManualBolus ?? 0 + // Manual Bolus recommendation screen after a carb entry (normally) yields a higher amount than the insulin reqiured amount computed for SMBs (auto boluses). Carbs combined with a manual bolus threfore now (test) uses the Eventual BG for glucose prediction, whereas the insulinReg for SMBs uses the minPredBG for glucose prediction (typically lower than Eventual BG). - if self.settingsManager.settings.insulinReqPercentage != 100 { - self.insulinRecommended = self - .insulinRequired * (self.settingsManager.settings.insulinReqPercentage / 100) - } else { self.insulinRecommended = self.insulinRequired } + self.evBG = self.provider.suggestion?.eventualBG ?? 0 + self.insulin = self.provider.suggestion?.insulinForManualBolus ?? 0 + self.target = self.provider.suggestion?.current_target ?? 0 + self.isf = self.provider.suggestion?.isf ?? 0 - } else { - self.insulinRequired = self.provider.suggestion?.insulinReq ?? 0 - self.insulinRecommended = self - .insulinRequired * (self.settingsManager.settings.insulinReqPercentage / 100) * 2 - } + if self.settingsManager.settings.insulinReqPercentage != 100 { + self.insulinRecommended = self.insulin * (self.settingsManager.settings.insulinReqPercentage / 100) + } else { self.insulinRecommended = self.insulin } + + self.errorString = self.provider.suggestion?.manualBolusErrorString ?? "" + if self.errorString.count > 8 { self.error = true } self.insulinRecommended = self.apsManager .roundBolus(amount: max(self.insulinRecommended, 0)) diff --git a/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift b/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift index 778011dab2..d6647203a8 100644 --- a/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift +++ b/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift @@ -8,6 +8,10 @@ extension Bolus { let manualBolus: Bool @StateObject var state = StateModel() @State private var isAddInsulinAlertPresented = false + @State private var presentInfo = false + @State private var displayError = false + + @Environment(\.colorScheme) var colorScheme private var formatter: NumberFormatter { let formatter = NumberFormatter() @@ -26,45 +30,25 @@ extension Bolus { ActivityIndicator(isAnimating: .constant(true), style: .medium) // fix iOS 15 bug } } else { - if state.manual { - HStack { - Text("Insulin recommended") - Spacer() - Text( - formatter - .string(from: state.insulinRecommended as NSNumber)! + - NSLocalizedString(" U", comment: "Insulin unit") - ).foregroundColor(.secondary) - }.contentShape(Rectangle()) - .onTapGesture { - state.amount = state.insulinRecommended - } - } else { - HStack { - Text("Insulin required").foregroundColor(.secondary) - Spacer() - Text( - formatter - .string(from: state.insulinRequired as NSNumber)! + - NSLocalizedString(" U", comment: "Insulin unit") - ).foregroundColor(.secondary) - }.contentShape(Rectangle()) - .onTapGesture { - state.amount = state.insulinRequired - } - - HStack { - Text("Insulin recommended") - Spacer() - Text( - formatter - .string(from: state.insulinRecommended as NSNumber)! + - NSLocalizedString(" U", comment: "Insulin unit") - ).foregroundColor(.secondary) - }.contentShape(Rectangle()) - .onTapGesture { - state.amount = state.insulinRecommended - } + HStack { + Text("Insulin recommended") + Spacer() + Text( + formatter + .string(from: state.insulinRecommended as NSNumber)! + + NSLocalizedString(" U", comment: "Insulin unit") + ).foregroundColor((state.error && state.insulinRecommended > 0) ? .red : .secondary) + }.contentShape(Rectangle()) + .onTapGesture { + if state.error, state.insulinRecommended > 0 { displayError = true } + else { state.amount = state.insulinRecommended } + } + HStack { + Image(systemName: "info.bubble").symbolRenderingMode(.palette).foregroundStyle( + .primary, .blue + ) + }.onTapGesture { + presentInfo.toggle() } } } @@ -118,6 +102,23 @@ extension Bolus { secondaryButton: .cancel() ) } + .alert(isPresented: $displayError) { + Alert( + title: Text("Warning!"), + message: Text("\n" + state.errorString + NSLocalizedString( + "\n\nTap 'Add' to continue with selected amount.", + comment: "Alert text to confirm bolus amount to add" + )), + primaryButton: .destructive( + Text("Add"), + action: { + state.amount = state.insulinRecommended + displayError = false + } + ), + secondaryButton: .cancel() + ) + } .onAppear { configureView { state.waitForSuggestionInitial = waitForSuggestion @@ -128,6 +129,102 @@ extension Bolus { .navigationTitle("Enact Bolus") .navigationBarTitleDisplayMode(.automatic) .navigationBarItems(leading: Button("Close", action: state.hideModal)) + .popup(isPresented: presentInfo, alignment: .center, direction: .bottom) { + bolusInfo + } + } + + var bolusInfo: some View { + VStack { + // Variables + VStack(spacing: 3) { + HStack { + Text("Eventual Glucose").foregroundColor(.secondary) + let evg = state.units == .mmolL ? Decimal(state.evBG).asMmolL : Decimal(state.evBG) + let fractionDigit = state.units == .mmolL ? 1 : 0 + Text(evg.formatted(.number.grouping(.never).rounded().precision(.fractionLength(fractionDigit)))) + Text(state.units.rawValue).foregroundColor(.secondary) + } + HStack { + Text("Target Glucose").foregroundColor(.secondary) + let target = state.units == .mmolL ? state.target.asMmolL : state.target + let fractionDigit = state.units == .mmolL ? 1 : 0 + Text(target.formatted(.number.grouping(.never).rounded().precision(.fractionLength(fractionDigit)))) + Text(state.units.rawValue).foregroundColor(.secondary) + } + HStack { + Text("ISF").foregroundColor(.secondary) + let isf = state.isf + Text(isf.formatted()) + Text(state.units.rawValue + NSLocalizedString("/U", comment: "/Insulin unit")) + .foregroundColor(.secondary) + } + HStack { + Text("ISF:") + Text("Insulin Sensitivity") + }.foregroundColor(.secondary).italic() + if state.percentage != 100 { + HStack { + Text("Percentage setting").foregroundColor(.secondary) + let percentage = state.percentage + Text(percentage.formatted()) + Text("%").foregroundColor(.secondary) + } + } + } + .font(.footnote) + .padding(.top, 10) + Divider() + // Formula + VStack(spacing: 5) { + let unit = NSLocalizedString( + " U", + comment: "Unit in number of units delivered (keep the space character!)" + ) + Text("(Eventual Glucose - Target) / ISF =").font(.callout).italic() + let color: Color = (state.percentage != 100 && state.insulin > 0) ? .secondary : .blue + let fontWeight: Font.Weight = (state.percentage != 100 && state.insulin > 0) ? .regular : .bold + HStack { + Text(" = ").font(.callout) + Text(state.insulin.formatted() + unit).font(.callout).foregroundColor(color).fontWeight(fontWeight) + } + if state.percentage != 100, state.insulin > 0 { + Divider() + HStack { Text(state.percentage.formatted() + " % ->").font(.callout).foregroundColor(.secondary) + Text( + state.insulinRecommended.formatted() + unit + ).font(.callout).foregroundColor(.blue).bold() + } + } + } + // Warning + VStack { + Divider() + if state.error, state.insulinRecommended > 0 { + Text("Warning!").font(.callout).foregroundColor(.orange).bold() + Text(state.errorString).font(.caption) + Divider() + } + }.padding(.horizontal, 10) + // Footer. Warning string . + if !(state.error && state.insulinRecommended > 0) { + VStack { + Text( + "Carbs and previous insulin are included in the glucose prediction, but if the Eventual Glucose is lower than the Target Glucose, a bolus will not be recommended." + ).font(.caption2).foregroundColor(.secondary) + }.padding(20) + } + // Hide button + VStack { + Button { presentInfo = false } + label: { Text("Hide") }.frame(maxWidth: .infinity, alignment: .center).font(.callout) + .foregroundColor(.blue) + }.padding(.bottom, 10) + } + .background( + RoundedRectangle(cornerRadius: 8, style: .continuous) + .fill(Color(colorScheme == .dark ? UIColor.systemGray4 : UIColor.systemGray4)) + ) } } } From 5792fb98b38f2b7fcb2ee29b923ebdd4764c7856 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Mon, 12 Jun 2023 11:32:56 +0200 Subject: [PATCH 31/45] Allow for larger range for low/high settings in stats and Home View (cherry picked from commit debb8a2690992489266bd9e29f5e2b4ddf032ad6) --- FreeAPS/Sources/Modules/StatConfig/StatConfigStateModel.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FreeAPS/Sources/Modules/StatConfig/StatConfigStateModel.swift b/FreeAPS/Sources/Modules/StatConfig/StatConfigStateModel.swift index 7c28b6a9b6..e645853317 100644 --- a/FreeAPS/Sources/Modules/StatConfig/StatConfigStateModel.swift +++ b/FreeAPS/Sources/Modules/StatConfig/StatConfigStateModel.swift @@ -26,7 +26,7 @@ extension StatConfig { subscribeSetting(\.oneDimensionalGraph, on: $oneDimensionalGraph) { oneDimensionalGraph = $0 } subscribeSetting(\.low, on: $low, initial: { - let value = max(min($0, 120), 40) + let value = max(min($0, 90), 40) low = units == .mmolL ? value.asMmolL : value }, map: { guard units == .mmolL else { return $0 } @@ -34,7 +34,7 @@ extension StatConfig { }) subscribeSetting(\.high, on: $high, initial: { - let value = max(min($0, 270), 130) + let value = max(min($0, 270), 110) high = units == .mmolL ? value.asMmolL : value }, map: { guard units == .mmolL else { return $0 } From e6ad164f4214aa8e7a916e3378bdaa7b789a22fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Mon, 12 Jun 2023 11:15:33 +0200 Subject: [PATCH 32/45] More error strings. (cherry picked from commit ef1312593b78ff4ae7f96a33fe9f9ec4a83c590d) --- .../Resources/javascript/bundle/determine-basal.js | 2 +- .../Localizations/Main/en.lproj/Localizable.strings | 12 ++++++++++++ .../Localizations/Main/sv.lproj/Localizable.strings | 12 ++++++++++++ .../Sources/Modules/Bolus/View/BolusRootView.swift | 4 ++-- 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/FreeAPS/Resources/javascript/bundle/determine-basal.js b/FreeAPS/Resources/javascript/bundle/determine-basal.js index 644ce39391..332954314b 100644 --- a/FreeAPS/Resources/javascript/bundle/determine-basal.js +++ b/FreeAPS/Resources/javascript/bundle/determine-basal.js @@ -1 +1 @@ -var freeaps_determineBasal;(()=>{var e={5546:(e,t,a)=>{var r=a(6880);function o(e,t){t||(t=0);var a=Math.pow(10,t);return Math.round(e*a)/a}function n(e,t){return"mmol/L"===t.out_units?o(.0555*e,1):Math.round(e)}e.exports=function(e,t,a,i,s,l,u,m,d,c,g,h,p,v){var f=i.min_bg,b=v.overrideTarget;const B=v.smbIsOff,M=v.advancedSettings,_=v.isfAndCr,y=v.isf,x=v.cr,S=v.smbIsAlwaysOff,w=v.start,D=v.end,T=v.smbMinutes,G=v.uamMinutes;var C=0,U=0,O="",R="",A="",I="",F="",j=0,P=0,E=0,q=0,W=0,k=0;const L=v.weightedAverage;var z=1,N=i.sens,H=i.carb_ratio;v.useOverride&&(z=v.overridePercentage/100,_?(N/=z,H/=z):(x&&(H/=z),y&&(N/=z)));const Z=i.weightPercentage,$=v.average_total_data;function J(e,t){var a=e.getTime();return new Date(a+36e5*t)}function K(e){var t=i.bolus_increment;.025!=t&&(t=.05);var a=e/t;return a>=1?o(Math.floor(a)*t,5):0}function Q(e){function t(e){return e<10&&(e="0"+e),e}return t(e.getHours())+":"+t(e.getMinutes())+":00"}function V(e,t){var a=new Date("1/1/1999 "+e),r=new Date("1/1/1999 "+t);return(a.getTime()-r.getTime())/36e5}function X(e,t){var a=0,r=t,o=(e-t)/36e5,n=0,i=o,s=0;do{if(o>0){var l=Q(r),u=p[0].rate;for(let e=0;e=(s=V(p[e+1].start,p[e].start))?n=s:o=s?n=s:om)if(e+1=(s=V(d,l))?n=s:o=(s=V("23:59:59",l))?n=s:o0&&o21)W=X(Y,(te=24-U,ae=Y.getTime(),new Date(ae-36e5*te))),I="24 hours of data is required for an accurate tdd calculation. Currently only "+U.toPrecision(3)+" hours of pump history data are available. Using your pump scheduled basals to fill in the missing hours. Scheduled basals added: "+W.toPrecision(5)+" U. ";else U<21?(he=!1,enableDynamicCR=!1):I=""}else console.log("Pumphistory is empty!"),he=!1,enableDynamicCR=!1;var te,ae;for(let e=0;e0){j=e,k=g[e].rate;var re=g[e-1]["duration (min)"]/60,oe=re,ne=new Date(g[e-1].timestamp),ie=ne,se=0;do{if(e--,0==e){ie=new Date;break}if("TempBasal"==g[e]._type||"PumpSuspend"==g[e]._type){ie=new Date(g[e].timestamp);break}var le=e-2;if(le>=0&&"Rewind"==g[le]._type){let e=g[le].timestamp;for(;le-1>=0&&"Prime"==g[le-=1]._type;)se=(g[le].timestamp-e)/36e5;se>=re&&(ie=e,se=0)}}while(e>0);var ue=(ie-ne)/36e5;ue0&&(--r,"TempBasal"==g[r]._type)){a=new Date(g[r].timestamp);break}}while(r>0);(a-t)/36e5>0&&(W+=X(a,t))}for(let e=g.length-1;e>0;e--)if("TempBasalDuration"==g[e]._type){let t=g[e]["duration (min)"]/60,a=new Date(g[e].timestamp);var me=a;let r=e;do{if(--r,r>=0&&("TempBasal"==g[r]._type||"PumpSuspend"==g[r]._type)){me=new Date(g[r].timestamp);break}}while(r>0);if(0==e&&"TempBasalDuration"==g[0]._type&&(me=new Date,t=g[e]["duration (min)"]/60),(me-a)/36e5-t>0){W+=X(me,J(a,t))}}var de,ce={TDD:o(P=q+E+W,5),bolus:o(q,5),temp_basal:o(E,5),scheduled_basal:o(W,5)};U>21?(R=". Bolus insulin: "+q.toPrecision(5)+" U",A=". Temporary basal insulin: "+E.toPrecision(5)+" U",O=". Insulin with scheduled basal rate: "+W.toPrecision(5)+" U",F=I+(" TDD past 24h is: "+P.toPrecision(5)+" U")+R+A+O,tddReason=", Total insulin: "+o(P,2)+" U, "+o(q/P*100,0)+"% Bolus "+o((E+W)/P*100,0)+"% Basal"):tddReason=", TDD: Not enough pumpData (< 21h)";const ge=e.glucose;var he=h.useNewFormula;const pe=h.enableDynamicCR,ve=Math.min(i.autosens_min,i.autosens_max),fe=Math.max(i.autosens_min,i.autosens_max);(fe==ve||fe<1||ve>1)&&(he=!1,console.log("Dynamic ISF disabled due to current autosens settings"));const be=h.adjustmentFactor,Be=i.min_bg;var Me=!1,_e="",ye=1,xe="";$>0&&(ye=L/$),xe=ye>1?"Basal adjustment with a 24 hour to total average (up to 14 days of data) TDD ratio (limited by Autosens max setting). Basal Ratio: "+(ye=o(ye=Math.min(ye,i.autosens_max),2))+". Upper limit = Autosens max ("+i.autosens_max+")":ye<1?"Basal adjustment with a 24 hour to to total average (up to 14 days of data) TDD ratio (limited by Autosens min setting). Basal Ratio: "+(ye=o(ye=Math.max(ye,i.autosens_min),2))+". Lower limit = Autosens min ("+i.autosens_min+")":"Basal adjusted with a 24 hour to total average (up to 14 days of data) TDD ratio: "+ye,xe=", Basal ratio: "+ye,(i.high_temptarget_raises_sensitivity||i.exercise_mode||v.isEnabled)&&(Me=!0),Be>=118&&Me&&(he=!1,_e="Dynamic ISF temporarily off due to a high temp target/exercising. Current min target: "+Be);var Se=", Dynamic ratios log: ",we=", AF: "+be,De="BG: "+ge+" mg/dl ("+(.0555*ge).toPrecision(2)+" mmol/l)",Te="",Ge="";const Ce=h.curve,Ue=h.insulinPeakTime,Oe=h.useCustomPeakTime;var Re=55,Ae=65;switch(Ce){case"rapid-acting":Ae=65;break;case"ultra-rapid":Ae=50}Oe?(Re=120-Ue,console.log("Custom insulinpeakTime set to :"+Ue+", insulinFactor: "+Re)):(Re=120-Ae,console.log("insulinFactor set to : "+Re)),de=P,Z<1&&L>0&&(P=L,console.log("Using weighted TDD average: "+o(P,2)+" U, instead of past 24 h ("+o(de,2)+" U), weight: "+Z),Ge=", Weighted TDD: "+o(P,2)+" U");const Ie=h.sigmoid;var Fe="";if(he){var je=N*be*P*Math.log(ge/Re+1)/1800;Te=", Logarithmic formula"}if(he&&Ie){const e=ve,t=fe-e,a=.0555*(ge-i.min_bg);var Pe=ye,Ee=fe-1;1==fe&&(Ee=fe+.01-1);const r=Math.log10(1/Ee-e/Ee)/Math.log10(Math.E),o=a*be*Pe+r;je=t/(1+Math.exp(-o))+e,Te=", Sigmoid function"}var qe=H;const We=o(H,1);var ke="",Le="";if(he&&P>0){if(ke=", Dynamic ISF/CR: On/",je>fe?(_e=", Dynamic ISF limited by autosens_max setting: "+fe+" ("+o(je,2)+"), ",Le=", Autosens/Dynamic Limit: "+fe+" ("+o(je,2)+")",je=fe):je-.5?"+"+o(e.delta,0):o(e.delta,0);var et=Math.min(e.delta,e.short_avgdelta),tt=Math.min(e.short_avgdelta,e.long_avgdelta),at=Math.max(e.delta,e.short_avgdelta,e.long_avgdelta);(Xe<=10||38===Xe||Ye>=3)&&(Ne.reason="CGM is calibrating, in ??? state, or noise is high");if(Xe>60&&0==e.delta&&e.short_avgdelta>-1&&e.short_avgdelta<1&&e.long_avgdelta>-1&&e.long_avgdelta<1&&("fakecgm"==e.device?(console.error("CGM data is unchanged ("+n(Xe,i)+"+"+n(e.delta,i)+") for 5m w/ "+n(e.short_avgdelta,i)+" mg/dL ~15m change & "+n(e.long_avgdelta,2)+" mg/dL ~45m change"),console.error("Simulator mode detected ("+e.device+"): continuing anyway")):!0),Ve>12||Ve<-5?Ne.reason="If current system time "+Je+" is correct, then BG data is too old. The last BG data was read "+Ve+"m ago at "+Qe:0===e.short_avgdelta&&0===e.long_avgdelta&&(e.last_cal&&e.last_cal<3?Ne.reason="CGM was just calibrated":Ne.reason="CGM data is unchanged ("+n(Xe,i)+"+"+n(e.delta,i)+") for 5m w/ "+n(e.short_avgdelta,i)+" mg/dL ~15m change & "+n(e.long_avgdelta,i)+" mg/dL ~45m change"),Xe<=10||38===Xe||Ye>=3||Ve>12||Ve<-5||0===e.short_avgdelta&&0===e.long_avgdelta)return t.rate>=$e?(Ne.reason+=". Canceling high temp basal of "+t.rate,Ne.deliverAt=He,Ne.temp="absolute",Ne.duration=0,Ne.rate=0,Ne):0===t.rate&&t.duration>30?(Ne.reason+=". Shortening "+t.duration+"m long zero temp to 30m. ",Ne.deliverAt=He,Ne.temp="absolute",Ne.duration=30,Ne.rate=0,Ne):(Ne.reason+=". Temp "+t.rate+" <= current basal "+$e+"U/hr; doing nothing. ",Ne);var rt,ot,nt,it,st=i.max_iob;if(void 0!==i.min_bg&&(ot=i.min_bg),void 0!==i.max_bg&&(nt=i.max_bg),void 0!==i.enableSMB_high_bg_target&&(it=i.enableSMB_high_bg_target),void 0===i.min_bg||void 0===i.max_bg)return Ne.error="Error: could not determine target_bg. ",Ne;rt=(i.min_bg+i.max_bg)/2;var lt=i.exercise_mode||i.high_temptarget_raises_sensitivity||v.isEnabled,ut=100,mt=160;if(mt=i.half_basal_exercise_target,v.isEnabled){const e=v.hbt;console.log("Half Basal Target used: "+n(e,i)+" "+i.out_units),mt=e}else console.log("Default Half Basal Target used: "+n(mt,i)+" "+i.out_units);if(lt&&i.temptargetSet&&rt>ut||i.low_temptarget_lowers_sensitivity&&i.temptargetSet&&rt=rt&&sensitivityRatio0&&(process.stderr.write("TDD-adjustment of basals activated, using tdd24h_14d_Ratio "+o(ye,2)+", TDD 24h = "+o(de,2)+"U, Weighted average TDD = "+o(L,2)+"U, (Weight percentage = "+Z+"), Total data of TDDs (up to 14 days) average = "+o($,2)+"U. "),$e!==Ze*z?process.stderr.write("Adjusting basal from "+Ze*z+" U/h to "+$e+" U/h; "):process.stderr.write("Basal unchanged: "+$e+" U/h; "))),i.temptargetSet);else if(void 0!==s&&s&&(i.sensitivity_raises_target&&s.ratio<1||i.resistance_lowers_target&&s.ratio>1)){ot=o((ot-60)/s.ratio)+60,nt=o((nt-60)/s.ratio)+60;var ct=o((rt-60)/s.ratio)+60;rt===(ct=Math.max(80,ct))?process.stderr.write("target_bg unchanged: "+n(ct,i)+"; "):process.stderr.write("target_bg from "+n(ct,i)+" to "+n(ct,i)+"; "),rt=ct}var gt=n(rt,i);rt!=f&&(gt=0!==b&&b!==rt?n(f,i)+"→"+n(b,i)+"→"+n(rt,i):n(f,i)+"→"+n(rt,i));var ht=200,pt=200,vt=200;if(e.noise>=2){var ft=Math.max(1.1,i.noisyCGMTargetMultiplier);Math.min(250,i.maxRaw);ht=o(Math.min(200,ot*ft)),pt=o(Math.min(200,rt*ft)),vt=o(Math.min(200,nt*ft)),process.stderr.write("Raising target_bg for noisy / raw CGM data, from "+n(ct,i)+" to "+n(pt,i)+"; "),ot=ht,rt=pt,nt=vt}var bt=ot-.5*(ot-40),Bt=i.threshold_setting;Bt>bt&&Bt<=120&&Bt>=65?(console.error("Threshold changed in settings from "+n(bt,i)+" to "+n(Bt,i)+". "),bt=Bt):console.error("Current threshold: "+n(bt,i));var Mt="",_t=(o(N,1),N);if(void 0!==s&&s&&((_t=o(_t=N/sensitivityRatio,1))!==N?process.stderr.write("ISF from "+n(N,i)+" to "+n(_t,i)):process.stderr.write("ISF unchanged: "+n(_t,i)),Mt+="Autosens ratio: "+o(sensitivityRatio,2)+", ISF: "+n(N,i)+"→"+n(_t,i)),console.error("CR:"+H),void 0===a)return Ne.error="Error: iob_data undefined. ",Ne;var yt,xt=a;if(a.length,a.length>1&&(a=xt[0]),void 0===a.activity||void 0===a.iob)return Ne.error="Error: iob_data missing some property. ",Ne;var St=((yt=void 0!==a.lastTemp?o((new Date(Je).getTime()-a.lastTemp.date)/6e4):0)+t.duration)%30;if(console.error("currenttemp:"+t.rate+" lastTempAge:"+yt+"m, tempModulus:"+St+"m"),Ne.temp="absolute",Ne.deliverAt=He,m&&t&&a.lastTemp&&t.rate!==a.lastTemp.rate&&yt>10&&t.duration)return Ne.reason="Warning: currenttemp rate "+t.rate+" != lastTemp rate "+a.lastTemp.rate+" from pumphistory; canceling temp",u.setTempBasal(0,0,i,Ne,t);if(t&&a.lastTemp&&t.duration>0){var wt=yt-a.lastTemp.duration;if(wt>5&&yt>10)return Ne.reason="Warning: currenttemp running but lastTemp from pumphistory ended "+wt+"m ago; canceling temp",u.setTempBasal(0,0,i,Ne,t)}var Dt=o(-a.activity*_t*5,2),Tt=o(6*(et-Dt));Tt<0&&(Tt=o(6*(tt-Dt)))<0&&(Tt=o(6*(e.long_avgdelta-Dt)));var Gt=Xe,Ct=(Gt=a.iob>0?o(Xe-a.iob*_t):o(Xe-a.iob*Math.min(_t,N)))+Tt;if(void 0===Ct||isNaN(Ct))return Ne.error="Error: could not calculate eventualBG. Sensitivity: "+_t+" Deviation: "+Tt,Ne;var Ut=function(e,t,a){return o(a+(e-t)/24,1)}(rt,Ct,Dt);Ne={temp:"absolute",bg:Xe,tick:Ke,eventualBG:Ct,insulinReq:0,reservoir:d,deliverAt:He,sensitivityRatio,TDD:de,insulin:ce,current_target:rt,insulinForManualBolus:C,manualBolusErrorString:""};var Ot=[],Rt=[],At=[],It=[];Ot.push(Xe),Rt.push(Xe),It.push(Xe),At.push(Xe);var Ft=function(e,t,a,r,o,i){return t?!e.allowSMB_with_high_temptarget&&e.temptargetSet&&o>100?(console.error("SMB disabled due to high temptarget of "+o),!1):!0===a.bwFound&&!1===e.A52_risk_enable?(console.error("SMB disabled due to Bolus Wizard activity in the last 6 hours."),!1):!0===e.enableSMB_always?(a.bwFound?console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled due to enableSMB_always"),!0):!0===e.enableSMB_with_COB&&a.mealCOB?(a.bwCarbs?console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for COB of "+a.mealCOB),!0):!0===e.enableSMB_after_carbs&&a.carbs?(a.bwCarbs?console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for 6h after carb entry"),!0):!0===e.enableSMB_with_temptarget&&e.temptargetSet&&o<100?(a.bwFound?console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for temptarget of "+n(o,e)),!0):!0===e.enableSMB_high_bg&&null!==i&&r>=i?(console.error("Checking BG to see if High for SMB enablement."),console.error("Current BG",r," | High BG ",i),a.bwFound?console.error("Warning: High BG SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("High BG detected. Enabling SMB."),!0):(console.error("SMB disabled (no enableSMB preferences active or no condition satisfied)"),!1):(console.error("SMB disabled (!microBolusAllowed)"),!1)}(i,m,l,Xe,rt,it);if(B)if(S){let e=c.getHours();e>=w&&e<=D&&(console.error("SMB disabled by schedule (a Profile is active with SMBs disabled)"),Ft=!1)}else console.error("SMBs are disabled (a Profile is active with SMBs disabled)"),Ft=!1;var jt=i.enableUAM,Pt=0,Et=0;Pt=o(et-Dt,1);var qt=o(et-Dt,1);csf=_t/H,console.error("profile.sens:"+n(N,i)+", sens:"+n(_t,i)+", CSF:"+o(csf,1));var Wt=o(30*csf*5/60,1);Pt>Wt&&(console.error("Limiting carb impact from "+Pt+" to "+Wt+"mg/dL/5m (30g/h)"),Pt=Wt);var kt=3;sensitivityRatio&&(kt/=sensitivityRatio);var Lt=kt;if(l.carbs){kt=Math.max(kt,l.mealCOB/20);var zt=o((new Date(Je).getTime()-l.lastCarbTime)/6e4),Nt=(l.carbs-l.mealCOB)/l.carbs;Lt=o(Lt=kt+1.5*zt/60,1),console.error("Last carbs "+zt+" minutes ago; remainingCATime:"+Lt+"hours; "+o(100*Nt,1)+"% carbs absorbed")}var Ht=Math.max(0,Pt/5*60*Lt/2)/csf,Zt=90,$t=1;i.remainingCarbsCap&&(Zt=Math.min(90,i.remainingCarbsCap)),i.remainingCarbsFraction&&($t=Math.min(1,i.remainingCarbsFraction));var Jt=1-$t,Kt=Math.max(0,l.mealCOB-Ht-l.carbs*Jt),Qt=(Kt=Math.min(Zt,Kt))*csf*5/60/(Lt/2),Vt=o(l.slopeFromMaxDeviation,2),Xt=o(l.slopeFromMinDeviation,2),Yt=Math.min(Vt,-Xt/3);Et=0===Pt?0:Math.min(60*Lt/5/2,Math.max(0,l.mealCOB*csf/Pt)),console.error("Carb Impact:"+Pt+"mg/dL per 5m; CI Duration:"+o(5*Et/60*2,1)+"hours; remaining CI ("+Lt/2+"h peak):"+o(Qt,1)+"mg/dL per 5m");var ea,ta,aa,ra,oa,na=999,ia=999,sa=999,la=Xe,ua=999,ma=999,da=999,ca=999,ga=Ct,ha=Xe,pa=Xe,va=0,fa=[],ba=[];try{xt.forEach((function(e){var t=o(-e.activity*_t*5,2),a=o(-e.iobWithZeroTemp.activity*_t*5,2),r=Gt,n=Pt*(1-Math.min(1,Rt.length/12));if(!0===(he&&!Ie))ga=Rt[Rt.length-1]+o(-e.activity*(1800/(P*be*Math.log(Math.max(Rt[Rt.length-1],39)/Re+1)))*5,2)+n,r=It[It.length-1]+o(-e.iobWithZeroTemp.activity*(1800/(P*be*Math.log(Math.max(It[It.length-1],39)/Re+1)))*5,2),console.log("Dynamic ISF (Logarithmic Formula) )adjusted predictions for IOB and ZT: IOBpredBG: "+o(ga,2)+" , ZTpredBG: "+o(r,2));else ga=Rt[Rt.length-1]+t+n,r=It[It.length-1]+a;var i=Math.max(0,Math.max(0,Pt)*(1-Ot.length/Math.max(2*Et,1))),s=Math.min(Ot.length,12*Lt-Ot.length),l=Math.max(0,s/(Lt/2*12)*Qt);i+l,fa.push(o(l,0)),ba.push(o(i,0)),COBpredBG=Ot[Ot.length-1]+t+Math.min(0,n)+i+l;var u=Math.max(0,qt+At.length*Yt),m=Math.max(0,qt*(1-At.length/Math.max(36,1))),d=Math.min(u,m);if(d>0&&(va=o(5*(At.length+1)/60,1)),!0===(he&&!Ie))UAMpredBG=At[At.length-1]+o(-e.activity*(1800/(P*be*Math.log(Math.max(At[At.length-1],39)/Re+1)))*5,2)+Math.min(0,n)+d,console.log("Dynamic ISF (Logarithmic Formula) adjusted prediction for UAM: UAMpredBG: "+o(UAMpredBG,2));else UAMpredBG=At[At.length-1]+t+Math.min(0,n)+d;Rt.length<48&&Rt.push(ga),Ot.length<48&&Ot.push(COBpredBG),At.length<48&&At.push(UAMpredBG),It.length<48&&It.push(r),COBpredBG18&&gaha&&(ha=ga),(Et||Qt>0)&&Ot.length>18&&COBpredBG0)&&COBpredBG>ha&&(pa=COBpredBG),jt&&At.length>12&&UAMpredBGha&&UAMpredBG}))}catch(e){console.error("Problem with iobArray. Optional feature Advanced Meal Assist disabled")}l.mealCOB&&(console.error("predCIs (mg/dL/5m):"+ba.join(" ")),console.error("remainingCIs: "+fa.join(" "))),Ne.predBGs={},Rt.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))}));for(var Ba=Rt.length-1;Ba>12&&Rt[Ba-1]===Rt[Ba];Ba--)Rt.pop();for(Ne.predBGs.IOB=Rt,aa=o(Rt[Rt.length-1]),It.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),Ba=It.length-1;Ba>6&&!(It[Ba-1]>=It[Ba]||It[Ba]<=rt);Ba--)It.pop();if(Ne.predBGs.ZT=It,o(It[It.length-1]),l.mealCOB>0&&(Pt>0||Qt>0)){for(Ot.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),Ba=Ot.length-1;Ba>12&&Ot[Ba-1]===Ot[Ba];Ba--)Ot.pop();Ne.predBGs.COB=Ot,ra=o(Ot[Ot.length-1]),Ct=Math.max(Ct,o(Ot[Ot.length-1]))}if(Pt>0||Qt>0){if(jt){for(At.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),Ba=At.length-1;Ba>12&&At[Ba-1]===At[Ba];Ba--)At.pop();Ne.predBGs.UAM=At,oa=o(At[At.length-1]),At[At.length-1]&&(Ct=Math.max(Ct,o(At[At.length-1])))}Ne.eventualBG=Ct}console.error("UAM Impact:"+qt+"mg/dL per 5m; UAM Duration:"+va+"hours"),na=Math.max(39,na),ia=Math.max(39,ia),sa=Math.max(39,sa),ea=o(na);var Ma=l.mealCOB/l.carbs;ta=o(sa<999&&ia<999?(1-Ma)*UAMpredBG+Ma*COBpredBG:ia<999?(ga+COBpredBG)/2:sa<999?(ga+UAMpredBG)/2:ga),ca>ta&&(ta=ca),la=o(la=Et||Qt>0?jt?Ma*ua+(1-Ma)*ma:ua:jt?ma:da);var _a=sa;if(casa&&(_a=(sa+ca)/2);if(_a=o(_a),l.carbs)if(!jt&&ia<999)ea=o(Math.max(na,ia));else if(ia<999){var xa=Ma*ia+(1-Ma)*_a;ea=o(Math.max(na,ia,xa))}else ea=jt?_a:la;else jt&&(ea=o(Math.max(na,_a)));ea=Math.min(ea,ta),process.stderr.write("minPredBG: "+ea+" minIOBPredBG: "+na+" minZTGuardBG: "+ca),ia<999&&process.stderr.write(" minCOBPredBG: "+ia),sa<999&&process.stderr.write(" minUAMPredBG: "+sa),console.error(" avgPredBG:"+ta+" COB/Carbs:"+l.mealCOB+"/"+l.carbs),pa>Xe&&(ea=Math.min(ea,pa)),Ne.COB=l.mealCOB,Ne.IOB=a.iob,Ne.BGI=n(Dt,i),Ne.deviation=n(Tt,i),Ne.ISF=n(_t,i),Ne.CR=o(H,1),Ne.target_bg=n(rt,i),Ne.TDD=o(de,2),Ne.current_target=o(rt,0);var Sa=Ne.CR;We!=Ne.CR&&(Sa=We+"→"+Ne.CR),Ne.reason=Mt+", COB: "+Ne.COB+", Dev: "+Ne.deviation+", BGI: "+Ne.BGI+", CR: "+Sa+", Target: "+gt+", minPredBG "+n(ea,i)+", minGuardBG "+n(la,i)+", IOBpredBG "+n(aa,i),ra>0&&(Ne.reason+=", COBpredBG "+n(ra,i)),oa>0&&(Ne.reason+=", UAMpredBG "+n(oa,i)),Ne.reason+=tddReason,Ne.reason+="; ";var wa=Gt;wa<40&&(wa=Math.min(la,wa));var Da,Ta=bt-wa,Ga=240,Ca=240;if(l.mealCOB>0&&(Pt>0||Qt>0)){for(Ba=0;BaDa*Xe&&(console.error("maxDelta "+n(at,i)+" > "+100*Da+"% of BG "+n(Xe,i)+" - disabling SMB"),Ne.reason+="maxDelta "+n(at,i)+" > "+100*Da+"% of BG "+n(Xe,i)+" - SMB disabled!, ",Ft=!1),console.error("BG projected to remain above "+n(ot,i)+" for "+Ga+"minutes"),(Ca<240||Ga<60)&&console.error("BG projected to remain above "+n(bt,i)+" for "+Ca+"minutes");var Ua=Ca,Oa=i.current_basal*z*_t*Ua/60,Ra=Math.max(0,l.mealCOB-.25*l.carbs),Aa=(Ta-Oa)/csf-Ra;Oa=o(Oa),Aa=o(Aa),console.error("naive_eventualBG:",Gt,"bgUndershoot:",Ta,"zeroTempDuration:",Ua,"zeroTempEffect:",Oa,"carbsReq:",Aa),"Could not parse clock data"==l.reason?console.error("carbsReq unknown: Could not parse clock data"):Aa>=i.carbsReqThreshold&&Ca<=45&&(Ne.carbsReq=Aa,Ne.reason+=Aa+" add'l carbs req w/in "+Ca+"m; ");var Ia=0;if(Xe0&&et>Ut)Ne.reason+="IOB "+a.iob+" < "+o(-i.current_basal*z*20/60,2),Ne.reason+=" and minDelta "+n(et,i)+" > expectedDelta "+n(Ut,i)+"; ";else if(Xe=55)return Ne.reason+="; Canceling temp at "+Ne.deliverAt.getMinutes()+"m past the hour. ",u.setTempBasal(0,0,i,Ne,t);var Fa=0,ja=$e,Pa=0;if(CtUt&&et>0&&!Aa)return Gt<40?(Ne.reason+=", naive_eventualBG < 40. ",u.setTempBasal(0,30,i,Ne,t)):(e.delta>et?Ne.reason+=", but Delta "+n(Ke,i)+" > expectedDelta "+n(Ut,i):Ne.reason+=", but Min. Delta "+et.toFixed(2)+" > Exp. Delta "+n(Ut,i),t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",u.setTempBasal($e,30,i,Ne,t)));Fa=o(Fa=2*Math.min(0,(Ct-rt)/_t),2);var Ea=Math.min(0,(Gt-rt)/_t);if(Ea=o(Ea,2),et<0&&et>Ut)Fa=o(Fa*(et/Ut),2);ja=r(ja=$e+2*Fa,i),Pa=t.duration*(t.rate-$e)/60;var qa=Math.min(Fa,Ea);if(console.log("naiveInsulinReq:"+Ea),Pa5&&ja>=.8*t.rate)return Ne.reason+=", temp "+t.rate+" ~< req "+ja+"U/hr. ",Ne;if(ja<=0){if((Ia=o(60*((Ta=rt-Gt)/_t)/i.current_basal*z))<0?Ia=0:(Ia=30*o(Ia/30),Ia=Math.min(120,Math.max(0,Ia))),Ia>0)return Ne.reason+=", setting "+Ia+"m zero temp. ",u.setTempBasal(ja,Ia,i,Ne,t)}else Ne.reason+=", setting "+ja+"U/hr. ";return u.setTempBasal(ja,30,i,Ne,t)}if(et Target Glucose, but glucose is falling faster than expected. Expected: "+Ut+". Falling: "+et,Ne.insulinForManualBolus=o((Ne.eventualBG-Ne.target_bg)/_t,2),!m||!Ft))return e.delta "+n(ot,i)+" but Delta "+n(Ke,i)+" < Exp. Delta "+n(Ut,i):Ne.reason+="Eventual BG "+n(Ct,i)+" > "+n(ot,i)+" but Min. Delta "+et.toFixed(2)+" < Exp. Delta "+n(Ut,i),t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",u.setTempBasal($e,30,i,Ne,t));if(Math.min(Ct,ea)ot&&(Ne.manualBolusErrorString="Minimum predicted Glucose is "+n(ea,i)+" "+i.out_units,Ne.insulinForManualBolus=o((Ne.eventualBG-Ne.target_bg)/_t,2)),!m||!Ft))return Ne.reason+=n(Ct,i)+"-"+n(ea,i)+" in range: no temp required",t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",u.setTempBasal($e,30,i,Ne,t));if(Ct>=nt&&(Ne.reason+="Eventual BG "+n(Ct,i)+" >= "+n(nt,i)+", "),a.iob>st)return Ne.reason+="IOB "+o(a.iob,2)+" > max_iob "+st,t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",u.setTempBasal($e,30,i,Ne,t));Fa=o((Math.min(ea,Ct)-rt)/_t,2),C=o((Ct-rt)/_t,2),Fa>st-a.iob?(console.error("SMB limited by maxIOB: "+st-a.iob+" (. insulinReq: "+Fa+" U)"),Ne.reason+="max_iob "+st+", ",Fa=st-a.iob):console.error("SMB not limited by maxIOB ( insulinReq: "+Fa+" U)."),C>st-a.iob?(console.error("Ev. Bolus limited by maxIOB: "+st-a.iob+" (. insulinForManualBolus: "+C+" U)"),Ne.reason+="max_iob "+st+", ",C=st-a.iob):console.error("Ev. Bolus would not be limited by maxIOB ( insulinForManualBolus: "+C+" U)."),ja=r(ja=$e+2*Fa,i),Fa=o(Fa,3),Ne.insulinReq=Fa,Ne.insulinForManualBolus=o(C,3);var Wa=o((new Date(Je).getTime()-a.lastBolusTime)/6e4,1);if(m&&Ft&&Xe>bt){var ka=30;void 0!==i.maxSMBBasalMinutes&&(ka=i.maxSMBBasalMinutes);var La=30;void 0!==i.maxUAMSMBBasalMinutes&&(La=i.maxUAMSMBBasalMinutes),v.useOverride&&M&&T!==ka&&(console.error("SMB Max Minutes - setting overriden from "+ka+" to "+T),ka=T),v.useOverride&&M&&G!==La&&(console.error("UAM Max Minutes - setting overriden from "+La+" to "+G),La=G);var za=o(l.mealCOB/H,3),Na=0;void 0===ka?(Na=o(i.current_basal*z*30/60,1),console.error("smbMinutesSetting undefined: defaulting to 30m"),Fa>Na&&console.error("SMB limited by maxBolus: "+Na+" ( "+Fa+" U)")):a.iob>za&&a.iob>0?(console.error("IOB"+a.iob+"> COB"+l.mealCOB+"; mealInsulinReq ="+za),La?(console.error("maxUAMSMBBasalMinutes: "+La+", profile.current_basal: "+i.current_basal*z),Na=o(i.current_basal*z*La/60,1)):(console.error("maxUAMSMBBasalMinutes undefined: defaulting to 30m"),Na=o(i.current_basal*z*30/60,1)),Fa>Na?console.error("SMB limited by maxUAMSMBBasalMinutes [ "+La+"m ]: "+Na+"U ( "+Fa+"U )"):console.error("SMB is not limited by maxUAMSMBBasalMinutes. ( insulinReq: "+Fa+"U )")):(console.error(".maxSMBBasalMinutes: "+ka+", profile.current_basal: "+i.current_basal*z),Fa>(Na=o(i.current_basal*ka/60,1))?console.error("SMB limited by maxSMBBasalMinutes: "+ka+"m ]: "+Na+"U ( insulinReq: "+Fa+"U )"):console.error("SMB is not limited by maxSMBBasalMinutes. ( insulinReq: "+Fa+"U )"));var Ha=i.bolus_increment,Za=1/Ha,$a=i.smb_delivery_ratio;$a>.5&&console.error("SMB Delivery Ratio increased from default 0.5 to "+o($a,2));var Ja=Math.min(Fa*$a,Na);Ja=Math.floor(Ja*Za)/Za,Ia=o(60*((rt-(Gt+na)/2)/_t)/i.current_basal*z),Fa>0&&Ja=30?(Ia=30*o(Ia/30),Ia=Math.min(60,Math.max(0,Ia))):(Ka=o($e*Ia/30,2),Ia=30),Ne.reason+=" insulinReq "+Fa,Ja>=Na&&(Ne.reason+="; maxBolus "+Na),Ia>0&&(Ne.reason+="; setting "+Ia+"m low temp of "+Ka+"U/h"),Ne.reason+=". ";var Qa=3;i.SMBInterval&&(Qa=Math.min(10,Math.max(1,i.SMBInterval)));var Va=o(Qa-Wa,0),Xa=o(60*(Qa-Wa),0)%60;if(console.error("naive_eventualBG "+Gt+","+Ia+"m "+Ka+"U/h temp needed; last bolus "+Wa+"m ago; maxBolus: "+Na),Wa>Qa?Ja>0&&(Ne.units=Ja,Ne.reason+="Microbolusing "+Ja+"U. "):Ne.reason+="Waiting "+Va+"m "+Xa+"s to microbolus again. ",Ia>0)return Ne.rate=Ka,Ne.duration=Ia,Ne}var Ya=u.getMaxSafeBasal(i);return ja>Ya&&(Ne.reason+="adj. req. rate: "+ja+" to maxSafeBasal: "+o(Ya,2)+", ",ja=r(Ya,i)),(Pa=t.duration*(t.rate-$e)/60)>=2*Fa?(Ne.reason+=t.duration+"m@"+t.rate.toFixed(2)+" > 2 * insulinReq. Setting temp basal of "+ja+"U/hr. ",u.setTempBasal(ja,30,i,Ne,t)):void 0===t.duration||0===t.duration?(Ne.reason+="no temp, setting "+ja+"U/hr. ",u.setTempBasal(ja,30,i,Ne,t)):t.duration>5&&r(ja,i)<=r(t.rate,i)?(Ne.reason+="temp "+t.rate+" >~ req "+ja+"U/hr. ",Ne):(Ne.reason+="temp "+t.rate+"<"+ja+"U/hr. ",u.setTempBasal(ja,30,i,Ne,t))}},6880:(e,t,a)=>{var r=a(6654);e.exports=function(e,t){var a=20;void 0!==t&&"string"==typeof t.model&&(r(t.model,"54")||r(t.model,"23"))&&(a=40);return e<1?Math.round(e*a)/a:e<10?Math.round(20*e)/20:Math.round(10*e)/10}},2705:(e,t,a)=>{var r=a(5639).Symbol;e.exports=r},9932:e=>{e.exports=function(e,t){for(var a=-1,r=null==e?0:e.length,o=Array(r);++a{e.exports=function(e,t,a){return e==e&&(void 0!==a&&(e=e<=a?e:a),void 0!==t&&(e=e>=t?e:t)),e}},4239:(e,t,a)=>{var r=a(2705),o=a(9607),n=a(2333),i=r?r.toStringTag:void 0;e.exports=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":i&&i in Object(e)?o(e):n(e)}},531:(e,t,a)=>{var r=a(2705),o=a(9932),n=a(1469),i=a(3448),s=r?r.prototype:void 0,l=s?s.toString:void 0;e.exports=function e(t){if("string"==typeof t)return t;if(n(t))return o(t,e)+"";if(i(t))return l?l.call(t):"";var a=t+"";return"0"==a&&1/t==-Infinity?"-0":a}},7561:(e,t,a)=>{var r=a(7990),o=/^\s+/;e.exports=function(e){return e?e.slice(0,r(e)+1).replace(o,""):e}},1957:(e,t,a)=>{var r="object"==typeof a.g&&a.g&&a.g.Object===Object&&a.g;e.exports=r},9607:(e,t,a)=>{var r=a(2705),o=Object.prototype,n=o.hasOwnProperty,i=o.toString,s=r?r.toStringTag:void 0;e.exports=function(e){var t=n.call(e,s),a=e[s];try{e[s]=void 0;var r=!0}catch(e){}var o=i.call(e);return r&&(t?e[s]=a:delete e[s]),o}},2333:e=>{var t=Object.prototype.toString;e.exports=function(e){return t.call(e)}},5639:(e,t,a)=>{var r=a(1957),o="object"==typeof self&&self&&self.Object===Object&&self,n=r||o||Function("return this")();e.exports=n},7990:e=>{var t=/\s/;e.exports=function(e){for(var a=e.length;a--&&t.test(e.charAt(a)););return a}},6654:(e,t,a)=>{var r=a(9750),o=a(531),n=a(554),i=a(9833);e.exports=function(e,t,a){e=i(e),t=o(t);var s=e.length,l=a=void 0===a?s:r(n(a),0,s);return(a-=t.length)>=0&&e.slice(a,l)==t}},1469:e=>{var t=Array.isArray;e.exports=t},3218:e=>{e.exports=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}},7005:e=>{e.exports=function(e){return null!=e&&"object"==typeof e}},3448:(e,t,a)=>{var r=a(4239),o=a(7005);e.exports=function(e){return"symbol"==typeof e||o(e)&&"[object Symbol]"==r(e)}},8601:(e,t,a)=>{var r=a(4841),o=1/0;e.exports=function(e){return e?(e=r(e))===o||e===-1/0?17976931348623157e292*(e<0?-1:1):e==e?e:0:0===e?e:0}},554:(e,t,a)=>{var r=a(8601);e.exports=function(e){var t=r(e),a=t%1;return t==t?a?t-a:t:0}},4841:(e,t,a)=>{var r=a(7561),o=a(3218),n=a(3448),i=/^[-+]0x[0-9a-f]+$/i,s=/^0b[01]+$/i,l=/^0o[0-7]+$/i,u=parseInt;e.exports=function(e){if("number"==typeof e)return e;if(n(e))return NaN;if(o(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=o(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=r(e);var a=s.test(e);return a||l.test(e)?u(e.slice(2),a?2:8):i.test(e)?NaN:+e}},9833:(e,t,a)=>{var r=a(531);e.exports=function(e){return null==e?"":r(e)}}},t={};function a(r){var o=t[r];if(void 0!==o)return o.exports;var n=t[r]={exports:{}};return e[r](n,n.exports,a),n.exports}a.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}();var r=a(5546);freeaps_determineBasal=r})(); \ No newline at end of file +var freeaps_determineBasal;(()=>{var e={5546:(e,t,a)=>{var r=a(6880);function o(e,t){t||(t=0);var a=Math.pow(10,t);return Math.round(e*a)/a}function n(e,t){return"mmol/L"===t.out_units?o(.0555*e,1):Math.round(e)}e.exports=function(e,t,a,i,s,l,u,d,m,c,g,h,p,v){var f=i.min_bg,b=v.overrideTarget;const B=v.smbIsOff,M=v.advancedSettings,_=v.isfAndCr,y=v.isf,x=v.cr,S=v.smbIsAlwaysOff,w=v.start,D=v.end,T=v.smbMinutes,G=v.uamMinutes;var C=0,U=0,O="",R="",A="",I="",F="",E=0,j=0,P=0,q=0,W=0,k=0;const L=v.weightedAverage;var z=1,N=i.sens,H=i.carb_ratio;v.useOverride&&(z=v.overridePercentage/100,_?(N/=z,H/=z):(x&&(H/=z),y&&(N/=z)));const Z=i.weightPercentage,$=v.average_total_data;function J(e,t){var a=e.getTime();return new Date(a+36e5*t)}function K(e){var t=i.bolus_increment;.025!=t&&(t=.05);var a=e/t;return a>=1?o(Math.floor(a)*t,5):0}function Q(e){function t(e){return e<10&&(e="0"+e),e}return t(e.getHours())+":"+t(e.getMinutes())+":00"}function V(e,t){var a=new Date("1/1/1999 "+e),r=new Date("1/1/1999 "+t);return(a.getTime()-r.getTime())/36e5}function X(e,t){var a=0,r=t,o=(e-t)/36e5,n=0,i=o,s=0;do{if(o>0){var l=Q(r),u=p[0].rate;for(let e=0;e=(s=V(p[e+1].start,p[e].start))?n=s:o=s?n=s:od)if(e+1=(s=V(m,l))?n=s:o=(s=V("23:59:59",l))?n=s:o0&&o21)W=X(Y,(te=24-U,ae=Y.getTime(),new Date(ae-36e5*te))),I="24 hours of data is required for an accurate tdd calculation. Currently only "+U.toPrecision(3)+" hours of pump history data are available. Using your pump scheduled basals to fill in the missing hours. Scheduled basals added: "+W.toPrecision(5)+" U. ";else U<21?(he=!1,enableDynamicCR=!1):I=""}else console.log("Pumphistory is empty!"),he=!1,enableDynamicCR=!1;var te,ae;for(let e=0;e0){E=e,k=g[e].rate;var re=g[e-1]["duration (min)"]/60,oe=re,ne=new Date(g[e-1].timestamp),ie=ne,se=0;do{if(e--,0==e){ie=new Date;break}if("TempBasal"==g[e]._type||"PumpSuspend"==g[e]._type){ie=new Date(g[e].timestamp);break}var le=e-2;if(le>=0&&"Rewind"==g[le]._type){let e=g[le].timestamp;for(;le-1>=0&&"Prime"==g[le-=1]._type;)se=(g[le].timestamp-e)/36e5;se>=re&&(ie=e,se=0)}}while(e>0);var ue=(ie-ne)/36e5;ue0&&(--r,"TempBasal"==g[r]._type)){a=new Date(g[r].timestamp);break}}while(r>0);(a-t)/36e5>0&&(W+=X(a,t))}for(let e=g.length-1;e>0;e--)if("TempBasalDuration"==g[e]._type){let t=g[e]["duration (min)"]/60,a=new Date(g[e].timestamp);var de=a;let r=e;do{if(--r,r>=0&&("TempBasal"==g[r]._type||"PumpSuspend"==g[r]._type)){de=new Date(g[r].timestamp);break}}while(r>0);if(0==e&&"TempBasalDuration"==g[0]._type&&(de=new Date,t=g[e]["duration (min)"]/60),(de-a)/36e5-t>0){W+=X(de,J(a,t))}}var me,ce={TDD:o(j=q+P+W,5),bolus:o(q,5),temp_basal:o(P,5),scheduled_basal:o(W,5)};U>21?(R=". Bolus insulin: "+q.toPrecision(5)+" U",A=". Temporary basal insulin: "+P.toPrecision(5)+" U",O=". Insulin with scheduled basal rate: "+W.toPrecision(5)+" U",F=I+(" TDD past 24h is: "+j.toPrecision(5)+" U")+R+A+O,tddReason=", Total insulin: "+o(j,2)+" U, "+o(q/j*100,0)+"% Bolus "+o((P+W)/j*100,0)+"% Basal"):tddReason=", TDD: Not enough pumpData (< 21h)";const ge=e.glucose;var he=h.useNewFormula;const pe=h.enableDynamicCR,ve=Math.min(i.autosens_min,i.autosens_max),fe=Math.max(i.autosens_min,i.autosens_max);(fe==ve||fe<1||ve>1)&&(he=!1,console.log("Dynamic ISF disabled due to current autosens settings"));const be=h.adjustmentFactor,Be=i.min_bg;var Me=!1,_e="",ye=1,xe="";$>0&&(ye=L/$),xe=ye>1?"Basal adjustment with a 24 hour to total average (up to 14 days of data) TDD ratio (limited by Autosens max setting). Basal Ratio: "+(ye=o(ye=Math.min(ye,i.autosens_max),2))+". Upper limit = Autosens max ("+i.autosens_max+")":ye<1?"Basal adjustment with a 24 hour to to total average (up to 14 days of data) TDD ratio (limited by Autosens min setting). Basal Ratio: "+(ye=o(ye=Math.max(ye,i.autosens_min),2))+". Lower limit = Autosens min ("+i.autosens_min+")":"Basal adjusted with a 24 hour to total average (up to 14 days of data) TDD ratio: "+ye,xe=", Basal ratio: "+ye,(i.high_temptarget_raises_sensitivity||i.exercise_mode||v.isEnabled)&&(Me=!0),Be>=118&&Me&&(he=!1,_e="Dynamic ISF temporarily off due to a high temp target/exercising. Current min target: "+Be);var Se=", Dynamic ratios log: ",we=", AF: "+be,De="BG: "+ge+" mg/dl ("+(.0555*ge).toPrecision(2)+" mmol/l)",Te="",Ge="";const Ce=h.curve,Ue=h.insulinPeakTime,Oe=h.useCustomPeakTime;var Re=55,Ae=65;switch(Ce){case"rapid-acting":Ae=65;break;case"ultra-rapid":Ae=50}Oe?(Re=120-Ue,console.log("Custom insulinpeakTime set to :"+Ue+", insulinFactor: "+Re)):(Re=120-Ae,console.log("insulinFactor set to : "+Re)),me=j,Z<1&&L>0&&(j=L,console.log("Using weighted TDD average: "+o(j,2)+" U, instead of past 24 h ("+o(me,2)+" U), weight: "+Z),Ge=", Weighted TDD: "+o(j,2)+" U");const Ie=h.sigmoid;var Fe="";if(he){var Ee=N*be*j*Math.log(ge/Re+1)/1800;Te=", Logarithmic formula"}if(he&&Ie){const e=ve,t=fe-e,a=.0555*(ge-i.min_bg);var je=ye,Pe=fe-1;1==fe&&(Pe=fe+.01-1);const r=Math.log10(1/Pe-e/Pe)/Math.log10(Math.E),o=a*be*je+r;Ee=t/(1+Math.exp(-o))+e,Te=", Sigmoid function"}var qe=H;const We=o(H,1);var ke="",Le="";if(he&&j>0){if(ke=", Dynamic ISF/CR: On/",Ee>fe?(_e=", Dynamic ISF limited by autosens_max setting: "+fe+" ("+o(Ee,2)+"), ",Le=", Autosens/Dynamic Limit: "+fe+" ("+o(Ee,2)+")",Ee=fe):Ee-.5?"+"+o(e.delta,0):o(e.delta,0);var et=Math.min(e.delta,e.short_avgdelta),tt=Math.min(e.short_avgdelta,e.long_avgdelta),at=Math.max(e.delta,e.short_avgdelta,e.long_avgdelta);(Xe<=10||38===Xe||Ye>=3)&&(Ne.reason="CGM is calibrating, in ??? state, or noise is high");if(Xe>60&&0==e.delta&&e.short_avgdelta>-1&&e.short_avgdelta<1&&e.long_avgdelta>-1&&e.long_avgdelta<1&&("fakecgm"==e.device?(console.error("CGM data is unchanged ("+n(Xe,i)+"+"+n(e.delta,i)+") for 5m w/ "+n(e.short_avgdelta,i)+" mg/dL ~15m change & "+n(e.long_avgdelta,2)+" mg/dL ~45m change"),console.error("Simulator mode detected ("+e.device+"): continuing anyway")):!0),Ve>12||Ve<-5?Ne.reason="If current system time "+Je+" is correct, then BG data is too old. The last BG data was read "+Ve+"m ago at "+Qe:0===e.short_avgdelta&&0===e.long_avgdelta&&(e.last_cal&&e.last_cal<3?Ne.reason="CGM was just calibrated":Ne.reason="CGM data is unchanged ("+n(Xe,i)+"+"+n(e.delta,i)+") for 5m w/ "+n(e.short_avgdelta,i)+" mg/dL ~15m change & "+n(e.long_avgdelta,i)+" mg/dL ~45m change"),Xe<=10||38===Xe||Ye>=3||Ve>12||Ve<-5||0===e.short_avgdelta&&0===e.long_avgdelta)return t.rate>=$e?(Ne.reason+=". Canceling high temp basal of "+t.rate,Ne.deliverAt=He,Ne.temp="absolute",Ne.duration=0,Ne.rate=0,Ne):0===t.rate&&t.duration>30?(Ne.reason+=". Shortening "+t.duration+"m long zero temp to 30m. ",Ne.deliverAt=He,Ne.temp="absolute",Ne.duration=30,Ne.rate=0,Ne):(Ne.reason+=". Temp "+t.rate+" <= current basal "+$e+"U/hr; doing nothing. ",Ne);var rt,ot,nt,it,st=i.max_iob;if(void 0!==i.min_bg&&(ot=i.min_bg),void 0!==i.max_bg&&(nt=i.max_bg),void 0!==i.enableSMB_high_bg_target&&(it=i.enableSMB_high_bg_target),void 0===i.min_bg||void 0===i.max_bg)return Ne.error="Error: could not determine target_bg. ",Ne;rt=(i.min_bg+i.max_bg)/2;var lt=i.exercise_mode||i.high_temptarget_raises_sensitivity||v.isEnabled,ut=100,dt=160;if(dt=i.half_basal_exercise_target,v.isEnabled){const e=v.hbt;console.log("Half Basal Target used: "+n(e,i)+" "+i.out_units),dt=e}else console.log("Default Half Basal Target used: "+n(dt,i)+" "+i.out_units);if(lt&&i.temptargetSet&&rt>ut||i.low_temptarget_lowers_sensitivity&&i.temptargetSet&&rt=rt&&sensitivityRatio0&&(process.stderr.write("TDD-adjustment of basals activated, using tdd24h_14d_Ratio "+o(ye,2)+", TDD 24h = "+o(me,2)+"U, Weighted average TDD = "+o(L,2)+"U, (Weight percentage = "+Z+"), Total data of TDDs (up to 14 days) average = "+o($,2)+"U. "),$e!==Ze*z?process.stderr.write("Adjusting basal from "+Ze*z+" U/h to "+$e+" U/h; "):process.stderr.write("Basal unchanged: "+$e+" U/h; "))),i.temptargetSet);else if(void 0!==s&&s&&(i.sensitivity_raises_target&&s.ratio<1||i.resistance_lowers_target&&s.ratio>1)){ot=o((ot-60)/s.ratio)+60,nt=o((nt-60)/s.ratio)+60;var ct=o((rt-60)/s.ratio)+60;rt===(ct=Math.max(80,ct))?process.stderr.write("target_bg unchanged: "+n(ct,i)+"; "):process.stderr.write("target_bg from "+n(ct,i)+" to "+n(ct,i)+"; "),rt=ct}var gt=n(rt,i);rt!=f&&(gt=0!==b&&b!==rt?n(f,i)+"→"+n(b,i)+"→"+n(rt,i):n(f,i)+"→"+n(rt,i));var ht=200,pt=200,vt=200;if(e.noise>=2){var ft=Math.max(1.1,i.noisyCGMTargetMultiplier);Math.min(250,i.maxRaw);ht=o(Math.min(200,ot*ft)),pt=o(Math.min(200,rt*ft)),vt=o(Math.min(200,nt*ft)),process.stderr.write("Raising target_bg for noisy / raw CGM data, from "+n(ct,i)+" to "+n(pt,i)+"; "),ot=ht,rt=pt,nt=vt}var bt=ot-.5*(ot-40),Bt=i.threshold_setting;Bt>bt&&Bt<=120&&Bt>=65?(console.error("Threshold changed in settings from "+n(bt,i)+" to "+n(Bt,i)+". "),bt=Bt):console.error("Current threshold: "+n(bt,i));var Mt="",_t=(o(N,1),N);if(void 0!==s&&s&&((_t=o(_t=N/sensitivityRatio,1))!==N?process.stderr.write("ISF from "+n(N,i)+" to "+n(_t,i)):process.stderr.write("ISF unchanged: "+n(_t,i)),Mt+="Autosens ratio: "+o(sensitivityRatio,2)+", ISF: "+n(N,i)+"→"+n(_t,i)),console.error("CR:"+H),void 0===a)return Ne.error="Error: iob_data undefined. ",Ne;var yt,xt=a;if(a.length,a.length>1&&(a=xt[0]),void 0===a.activity||void 0===a.iob)return Ne.error="Error: iob_data missing some property. ",Ne;var St=((yt=void 0!==a.lastTemp?o((new Date(Je).getTime()-a.lastTemp.date)/6e4):0)+t.duration)%30;if(console.error("currenttemp:"+t.rate+" lastTempAge:"+yt+"m, tempModulus:"+St+"m"),Ne.temp="absolute",Ne.deliverAt=He,d&&t&&a.lastTemp&&t.rate!==a.lastTemp.rate&&yt>10&&t.duration)return Ne.reason="Warning: currenttemp rate "+t.rate+" != lastTemp rate "+a.lastTemp.rate+" from pumphistory; canceling temp",u.setTempBasal(0,0,i,Ne,t);if(t&&a.lastTemp&&t.duration>0){var wt=yt-a.lastTemp.duration;if(wt>5&&yt>10)return Ne.reason="Warning: currenttemp running but lastTemp from pumphistory ended "+wt+"m ago; canceling temp",u.setTempBasal(0,0,i,Ne,t)}var Dt=o(-a.activity*_t*5,2),Tt=o(6*(et-Dt));Tt<0&&(Tt=o(6*(tt-Dt)))<0&&(Tt=o(6*(e.long_avgdelta-Dt)));var Gt=Xe,Ct=(Gt=a.iob>0?o(Xe-a.iob*_t):o(Xe-a.iob*Math.min(_t,N)))+Tt;if(void 0===Ct||isNaN(Ct))return Ne.error="Error: could not calculate eventualBG. Sensitivity: "+_t+" Deviation: "+Tt,Ne;var Ut=function(e,t,a){return o(a+(e-t)/24,1)}(rt,Ct,Dt);Ne={temp:"absolute",bg:Xe,tick:Ke,eventualBG:Ct,insulinReq:0,reservoir:m,deliverAt:He,sensitivityRatio,TDD:me,insulin:ce,current_target:rt,insulinForManualBolus:C,manualBolusErrorString:""};var Ot=[],Rt=[],At=[],It=[];Ot.push(Xe),Rt.push(Xe),It.push(Xe),At.push(Xe);var Ft=function(e,t,a,r,o,i){return t?!e.allowSMB_with_high_temptarget&&e.temptargetSet&&o>100?(console.error("SMB disabled due to high temptarget of "+o),!1):!0===a.bwFound&&!1===e.A52_risk_enable?(console.error("SMB disabled due to Bolus Wizard activity in the last 6 hours."),!1):!0===e.enableSMB_always?(a.bwFound?console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled due to enableSMB_always"),!0):!0===e.enableSMB_with_COB&&a.mealCOB?(a.bwCarbs?console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for COB of "+a.mealCOB),!0):!0===e.enableSMB_after_carbs&&a.carbs?(a.bwCarbs?console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for 6h after carb entry"),!0):!0===e.enableSMB_with_temptarget&&e.temptargetSet&&o<100?(a.bwFound?console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for temptarget of "+n(o,e)),!0):!0===e.enableSMB_high_bg&&null!==i&&r>=i?(console.error("Checking BG to see if High for SMB enablement."),console.error("Current BG",r," | High BG ",i),a.bwFound?console.error("Warning: High BG SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("High BG detected. Enabling SMB."),!0):(console.error("SMB disabled (no enableSMB preferences active or no condition satisfied)"),!1):(console.error("SMB disabled (!microBolusAllowed)"),!1)}(i,d,l,Xe,rt,it);if(B)if(S){let e=c.getHours();e>=w&&e<=D&&(console.error("SMB disabled by schedule (a Profile is active with SMBs disabled)"),Ft=!1)}else console.error("SMBs are disabled (a Profile is active with SMBs disabled)"),Ft=!1;var Et=i.enableUAM,jt=0,Pt=0;jt=o(et-Dt,1);var qt=o(et-Dt,1);csf=_t/H,console.error("profile.sens:"+n(N,i)+", sens:"+n(_t,i)+", CSF:"+o(csf,1));var Wt=o(30*csf*5/60,1);jt>Wt&&(console.error("Limiting carb impact from "+jt+" to "+Wt+"mg/dL/5m (30g/h)"),jt=Wt);var kt=3;sensitivityRatio&&(kt/=sensitivityRatio);var Lt=kt;if(l.carbs){kt=Math.max(kt,l.mealCOB/20);var zt=o((new Date(Je).getTime()-l.lastCarbTime)/6e4),Nt=(l.carbs-l.mealCOB)/l.carbs;Lt=o(Lt=kt+1.5*zt/60,1),console.error("Last carbs "+zt+" minutes ago; remainingCATime:"+Lt+"hours; "+o(100*Nt,1)+"% carbs absorbed")}var Ht=Math.max(0,jt/5*60*Lt/2)/csf,Zt=90,$t=1;i.remainingCarbsCap&&(Zt=Math.min(90,i.remainingCarbsCap)),i.remainingCarbsFraction&&($t=Math.min(1,i.remainingCarbsFraction));var Jt=1-$t,Kt=Math.max(0,l.mealCOB-Ht-l.carbs*Jt),Qt=(Kt=Math.min(Zt,Kt))*csf*5/60/(Lt/2),Vt=o(l.slopeFromMaxDeviation,2),Xt=o(l.slopeFromMinDeviation,2),Yt=Math.min(Vt,-Xt/3);Pt=0===jt?0:Math.min(60*Lt/5/2,Math.max(0,l.mealCOB*csf/jt)),console.error("Carb Impact:"+jt+"mg/dL per 5m; CI Duration:"+o(5*Pt/60*2,1)+"hours; remaining CI ("+Lt/2+"h peak):"+o(Qt,1)+"mg/dL per 5m");var ea,ta,aa,ra,oa,na=999,ia=999,sa=999,la=Xe,ua=999,da=999,ma=999,ca=999,ga=Ct,ha=Xe,pa=Xe,va=0,fa=[],ba=[];try{xt.forEach((function(e){var t=o(-e.activity*_t*5,2),a=o(-e.iobWithZeroTemp.activity*_t*5,2),r=Gt,n=jt*(1-Math.min(1,Rt.length/12));if(!0===(he&&!Ie))ga=Rt[Rt.length-1]+o(-e.activity*(1800/(j*be*Math.log(Math.max(Rt[Rt.length-1],39)/Re+1)))*5,2)+n,r=It[It.length-1]+o(-e.iobWithZeroTemp.activity*(1800/(j*be*Math.log(Math.max(It[It.length-1],39)/Re+1)))*5,2),console.log("Dynamic ISF (Logarithmic Formula) )adjusted predictions for IOB and ZT: IOBpredBG: "+o(ga,2)+" , ZTpredBG: "+o(r,2));else ga=Rt[Rt.length-1]+t+n,r=It[It.length-1]+a;var i=Math.max(0,Math.max(0,jt)*(1-Ot.length/Math.max(2*Pt,1))),s=Math.min(Ot.length,12*Lt-Ot.length),l=Math.max(0,s/(Lt/2*12)*Qt);i+l,fa.push(o(l,0)),ba.push(o(i,0)),COBpredBG=Ot[Ot.length-1]+t+Math.min(0,n)+i+l;var u=Math.max(0,qt+At.length*Yt),d=Math.max(0,qt*(1-At.length/Math.max(36,1))),m=Math.min(u,d);if(m>0&&(va=o(5*(At.length+1)/60,1)),!0===(he&&!Ie))UAMpredBG=At[At.length-1]+o(-e.activity*(1800/(j*be*Math.log(Math.max(At[At.length-1],39)/Re+1)))*5,2)+Math.min(0,n)+m,console.log("Dynamic ISF (Logarithmic Formula) adjusted prediction for UAM: UAMpredBG: "+o(UAMpredBG,2));else UAMpredBG=At[At.length-1]+t+Math.min(0,n)+m;Rt.length<48&&Rt.push(ga),Ot.length<48&&Ot.push(COBpredBG),At.length<48&&At.push(UAMpredBG),It.length<48&&It.push(r),COBpredBG18&&gaha&&(ha=ga),(Pt||Qt>0)&&Ot.length>18&&COBpredBG0)&&COBpredBG>ha&&(pa=COBpredBG),Et&&At.length>12&&UAMpredBGha&&UAMpredBG}))}catch(e){console.error("Problem with iobArray. Optional feature Advanced Meal Assist disabled")}l.mealCOB&&(console.error("predCIs (mg/dL/5m):"+ba.join(" ")),console.error("remainingCIs: "+fa.join(" "))),Ne.predBGs={},Rt.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))}));for(var Ba=Rt.length-1;Ba>12&&Rt[Ba-1]===Rt[Ba];Ba--)Rt.pop();for(Ne.predBGs.IOB=Rt,aa=o(Rt[Rt.length-1]),It.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),Ba=It.length-1;Ba>6&&!(It[Ba-1]>=It[Ba]||It[Ba]<=rt);Ba--)It.pop();if(Ne.predBGs.ZT=It,o(It[It.length-1]),l.mealCOB>0&&(jt>0||Qt>0)){for(Ot.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),Ba=Ot.length-1;Ba>12&&Ot[Ba-1]===Ot[Ba];Ba--)Ot.pop();Ne.predBGs.COB=Ot,ra=o(Ot[Ot.length-1]),Ct=Math.max(Ct,o(Ot[Ot.length-1]))}if(jt>0||Qt>0){if(Et){for(At.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),Ba=At.length-1;Ba>12&&At[Ba-1]===At[Ba];Ba--)At.pop();Ne.predBGs.UAM=At,oa=o(At[At.length-1]),At[At.length-1]&&(Ct=Math.max(Ct,o(At[At.length-1])))}Ne.eventualBG=Ct}console.error("UAM Impact:"+qt+"mg/dL per 5m; UAM Duration:"+va+"hours"),na=Math.max(39,na),ia=Math.max(39,ia),sa=Math.max(39,sa),ea=o(na);var Ma=l.mealCOB/l.carbs;ta=o(sa<999&&ia<999?(1-Ma)*UAMpredBG+Ma*COBpredBG:ia<999?(ga+COBpredBG)/2:sa<999?(ga+UAMpredBG)/2:ga),ca>ta&&(ta=ca),la=o(la=Pt||Qt>0?Et?Ma*ua+(1-Ma)*da:ua:Et?da:ma);var _a=sa;if(casa&&(_a=(sa+ca)/2);if(_a=o(_a),l.carbs)if(!Et&&ia<999)ea=o(Math.max(na,ia));else if(ia<999){var xa=Ma*ia+(1-Ma)*_a;ea=o(Math.max(na,ia,xa))}else ea=Et?_a:la;else Et&&(ea=o(Math.max(na,_a)));ea=Math.min(ea,ta),process.stderr.write("minPredBG: "+ea+" minIOBPredBG: "+na+" minZTGuardBG: "+ca),ia<999&&process.stderr.write(" minCOBPredBG: "+ia),sa<999&&process.stderr.write(" minUAMPredBG: "+sa),console.error(" avgPredBG:"+ta+" COB/Carbs:"+l.mealCOB+"/"+l.carbs),pa>Xe&&(ea=Math.min(ea,pa)),Ne.COB=l.mealCOB,Ne.IOB=a.iob,Ne.BGI=n(Dt,i),Ne.deviation=n(Tt,i),Ne.ISF=n(_t,i),Ne.CR=o(H,1),Ne.target_bg=n(rt,i),Ne.TDD=o(me,2),Ne.current_target=o(rt,0);var Sa=Ne.CR;We!=Ne.CR&&(Sa=We+"→"+Ne.CR),Ne.reason=Mt+", COB: "+Ne.COB+", Dev: "+Ne.deviation+", BGI: "+Ne.BGI+", CR: "+Sa+", Target: "+gt+", minPredBG "+n(ea,i)+", minGuardBG "+n(la,i)+", IOBpredBG "+n(aa,i),ra>0&&(Ne.reason+=", COBpredBG "+n(ra,i)),oa>0&&(Ne.reason+=", UAMpredBG "+n(oa,i)),Ne.reason+=tddReason,Ne.reason+="; ";var wa=Gt;wa<40&&(wa=Math.min(la,wa));var Da,Ta=bt-wa,Ga=240,Ca=240;if(l.mealCOB>0&&(jt>0||Qt>0)){for(Ba=0;BaDa*Xe&&(console.error("maxDelta "+n(at,i)+" > "+100*Da+"% of BG "+n(Xe,i)+" - disabling SMB"),Ne.reason+="maxDelta "+n(at,i)+" > "+100*Da+"% of BG "+n(Xe,i)+" - SMB disabled!, ",Ft=!1),console.error("BG projected to remain above "+n(ot,i)+" for "+Ga+"minutes"),(Ca<240||Ga<60)&&console.error("BG projected to remain above "+n(bt,i)+" for "+Ca+"minutes");var Ua=Ca,Oa=i.current_basal*z*_t*Ua/60,Ra=Math.max(0,l.mealCOB-.25*l.carbs),Aa=(Ta-Oa)/csf-Ra;Oa=o(Oa),Aa=o(Aa),console.error("naive_eventualBG:",Gt,"bgUndershoot:",Ta,"zeroTempDuration:",Ua,"zeroTempEffect:",Oa,"carbsReq:",Aa),"Could not parse clock data"==l.reason?console.error("carbsReq unknown: Could not parse clock data"):Aa>=i.carbsReqThreshold&&Ca<=45&&(Ne.carbsReq=Aa,Ne.reason+=Aa+" add'l carbs req w/in "+Ca+"m; ");var Ia=0;if(Xe0&&et>Ut)Ne.reason+="IOB "+a.iob+" < "+o(-i.current_basal*z*20/60,2),Ne.reason+=" and minDelta "+n(et,i)+" > expectedDelta "+n(Ut,i)+"; ";else if(Xe=55)return Ne.reason+="; Canceling temp at "+Ne.deliverAt.getMinutes()+"m past the hour. ",u.setTempBasal(0,0,i,Ne,t);var Fa=0,Ea=$e,ja=0;if(CtUt&&et>0&&!Aa)return Gt<40?(Ne.reason+=", naive_eventualBG < 40. ",u.setTempBasal(0,30,i,Ne,t)):(e.delta>et?Ne.reason+=", but Delta "+n(Ke,i)+" > expectedDelta "+n(Ut,i):Ne.reason+=", but Min. Delta "+et.toFixed(2)+" > Exp. Delta "+n(Ut,i),t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",u.setTempBasal($e,30,i,Ne,t)));Fa=o(Fa=2*Math.min(0,(Ct-rt)/_t),2);var Pa=Math.min(0,(Gt-rt)/_t);if(Pa=o(Pa,2),et<0&&et>Ut)Fa=o(Fa*(et/Ut),2);Ea=r(Ea=$e+2*Fa,i),ja=t.duration*(t.rate-$e)/60;var qa=Math.min(Fa,Pa);if(console.log("naiveInsulinReq:"+Pa),ja5&&Ea>=.8*t.rate)return Ne.reason+=", temp "+t.rate+" ~< req "+Ea+"U/hr. ",Ne;if(Ea<=0){if((Ia=o(60*((Ta=rt-Gt)/_t)/i.current_basal*z))<0?Ia=0:(Ia=30*o(Ia/30),Ia=Math.min(120,Math.max(0,Ia))),Ia>0)return Ne.reason+=", setting "+Ia+"m zero temp. ",u.setTempBasal(Ea,Ia,i,Ne,t)}else Ne.reason+=", setting "+Ea+"U/hr. ";return u.setTempBasal(Ea,30,i,Ne,t)}if(et=0&&Ut>=0?"Eventual Glucose > Target Glucose, but glucose is climbing slower than expected. Expected: "+Ut+". Climbing: "+et:et<=0&&Ut<=0?"Eventual Glucose > Target Glucose, but glucose is falling faster than expected. Expected: "+Ut+". Falling: "+et:"Eventual Glucose > Target Glucose, but glucose is changing faster than expected. Expected: "+Ut+". Changing: "+et,Ne.insulinForManualBolus=o((Ne.eventualBG-Ne.target_bg)/_t,2),!d||!Ft))return e.delta "+n(ot,i)+" but Delta "+n(Ke,i)+" < Exp. Delta "+n(Ut,i):Ne.reason+="Eventual BG "+n(Ct,i)+" > "+n(ot,i)+" but Min. Delta "+et.toFixed(2)+" < Exp. Delta "+n(Ut,i),t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",u.setTempBasal($e,30,i,Ne,t));if(Math.min(Ct,ea)ot&&(Ne.manualBolusErrorString="Minimum predicted Glucose is "+n(ea,i)+" "+i.out_units,Ne.insulinForManualBolus=o((Ne.eventualBG-Ne.target_bg)/_t,2)),!d||!Ft))return Ne.reason+=n(Ct,i)+"-"+n(ea,i)+" in range: no temp required",t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",u.setTempBasal($e,30,i,Ne,t));if(Ct>=nt&&(Ne.reason+="Eventual BG "+n(Ct,i)+" >= "+n(nt,i)+", "),a.iob>st)return Ne.reason+="IOB "+o(a.iob,2)+" > max_iob "+st,t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",u.setTempBasal($e,30,i,Ne,t));Fa=o((Math.min(ea,Ct)-rt)/_t,2),C=o((Ct-rt)/_t,2),Fa>st-a.iob?(console.error("SMB limited by maxIOB: "+st-a.iob+" (. insulinReq: "+Fa+" U)"),Ne.reason+="max_iob "+st+", ",Fa=st-a.iob):console.error("SMB not limited by maxIOB ( insulinReq: "+Fa+" U)."),C>st-a.iob?(console.error("Ev. Bolus limited by maxIOB: "+st-a.iob+" (. insulinForManualBolus: "+C+" U)"),Ne.reason+="max_iob "+st+", "):console.error("Ev. Bolus would not be limited by maxIOB ( insulinForManualBolus: "+C+" U)."),Ea=r(Ea=$e+2*Fa,i),Fa=o(Fa,3),Ne.insulinReq=Fa,Ne.insulinForManualBolus=o(C,3);var Wa=o((new Date(Je).getTime()-a.lastBolusTime)/6e4,1);if(d&&Ft&&Xe>bt){var ka=30;void 0!==i.maxSMBBasalMinutes&&(ka=i.maxSMBBasalMinutes);var La=30;void 0!==i.maxUAMSMBBasalMinutes&&(La=i.maxUAMSMBBasalMinutes),v.useOverride&&M&&T!==ka&&(console.error("SMB Max Minutes - setting overriden from "+ka+" to "+T),ka=T),v.useOverride&&M&&G!==La&&(console.error("UAM Max Minutes - setting overriden from "+La+" to "+G),La=G);var za=o(l.mealCOB/H,3),Na=0;void 0===ka?(Na=o(i.current_basal*z*30/60,1),console.error("smbMinutesSetting undefined: defaulting to 30m"),Fa>Na&&console.error("SMB limited by maxBolus: "+Na+" ( "+Fa+" U)")):a.iob>za&&a.iob>0?(console.error("IOB"+a.iob+"> COB"+l.mealCOB+"; mealInsulinReq ="+za),La?(console.error("maxUAMSMBBasalMinutes: "+La+", profile.current_basal: "+i.current_basal*z),Na=o(i.current_basal*z*La/60,1)):(console.error("maxUAMSMBBasalMinutes undefined: defaulting to 30m"),Na=o(i.current_basal*z*30/60,1)),Fa>Na?console.error("SMB limited by maxUAMSMBBasalMinutes [ "+La+"m ]: "+Na+"U ( "+Fa+"U )"):console.error("SMB is not limited by maxUAMSMBBasalMinutes. ( insulinReq: "+Fa+"U )")):(console.error(".maxSMBBasalMinutes: "+ka+", profile.current_basal: "+i.current_basal*z),Fa>(Na=o(i.current_basal*ka/60,1))?console.error("SMB limited by maxSMBBasalMinutes: "+ka+"m ]: "+Na+"U ( insulinReq: "+Fa+"U )"):console.error("SMB is not limited by maxSMBBasalMinutes. ( insulinReq: "+Fa+"U )"));var Ha=i.bolus_increment,Za=1/Ha,$a=i.smb_delivery_ratio;$a>.5&&console.error("SMB Delivery Ratio increased from default 0.5 to "+o($a,2));var Ja=Math.min(Fa*$a,Na);Ja=Math.floor(Ja*Za)/Za,Ia=o(60*((rt-(Gt+na)/2)/_t)/i.current_basal*z),Fa>0&&Ja=30?(Ia=30*o(Ia/30),Ia=Math.min(60,Math.max(0,Ia))):(Ka=o($e*Ia/30,2),Ia=30),Ne.reason+=" insulinReq "+Fa,Ja>=Na&&(Ne.reason+="; maxBolus "+Na),Ia>0&&(Ne.reason+="; setting "+Ia+"m low temp of "+Ka+"U/h"),Ne.reason+=". ";var Qa=3;i.SMBInterval&&(Qa=Math.min(10,Math.max(1,i.SMBInterval)));var Va=o(Qa-Wa,0),Xa=o(60*(Qa-Wa),0)%60;if(console.error("naive_eventualBG "+Gt+","+Ia+"m "+Ka+"U/h temp needed; last bolus "+Wa+"m ago; maxBolus: "+Na),Wa>Qa?Ja>0&&(Ne.units=Ja,Ne.reason+="Microbolusing "+Ja+"U. "):Ne.reason+="Waiting "+Va+"m "+Xa+"s to microbolus again. ",Ia>0)return Ne.rate=Ka,Ne.duration=Ia,Ne}var Ya=u.getMaxSafeBasal(i);return Ea>Ya&&(Ne.reason+="adj. req. rate: "+Ea+" to maxSafeBasal: "+o(Ya,2)+", ",Ea=r(Ya,i)),(ja=t.duration*(t.rate-$e)/60)>=2*Fa?(Ne.reason+=t.duration+"m@"+t.rate.toFixed(2)+" > 2 * insulinReq. Setting temp basal of "+Ea+"U/hr. ",u.setTempBasal(Ea,30,i,Ne,t)):void 0===t.duration||0===t.duration?(Ne.reason+="no temp, setting "+Ea+"U/hr. ",u.setTempBasal(Ea,30,i,Ne,t)):t.duration>5&&r(Ea,i)<=r(t.rate,i)?(Ne.reason+="temp "+t.rate+" >~ req "+Ea+"U/hr. ",Ne):(Ne.reason+="temp "+t.rate+"<"+Ea+"U/hr. ",u.setTempBasal(Ea,30,i,Ne,t))}},6880:(e,t,a)=>{var r=a(6654);e.exports=function(e,t){var a=20;void 0!==t&&"string"==typeof t.model&&(r(t.model,"54")||r(t.model,"23"))&&(a=40);return e<1?Math.round(e*a)/a:e<10?Math.round(20*e)/20:Math.round(10*e)/10}},2705:(e,t,a)=>{var r=a(5639).Symbol;e.exports=r},9932:e=>{e.exports=function(e,t){for(var a=-1,r=null==e?0:e.length,o=Array(r);++a{e.exports=function(e,t,a){return e==e&&(void 0!==a&&(e=e<=a?e:a),void 0!==t&&(e=e>=t?e:t)),e}},4239:(e,t,a)=>{var r=a(2705),o=a(9607),n=a(2333),i=r?r.toStringTag:void 0;e.exports=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":i&&i in Object(e)?o(e):n(e)}},531:(e,t,a)=>{var r=a(2705),o=a(9932),n=a(1469),i=a(3448),s=r?r.prototype:void 0,l=s?s.toString:void 0;e.exports=function e(t){if("string"==typeof t)return t;if(n(t))return o(t,e)+"";if(i(t))return l?l.call(t):"";var a=t+"";return"0"==a&&1/t==-Infinity?"-0":a}},7561:(e,t,a)=>{var r=a(7990),o=/^\s+/;e.exports=function(e){return e?e.slice(0,r(e)+1).replace(o,""):e}},1957:(e,t,a)=>{var r="object"==typeof a.g&&a.g&&a.g.Object===Object&&a.g;e.exports=r},9607:(e,t,a)=>{var r=a(2705),o=Object.prototype,n=o.hasOwnProperty,i=o.toString,s=r?r.toStringTag:void 0;e.exports=function(e){var t=n.call(e,s),a=e[s];try{e[s]=void 0;var r=!0}catch(e){}var o=i.call(e);return r&&(t?e[s]=a:delete e[s]),o}},2333:e=>{var t=Object.prototype.toString;e.exports=function(e){return t.call(e)}},5639:(e,t,a)=>{var r=a(1957),o="object"==typeof self&&self&&self.Object===Object&&self,n=r||o||Function("return this")();e.exports=n},7990:e=>{var t=/\s/;e.exports=function(e){for(var a=e.length;a--&&t.test(e.charAt(a)););return a}},6654:(e,t,a)=>{var r=a(9750),o=a(531),n=a(554),i=a(9833);e.exports=function(e,t,a){e=i(e),t=o(t);var s=e.length,l=a=void 0===a?s:r(n(a),0,s);return(a-=t.length)>=0&&e.slice(a,l)==t}},1469:e=>{var t=Array.isArray;e.exports=t},3218:e=>{e.exports=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}},7005:e=>{e.exports=function(e){return null!=e&&"object"==typeof e}},3448:(e,t,a)=>{var r=a(4239),o=a(7005);e.exports=function(e){return"symbol"==typeof e||o(e)&&"[object Symbol]"==r(e)}},8601:(e,t,a)=>{var r=a(4841),o=1/0;e.exports=function(e){return e?(e=r(e))===o||e===-1/0?17976931348623157e292*(e<0?-1:1):e==e?e:0:0===e?e:0}},554:(e,t,a)=>{var r=a(8601);e.exports=function(e){var t=r(e),a=t%1;return t==t?a?t-a:t:0}},4841:(e,t,a)=>{var r=a(7561),o=a(3218),n=a(3448),i=/^[-+]0x[0-9a-f]+$/i,s=/^0b[01]+$/i,l=/^0o[0-7]+$/i,u=parseInt;e.exports=function(e){if("number"==typeof e)return e;if(n(e))return NaN;if(o(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=o(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=r(e);var a=s.test(e);return a||l.test(e)?u(e.slice(2),a?2:8):i.test(e)?NaN:+e}},9833:(e,t,a)=>{var r=a(531);e.exports=function(e){return null==e?"":r(e)}}},t={};function a(r){var o=t[r];if(void 0!==o)return o.exports;var n=t[r]={exports:{}};return e[r](n,n.exports,a),n.exports}a.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}();var r=a(5546);freeaps_determineBasal=r})(); \ No newline at end of file diff --git a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings index 39f9f01924..8507290c83 100644 --- a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings @@ -1307,6 +1307,18 @@ Enact a temp Basal or a temp target */ /* Hide pop-up */ "Hide" = "Hide"; +/* Error string 1. Make translation very short! */ +"Predicted Glucose, %@ %@, is below threshold (%@!)" = "Predicted Glucose, %@ %@, is below threshold (%@!)"; + +/* Error string 2. Make translation very short! */ +"Eventual Glucose > Target Glucose, but glucose is falling faster than expected. Expected: %@. Falling: %@" = "Eventual Glucose > Target Glucose, but glucose is falling faster than expected. Expected: %@. Falling: %@"; + +/* Error string 3. Make translation very short! */ +"Minimum predicted Glucose is %@ %@" = "Minimum predicted Glucose is %@ %@"; + +/* Error string 4. Make translation very short! */ +"Predicted Glucose %@ %@, is below Threshold of %@" = "Predicted Glucose %@ %@, is below Threshold of %@"; + /* ------------------------------------------------------------------------------------------- DASH strings */ diff --git a/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings index 87e52d54f9..7c60c0f03c 100644 --- a/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings @@ -1307,6 +1307,18 @@ Enact a temp Basal or a temp target */ /* Hide pop-up */ "Hide" = "Göm"; +/* Error string 1. Make translation very short! */ +"Predicted Glucose, %@ %@, is below threshold (%@!)" = "Blodsockerprognos, %@ %@, är lägre än (%@!)"; + +/* Error string 2. Make translation very short! */ +"Eventual Glucose > Target Glucose, but glucose is falling faster than expected. Expected: %@. Falling: %@" = "Blodsockerprognos > målvärde, med blodsockret sjunker snabbare än väntat. Förväntat: %@. Sjunker: %@"; + +/* Error string 3. Make translation very short! */ +"Minimum predicted Glucose is %@ %@" = "Lägsta blodsockerprognos är %@ %@!"; + +/* Error string 4. Make translation very short! */ +"Predicted Glucose %@ %@, is below Threshold of %@" = "Blodsockerprognos %@ %@, är under tröskelvärde %@"; + /* ------------------------------------------------------------------------------------------- DASH strings */ diff --git a/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift b/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift index d6647203a8..665415d8ea 100644 --- a/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift +++ b/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift @@ -105,7 +105,7 @@ extension Bolus { .alert(isPresented: $displayError) { Alert( title: Text("Warning!"), - message: Text("\n" + state.errorString + NSLocalizedString( + message: Text("\n" + NSLocalizedString(state.errorString, comment: "") + NSLocalizedString( "\n\nTap 'Add' to continue with selected amount.", comment: "Alert text to confirm bolus amount to add" )), @@ -202,7 +202,7 @@ extension Bolus { Divider() if state.error, state.insulinRecommended > 0 { Text("Warning!").font(.callout).foregroundColor(.orange).bold() - Text(state.errorString).font(.caption) + Text(NSLocalizedString(state.errorString, comment: "")).font(.caption) Divider() } }.padding(.horizontal, 10) From 3be9604fe6bd097041290994edcdce55eef5e7cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20B=20M=C3=A5rtensson?= <53905247+Jon-b-m@users.noreply.github.com> Date: Mon, 12 Jun 2023 11:44:12 +0200 Subject: [PATCH 33/45] New Libre 2 versions. Support for patchInfo starting with "c5" (#104) Ported from the xdripswift repo --- .../Bluetooth/LibreTransmitterMetadata.swift | 5 +++-- .../LibreSensor/SensorContents/PreLibre2.swift | 4 ++-- FreeAPS/Sources/APS/CGM/CGMType.swift | 14 +++++++------- .../Sources/Modules/CGM/View/CGMSetupView.swift | 8 ++++---- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/Dependencies/LibreTransmitter/Sources/LibreTransmitter/Bluetooth/LibreTransmitterMetadata.swift b/Dependencies/LibreTransmitter/Sources/LibreTransmitter/Bluetooth/LibreTransmitterMetadata.swift index 527f583d5f..b714c65440 100644 --- a/Dependencies/LibreTransmitter/Sources/LibreTransmitter/Bluetooth/LibreTransmitterMetadata.swift +++ b/Dependencies/LibreTransmitter/Sources/LibreTransmitter/Bluetooth/LibreTransmitterMetadata.swift @@ -80,6 +80,7 @@ public enum SensorType: String, CustomStringConvertible { case libre1 = "DF" case libre1A2 = "A2" case libre2 = "9D" + case libre2C5 = "C5" case libreUS14day = "E5" case libreUS14dayE6 = "E6" case libreProH = "70" @@ -90,7 +91,7 @@ public enum SensorType: String, CustomStringConvertible { return "Libre 1" case .libre1A2: return "Libre 1 A2" - case .libre2: + case .libre2, .libre2C5: return "Libre 2" case .libreUS14day, .libreUS14dayE6: return "Libre US" @@ -106,7 +107,7 @@ public extension SensorType { let start = patchInfo[0..<2].uppercased() - let choices: [String: SensorType] = ["DF": .libre1, "A2": .libre1A2, "9D": .libre2, "E5": .libreUS14day, "E6": .libreUS14dayE6, "70": .libreProH] + let choices: [String: SensorType] = ["DF": .libre1, "A2": .libre1A2, "9D": .libre2, "C5": .libre2, "E5": .libreUS14day, "E6": .libreUS14dayE6, "70": .libreProH] if let res = choices[start] { self = res diff --git a/Dependencies/LibreTransmitter/Sources/LibreTransmitter/LibreSensor/SensorContents/PreLibre2.swift b/Dependencies/LibreTransmitter/Sources/LibreTransmitter/LibreSensor/SensorContents/PreLibre2.swift index 1e7cdda57a..9ae09b6d83 100644 --- a/Dependencies/LibreTransmitter/Sources/LibreTransmitter/LibreSensor/SensorContents/PreLibre2.swift +++ b/Dependencies/LibreTransmitter/Sources/LibreTransmitter/LibreSensor/SensorContents/PreLibre2.swift @@ -9,7 +9,7 @@ public enum Libre2 { /// - data: Encrypted FRAM data /// - Returns: Decrypted FRAM data static public func decryptFRAM(type: SensorType, id: [UInt8], info: [UInt8], data: [UInt8]) throws -> [UInt8] { - guard type == .libre2 || type == .libreUS14day || type == .libreUS14dayE6 else { + guard type == .libre2 || type == .libre2C5 || type == .libreUS14day || type == .libreUS14dayE6 else { struct DecryptFRAMError: Error { let errorDescription = "Unsupported sensor type" } @@ -24,7 +24,7 @@ public enum Libre2 { return 0xcadc } return UInt16(info[5], info[4]) - case .libre2: + case .libre2, .libre2C5: return UInt16(info[5], info[4]) ^ 0x44 default: fatalError("Unsupported sensor type") } diff --git a/FreeAPS/Sources/APS/CGM/CGMType.swift b/FreeAPS/Sources/APS/CGM/CGMType.swift index 477db37890..40eb7ccfcf 100644 --- a/FreeAPS/Sources/APS/CGM/CGMType.swift +++ b/FreeAPS/Sources/APS/CGM/CGMType.swift @@ -5,8 +5,8 @@ enum CGMType: String, JSON, CaseIterable, Identifiable { case nightscout case xdrip - case dexcomG6 case dexcomG5 + case dexcomG6 case dexcomG7 case simulator case libreTransmitter @@ -21,10 +21,10 @@ enum CGMType: String, JSON, CaseIterable, Identifiable { return "xDrip" case .glucoseDirect: return "Glucose Direct" - case .dexcomG6: - return "Dexcom G6" case .dexcomG5: return "Dexcom G5" + case .dexcomG6: + return "Dexcom G6" case .dexcomG7: return "Dexcom G7" case .simulator: @@ -45,12 +45,12 @@ enum CGMType: String, JSON, CaseIterable, Identifiable { return URL(string: "xdripswift://")! case .glucoseDirect: return URL(string: "libredirect://")! + case .dexcomG5: + return URL(string: "dexcomgcgm://")! case .dexcomG6: return URL(string: "dexcomg6://")! case .dexcomG7: return URL(string: "dexcomg7://")! - case .dexcomG5: - return URL(string: "dexcomgcgm://")! case .simulator: return nil case .libreTransmitter: @@ -77,10 +77,10 @@ enum CGMType: String, JSON, CaseIterable, Identifiable { "Using shared app group with external CGM app xDrip4iOS", comment: "Shared app group xDrip4iOS" ) - case .dexcomG6: - return NSLocalizedString("Dexcom G6 app", comment: "Dexcom G6 app") case .dexcomG5: return NSLocalizedString("Native G5 app", comment: "Native G5 app") + case .dexcomG6: + return NSLocalizedString("Dexcom G6 app", comment: "Dexcom G6 app") case .dexcomG7: return NSLocalizedString("Dexcom G7 app", comment: "Dexcom G76 app") case .simulator: diff --git a/FreeAPS/Sources/Modules/CGM/View/CGMSetupView.swift b/FreeAPS/Sources/Modules/CGM/View/CGMSetupView.swift index 5dfff72ede..a192c81895 100644 --- a/FreeAPS/Sources/Modules/CGM/View/CGMSetupView.swift +++ b/FreeAPS/Sources/Modules/CGM/View/CGMSetupView.swift @@ -30,15 +30,15 @@ extension CGM { } switch CGMType { - case .dexcomG6: - setupViewController = G6CGMManager.setupViewController( + case .dexcomG5: + setupViewController = G5CGMManager.setupViewController( bluetoothProvider: bluetoothManager, displayGlucoseUnitObservable: displayGlucoseUnitObservable, colorPalette: .default, allowDebugFeatures: false ) - case .dexcomG5: - setupViewController = G5CGMManager.setupViewController( + case .dexcomG6: + setupViewController = G6CGMManager.setupViewController( bluetoothProvider: bluetoothManager, displayGlucoseUnitObservable: displayGlucoseUnitObservable, colorPalette: .default, From 819c53e29d9d14683ae136144f7589c21262093e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20B=20M=C3=A5rtensson?= <53905247+Jon-b-m@users.noreply.github.com> Date: Mon, 12 Jun 2023 12:54:00 +0200 Subject: [PATCH 34/45] Crowdin translations (#106) --- .../Main/sv.lproj/Localizable.strings | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings index 7c60c0f03c..aff9c0ae4d 100644 --- a/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings @@ -348,25 +348,25 @@ Enact a temp Basal or a temp target */ "U/hr" = "IE/h"; /* Unit in number of units delivered (keep the space character!) */ -" U" = " IE"; +" U" = " E"; /* /Insulin unit */ -"/U" = "/IE"; +"/U" = "/E"; /* Insulin unit */ -"U" = "IE"; +"U" = "E"; /* Unit per hour with space */ -" U/hr" = " IE/h"; +" U/hr" = " E/h"; /* Number of units per hour*/ -"%@ U/hr" = "%@ IE/h"; +"%@ U/hr" = "%@ E/h"; /* Number of units insulin delivered */ -"%@ U" = "%@ IE"; +"%@ U" = "%@ E"; /*Carb ratio unit */ -"g/U" = "g/IE"; +"g/U" = "g/E"; /* grams */ " g" = " g"; @@ -375,7 +375,7 @@ Enact a temp Basal or a temp target */ "g" = "g"; /* when 0 U/hr */ -"0 U/hr" = "0 IE/h"; +"0 U/hr" = "0 E/h"; /* abbreviation for days */ "d" = "d"; From 902b782235959b7c957f563dbd71349b6b060256 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Tue, 13 Jun 2023 09:50:49 +0200 Subject: [PATCH 35/45] Use systemGray and gradient (cherry picked from commit 3a09cb4343802b65508a3fb1ed7e07135b909889) --- FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift b/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift index 665415d8ea..3e3cdaed77 100644 --- a/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift +++ b/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift @@ -222,8 +222,7 @@ extension Bolus { }.padding(.bottom, 10) } .background( - RoundedRectangle(cornerRadius: 8, style: .continuous) - .fill(Color(colorScheme == .dark ? UIColor.systemGray4 : UIColor.systemGray4)) + RoundedRectangle(cornerRadius: 8, style: .continuous).fill(Color(.systemGray).gradient) ) } } From f6fb807af811b6d42ae2a71d050055adfce0074b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Tue, 13 Jun 2023 10:19:48 +0200 Subject: [PATCH 36/45] Revert (cherry picked from commit 3f73bbc951092f54a3ab433ab94df327b2e1cd4e) --- FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift b/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift index 3e3cdaed77..144ad05f4f 100644 --- a/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift +++ b/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift @@ -222,7 +222,9 @@ extension Bolus { }.padding(.bottom, 10) } .background( - RoundedRectangle(cornerRadius: 8, style: .continuous).fill(Color(.systemGray).gradient) + RoundedRectangle(cornerRadius: 8, style: .continuous) + .fill(Color(colorScheme == .dark ? UIColor.systemGray4 : UIColor.systemGray4)) + // .fill(Color(.systemGray).gradient) // A more prominent pop-up, but harder to read ) } } From 19893c8452da6965a3faa8063754943b9af6ce3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Wed, 14 Jun 2023 22:46:10 +0200 Subject: [PATCH 37/45] 1.Bug fix for adding insulin without blousing. 2. Localize the error strings from oref0. (cherry picked from commit 3f8e09fe9f3233a968d06bdbffbbd958a05df44d) --- .../javascript/bundle/determine-basal.js | 2 +- .../Main/en.lproj/Localizable.strings | 39 +++-- .../Main/sv.lproj/Localizable.strings | 71 ++++++++-- FreeAPS/Sources/Models/Suggestion.swift | 10 +- .../Modules/Bolus/BolusStateModel.swift | 24 +++- .../Modules/Bolus/View/BolusRootView.swift | 134 ++++++++++++++---- .../Modules/Stat/View/StatRootView.swift | 4 +- 7 files changed, 228 insertions(+), 56 deletions(-) diff --git a/FreeAPS/Resources/javascript/bundle/determine-basal.js b/FreeAPS/Resources/javascript/bundle/determine-basal.js index 332954314b..d1f10ddceb 100644 --- a/FreeAPS/Resources/javascript/bundle/determine-basal.js +++ b/FreeAPS/Resources/javascript/bundle/determine-basal.js @@ -1 +1 @@ -var freeaps_determineBasal;(()=>{var e={5546:(e,t,a)=>{var r=a(6880);function o(e,t){t||(t=0);var a=Math.pow(10,t);return Math.round(e*a)/a}function n(e,t){return"mmol/L"===t.out_units?o(.0555*e,1):Math.round(e)}e.exports=function(e,t,a,i,s,l,u,d,m,c,g,h,p,v){var f=i.min_bg,b=v.overrideTarget;const B=v.smbIsOff,M=v.advancedSettings,_=v.isfAndCr,y=v.isf,x=v.cr,S=v.smbIsAlwaysOff,w=v.start,D=v.end,T=v.smbMinutes,G=v.uamMinutes;var C=0,U=0,O="",R="",A="",I="",F="",E=0,j=0,P=0,q=0,W=0,k=0;const L=v.weightedAverage;var z=1,N=i.sens,H=i.carb_ratio;v.useOverride&&(z=v.overridePercentage/100,_?(N/=z,H/=z):(x&&(H/=z),y&&(N/=z)));const Z=i.weightPercentage,$=v.average_total_data;function J(e,t){var a=e.getTime();return new Date(a+36e5*t)}function K(e){var t=i.bolus_increment;.025!=t&&(t=.05);var a=e/t;return a>=1?o(Math.floor(a)*t,5):0}function Q(e){function t(e){return e<10&&(e="0"+e),e}return t(e.getHours())+":"+t(e.getMinutes())+":00"}function V(e,t){var a=new Date("1/1/1999 "+e),r=new Date("1/1/1999 "+t);return(a.getTime()-r.getTime())/36e5}function X(e,t){var a=0,r=t,o=(e-t)/36e5,n=0,i=o,s=0;do{if(o>0){var l=Q(r),u=p[0].rate;for(let e=0;e=(s=V(p[e+1].start,p[e].start))?n=s:o=s?n=s:od)if(e+1=(s=V(m,l))?n=s:o=(s=V("23:59:59",l))?n=s:o0&&o21)W=X(Y,(te=24-U,ae=Y.getTime(),new Date(ae-36e5*te))),I="24 hours of data is required for an accurate tdd calculation. Currently only "+U.toPrecision(3)+" hours of pump history data are available. Using your pump scheduled basals to fill in the missing hours. Scheduled basals added: "+W.toPrecision(5)+" U. ";else U<21?(he=!1,enableDynamicCR=!1):I=""}else console.log("Pumphistory is empty!"),he=!1,enableDynamicCR=!1;var te,ae;for(let e=0;e0){E=e,k=g[e].rate;var re=g[e-1]["duration (min)"]/60,oe=re,ne=new Date(g[e-1].timestamp),ie=ne,se=0;do{if(e--,0==e){ie=new Date;break}if("TempBasal"==g[e]._type||"PumpSuspend"==g[e]._type){ie=new Date(g[e].timestamp);break}var le=e-2;if(le>=0&&"Rewind"==g[le]._type){let e=g[le].timestamp;for(;le-1>=0&&"Prime"==g[le-=1]._type;)se=(g[le].timestamp-e)/36e5;se>=re&&(ie=e,se=0)}}while(e>0);var ue=(ie-ne)/36e5;ue0&&(--r,"TempBasal"==g[r]._type)){a=new Date(g[r].timestamp);break}}while(r>0);(a-t)/36e5>0&&(W+=X(a,t))}for(let e=g.length-1;e>0;e--)if("TempBasalDuration"==g[e]._type){let t=g[e]["duration (min)"]/60,a=new Date(g[e].timestamp);var de=a;let r=e;do{if(--r,r>=0&&("TempBasal"==g[r]._type||"PumpSuspend"==g[r]._type)){de=new Date(g[r].timestamp);break}}while(r>0);if(0==e&&"TempBasalDuration"==g[0]._type&&(de=new Date,t=g[e]["duration (min)"]/60),(de-a)/36e5-t>0){W+=X(de,J(a,t))}}var me,ce={TDD:o(j=q+P+W,5),bolus:o(q,5),temp_basal:o(P,5),scheduled_basal:o(W,5)};U>21?(R=". Bolus insulin: "+q.toPrecision(5)+" U",A=". Temporary basal insulin: "+P.toPrecision(5)+" U",O=". Insulin with scheduled basal rate: "+W.toPrecision(5)+" U",F=I+(" TDD past 24h is: "+j.toPrecision(5)+" U")+R+A+O,tddReason=", Total insulin: "+o(j,2)+" U, "+o(q/j*100,0)+"% Bolus "+o((P+W)/j*100,0)+"% Basal"):tddReason=", TDD: Not enough pumpData (< 21h)";const ge=e.glucose;var he=h.useNewFormula;const pe=h.enableDynamicCR,ve=Math.min(i.autosens_min,i.autosens_max),fe=Math.max(i.autosens_min,i.autosens_max);(fe==ve||fe<1||ve>1)&&(he=!1,console.log("Dynamic ISF disabled due to current autosens settings"));const be=h.adjustmentFactor,Be=i.min_bg;var Me=!1,_e="",ye=1,xe="";$>0&&(ye=L/$),xe=ye>1?"Basal adjustment with a 24 hour to total average (up to 14 days of data) TDD ratio (limited by Autosens max setting). Basal Ratio: "+(ye=o(ye=Math.min(ye,i.autosens_max),2))+". Upper limit = Autosens max ("+i.autosens_max+")":ye<1?"Basal adjustment with a 24 hour to to total average (up to 14 days of data) TDD ratio (limited by Autosens min setting). Basal Ratio: "+(ye=o(ye=Math.max(ye,i.autosens_min),2))+". Lower limit = Autosens min ("+i.autosens_min+")":"Basal adjusted with a 24 hour to total average (up to 14 days of data) TDD ratio: "+ye,xe=", Basal ratio: "+ye,(i.high_temptarget_raises_sensitivity||i.exercise_mode||v.isEnabled)&&(Me=!0),Be>=118&&Me&&(he=!1,_e="Dynamic ISF temporarily off due to a high temp target/exercising. Current min target: "+Be);var Se=", Dynamic ratios log: ",we=", AF: "+be,De="BG: "+ge+" mg/dl ("+(.0555*ge).toPrecision(2)+" mmol/l)",Te="",Ge="";const Ce=h.curve,Ue=h.insulinPeakTime,Oe=h.useCustomPeakTime;var Re=55,Ae=65;switch(Ce){case"rapid-acting":Ae=65;break;case"ultra-rapid":Ae=50}Oe?(Re=120-Ue,console.log("Custom insulinpeakTime set to :"+Ue+", insulinFactor: "+Re)):(Re=120-Ae,console.log("insulinFactor set to : "+Re)),me=j,Z<1&&L>0&&(j=L,console.log("Using weighted TDD average: "+o(j,2)+" U, instead of past 24 h ("+o(me,2)+" U), weight: "+Z),Ge=", Weighted TDD: "+o(j,2)+" U");const Ie=h.sigmoid;var Fe="";if(he){var Ee=N*be*j*Math.log(ge/Re+1)/1800;Te=", Logarithmic formula"}if(he&&Ie){const e=ve,t=fe-e,a=.0555*(ge-i.min_bg);var je=ye,Pe=fe-1;1==fe&&(Pe=fe+.01-1);const r=Math.log10(1/Pe-e/Pe)/Math.log10(Math.E),o=a*be*je+r;Ee=t/(1+Math.exp(-o))+e,Te=", Sigmoid function"}var qe=H;const We=o(H,1);var ke="",Le="";if(he&&j>0){if(ke=", Dynamic ISF/CR: On/",Ee>fe?(_e=", Dynamic ISF limited by autosens_max setting: "+fe+" ("+o(Ee,2)+"), ",Le=", Autosens/Dynamic Limit: "+fe+" ("+o(Ee,2)+")",Ee=fe):Ee-.5?"+"+o(e.delta,0):o(e.delta,0);var et=Math.min(e.delta,e.short_avgdelta),tt=Math.min(e.short_avgdelta,e.long_avgdelta),at=Math.max(e.delta,e.short_avgdelta,e.long_avgdelta);(Xe<=10||38===Xe||Ye>=3)&&(Ne.reason="CGM is calibrating, in ??? state, or noise is high");if(Xe>60&&0==e.delta&&e.short_avgdelta>-1&&e.short_avgdelta<1&&e.long_avgdelta>-1&&e.long_avgdelta<1&&("fakecgm"==e.device?(console.error("CGM data is unchanged ("+n(Xe,i)+"+"+n(e.delta,i)+") for 5m w/ "+n(e.short_avgdelta,i)+" mg/dL ~15m change & "+n(e.long_avgdelta,2)+" mg/dL ~45m change"),console.error("Simulator mode detected ("+e.device+"): continuing anyway")):!0),Ve>12||Ve<-5?Ne.reason="If current system time "+Je+" is correct, then BG data is too old. The last BG data was read "+Ve+"m ago at "+Qe:0===e.short_avgdelta&&0===e.long_avgdelta&&(e.last_cal&&e.last_cal<3?Ne.reason="CGM was just calibrated":Ne.reason="CGM data is unchanged ("+n(Xe,i)+"+"+n(e.delta,i)+") for 5m w/ "+n(e.short_avgdelta,i)+" mg/dL ~15m change & "+n(e.long_avgdelta,i)+" mg/dL ~45m change"),Xe<=10||38===Xe||Ye>=3||Ve>12||Ve<-5||0===e.short_avgdelta&&0===e.long_avgdelta)return t.rate>=$e?(Ne.reason+=". Canceling high temp basal of "+t.rate,Ne.deliverAt=He,Ne.temp="absolute",Ne.duration=0,Ne.rate=0,Ne):0===t.rate&&t.duration>30?(Ne.reason+=". Shortening "+t.duration+"m long zero temp to 30m. ",Ne.deliverAt=He,Ne.temp="absolute",Ne.duration=30,Ne.rate=0,Ne):(Ne.reason+=". Temp "+t.rate+" <= current basal "+$e+"U/hr; doing nothing. ",Ne);var rt,ot,nt,it,st=i.max_iob;if(void 0!==i.min_bg&&(ot=i.min_bg),void 0!==i.max_bg&&(nt=i.max_bg),void 0!==i.enableSMB_high_bg_target&&(it=i.enableSMB_high_bg_target),void 0===i.min_bg||void 0===i.max_bg)return Ne.error="Error: could not determine target_bg. ",Ne;rt=(i.min_bg+i.max_bg)/2;var lt=i.exercise_mode||i.high_temptarget_raises_sensitivity||v.isEnabled,ut=100,dt=160;if(dt=i.half_basal_exercise_target,v.isEnabled){const e=v.hbt;console.log("Half Basal Target used: "+n(e,i)+" "+i.out_units),dt=e}else console.log("Default Half Basal Target used: "+n(dt,i)+" "+i.out_units);if(lt&&i.temptargetSet&&rt>ut||i.low_temptarget_lowers_sensitivity&&i.temptargetSet&&rt=rt&&sensitivityRatio0&&(process.stderr.write("TDD-adjustment of basals activated, using tdd24h_14d_Ratio "+o(ye,2)+", TDD 24h = "+o(me,2)+"U, Weighted average TDD = "+o(L,2)+"U, (Weight percentage = "+Z+"), Total data of TDDs (up to 14 days) average = "+o($,2)+"U. "),$e!==Ze*z?process.stderr.write("Adjusting basal from "+Ze*z+" U/h to "+$e+" U/h; "):process.stderr.write("Basal unchanged: "+$e+" U/h; "))),i.temptargetSet);else if(void 0!==s&&s&&(i.sensitivity_raises_target&&s.ratio<1||i.resistance_lowers_target&&s.ratio>1)){ot=o((ot-60)/s.ratio)+60,nt=o((nt-60)/s.ratio)+60;var ct=o((rt-60)/s.ratio)+60;rt===(ct=Math.max(80,ct))?process.stderr.write("target_bg unchanged: "+n(ct,i)+"; "):process.stderr.write("target_bg from "+n(ct,i)+" to "+n(ct,i)+"; "),rt=ct}var gt=n(rt,i);rt!=f&&(gt=0!==b&&b!==rt?n(f,i)+"→"+n(b,i)+"→"+n(rt,i):n(f,i)+"→"+n(rt,i));var ht=200,pt=200,vt=200;if(e.noise>=2){var ft=Math.max(1.1,i.noisyCGMTargetMultiplier);Math.min(250,i.maxRaw);ht=o(Math.min(200,ot*ft)),pt=o(Math.min(200,rt*ft)),vt=o(Math.min(200,nt*ft)),process.stderr.write("Raising target_bg for noisy / raw CGM data, from "+n(ct,i)+" to "+n(pt,i)+"; "),ot=ht,rt=pt,nt=vt}var bt=ot-.5*(ot-40),Bt=i.threshold_setting;Bt>bt&&Bt<=120&&Bt>=65?(console.error("Threshold changed in settings from "+n(bt,i)+" to "+n(Bt,i)+". "),bt=Bt):console.error("Current threshold: "+n(bt,i));var Mt="",_t=(o(N,1),N);if(void 0!==s&&s&&((_t=o(_t=N/sensitivityRatio,1))!==N?process.stderr.write("ISF from "+n(N,i)+" to "+n(_t,i)):process.stderr.write("ISF unchanged: "+n(_t,i)),Mt+="Autosens ratio: "+o(sensitivityRatio,2)+", ISF: "+n(N,i)+"→"+n(_t,i)),console.error("CR:"+H),void 0===a)return Ne.error="Error: iob_data undefined. ",Ne;var yt,xt=a;if(a.length,a.length>1&&(a=xt[0]),void 0===a.activity||void 0===a.iob)return Ne.error="Error: iob_data missing some property. ",Ne;var St=((yt=void 0!==a.lastTemp?o((new Date(Je).getTime()-a.lastTemp.date)/6e4):0)+t.duration)%30;if(console.error("currenttemp:"+t.rate+" lastTempAge:"+yt+"m, tempModulus:"+St+"m"),Ne.temp="absolute",Ne.deliverAt=He,d&&t&&a.lastTemp&&t.rate!==a.lastTemp.rate&&yt>10&&t.duration)return Ne.reason="Warning: currenttemp rate "+t.rate+" != lastTemp rate "+a.lastTemp.rate+" from pumphistory; canceling temp",u.setTempBasal(0,0,i,Ne,t);if(t&&a.lastTemp&&t.duration>0){var wt=yt-a.lastTemp.duration;if(wt>5&&yt>10)return Ne.reason="Warning: currenttemp running but lastTemp from pumphistory ended "+wt+"m ago; canceling temp",u.setTempBasal(0,0,i,Ne,t)}var Dt=o(-a.activity*_t*5,2),Tt=o(6*(et-Dt));Tt<0&&(Tt=o(6*(tt-Dt)))<0&&(Tt=o(6*(e.long_avgdelta-Dt)));var Gt=Xe,Ct=(Gt=a.iob>0?o(Xe-a.iob*_t):o(Xe-a.iob*Math.min(_t,N)))+Tt;if(void 0===Ct||isNaN(Ct))return Ne.error="Error: could not calculate eventualBG. Sensitivity: "+_t+" Deviation: "+Tt,Ne;var Ut=function(e,t,a){return o(a+(e-t)/24,1)}(rt,Ct,Dt);Ne={temp:"absolute",bg:Xe,tick:Ke,eventualBG:Ct,insulinReq:0,reservoir:m,deliverAt:He,sensitivityRatio,TDD:me,insulin:ce,current_target:rt,insulinForManualBolus:C,manualBolusErrorString:""};var Ot=[],Rt=[],At=[],It=[];Ot.push(Xe),Rt.push(Xe),It.push(Xe),At.push(Xe);var Ft=function(e,t,a,r,o,i){return t?!e.allowSMB_with_high_temptarget&&e.temptargetSet&&o>100?(console.error("SMB disabled due to high temptarget of "+o),!1):!0===a.bwFound&&!1===e.A52_risk_enable?(console.error("SMB disabled due to Bolus Wizard activity in the last 6 hours."),!1):!0===e.enableSMB_always?(a.bwFound?console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled due to enableSMB_always"),!0):!0===e.enableSMB_with_COB&&a.mealCOB?(a.bwCarbs?console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for COB of "+a.mealCOB),!0):!0===e.enableSMB_after_carbs&&a.carbs?(a.bwCarbs?console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for 6h after carb entry"),!0):!0===e.enableSMB_with_temptarget&&e.temptargetSet&&o<100?(a.bwFound?console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for temptarget of "+n(o,e)),!0):!0===e.enableSMB_high_bg&&null!==i&&r>=i?(console.error("Checking BG to see if High for SMB enablement."),console.error("Current BG",r," | High BG ",i),a.bwFound?console.error("Warning: High BG SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("High BG detected. Enabling SMB."),!0):(console.error("SMB disabled (no enableSMB preferences active or no condition satisfied)"),!1):(console.error("SMB disabled (!microBolusAllowed)"),!1)}(i,d,l,Xe,rt,it);if(B)if(S){let e=c.getHours();e>=w&&e<=D&&(console.error("SMB disabled by schedule (a Profile is active with SMBs disabled)"),Ft=!1)}else console.error("SMBs are disabled (a Profile is active with SMBs disabled)"),Ft=!1;var Et=i.enableUAM,jt=0,Pt=0;jt=o(et-Dt,1);var qt=o(et-Dt,1);csf=_t/H,console.error("profile.sens:"+n(N,i)+", sens:"+n(_t,i)+", CSF:"+o(csf,1));var Wt=o(30*csf*5/60,1);jt>Wt&&(console.error("Limiting carb impact from "+jt+" to "+Wt+"mg/dL/5m (30g/h)"),jt=Wt);var kt=3;sensitivityRatio&&(kt/=sensitivityRatio);var Lt=kt;if(l.carbs){kt=Math.max(kt,l.mealCOB/20);var zt=o((new Date(Je).getTime()-l.lastCarbTime)/6e4),Nt=(l.carbs-l.mealCOB)/l.carbs;Lt=o(Lt=kt+1.5*zt/60,1),console.error("Last carbs "+zt+" minutes ago; remainingCATime:"+Lt+"hours; "+o(100*Nt,1)+"% carbs absorbed")}var Ht=Math.max(0,jt/5*60*Lt/2)/csf,Zt=90,$t=1;i.remainingCarbsCap&&(Zt=Math.min(90,i.remainingCarbsCap)),i.remainingCarbsFraction&&($t=Math.min(1,i.remainingCarbsFraction));var Jt=1-$t,Kt=Math.max(0,l.mealCOB-Ht-l.carbs*Jt),Qt=(Kt=Math.min(Zt,Kt))*csf*5/60/(Lt/2),Vt=o(l.slopeFromMaxDeviation,2),Xt=o(l.slopeFromMinDeviation,2),Yt=Math.min(Vt,-Xt/3);Pt=0===jt?0:Math.min(60*Lt/5/2,Math.max(0,l.mealCOB*csf/jt)),console.error("Carb Impact:"+jt+"mg/dL per 5m; CI Duration:"+o(5*Pt/60*2,1)+"hours; remaining CI ("+Lt/2+"h peak):"+o(Qt,1)+"mg/dL per 5m");var ea,ta,aa,ra,oa,na=999,ia=999,sa=999,la=Xe,ua=999,da=999,ma=999,ca=999,ga=Ct,ha=Xe,pa=Xe,va=0,fa=[],ba=[];try{xt.forEach((function(e){var t=o(-e.activity*_t*5,2),a=o(-e.iobWithZeroTemp.activity*_t*5,2),r=Gt,n=jt*(1-Math.min(1,Rt.length/12));if(!0===(he&&!Ie))ga=Rt[Rt.length-1]+o(-e.activity*(1800/(j*be*Math.log(Math.max(Rt[Rt.length-1],39)/Re+1)))*5,2)+n,r=It[It.length-1]+o(-e.iobWithZeroTemp.activity*(1800/(j*be*Math.log(Math.max(It[It.length-1],39)/Re+1)))*5,2),console.log("Dynamic ISF (Logarithmic Formula) )adjusted predictions for IOB and ZT: IOBpredBG: "+o(ga,2)+" , ZTpredBG: "+o(r,2));else ga=Rt[Rt.length-1]+t+n,r=It[It.length-1]+a;var i=Math.max(0,Math.max(0,jt)*(1-Ot.length/Math.max(2*Pt,1))),s=Math.min(Ot.length,12*Lt-Ot.length),l=Math.max(0,s/(Lt/2*12)*Qt);i+l,fa.push(o(l,0)),ba.push(o(i,0)),COBpredBG=Ot[Ot.length-1]+t+Math.min(0,n)+i+l;var u=Math.max(0,qt+At.length*Yt),d=Math.max(0,qt*(1-At.length/Math.max(36,1))),m=Math.min(u,d);if(m>0&&(va=o(5*(At.length+1)/60,1)),!0===(he&&!Ie))UAMpredBG=At[At.length-1]+o(-e.activity*(1800/(j*be*Math.log(Math.max(At[At.length-1],39)/Re+1)))*5,2)+Math.min(0,n)+m,console.log("Dynamic ISF (Logarithmic Formula) adjusted prediction for UAM: UAMpredBG: "+o(UAMpredBG,2));else UAMpredBG=At[At.length-1]+t+Math.min(0,n)+m;Rt.length<48&&Rt.push(ga),Ot.length<48&&Ot.push(COBpredBG),At.length<48&&At.push(UAMpredBG),It.length<48&&It.push(r),COBpredBG18&&gaha&&(ha=ga),(Pt||Qt>0)&&Ot.length>18&&COBpredBG0)&&COBpredBG>ha&&(pa=COBpredBG),Et&&At.length>12&&UAMpredBGha&&UAMpredBG}))}catch(e){console.error("Problem with iobArray. Optional feature Advanced Meal Assist disabled")}l.mealCOB&&(console.error("predCIs (mg/dL/5m):"+ba.join(" ")),console.error("remainingCIs: "+fa.join(" "))),Ne.predBGs={},Rt.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))}));for(var Ba=Rt.length-1;Ba>12&&Rt[Ba-1]===Rt[Ba];Ba--)Rt.pop();for(Ne.predBGs.IOB=Rt,aa=o(Rt[Rt.length-1]),It.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),Ba=It.length-1;Ba>6&&!(It[Ba-1]>=It[Ba]||It[Ba]<=rt);Ba--)It.pop();if(Ne.predBGs.ZT=It,o(It[It.length-1]),l.mealCOB>0&&(jt>0||Qt>0)){for(Ot.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),Ba=Ot.length-1;Ba>12&&Ot[Ba-1]===Ot[Ba];Ba--)Ot.pop();Ne.predBGs.COB=Ot,ra=o(Ot[Ot.length-1]),Ct=Math.max(Ct,o(Ot[Ot.length-1]))}if(jt>0||Qt>0){if(Et){for(At.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),Ba=At.length-1;Ba>12&&At[Ba-1]===At[Ba];Ba--)At.pop();Ne.predBGs.UAM=At,oa=o(At[At.length-1]),At[At.length-1]&&(Ct=Math.max(Ct,o(At[At.length-1])))}Ne.eventualBG=Ct}console.error("UAM Impact:"+qt+"mg/dL per 5m; UAM Duration:"+va+"hours"),na=Math.max(39,na),ia=Math.max(39,ia),sa=Math.max(39,sa),ea=o(na);var Ma=l.mealCOB/l.carbs;ta=o(sa<999&&ia<999?(1-Ma)*UAMpredBG+Ma*COBpredBG:ia<999?(ga+COBpredBG)/2:sa<999?(ga+UAMpredBG)/2:ga),ca>ta&&(ta=ca),la=o(la=Pt||Qt>0?Et?Ma*ua+(1-Ma)*da:ua:Et?da:ma);var _a=sa;if(casa&&(_a=(sa+ca)/2);if(_a=o(_a),l.carbs)if(!Et&&ia<999)ea=o(Math.max(na,ia));else if(ia<999){var xa=Ma*ia+(1-Ma)*_a;ea=o(Math.max(na,ia,xa))}else ea=Et?_a:la;else Et&&(ea=o(Math.max(na,_a)));ea=Math.min(ea,ta),process.stderr.write("minPredBG: "+ea+" minIOBPredBG: "+na+" minZTGuardBG: "+ca),ia<999&&process.stderr.write(" minCOBPredBG: "+ia),sa<999&&process.stderr.write(" minUAMPredBG: "+sa),console.error(" avgPredBG:"+ta+" COB/Carbs:"+l.mealCOB+"/"+l.carbs),pa>Xe&&(ea=Math.min(ea,pa)),Ne.COB=l.mealCOB,Ne.IOB=a.iob,Ne.BGI=n(Dt,i),Ne.deviation=n(Tt,i),Ne.ISF=n(_t,i),Ne.CR=o(H,1),Ne.target_bg=n(rt,i),Ne.TDD=o(me,2),Ne.current_target=o(rt,0);var Sa=Ne.CR;We!=Ne.CR&&(Sa=We+"→"+Ne.CR),Ne.reason=Mt+", COB: "+Ne.COB+", Dev: "+Ne.deviation+", BGI: "+Ne.BGI+", CR: "+Sa+", Target: "+gt+", minPredBG "+n(ea,i)+", minGuardBG "+n(la,i)+", IOBpredBG "+n(aa,i),ra>0&&(Ne.reason+=", COBpredBG "+n(ra,i)),oa>0&&(Ne.reason+=", UAMpredBG "+n(oa,i)),Ne.reason+=tddReason,Ne.reason+="; ";var wa=Gt;wa<40&&(wa=Math.min(la,wa));var Da,Ta=bt-wa,Ga=240,Ca=240;if(l.mealCOB>0&&(jt>0||Qt>0)){for(Ba=0;BaDa*Xe&&(console.error("maxDelta "+n(at,i)+" > "+100*Da+"% of BG "+n(Xe,i)+" - disabling SMB"),Ne.reason+="maxDelta "+n(at,i)+" > "+100*Da+"% of BG "+n(Xe,i)+" - SMB disabled!, ",Ft=!1),console.error("BG projected to remain above "+n(ot,i)+" for "+Ga+"minutes"),(Ca<240||Ga<60)&&console.error("BG projected to remain above "+n(bt,i)+" for "+Ca+"minutes");var Ua=Ca,Oa=i.current_basal*z*_t*Ua/60,Ra=Math.max(0,l.mealCOB-.25*l.carbs),Aa=(Ta-Oa)/csf-Ra;Oa=o(Oa),Aa=o(Aa),console.error("naive_eventualBG:",Gt,"bgUndershoot:",Ta,"zeroTempDuration:",Ua,"zeroTempEffect:",Oa,"carbsReq:",Aa),"Could not parse clock data"==l.reason?console.error("carbsReq unknown: Could not parse clock data"):Aa>=i.carbsReqThreshold&&Ca<=45&&(Ne.carbsReq=Aa,Ne.reason+=Aa+" add'l carbs req w/in "+Ca+"m; ");var Ia=0;if(Xe0&&et>Ut)Ne.reason+="IOB "+a.iob+" < "+o(-i.current_basal*z*20/60,2),Ne.reason+=" and minDelta "+n(et,i)+" > expectedDelta "+n(Ut,i)+"; ";else if(Xe=55)return Ne.reason+="; Canceling temp at "+Ne.deliverAt.getMinutes()+"m past the hour. ",u.setTempBasal(0,0,i,Ne,t);var Fa=0,Ea=$e,ja=0;if(CtUt&&et>0&&!Aa)return Gt<40?(Ne.reason+=", naive_eventualBG < 40. ",u.setTempBasal(0,30,i,Ne,t)):(e.delta>et?Ne.reason+=", but Delta "+n(Ke,i)+" > expectedDelta "+n(Ut,i):Ne.reason+=", but Min. Delta "+et.toFixed(2)+" > Exp. Delta "+n(Ut,i),t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",u.setTempBasal($e,30,i,Ne,t)));Fa=o(Fa=2*Math.min(0,(Ct-rt)/_t),2);var Pa=Math.min(0,(Gt-rt)/_t);if(Pa=o(Pa,2),et<0&&et>Ut)Fa=o(Fa*(et/Ut),2);Ea=r(Ea=$e+2*Fa,i),ja=t.duration*(t.rate-$e)/60;var qa=Math.min(Fa,Pa);if(console.log("naiveInsulinReq:"+Pa),ja5&&Ea>=.8*t.rate)return Ne.reason+=", temp "+t.rate+" ~< req "+Ea+"U/hr. ",Ne;if(Ea<=0){if((Ia=o(60*((Ta=rt-Gt)/_t)/i.current_basal*z))<0?Ia=0:(Ia=30*o(Ia/30),Ia=Math.min(120,Math.max(0,Ia))),Ia>0)return Ne.reason+=", setting "+Ia+"m zero temp. ",u.setTempBasal(Ea,Ia,i,Ne,t)}else Ne.reason+=", setting "+Ea+"U/hr. ";return u.setTempBasal(Ea,30,i,Ne,t)}if(et=0&&Ut>=0?"Eventual Glucose > Target Glucose, but glucose is climbing slower than expected. Expected: "+Ut+". Climbing: "+et:et<=0&&Ut<=0?"Eventual Glucose > Target Glucose, but glucose is falling faster than expected. Expected: "+Ut+". Falling: "+et:"Eventual Glucose > Target Glucose, but glucose is changing faster than expected. Expected: "+Ut+". Changing: "+et,Ne.insulinForManualBolus=o((Ne.eventualBG-Ne.target_bg)/_t,2),!d||!Ft))return e.delta "+n(ot,i)+" but Delta "+n(Ke,i)+" < Exp. Delta "+n(Ut,i):Ne.reason+="Eventual BG "+n(Ct,i)+" > "+n(ot,i)+" but Min. Delta "+et.toFixed(2)+" < Exp. Delta "+n(Ut,i),t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",u.setTempBasal($e,30,i,Ne,t));if(Math.min(Ct,ea)ot&&(Ne.manualBolusErrorString="Minimum predicted Glucose is "+n(ea,i)+" "+i.out_units,Ne.insulinForManualBolus=o((Ne.eventualBG-Ne.target_bg)/_t,2)),!d||!Ft))return Ne.reason+=n(Ct,i)+"-"+n(ea,i)+" in range: no temp required",t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",u.setTempBasal($e,30,i,Ne,t));if(Ct>=nt&&(Ne.reason+="Eventual BG "+n(Ct,i)+" >= "+n(nt,i)+", "),a.iob>st)return Ne.reason+="IOB "+o(a.iob,2)+" > max_iob "+st,t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",u.setTempBasal($e,30,i,Ne,t));Fa=o((Math.min(ea,Ct)-rt)/_t,2),C=o((Ct-rt)/_t,2),Fa>st-a.iob?(console.error("SMB limited by maxIOB: "+st-a.iob+" (. insulinReq: "+Fa+" U)"),Ne.reason+="max_iob "+st+", ",Fa=st-a.iob):console.error("SMB not limited by maxIOB ( insulinReq: "+Fa+" U)."),C>st-a.iob?(console.error("Ev. Bolus limited by maxIOB: "+st-a.iob+" (. insulinForManualBolus: "+C+" U)"),Ne.reason+="max_iob "+st+", "):console.error("Ev. Bolus would not be limited by maxIOB ( insulinForManualBolus: "+C+" U)."),Ea=r(Ea=$e+2*Fa,i),Fa=o(Fa,3),Ne.insulinReq=Fa,Ne.insulinForManualBolus=o(C,3);var Wa=o((new Date(Je).getTime()-a.lastBolusTime)/6e4,1);if(d&&Ft&&Xe>bt){var ka=30;void 0!==i.maxSMBBasalMinutes&&(ka=i.maxSMBBasalMinutes);var La=30;void 0!==i.maxUAMSMBBasalMinutes&&(La=i.maxUAMSMBBasalMinutes),v.useOverride&&M&&T!==ka&&(console.error("SMB Max Minutes - setting overriden from "+ka+" to "+T),ka=T),v.useOverride&&M&&G!==La&&(console.error("UAM Max Minutes - setting overriden from "+La+" to "+G),La=G);var za=o(l.mealCOB/H,3),Na=0;void 0===ka?(Na=o(i.current_basal*z*30/60,1),console.error("smbMinutesSetting undefined: defaulting to 30m"),Fa>Na&&console.error("SMB limited by maxBolus: "+Na+" ( "+Fa+" U)")):a.iob>za&&a.iob>0?(console.error("IOB"+a.iob+"> COB"+l.mealCOB+"; mealInsulinReq ="+za),La?(console.error("maxUAMSMBBasalMinutes: "+La+", profile.current_basal: "+i.current_basal*z),Na=o(i.current_basal*z*La/60,1)):(console.error("maxUAMSMBBasalMinutes undefined: defaulting to 30m"),Na=o(i.current_basal*z*30/60,1)),Fa>Na?console.error("SMB limited by maxUAMSMBBasalMinutes [ "+La+"m ]: "+Na+"U ( "+Fa+"U )"):console.error("SMB is not limited by maxUAMSMBBasalMinutes. ( insulinReq: "+Fa+"U )")):(console.error(".maxSMBBasalMinutes: "+ka+", profile.current_basal: "+i.current_basal*z),Fa>(Na=o(i.current_basal*ka/60,1))?console.error("SMB limited by maxSMBBasalMinutes: "+ka+"m ]: "+Na+"U ( insulinReq: "+Fa+"U )"):console.error("SMB is not limited by maxSMBBasalMinutes. ( insulinReq: "+Fa+"U )"));var Ha=i.bolus_increment,Za=1/Ha,$a=i.smb_delivery_ratio;$a>.5&&console.error("SMB Delivery Ratio increased from default 0.5 to "+o($a,2));var Ja=Math.min(Fa*$a,Na);Ja=Math.floor(Ja*Za)/Za,Ia=o(60*((rt-(Gt+na)/2)/_t)/i.current_basal*z),Fa>0&&Ja=30?(Ia=30*o(Ia/30),Ia=Math.min(60,Math.max(0,Ia))):(Ka=o($e*Ia/30,2),Ia=30),Ne.reason+=" insulinReq "+Fa,Ja>=Na&&(Ne.reason+="; maxBolus "+Na),Ia>0&&(Ne.reason+="; setting "+Ia+"m low temp of "+Ka+"U/h"),Ne.reason+=". ";var Qa=3;i.SMBInterval&&(Qa=Math.min(10,Math.max(1,i.SMBInterval)));var Va=o(Qa-Wa,0),Xa=o(60*(Qa-Wa),0)%60;if(console.error("naive_eventualBG "+Gt+","+Ia+"m "+Ka+"U/h temp needed; last bolus "+Wa+"m ago; maxBolus: "+Na),Wa>Qa?Ja>0&&(Ne.units=Ja,Ne.reason+="Microbolusing "+Ja+"U. "):Ne.reason+="Waiting "+Va+"m "+Xa+"s to microbolus again. ",Ia>0)return Ne.rate=Ka,Ne.duration=Ia,Ne}var Ya=u.getMaxSafeBasal(i);return Ea>Ya&&(Ne.reason+="adj. req. rate: "+Ea+" to maxSafeBasal: "+o(Ya,2)+", ",Ea=r(Ya,i)),(ja=t.duration*(t.rate-$e)/60)>=2*Fa?(Ne.reason+=t.duration+"m@"+t.rate.toFixed(2)+" > 2 * insulinReq. Setting temp basal of "+Ea+"U/hr. ",u.setTempBasal(Ea,30,i,Ne,t)):void 0===t.duration||0===t.duration?(Ne.reason+="no temp, setting "+Ea+"U/hr. ",u.setTempBasal(Ea,30,i,Ne,t)):t.duration>5&&r(Ea,i)<=r(t.rate,i)?(Ne.reason+="temp "+t.rate+" >~ req "+Ea+"U/hr. ",Ne):(Ne.reason+="temp "+t.rate+"<"+Ea+"U/hr. ",u.setTempBasal(Ea,30,i,Ne,t))}},6880:(e,t,a)=>{var r=a(6654);e.exports=function(e,t){var a=20;void 0!==t&&"string"==typeof t.model&&(r(t.model,"54")||r(t.model,"23"))&&(a=40);return e<1?Math.round(e*a)/a:e<10?Math.round(20*e)/20:Math.round(10*e)/10}},2705:(e,t,a)=>{var r=a(5639).Symbol;e.exports=r},9932:e=>{e.exports=function(e,t){for(var a=-1,r=null==e?0:e.length,o=Array(r);++a{e.exports=function(e,t,a){return e==e&&(void 0!==a&&(e=e<=a?e:a),void 0!==t&&(e=e>=t?e:t)),e}},4239:(e,t,a)=>{var r=a(2705),o=a(9607),n=a(2333),i=r?r.toStringTag:void 0;e.exports=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":i&&i in Object(e)?o(e):n(e)}},531:(e,t,a)=>{var r=a(2705),o=a(9932),n=a(1469),i=a(3448),s=r?r.prototype:void 0,l=s?s.toString:void 0;e.exports=function e(t){if("string"==typeof t)return t;if(n(t))return o(t,e)+"";if(i(t))return l?l.call(t):"";var a=t+"";return"0"==a&&1/t==-Infinity?"-0":a}},7561:(e,t,a)=>{var r=a(7990),o=/^\s+/;e.exports=function(e){return e?e.slice(0,r(e)+1).replace(o,""):e}},1957:(e,t,a)=>{var r="object"==typeof a.g&&a.g&&a.g.Object===Object&&a.g;e.exports=r},9607:(e,t,a)=>{var r=a(2705),o=Object.prototype,n=o.hasOwnProperty,i=o.toString,s=r?r.toStringTag:void 0;e.exports=function(e){var t=n.call(e,s),a=e[s];try{e[s]=void 0;var r=!0}catch(e){}var o=i.call(e);return r&&(t?e[s]=a:delete e[s]),o}},2333:e=>{var t=Object.prototype.toString;e.exports=function(e){return t.call(e)}},5639:(e,t,a)=>{var r=a(1957),o="object"==typeof self&&self&&self.Object===Object&&self,n=r||o||Function("return this")();e.exports=n},7990:e=>{var t=/\s/;e.exports=function(e){for(var a=e.length;a--&&t.test(e.charAt(a)););return a}},6654:(e,t,a)=>{var r=a(9750),o=a(531),n=a(554),i=a(9833);e.exports=function(e,t,a){e=i(e),t=o(t);var s=e.length,l=a=void 0===a?s:r(n(a),0,s);return(a-=t.length)>=0&&e.slice(a,l)==t}},1469:e=>{var t=Array.isArray;e.exports=t},3218:e=>{e.exports=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}},7005:e=>{e.exports=function(e){return null!=e&&"object"==typeof e}},3448:(e,t,a)=>{var r=a(4239),o=a(7005);e.exports=function(e){return"symbol"==typeof e||o(e)&&"[object Symbol]"==r(e)}},8601:(e,t,a)=>{var r=a(4841),o=1/0;e.exports=function(e){return e?(e=r(e))===o||e===-1/0?17976931348623157e292*(e<0?-1:1):e==e?e:0:0===e?e:0}},554:(e,t,a)=>{var r=a(8601);e.exports=function(e){var t=r(e),a=t%1;return t==t?a?t-a:t:0}},4841:(e,t,a)=>{var r=a(7561),o=a(3218),n=a(3448),i=/^[-+]0x[0-9a-f]+$/i,s=/^0b[01]+$/i,l=/^0o[0-7]+$/i,u=parseInt;e.exports=function(e){if("number"==typeof e)return e;if(n(e))return NaN;if(o(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=o(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=r(e);var a=s.test(e);return a||l.test(e)?u(e.slice(2),a?2:8):i.test(e)?NaN:+e}},9833:(e,t,a)=>{var r=a(531);e.exports=function(e){return null==e?"":r(e)}}},t={};function a(r){var o=t[r];if(void 0!==o)return o.exports;var n=t[r]={exports:{}};return e[r](n,n.exports,a),n.exports}a.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}();var r=a(5546);freeaps_determineBasal=r})(); \ No newline at end of file +var freeaps_determineBasal;(()=>{var e={5546:(e,t,a)=>{var r=a(6880);function o(e,t){t||(t=0);var a=Math.pow(10,t);return Math.round(e*a)/a}function n(e,t){return"mmol/L"===t.out_units?o(.0555*e,1):Math.round(e)}e.exports=function(e,t,a,i,s,l,u,m,d,c,g,h,p,v){var f=i.min_bg,B=v.overrideTarget;const b=v.smbIsOff,M=v.advancedSettings,_=v.isfAndCr,y=v.isf,x=v.cr,S=v.smbIsAlwaysOff,D=v.start,w=v.end,G=v.smbMinutes,T=v.uamMinutes;var C=0,U=0,O="",R="",A="",I="",F="",j=0,P=0,E=0,q=0,W=0,k=0;const L=v.weightedAverage;var z=1,N=i.sens,H=i.carb_ratio;v.useOverride&&(z=v.overridePercentage/100,_?(N/=z,H/=z):(x&&(H/=z),y&&(N/=z)));const Z=i.weightPercentage,$=v.average_total_data;function J(e,t){var a=e.getTime();return new Date(a+36e5*t)}function K(e){var t=i.bolus_increment;.025!=t&&(t=.05);var a=e/t;return a>=1?o(Math.floor(a)*t,5):0}function Q(e){function t(e){return e<10&&(e="0"+e),e}return t(e.getHours())+":"+t(e.getMinutes())+":00"}function V(e,t){var a=new Date("1/1/1999 "+e),r=new Date("1/1/1999 "+t);return(a.getTime()-r.getTime())/36e5}function X(e,t){var a=0,r=t,o=(e-t)/36e5,n=0,i=o,s=0;do{if(o>0){var l=Q(r),u=p[0].rate;for(let e=0;e=(s=V(p[e+1].start,p[e].start))?n=s:o=s?n=s:om)if(e+1=(s=V(d,l))?n=s:o=(s=V("23:59:59",l))?n=s:o0&&o21)W=X(Y,(te=24-U,ae=Y.getTime(),new Date(ae-36e5*te))),I="24 hours of data is required for an accurate tdd calculation. Currently only "+U.toPrecision(3)+" hours of pump history data are available. Using your pump scheduled basals to fill in the missing hours. Scheduled basals added: "+W.toPrecision(5)+" U. ";else U<21?(he=!1,enableDynamicCR=!1):I=""}else console.log("Pumphistory is empty!"),he=!1,enableDynamicCR=!1;var te,ae;for(let e=0;e0){j=e,k=g[e].rate;var re=g[e-1]["duration (min)"]/60,oe=re,ne=new Date(g[e-1].timestamp),ie=ne,se=0;do{if(e--,0==e){ie=new Date;break}if("TempBasal"==g[e]._type||"PumpSuspend"==g[e]._type){ie=new Date(g[e].timestamp);break}var le=e-2;if(le>=0&&"Rewind"==g[le]._type){let e=g[le].timestamp;for(;le-1>=0&&"Prime"==g[le-=1]._type;)se=(g[le].timestamp-e)/36e5;se>=re&&(ie=e,se=0)}}while(e>0);var ue=(ie-ne)/36e5;ue0&&(--r,"TempBasal"==g[r]._type)){a=new Date(g[r].timestamp);break}}while(r>0);(a-t)/36e5>0&&(W+=X(a,t))}for(let e=g.length-1;e>0;e--)if("TempBasalDuration"==g[e]._type){let t=g[e]["duration (min)"]/60,a=new Date(g[e].timestamp);var me=a;let r=e;do{if(--r,r>=0&&("TempBasal"==g[r]._type||"PumpSuspend"==g[r]._type)){me=new Date(g[r].timestamp);break}}while(r>0);if(0==e&&"TempBasalDuration"==g[0]._type&&(me=new Date,t=g[e]["duration (min)"]/60),(me-a)/36e5-t>0){W+=X(me,J(a,t))}}var de,ce={TDD:o(P=q+E+W,5),bolus:o(q,5),temp_basal:o(E,5),scheduled_basal:o(W,5)};U>21?(R=". Bolus insulin: "+q.toPrecision(5)+" U",A=". Temporary basal insulin: "+E.toPrecision(5)+" U",O=". Insulin with scheduled basal rate: "+W.toPrecision(5)+" U",F=I+(" TDD past 24h is: "+P.toPrecision(5)+" U")+R+A+O,tddReason=", Total insulin: "+o(P,2)+" U, "+o(q/P*100,0)+"% Bolus "+o((E+W)/P*100,0)+"% Basal"):tddReason=", TDD: Not enough pumpData (< 21h)";const ge=e.glucose;var he=h.useNewFormula;const pe=h.enableDynamicCR,ve=Math.min(i.autosens_min,i.autosens_max),fe=Math.max(i.autosens_min,i.autosens_max);(fe==ve||fe<1||ve>1)&&(he=!1,console.log("Dynamic ISF disabled due to current autosens settings"));const Be=h.adjustmentFactor,be=i.min_bg;var Me=!1,_e="",ye=1,xe="";$>0&&(ye=L/$),xe=ye>1?"Basal adjustment with a 24 hour to total average (up to 14 days of data) TDD ratio (limited by Autosens max setting). Basal Ratio: "+(ye=o(ye=Math.min(ye,i.autosens_max),2))+". Upper limit = Autosens max ("+i.autosens_max+")":ye<1?"Basal adjustment with a 24 hour to to total average (up to 14 days of data) TDD ratio (limited by Autosens min setting). Basal Ratio: "+(ye=o(ye=Math.max(ye,i.autosens_min),2))+". Lower limit = Autosens min ("+i.autosens_min+")":"Basal adjusted with a 24 hour to total average (up to 14 days of data) TDD ratio: "+ye,xe=", Basal ratio: "+ye,(i.high_temptarget_raises_sensitivity||i.exercise_mode||v.isEnabled)&&(Me=!0),be>=118&&Me&&(he=!1,_e="Dynamic ISF temporarily off due to a high temp target/exercising. Current min target: "+be);var Se=", Dynamic ratios log: ",De=", AF: "+Be,we="BG: "+ge+" mg/dl ("+(.0555*ge).toPrecision(2)+" mmol/l)",Ge="",Te="";const Ce=h.curve,Ue=h.insulinPeakTime,Oe=h.useCustomPeakTime;var Re=55,Ae=65;switch(Ce){case"rapid-acting":Ae=65;break;case"ultra-rapid":Ae=50}Oe?(Re=120-Ue,console.log("Custom insulinpeakTime set to :"+Ue+", insulinFactor: "+Re)):(Re=120-Ae,console.log("insulinFactor set to : "+Re)),de=P,Z<1&&L>0&&(P=L,console.log("Using weighted TDD average: "+o(P,2)+" U, instead of past 24 h ("+o(de,2)+" U), weight: "+Z),Te=", Weighted TDD: "+o(P,2)+" U");const Ie=h.sigmoid;var Fe="";if(he){var je=N*Be*P*Math.log(ge/Re+1)/1800;Ge=", Logarithmic formula"}if(he&&Ie){const e=ve,t=fe-e,a=.0555*(ge-i.min_bg);var Pe=ye,Ee=fe-1;1==fe&&(Ee=fe+.01-1);const r=Math.log10(1/Ee-e/Ee)/Math.log10(Math.E),o=a*Be*Pe+r;je=t/(1+Math.exp(-o))+e,Ge=", Sigmoid function"}var qe=H;const We=o(H,1);var ke="",Le="";if(he&&P>0){if(ke=", Dynamic ISF/CR: On/",je>fe?(_e=", Dynamic ISF limited by autosens_max setting: "+fe+" ("+o(je,2)+"), ",Le=", Autosens/Dynamic Limit: "+fe+" ("+o(je,2)+")",je=fe):je-.5?"+"+o(e.delta,0):o(e.delta,0);var et=Math.min(e.delta,e.short_avgdelta),tt=Math.min(e.short_avgdelta,e.long_avgdelta),at=Math.max(e.delta,e.short_avgdelta,e.long_avgdelta);(Xe<=10||38===Xe||Ye>=3)&&(Ne.reason="CGM is calibrating, in ??? state, or noise is high");if(Xe>60&&0==e.delta&&e.short_avgdelta>-1&&e.short_avgdelta<1&&e.long_avgdelta>-1&&e.long_avgdelta<1&&("fakecgm"==e.device?(console.error("CGM data is unchanged ("+n(Xe,i)+"+"+n(e.delta,i)+") for 5m w/ "+n(e.short_avgdelta,i)+" mg/dL ~15m change & "+n(e.long_avgdelta,2)+" mg/dL ~45m change"),console.error("Simulator mode detected ("+e.device+"): continuing anyway")):!0),Ve>12||Ve<-5?Ne.reason="If current system time "+Je+" is correct, then BG data is too old. The last BG data was read "+Ve+"m ago at "+Qe:0===e.short_avgdelta&&0===e.long_avgdelta&&(e.last_cal&&e.last_cal<3?Ne.reason="CGM was just calibrated":Ne.reason="CGM data is unchanged ("+n(Xe,i)+"+"+n(e.delta,i)+") for 5m w/ "+n(e.short_avgdelta,i)+" mg/dL ~15m change & "+n(e.long_avgdelta,i)+" mg/dL ~45m change"),Xe<=10||38===Xe||Ye>=3||Ve>12||Ve<-5||0===e.short_avgdelta&&0===e.long_avgdelta)return t.rate>=$e?(Ne.reason+=". Canceling high temp basal of "+t.rate,Ne.deliverAt=He,Ne.temp="absolute",Ne.duration=0,Ne.rate=0,Ne):0===t.rate&&t.duration>30?(Ne.reason+=". Shortening "+t.duration+"m long zero temp to 30m. ",Ne.deliverAt=He,Ne.temp="absolute",Ne.duration=30,Ne.rate=0,Ne):(Ne.reason+=". Temp "+t.rate+" <= current basal "+$e+"U/hr; doing nothing. ",Ne);var rt,ot,nt,it,st=i.max_iob;if(void 0!==i.min_bg&&(ot=i.min_bg),void 0!==i.max_bg&&(nt=i.max_bg),void 0!==i.enableSMB_high_bg_target&&(it=i.enableSMB_high_bg_target),void 0===i.min_bg||void 0===i.max_bg)return Ne.error="Error: could not determine target_bg. ",Ne;rt=(i.min_bg+i.max_bg)/2;var lt=i.exercise_mode||i.high_temptarget_raises_sensitivity||v.isEnabled,ut=100,mt=160;if(mt=i.half_basal_exercise_target,v.isEnabled){const e=v.hbt;console.log("Half Basal Target used: "+n(e,i)+" "+i.out_units),mt=e}else console.log("Default Half Basal Target used: "+n(mt,i)+" "+i.out_units);if(lt&&i.temptargetSet&&rt>ut||i.low_temptarget_lowers_sensitivity&&i.temptargetSet&&rt=rt&&sensitivityRatio0&&(process.stderr.write("TDD-adjustment of basals activated, using tdd24h_14d_Ratio "+o(ye,2)+", TDD 24h = "+o(de,2)+"U, Weighted average TDD = "+o(L,2)+"U, (Weight percentage = "+Z+"), Total data of TDDs (up to 14 days) average = "+o($,2)+"U. "),$e!==Ze*z?process.stderr.write("Adjusting basal from "+Ze*z+" U/h to "+$e+" U/h; "):process.stderr.write("Basal unchanged: "+$e+" U/h; "))),i.temptargetSet);else if(void 0!==s&&s&&(i.sensitivity_raises_target&&s.ratio<1||i.resistance_lowers_target&&s.ratio>1)){ot=o((ot-60)/s.ratio)+60,nt=o((nt-60)/s.ratio)+60;var ct=o((rt-60)/s.ratio)+60;rt===(ct=Math.max(80,ct))?process.stderr.write("target_bg unchanged: "+n(ct,i)+"; "):process.stderr.write("target_bg from "+n(ct,i)+" to "+n(ct,i)+"; "),rt=ct}var gt=n(rt,i);rt!=f&&(gt=0!==B&&B!==rt?n(f,i)+"→"+n(B,i)+"→"+n(rt,i):n(f,i)+"→"+n(rt,i));var ht=200,pt=200,vt=200;if(e.noise>=2){var ft=Math.max(1.1,i.noisyCGMTargetMultiplier);Math.min(250,i.maxRaw);ht=o(Math.min(200,ot*ft)),pt=o(Math.min(200,rt*ft)),vt=o(Math.min(200,nt*ft)),process.stderr.write("Raising target_bg for noisy / raw CGM data, from "+n(ct,i)+" to "+n(pt,i)+"; "),ot=ht,rt=pt,nt=vt}var Bt=ot-.5*(ot-40),bt=i.threshold_setting;bt>Bt&&bt<=120&&bt>=65?(console.error("Threshold changed in settings from "+n(Bt,i)+" to "+n(bt,i)+". "),Bt=bt):console.error("Current threshold: "+n(Bt,i));var Mt="",_t=(o(N,1),N);if(void 0!==s&&s&&((_t=o(_t=N/sensitivityRatio,1))!==N?process.stderr.write("ISF from "+n(N,i)+" to "+n(_t,i)):process.stderr.write("ISF unchanged: "+n(_t,i)),Mt+="Autosens ratio: "+o(sensitivityRatio,2)+", ISF: "+n(N,i)+"→"+n(_t,i)),console.error("CR:"+H),void 0===a)return Ne.error="Error: iob_data undefined. ",Ne;var yt,xt=a;if(a.length,a.length>1&&(a=xt[0]),void 0===a.activity||void 0===a.iob)return Ne.error="Error: iob_data missing some property. ",Ne;var St=((yt=void 0!==a.lastTemp?o((new Date(Je).getTime()-a.lastTemp.date)/6e4):0)+t.duration)%30;if(console.error("currenttemp:"+t.rate+" lastTempAge:"+yt+"m, tempModulus:"+St+"m"),Ne.temp="absolute",Ne.deliverAt=He,m&&t&&a.lastTemp&&t.rate!==a.lastTemp.rate&&yt>10&&t.duration)return Ne.reason="Warning: currenttemp rate "+t.rate+" != lastTemp rate "+a.lastTemp.rate+" from pumphistory; canceling temp",u.setTempBasal(0,0,i,Ne,t);if(t&&a.lastTemp&&t.duration>0){var Dt=yt-a.lastTemp.duration;if(Dt>5&&yt>10)return Ne.reason="Warning: currenttemp running but lastTemp from pumphistory ended "+Dt+"m ago; canceling temp",u.setTempBasal(0,0,i,Ne,t)}var wt=o(-a.activity*_t*5,2),Gt=o(6*(et-wt));Gt<0&&(Gt=o(6*(tt-wt)))<0&&(Gt=o(6*(e.long_avgdelta-wt)));var Tt=Xe,Ct=(Tt=a.iob>0?o(Xe-a.iob*_t):o(Xe-a.iob*Math.min(_t,N)))+Gt;if(void 0===Ct||isNaN(Ct))return Ne.error="Error: could not calculate eventualBG. Sensitivity: "+_t+" Deviation: "+Gt,Ne;var Ut,Ot,Rt=function(e,t,a){return o(a+(e-t)/24,1)}(rt,Ct,wt);Ne={temp:"absolute",bg:Xe,tick:Ke,eventualBG:Ct,insulinReq:0,reservoir:d,deliverAt:He,sensitivityRatio,TDD:de,insulin:ce,current_target:rt,insulinForManualBolus:C,manualBolusErrorString:0,minDelta:et,expectedDelta:Rt,minGuardBG:Ot,minPredBG:Ut};var At=[],It=[],Ft=[],jt=[];At.push(Xe),It.push(Xe),jt.push(Xe),Ft.push(Xe);var Pt=function(e,t,a,r,o,i){return t?!e.allowSMB_with_high_temptarget&&e.temptargetSet&&o>100?(console.error("SMB disabled due to high temptarget of "+o),!1):!0===a.bwFound&&!1===e.A52_risk_enable?(console.error("SMB disabled due to Bolus Wizard activity in the last 6 hours."),!1):!0===e.enableSMB_always?(a.bwFound?console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled due to enableSMB_always"),!0):!0===e.enableSMB_with_COB&&a.mealCOB?(a.bwCarbs?console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for COB of "+a.mealCOB),!0):!0===e.enableSMB_after_carbs&&a.carbs?(a.bwCarbs?console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for 6h after carb entry"),!0):!0===e.enableSMB_with_temptarget&&e.temptargetSet&&o<100?(a.bwFound?console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for temptarget of "+n(o,e)),!0):!0===e.enableSMB_high_bg&&null!==i&&r>=i?(console.error("Checking BG to see if High for SMB enablement."),console.error("Current BG",r," | High BG ",i),a.bwFound?console.error("Warning: High BG SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("High BG detected. Enabling SMB."),!0):(console.error("SMB disabled (no enableSMB preferences active or no condition satisfied)"),!1):(console.error("SMB disabled (!microBolusAllowed)"),!1)}(i,m,l,Xe,rt,it);if(b)if(S){let e=c.getHours();e>=D&&e<=w&&(console.error("SMB disabled by schedule (a Profile is active with SMBs disabled)"),Pt=!1)}else console.error("SMBs are disabled (a Profile is active with SMBs disabled)"),Pt=!1;var Et=i.enableUAM,qt=0,Wt=0;qt=o(et-wt,1);var kt=o(et-wt,1);csf=_t/H,console.error("profile.sens:"+n(N,i)+", sens:"+n(_t,i)+", CSF:"+o(csf,1));var Lt=o(30*csf*5/60,1);qt>Lt&&(console.error("Limiting carb impact from "+qt+" to "+Lt+"mg/dL/5m (30g/h)"),qt=Lt);var zt=3;sensitivityRatio&&(zt/=sensitivityRatio);var Nt=zt;if(l.carbs){zt=Math.max(zt,l.mealCOB/20);var Ht=o((new Date(Je).getTime()-l.lastCarbTime)/6e4),Zt=(l.carbs-l.mealCOB)/l.carbs;Nt=o(Nt=zt+1.5*Ht/60,1),console.error("Last carbs "+Ht+" minutes ago; remainingCATime:"+Nt+"hours; "+o(100*Zt,1)+"% carbs absorbed")}var $t=Math.max(0,qt/5*60*Nt/2)/csf,Jt=90,Kt=1;i.remainingCarbsCap&&(Jt=Math.min(90,i.remainingCarbsCap)),i.remainingCarbsFraction&&(Kt=Math.min(1,i.remainingCarbsFraction));var Qt=1-Kt,Vt=Math.max(0,l.mealCOB-$t-l.carbs*Qt),Xt=(Vt=Math.min(Jt,Vt))*csf*5/60/(Nt/2),Yt=o(l.slopeFromMaxDeviation,2),ea=o(l.slopeFromMinDeviation,2),ta=Math.min(Yt,-ea/3);Wt=0===qt?0:Math.min(60*Nt/5/2,Math.max(0,l.mealCOB*csf/qt)),console.error("Carb Impact:"+qt+"mg/dL per 5m; CI Duration:"+o(5*Wt/60*2,1)+"hours; remaining CI ("+Nt/2+"h peak):"+o(Xt,1)+"mg/dL per 5m");var aa,ra,oa,na,ia=999,sa=999,la=999,ua=999,ma=999,da=999,ca=999,ga=Ct,ha=Xe,pa=Xe,va=0,fa=[],Ba=[];try{xt.forEach((function(e){var t=o(-e.activity*_t*5,2),a=o(-e.iobWithZeroTemp.activity*_t*5,2),r=Tt,n=qt*(1-Math.min(1,It.length/12));if(!0===(he&&!Ie))ga=It[It.length-1]+o(-e.activity*(1800/(P*Be*Math.log(Math.max(It[It.length-1],39)/Re+1)))*5,2)+n,r=jt[jt.length-1]+o(-e.iobWithZeroTemp.activity*(1800/(P*Be*Math.log(Math.max(jt[jt.length-1],39)/Re+1)))*5,2),console.log("Dynamic ISF (Logarithmic Formula) )adjusted predictions for IOB and ZT: IOBpredBG: "+o(ga,2)+" , ZTpredBG: "+o(r,2));else ga=It[It.length-1]+t+n,r=jt[jt.length-1]+a;var i=Math.max(0,Math.max(0,qt)*(1-At.length/Math.max(2*Wt,1))),s=Math.min(At.length,12*Nt-At.length),l=Math.max(0,s/(Nt/2*12)*Xt);i+l,fa.push(o(l,0)),Ba.push(o(i,0)),COBpredBG=At[At.length-1]+t+Math.min(0,n)+i+l;var u=Math.max(0,kt+Ft.length*ta),m=Math.max(0,kt*(1-Ft.length/Math.max(36,1))),d=Math.min(u,m);if(d>0&&(va=o(5*(Ft.length+1)/60,1)),!0===(he&&!Ie))UAMpredBG=Ft[Ft.length-1]+o(-e.activity*(1800/(P*Be*Math.log(Math.max(Ft[Ft.length-1],39)/Re+1)))*5,2)+Math.min(0,n)+d,console.log("Dynamic ISF (Logarithmic Formula) adjusted prediction for UAM: UAMpredBG: "+o(UAMpredBG,2));else UAMpredBG=Ft[Ft.length-1]+t+Math.min(0,n)+d;It.length<48&&It.push(ga),At.length<48&&At.push(COBpredBG),Ft.length<48&&Ft.push(UAMpredBG),jt.length<48&&jt.push(r),COBpredBG18&&gaha&&(ha=ga),(Wt||Xt>0)&&At.length>18&&COBpredBG0)&&COBpredBG>ha&&(pa=COBpredBG),Et&&Ft.length>12&&UAMpredBGha&&UAMpredBG}))}catch(e){console.error("Problem with iobArray. Optional feature Advanced Meal Assist disabled")}l.mealCOB&&(console.error("predCIs (mg/dL/5m):"+Ba.join(" ")),console.error("remainingCIs: "+fa.join(" "))),Ne.predBGs={},It.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))}));for(var ba=It.length-1;ba>12&&It[ba-1]===It[ba];ba--)It.pop();for(Ne.predBGs.IOB=It,ra=o(It[It.length-1]),jt.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),ba=jt.length-1;ba>6&&!(jt[ba-1]>=jt[ba]||jt[ba]<=rt);ba--)jt.pop();if(Ne.predBGs.ZT=jt,o(jt[jt.length-1]),l.mealCOB>0&&(qt>0||Xt>0)){for(At.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),ba=At.length-1;ba>12&&At[ba-1]===At[ba];ba--)At.pop();Ne.predBGs.COB=At,oa=o(At[At.length-1]),Ct=Math.max(Ct,o(At[At.length-1]))}if(qt>0||Xt>0){if(Et){for(Ft.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),ba=Ft.length-1;ba>12&&Ft[ba-1]===Ft[ba];ba--)Ft.pop();Ne.predBGs.UAM=Ft,na=o(Ft[Ft.length-1]),Ft[Ft.length-1]&&(Ct=Math.max(Ct,o(Ft[Ft.length-1])))}Ne.eventualBG=Ct}console.error("UAM Impact:"+kt+"mg/dL per 5m; UAM Duration:"+va+"hours"),ia=Math.max(39,ia),sa=Math.max(39,sa),la=Math.max(39,la),Ut=o(ia);var Ma=l.mealCOB/l.carbs;aa=o(la<999&&sa<999?(1-Ma)*UAMpredBG+Ma*COBpredBG:sa<999?(ga+COBpredBG)/2:la<999?(ga+UAMpredBG)/2:ga),ca>aa&&(aa=ca),Ot=o(Ot=Wt||Xt>0?Et?Ma*ua+(1-Ma)*ma:ua:Et?ma:da);var _a=la;if(cala&&(_a=(la+ca)/2);if(_a=o(_a),l.carbs)if(!Et&&sa<999)Ut=o(Math.max(ia,sa));else if(sa<999){var xa=Ma*sa+(1-Ma)*_a;Ut=o(Math.max(ia,sa,xa))}else Ut=Et?_a:Ot;else Et&&(Ut=o(Math.max(ia,_a)));Ut=Math.min(Ut,aa),process.stderr.write("minPredBG: "+Ut+" minIOBPredBG: "+ia+" minZTGuardBG: "+ca),sa<999&&process.stderr.write(" minCOBPredBG: "+sa),la<999&&process.stderr.write(" minUAMPredBG: "+la),console.error(" avgPredBG:"+aa+" COB/Carbs:"+l.mealCOB+"/"+l.carbs),pa>Xe&&(Ut=Math.min(Ut,pa)),Ne.COB=l.mealCOB,Ne.IOB=a.iob,Ne.BGI=n(wt,i),Ne.deviation=n(Gt,i),Ne.ISF=n(_t,i),Ne.CR=o(H,1),Ne.target_bg=n(rt,i),Ne.TDD=o(de,2),Ne.current_target=o(rt,0);var Sa=Ne.CR;We!=Ne.CR&&(Sa=We+"→"+Ne.CR),Ne.reason=Mt+", COB: "+Ne.COB+", Dev: "+Ne.deviation+", BGI: "+Ne.BGI+", CR: "+Sa+", Target: "+gt+", minPredBG "+n(Ut,i)+", minGuardBG "+n(Ot,i)+", IOBpredBG "+n(ra,i),oa>0&&(Ne.reason+=", COBpredBG "+n(oa,i)),na>0&&(Ne.reason+=", UAMpredBG "+n(na,i)),Ne.reason+=tddReason,Ne.reason+="; ";var Da=Tt;Da<40&&(Da=Math.min(Ot,Da));var wa,Ga=Bt-Da,Ta=240,Ca=240;if(l.mealCOB>0&&(qt>0||Xt>0)){for(ba=0;bawa*Xe&&(console.error("maxDelta "+n(at,i)+" > "+100*wa+"% of BG "+n(Xe,i)+" - disabling SMB"),Ne.reason+="maxDelta "+n(at,i)+" > "+100*wa+"% of BG "+n(Xe,i)+" - SMB disabled!, ",Pt=!1),console.error("BG projected to remain above "+n(ot,i)+" for "+Ta+"minutes"),(Ca<240||Ta<60)&&console.error("BG projected to remain above "+n(Bt,i)+" for "+Ca+"minutes");var Ua=Ca,Oa=i.current_basal*z*_t*Ua/60,Ra=Math.max(0,l.mealCOB-.25*l.carbs),Aa=(Ga-Oa)/csf-Ra;Oa=o(Oa),Aa=o(Aa),console.error("naive_eventualBG:",Tt,"bgUndershoot:",Ga,"zeroTempDuration:",Ua,"zeroTempEffect:",Oa,"carbsReq:",Aa),"Could not parse clock data"==l.reason?console.error("carbsReq unknown: Could not parse clock data"):Aa>=i.carbsReqThreshold&&Ca<=45&&(Ne.carbsReq=Aa,Ne.reason+=Aa+" add'l carbs req w/in "+Ca+"m; ");var Ia=0;if(Xe0&&et>Rt)Ne.reason+="IOB "+a.iob+" < "+o(-i.current_basal*z*20/60,2),Ne.reason+=" and minDelta "+n(et,i)+" > expectedDelta "+n(Rt,i)+"; ";else if(Xe=55)return Ne.reason+="; Canceling temp at "+Ne.deliverAt.getMinutes()+"m past the hour. ",u.setTempBasal(0,0,i,Ne,t);var Fa=0,ja=$e,Pa=0;if(CtRt&&et>0&&!Aa)return Tt<40?(Ne.reason+=", naive_eventualBG < 40. ",u.setTempBasal(0,30,i,Ne,t)):(e.delta>et?Ne.reason+=", but Delta "+n(Ke,i)+" > expectedDelta "+n(Rt,i):Ne.reason+=", but Min. Delta "+et.toFixed(2)+" > Exp. Delta "+n(Rt,i),t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",u.setTempBasal($e,30,i,Ne,t)));Fa=o(Fa=2*Math.min(0,(Ct-rt)/_t),2);var Ea=Math.min(0,(Tt-rt)/_t);if(Ea=o(Ea,2),et<0&&et>Rt)Fa=o(Fa*(et/Rt),2);ja=r(ja=$e+2*Fa,i),Pa=t.duration*(t.rate-$e)/60;var qa=Math.min(Fa,Ea);if(console.log("naiveInsulinReq:"+Ea),Pa5&&ja>=.8*t.rate)return Ne.reason+=", temp "+t.rate+" ~< req "+ja+"U/hr. ",Ne;if(ja<=0){if((Ia=o(60*((Ga=rt-Tt)/_t)/i.current_basal*z))<0?Ia=0:(Ia=30*o(Ia/30),Ia=Math.min(120,Math.max(0,Ia))),Ia>0)return Ne.reason+=", setting "+Ia+"m zero temp. ",u.setTempBasal(ja,Ia,i,Ne,t)}else Ne.reason+=", setting "+ja+"U/hr. ";return u.setTempBasal(ja,30,i,Ne,t)}if(et=0&&Rt>=0?3:et<=0&&Rt<=0?4:5,Ne.insulinForManualBolus=o((Ne.eventualBG-Ne.target_bg)/_t,2),!m||!Pt))return e.delta "+n(ot,i)+" but Delta "+n(Ke,i)+" < Exp. Delta "+n(Rt,i):Ne.reason+="Eventual BG "+n(Ct,i)+" > "+n(ot,i)+" but Min. Delta "+et.toFixed(2)+" < Exp. Delta "+n(Rt,i),t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",u.setTempBasal($e,30,i,Ne,t));if(Math.min(Ct,Ut)ot&&(Ne.manualBolusErrorString=6,Ne.insulinForManualBolus=o((Ne.eventualBG-Ne.target_bg)/_t,2),Ne.minPredBG=Ut),!m||!Pt))return Ne.reason+=n(Ct,i)+"-"+n(Ut,i)+" in range: no temp required",t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",u.setTempBasal($e,30,i,Ne,t));if(Ct>=nt&&(Ne.reason+="Eventual BG "+n(Ct,i)+" >= "+n(nt,i)+", "),a.iob>st)return Ne.reason+="IOB "+o(a.iob,2)+" > max_iob "+st,t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",u.setTempBasal($e,30,i,Ne,t));Fa=o((Math.min(Ut,Ct)-rt)/_t,2),C=o((Ct-rt)/_t,2),Fa>st-a.iob?(console.error("SMB limited by maxIOB: "+st-a.iob+" (. insulinReq: "+Fa+" U)"),Ne.reason+="max_iob "+st+", ",Fa=st-a.iob):console.error("SMB not limited by maxIOB ( insulinReq: "+Fa+" U)."),C>st-a.iob?(console.error("Ev. Bolus limited by maxIOB: "+st-a.iob+" (. insulinForManualBolus: "+C+" U)"),Ne.reason+="max_iob "+st+", "):console.error("Ev. Bolus would not be limited by maxIOB ( insulinForManualBolus: "+C+" U)."),ja=r(ja=$e+2*Fa,i),Fa=o(Fa,3),Ne.insulinReq=Fa,Ne.insulinForManualBolus=o(C,3);var Wa=o((new Date(Je).getTime()-a.lastBolusTime)/6e4,1);if(m&&Pt&&Xe>Bt){var ka=30;void 0!==i.maxSMBBasalMinutes&&(ka=i.maxSMBBasalMinutes);var La=30;void 0!==i.maxUAMSMBBasalMinutes&&(La=i.maxUAMSMBBasalMinutes),v.useOverride&&M&&G!==ka&&(console.error("SMB Max Minutes - setting overriden from "+ka+" to "+G),ka=G),v.useOverride&&M&&T!==La&&(console.error("UAM Max Minutes - setting overriden from "+La+" to "+T),La=T);var za=o(l.mealCOB/H,3),Na=0;void 0===ka?(Na=o(i.current_basal*z*30/60,1),console.error("smbMinutesSetting undefined: defaulting to 30m"),Fa>Na&&console.error("SMB limited by maxBolus: "+Na+" ( "+Fa+" U)")):a.iob>za&&a.iob>0?(console.error("IOB"+a.iob+"> COB"+l.mealCOB+"; mealInsulinReq ="+za),La?(console.error("maxUAMSMBBasalMinutes: "+La+", profile.current_basal: "+i.current_basal*z),Na=o(i.current_basal*z*La/60,1)):(console.error("maxUAMSMBBasalMinutes undefined: defaulting to 30m"),Na=o(i.current_basal*z*30/60,1)),Fa>Na?console.error("SMB limited by maxUAMSMBBasalMinutes [ "+La+"m ]: "+Na+"U ( "+Fa+"U )"):console.error("SMB is not limited by maxUAMSMBBasalMinutes. ( insulinReq: "+Fa+"U )")):(console.error(".maxSMBBasalMinutes: "+ka+", profile.current_basal: "+i.current_basal*z),Fa>(Na=o(i.current_basal*ka/60,1))?console.error("SMB limited by maxSMBBasalMinutes: "+ka+"m ]: "+Na+"U ( insulinReq: "+Fa+"U )"):console.error("SMB is not limited by maxSMBBasalMinutes. ( insulinReq: "+Fa+"U )"));var Ha=i.bolus_increment,Za=1/Ha,$a=i.smb_delivery_ratio;$a>.5&&console.error("SMB Delivery Ratio increased from default 0.5 to "+o($a,2));var Ja=Math.min(Fa*$a,Na);Ja=Math.floor(Ja*Za)/Za,Ia=o(60*((rt-(Tt+ia)/2)/_t)/i.current_basal*z),Fa>0&&Ja=30?(Ia=30*o(Ia/30),Ia=Math.min(60,Math.max(0,Ia))):(Ka=o($e*Ia/30,2),Ia=30),Ne.reason+=" insulinReq "+Fa,Ja>=Na&&(Ne.reason+="; maxBolus "+Na),Ia>0&&(Ne.reason+="; setting "+Ia+"m low temp of "+Ka+"U/h"),Ne.reason+=". ";var Qa=3;i.SMBInterval&&(Qa=Math.min(10,Math.max(1,i.SMBInterval)));var Va=o(Qa-Wa,0),Xa=o(60*(Qa-Wa),0)%60;if(console.error("naive_eventualBG "+Tt+","+Ia+"m "+Ka+"U/h temp needed; last bolus "+Wa+"m ago; maxBolus: "+Na),Wa>Qa?Ja>0&&(Ne.units=Ja,Ne.reason+="Microbolusing "+Ja+"U. "):Ne.reason+="Waiting "+Va+"m "+Xa+"s to microbolus again. ",Ia>0)return Ne.rate=Ka,Ne.duration=Ia,Ne}var Ya=u.getMaxSafeBasal(i);return ja>Ya&&(Ne.reason+="adj. req. rate: "+ja+" to maxSafeBasal: "+o(Ya,2)+", ",ja=r(Ya,i)),(Pa=t.duration*(t.rate-$e)/60)>=2*Fa?(Ne.reason+=t.duration+"m@"+t.rate.toFixed(2)+" > 2 * insulinReq. Setting temp basal of "+ja+"U/hr. ",u.setTempBasal(ja,30,i,Ne,t)):void 0===t.duration||0===t.duration?(Ne.reason+="no temp, setting "+ja+"U/hr. ",u.setTempBasal(ja,30,i,Ne,t)):t.duration>5&&r(ja,i)<=r(t.rate,i)?(Ne.reason+="temp "+t.rate+" >~ req "+ja+"U/hr. ",Ne):(Ne.reason+="temp "+t.rate+"<"+ja+"U/hr. ",u.setTempBasal(ja,30,i,Ne,t))}},6880:(e,t,a)=>{var r=a(6654);e.exports=function(e,t){var a=20;void 0!==t&&"string"==typeof t.model&&(r(t.model,"54")||r(t.model,"23"))&&(a=40);return e<1?Math.round(e*a)/a:e<10?Math.round(20*e)/20:Math.round(10*e)/10}},2705:(e,t,a)=>{var r=a(5639).Symbol;e.exports=r},9932:e=>{e.exports=function(e,t){for(var a=-1,r=null==e?0:e.length,o=Array(r);++a{e.exports=function(e,t,a){return e==e&&(void 0!==a&&(e=e<=a?e:a),void 0!==t&&(e=e>=t?e:t)),e}},4239:(e,t,a)=>{var r=a(2705),o=a(9607),n=a(2333),i=r?r.toStringTag:void 0;e.exports=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":i&&i in Object(e)?o(e):n(e)}},531:(e,t,a)=>{var r=a(2705),o=a(9932),n=a(1469),i=a(3448),s=r?r.prototype:void 0,l=s?s.toString:void 0;e.exports=function e(t){if("string"==typeof t)return t;if(n(t))return o(t,e)+"";if(i(t))return l?l.call(t):"";var a=t+"";return"0"==a&&1/t==-Infinity?"-0":a}},7561:(e,t,a)=>{var r=a(7990),o=/^\s+/;e.exports=function(e){return e?e.slice(0,r(e)+1).replace(o,""):e}},1957:(e,t,a)=>{var r="object"==typeof a.g&&a.g&&a.g.Object===Object&&a.g;e.exports=r},9607:(e,t,a)=>{var r=a(2705),o=Object.prototype,n=o.hasOwnProperty,i=o.toString,s=r?r.toStringTag:void 0;e.exports=function(e){var t=n.call(e,s),a=e[s];try{e[s]=void 0;var r=!0}catch(e){}var o=i.call(e);return r&&(t?e[s]=a:delete e[s]),o}},2333:e=>{var t=Object.prototype.toString;e.exports=function(e){return t.call(e)}},5639:(e,t,a)=>{var r=a(1957),o="object"==typeof self&&self&&self.Object===Object&&self,n=r||o||Function("return this")();e.exports=n},7990:e=>{var t=/\s/;e.exports=function(e){for(var a=e.length;a--&&t.test(e.charAt(a)););return a}},6654:(e,t,a)=>{var r=a(9750),o=a(531),n=a(554),i=a(9833);e.exports=function(e,t,a){e=i(e),t=o(t);var s=e.length,l=a=void 0===a?s:r(n(a),0,s);return(a-=t.length)>=0&&e.slice(a,l)==t}},1469:e=>{var t=Array.isArray;e.exports=t},3218:e=>{e.exports=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}},7005:e=>{e.exports=function(e){return null!=e&&"object"==typeof e}},3448:(e,t,a)=>{var r=a(4239),o=a(7005);e.exports=function(e){return"symbol"==typeof e||o(e)&&"[object Symbol]"==r(e)}},8601:(e,t,a)=>{var r=a(4841),o=1/0;e.exports=function(e){return e?(e=r(e))===o||e===-1/0?17976931348623157e292*(e<0?-1:1):e==e?e:0:0===e?e:0}},554:(e,t,a)=>{var r=a(8601);e.exports=function(e){var t=r(e),a=t%1;return t==t?a?t-a:t:0}},4841:(e,t,a)=>{var r=a(7561),o=a(3218),n=a(3448),i=/^[-+]0x[0-9a-f]+$/i,s=/^0b[01]+$/i,l=/^0o[0-7]+$/i,u=parseInt;e.exports=function(e){if("number"==typeof e)return e;if(n(e))return NaN;if(o(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=o(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=r(e);var a=s.test(e);return a||l.test(e)?u(e.slice(2),a?2:8):i.test(e)?NaN:+e}},9833:(e,t,a)=>{var r=a(531);e.exports=function(e){return null==e?"":r(e)}}},t={};function a(r){var o=t[r];if(void 0!==o)return o.exports;var n=t[r]={exports:{}};return e[r](n,n.exports,a),n.exports}a.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}();var r=a(5546);freeaps_determineBasal=r})(); diff --git a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings index 8507290c83..8fd82de480 100644 --- a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings @@ -143,7 +143,7 @@ "Save" = "Save"; /* */ -"Save as preset" = "Save as preset"; +"Save as Preset" = "Save as Preset"; /* Delete Meal Preset */ "Delete Preset" = "Delete Preset"; @@ -260,7 +260,7 @@ Enact a temp Basal or a temp target */ /* */ "Manual Temp Basal" = "Manual Temp Basal"; -/* Allow uploads tp NS */ +/* Allow uploads to different services */ "Allow uploads" = "Allow uploads"; /* API secret in NS */ @@ -1165,6 +1165,7 @@ Enact a temp Basal or a temp target */ /* */ "Normal " = "Normal "; +/* */ "Currently no Override active" = "Currently no Override active"; /* */ @@ -1307,17 +1308,35 @@ Enact a temp Basal or a temp target */ /* Hide pop-up */ "Hide" = "Hide"; -/* Error string 1. Make translation very short! */ -"Predicted Glucose, %@ %@, is below threshold (%@!)" = "Predicted Glucose, %@ %@, is below threshold (%@!)"; +/* Bolus pop-up / Alert string. Make translations concise! */ +"Predicted Glucose, " = "Predicted Glucose, "; + +/* Bolus pop-up / Alert string. Make translations concise! */ +"is predicted below threshold " = "is predicted below threshold "; + +/* Bolus pop-up / Alert string. Make translations concise! */ +"is below Threshold of " = "is below Threshold of "; + +/* Bolus pop-up / Alert string. Make translations concise! */ +"Eventual Glucose > Target Glucose, but glucose is climbing slower than expected. Expected: " = "Eventual Glucose > Target Glucose, but glucose is climbing slower than expected. Expected: "; + +//* Bolus pop-up / Alert string. Make translations concise! */ +". Climbing: " = ". Climbing: "; + +/* Bolus pop-up / Alert string. Make translations concise! */ +"Eventual Glucose > Target Glucose, but glucose is falling slower than expected. Expected: " = "Eventual Glucose > Target Glucose, but glucose is falling slower than expected. Expected: "; + +/* Bolus pop-up / Alert string. Make translations concise! */ +". Falling: " = ". Falling: "; -/* Error string 2. Make translation very short! */ -"Eventual Glucose > Target Glucose, but glucose is falling faster than expected. Expected: %@. Falling: %@" = "Eventual Glucose > Target Glucose, but glucose is falling faster than expected. Expected: %@. Falling: %@"; +/* Bolus pop-up / Alert string. Make translations concise! */ +"Eventual Glucose > Target Glucose, but glucose is changing faster than expected. Expected: " = "Eventual Glucose > Target Glucose, but glucose is changing faster than expected. Expected: "; -/* Error string 3. Make translation very short! */ -"Minimum predicted Glucose is %@ %@" = "Minimum predicted Glucose is %@ %@"; +/* Bolus pop-up / Alert string. Make translations concise! */ +". Changing: " = ". Changing: "; -/* Error string 4. Make translation very short! */ -"Predicted Glucose %@ %@, is below Threshold of %@" = "Predicted Glucose %@ %@, is below Threshold of %@"; +/* Bolus pop-up / Alert string. Make translations concise! */ +"Minimum predicted Glucose is " = "Minimum predicted Glucose is "; /* ------------------------------------------------------------------------------------------- DASH strings diff --git a/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings index aff9c0ae4d..b00820e968 100644 --- a/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings @@ -143,7 +143,7 @@ "Save" = "Spara"; /* */ -"Save as preset" = "Spara som förval"; +"Save as Preset" = "Spara som förval"; /* Delete Meal Preset */ "Delete Preset" = "Radera Förval"; @@ -1143,6 +1143,9 @@ Enact a temp Basal or a temp target */ /* Display fat and protein entities */ "Fat & Protein" = "Fett & protein"; +/* FPU Setttings Title */ +"Fat and Protein" = "Omvandling"; + /* */ "Hide Fat & Protein" = "Dölj fett & protein"; @@ -1271,6 +1274,37 @@ Enact a temp Basal or a temp target */ /* */ "Name Of Dish" = "Namn på rätt"; +"Currently no Override active" = "Inget undantag aktivt"; + +/* */ +"Total Insulin Adjustment" = "Total justering av ditt insulinbehov"; + +/* */ +"Override your Basal, ISF, CR and Target profiles" = "Ändra sparad basal, korrektionsfaktor, insulinkvot and målvärde med ett tillfäligt undantag"; + +/* */ +"Enable indefinitely" = "Aktivera tillsvidare"; + +/* */ +"Override Profiles" = "Aktivera tillfälligt undantag"; + +/* */ +"Override Profile Target" = "Ändra målvärde"; + +/* */ +"Disable SMBs" = "Stäng av autobolusar (SMBs)"; + +/* */ +"Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal." = "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage.\n\nIf you toggle off the override every profile setting will return to normal."; + +/* Service Section */ +"App Icons" = "Ikoner"; + +/* */ +"iAPS Icon" = "iAPS - ikon"; + +/* Service Section */ +"Statistics and Home View" = "Statistik och Diagram"; /* Save Carbs and continue to bolus recommendation */ "Save and continue" = "Spara och fortsätt"; @@ -1307,18 +1341,35 @@ Enact a temp Basal or a temp target */ /* Hide pop-up */ "Hide" = "Göm"; -/* Error string 1. Make translation very short! */ -"Predicted Glucose, %@ %@, is below threshold (%@!)" = "Blodsockerprognos, %@ %@, är lägre än (%@!)"; +/* Bolus pop-up / Alert string. Make translations concise! */ +"Predicted Glucose, " = "Prognos, "; + +/* Bolus pop-up / Alert string. Make translations concise! */ +"is predicted below threshold " = "är under tröskelvärde "; + +/* Bolus pop-up / Alert string. Make translations concise! */ +"is below Threshold of " = "är under tröskelvärde "; + +/* Bolus pop-up / Alert string. Make translations concise! */ +"Eventual Glucose > Target Glucose, but glucose is climbing slower than expected. Expected: " = "Prognos > Målvärde, men blodsocker stiger snabbare än väntat. Förväntat: "; -/* Error string 2. Make translation very short! */ -"Eventual Glucose > Target Glucose, but glucose is falling faster than expected. Expected: %@. Falling: %@" = "Blodsockerprognos > målvärde, med blodsockret sjunker snabbare än väntat. Förväntat: %@. Sjunker: %@"; +//* Bolus pop-up / Alert string. Make translations concise! */ +". Climbing: " = ". Stiger: "; -/* Error string 3. Make translation very short! */ -"Minimum predicted Glucose is %@ %@" = "Lägsta blodsockerprognos är %@ %@!"; +/* Bolus pop-up / Alert string. Make translations concise! */ +"Eventual Glucose > Target Glucose, but glucose is falling slower than expected. Expected: " = "Prognos > Målvärde, men blodsocker sjunker snabbare än väntat. Förväntat: "; -/* Error string 4. Make translation very short! */ -"Predicted Glucose %@ %@, is below Threshold of %@" = "Blodsockerprognos %@ %@, är under tröskelvärde %@"; +/* Bolus pop-up / Alert string. Make translations concise! */ +". Falling: " = ". Sjunker: "; +/* Bolus pop-up / Alert string. Make translations concise! */ +"Eventual Glucose > Target Glucose, but glucose is changing faster than expected. Expected: " = "Prognos > Målvärde, men blodsocker ändras snabbare än väntat. Förväntat: "; + +/* Bolus pop-up / Alert string. Make translations concise! */ +". Changing: " = ". Ändras: "; + +/* Bolus pop-up / Alert string. Make translations concise! */ +"Minimum predicted Glucose is " = "Lägsta prognos är "; /* ------------------------------------------------------------------------------------------- DASH strings */ @@ -1461,6 +1512,8 @@ Enact a temp Basal or a temp target */ /* ----------------------Statistics strings -------------------------------*/ /* */ +/* */ +"Today" = "Idag"; "Today" = "Idag"; diff --git a/FreeAPS/Sources/Models/Suggestion.swift b/FreeAPS/Sources/Models/Suggestion.swift index 25d074a946..6986773e27 100644 --- a/FreeAPS/Sources/Models/Suggestion.swift +++ b/FreeAPS/Sources/Models/Suggestion.swift @@ -23,7 +23,11 @@ struct Suggestion: JSON, Equatable { let insulin: Insulin? let current_target: Decimal? let insulinForManualBolus: Decimal? - let manualBolusErrorString: String? + let manualBolusErrorString: Decimal? + let minDelta: Decimal? + let expectedDelta: Decimal? + let minGuardBG: Decimal? + let minPredBG: Decimal? } struct Predictions: JSON, Equatable { @@ -65,6 +69,10 @@ extension Suggestion { case current_target case insulinForManualBolus case manualBolusErrorString + case minDelta + case expectedDelta + case minGuardBG + case minPredBG } } diff --git a/FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift b/FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift index 6491b121df..c4c8aefe2f 100644 --- a/FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift +++ b/FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift @@ -13,13 +13,18 @@ extension Bolus { @Published var waitForSuggestion: Bool = false @Published var manual: Bool = false @Published var error: Bool = false - @Published var errorString: String = "" + @Published var errorString: Decimal = 0 @Published var evBG: Int = 0 @Published var insulin: Decimal = 0 @Published var target: Decimal = 0 @Published var isf: Decimal = 0 @Published var percentage: Decimal = 0 + @Published var threshold: Decimal = 0 + @Published var minGuardBG: Decimal = 0 + @Published var minDelta: Decimal = 0 + @Published var expectedDelta: Decimal = 0 + @Published var minPredBG: Decimal = 0 @Published var units: GlucoseUnits = .mmolL @@ -30,6 +35,8 @@ extension Bolus { broadcaster.register(SuggestionObserver.self, observer: self) units = settingsManager.settings.units percentage = settingsManager.settings.insulinReqPercentage + threshold = units == .mmolL ? settingsManager.preferences.threshold_setting.asMmolL : settingsManager.preferences + .threshold_setting if waitForSuggestionInitial { apsManager.determineBasal() @@ -92,6 +99,11 @@ extension Bolus { // Manual Bolus recommendation screen after a carb entry (normally) yields a higher amount than the insulin reqiured amount computed for SMBs (auto boluses). Carbs combined with a manual bolus threfore now (test) uses the Eventual BG for glucose prediction, whereas the insulinReg for SMBs uses the minPredBG for glucose prediction (typically lower than Eventual BG). + var conversion: Decimal = 1.0 + if self.units == .mmolL { + conversion = 0.0555 + } + self.evBG = self.provider.suggestion?.eventualBG ?? 0 self.insulin = self.provider.suggestion?.insulinForManualBolus ?? 0 self.target = self.provider.suggestion?.current_target ?? 0 @@ -101,8 +113,14 @@ extension Bolus { self.insulinRecommended = self.insulin * (self.settingsManager.settings.insulinReqPercentage / 100) } else { self.insulinRecommended = self.insulin } - self.errorString = self.provider.suggestion?.manualBolusErrorString ?? "" - if self.errorString.count > 8 { self.error = true } + self.errorString = self.provider.suggestion?.manualBolusErrorString ?? 0 + if self.errorString != 0 { + self.error = true + self.minGuardBG = (self.provider.suggestion?.minGuardBG ?? 0) * conversion + self.minDelta = (self.provider.suggestion?.minDelta ?? 0) * conversion + self.expectedDelta = (self.provider.suggestion?.expectedDelta ?? 0) * conversion + self.minPredBG = (self.provider.suggestion?.minPredBG ?? 0) * conversion + } else { self.error = false } self.insulinRecommended = self.apsManager .roundBolus(amount: max(self.insulinRecommended, 0)) diff --git a/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift b/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift index 144ad05f4f..95782d341f 100644 --- a/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift +++ b/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift @@ -7,6 +7,7 @@ extension Bolus { let waitForSuggestion: Bool let manualBolus: Bool @StateObject var state = StateModel() + @State private var isAddInsulinAlertPresented = false @State private var presentInfo = false @State private var displayError = false @@ -20,6 +21,12 @@ extension Bolus { return formatter } + private var fractionDigits: Int { + if state.units == .mmolL { + return 1 + } else { return 0 } + } + var body: some View { Form { Section { @@ -70,13 +77,11 @@ extension Bolus { } } header: { Text("Bolus") } - Section { Button { state.add() } label: { Text("Enact bolus") } .disabled(state.amount <= 0) } - Section { if waitForSuggestion { Button { state.showModal(for: nil) } @@ -87,25 +92,30 @@ extension Bolus { .disabled(state.amount <= 0) } } + .alert(isPresented: $isAddInsulinAlertPresented) { + Alert( + title: Text("Are you sure?"), + message: Text( + "Add" + formatter + .string(from: state.amount as NSNumber)! + NSLocalizedString(" U", comment: "Insulin unit") + + NSLocalizedString(" without bolusing", comment: "") + ), + primaryButton: .destructive( + Text("Add"), + action: { + state.addWithoutBolus() + isAddInsulinAlertPresented = false + } + ), + secondaryButton: .cancel() + ) + } } } - .alert(isPresented: $isAddInsulinAlertPresented) { - let amount = formatter - .string(from: state.amount as NSNumber)! + NSLocalizedString(" U", comment: "Insulin unit") - return Alert( - title: Text("Are you sure?"), - message: Text("Add \(amount) without bolusing"), - primaryButton: .destructive( - Text("Add"), - action: { state.addWithoutBolus() } - ), - secondaryButton: .cancel() - ) - } .alert(isPresented: $displayError) { Alert( title: Text("Warning!"), - message: Text("\n" + NSLocalizedString(state.errorString, comment: "") + NSLocalizedString( + message: Text("\n" + alertString() + NSLocalizedString( "\n\nTap 'Add' to continue with selected amount.", comment: "Alert text to confirm bolus amount to add" )), @@ -123,7 +133,6 @@ extension Bolus { configureView { state.waitForSuggestionInitial = waitForSuggestion state.waitForSuggestion = waitForSuggestion - state.manual = manualBolus } } .navigationTitle("Enact Bolus") @@ -141,15 +150,13 @@ extension Bolus { HStack { Text("Eventual Glucose").foregroundColor(.secondary) let evg = state.units == .mmolL ? Decimal(state.evBG).asMmolL : Decimal(state.evBG) - let fractionDigit = state.units == .mmolL ? 1 : 0 - Text(evg.formatted(.number.grouping(.never).rounded().precision(.fractionLength(fractionDigit)))) + Text(evg.formatted(.number.grouping(.never).rounded().precision(.fractionLength(fractionDigits)))) Text(state.units.rawValue).foregroundColor(.secondary) } HStack { Text("Target Glucose").foregroundColor(.secondary) let target = state.units == .mmolL ? state.target.asMmolL : state.target - let fractionDigit = state.units == .mmolL ? 1 : 0 - Text(target.formatted(.number.grouping(.never).rounded().precision(.fractionLength(fractionDigit)))) + Text(target.formatted(.number.grouping(.never).rounded().precision(.fractionLength(fractionDigits)))) Text(state.units.rawValue).foregroundColor(.secondary) } HStack { @@ -198,15 +205,15 @@ extension Bolus { } } // Warning - VStack { - Divider() - if state.error, state.insulinRecommended > 0 { - Text("Warning!").font(.callout).foregroundColor(.orange).bold() - Text(NSLocalizedString(state.errorString, comment: "")).font(.caption) + if state.error, state.insulinRecommended > 0 { + VStack(spacing: 5) { Divider() - } - }.padding(.horizontal, 10) - // Footer. Warning string . + Text("Warning!").font(.callout).bold().foregroundColor(.orange) + Text(alertString()).font(.footnote) + Divider() + }.padding(.horizontal, 10) + } + // Footer. if !(state.error && state.insulinRecommended > 0) { VStack { Text( @@ -227,10 +234,77 @@ extension Bolus { // .fill(Color(.systemGray).gradient) // A more prominent pop-up, but harder to read ) } + + // Localize the Oref0 error/warning strings + private func alertString() -> String { + switch state.errorString { + case 1: + return NSLocalizedString( + "Predicted Glucose, ", + comment: "Bolus pop-up / Alert string. Make translations concise!" + ) + state.minGuardBG + .formatted(.number.grouping(.never).rounded().precision(.fractionLength(fractionDigits))) + " " + state.units + .rawValue + ", " + + NSLocalizedString( + "is predicted below threshold ", + comment: "Bolus pop-up / Alert string. Make translations concise!" + ) + state + .threshold.formatted(.number.grouping(.never).rounded().precision(.fractionLength(fractionDigits))) + "!" + case 2: + return NSLocalizedString( + "Predicted Glucose, ", + comment: "Bolus pop-up / Alert string. Make translations concise!" + ) + state.minGuardBG + .formatted(.number.grouping(.never).rounded().precision(.fractionLength(fractionDigits))) + " " + state.units + .rawValue + ", " + + NSLocalizedString( + "is below Threshold of ", + comment: "Bolus pop-up / Alert string. Make translations concise!" + ) + state + .threshold.formatted(.number.grouping(.never).rounded().precision(.fractionLength(fractionDigits))) + case 3: + return NSLocalizedString( + "Eventual Glucose > Target Glucose, but glucose is climbing slower than expected. Expected: ", + comment: "Bolus pop-up / Alert string. Make translations concise!" + ) + + state.expectedDelta + .formatted(.number.grouping(.never).rounded().precision(.fractionLength(fractionDigits))) + + NSLocalizedString(". Climbing: ", comment: "Bolus pop-up / Alert string. Make translatons concise!") + state + .minDelta.formatted(.number.grouping(.never).rounded().precision(.fractionLength(fractionDigits))) + case 4: + return NSLocalizedString( + "Eventual Glucose > Target Glucose, but glucose is falling slower than expected. Expected: ", + comment: "Bolus pop-up / Alert string. Make translations concise!" + ) + + state.expectedDelta + .formatted(.number.grouping(.never).rounded().precision(.fractionLength(fractionDigits))) + + NSLocalizedString(". Falling: ", comment: "Bolus pop-up / Alert string. Make translations concise!") + state + .minDelta.formatted(.number.grouping(.never).rounded().precision(.fractionLength(fractionDigits))) + case 5: + return NSLocalizedString( + "Eventual Glucose > Target Glucose, but glucose is changing faster than expected. Expected: ", + comment: "Bolus pop-up / Alert string. Make translations concise!" + ) + + state.expectedDelta + .formatted(.number.grouping(.never).rounded().precision(.fractionLength(fractionDigits))) + + NSLocalizedString(". Changing: ", comment: "Bolus pop-up / Alert string. Make translations concise!") + state + .minDelta.formatted(.number.grouping(.never).rounded().precision(.fractionLength(fractionDigits))) + case 6: + return NSLocalizedString( + "Minimum predicted Glucose is ", + comment: "Bolus pop-up / Alert string. Make translations concise!" + ) + state + .minPredBG + .formatted(.number.grouping(.never).rounded().precision(.fractionLength(fractionDigits))) + " " + state + .units + .rawValue + default: + return "Ignore Warning..." + } + } } } -// fix iOS 15 bug struct ActivityIndicator: UIViewRepresentable { @Binding var isAnimating: Bool let style: UIActivityIndicatorView.Style diff --git a/FreeAPS/Sources/Modules/Stat/View/StatRootView.swift b/FreeAPS/Sources/Modules/Stat/View/StatRootView.swift index 28f266ded3..5fbc937794 100644 --- a/FreeAPS/Sources/Modules/Stat/View/StatRootView.swift +++ b/FreeAPS/Sources/Modules/Stat/View/StatRootView.swift @@ -143,9 +143,9 @@ extension Stat { Text(NSLocalizedString(duration.rawValue, comment: "")).tag(Optional(duration)) } } - .pickerStyle(.segmented).background(.cyan.opacity(0.2)) + .pickerStyle(.segmented).background(.cyan.opacity(0.1)) stats() - } + } // .background(Color(red: 0.235, green: 0.18, blue: 0.396).gradient) // .brightness(0.2) .onAppear(perform: configureView) .navigationBarTitle("Statistics") .navigationBarTitleDisplayMode(.automatic) From ff0e92fde2584aaca27cc753b6b9fcd93e280bae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Wed, 14 Jun 2023 22:59:14 +0200 Subject: [PATCH 38/45] Clean --- FreeAPS/Sources/Modules/Stat/View/StatRootView.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FreeAPS/Sources/Modules/Stat/View/StatRootView.swift b/FreeAPS/Sources/Modules/Stat/View/StatRootView.swift index 5fbc937794..28f266ded3 100644 --- a/FreeAPS/Sources/Modules/Stat/View/StatRootView.swift +++ b/FreeAPS/Sources/Modules/Stat/View/StatRootView.swift @@ -143,9 +143,9 @@ extension Stat { Text(NSLocalizedString(duration.rawValue, comment: "")).tag(Optional(duration)) } } - .pickerStyle(.segmented).background(.cyan.opacity(0.1)) + .pickerStyle(.segmented).background(.cyan.opacity(0.2)) stats() - } // .background(Color(red: 0.235, green: 0.18, blue: 0.396).gradient) // .brightness(0.2) + } .onAppear(perform: configureView) .navigationBarTitle("Statistics") .navigationBarTitleDisplayMode(.automatic) From e55442415d4542fc60763c1516e0176f13e1fcaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Wed, 14 Jun 2023 23:12:07 +0200 Subject: [PATCH 39/45] Missing loc --- .../Sources/Localizations/Main/en.lproj/Localizable.strings | 3 +++ .../Sources/Localizations/Main/sv.lproj/Localizable.strings | 4 ++++ FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift | 4 ++-- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings index 8fd82de480..200a7c537b 100644 --- a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings @@ -1338,6 +1338,9 @@ Enact a temp Basal or a temp target */ /* Bolus pop-up / Alert string. Make translations concise! */ "Minimum predicted Glucose is " = "Minimum predicted Glucose is "; +/* Add insulin without bolusing alert */ +" without bolusing" = " without bolusing"; + /* ------------------------------------------------------------------------------------------- DASH strings */ diff --git a/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings index b00820e968..4926f659a6 100644 --- a/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings @@ -1370,6 +1370,10 @@ Enact a temp Basal or a temp target */ /* Bolus pop-up / Alert string. Make translations concise! */ "Minimum predicted Glucose is " = "Lägsta prognos är "; + +/* Add insulin without bolusing alert */ +" without bolusing" = " utan att ge insulin"; + /* ------------------------------------------------------------------------------------------- DASH strings */ diff --git a/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift b/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift index 95782d341f..c4d63ceb42 100644 --- a/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift +++ b/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift @@ -96,9 +96,9 @@ extension Bolus { Alert( title: Text("Are you sure?"), message: Text( - "Add" + formatter + "Add " + formatter .string(from: state.amount as NSNumber)! + NSLocalizedString(" U", comment: "Insulin unit") + - NSLocalizedString(" without bolusing", comment: "") + NSLocalizedString(" without bolusing", comment: "Add insulin without bolusing alert") ), primaryButton: .destructive( Text("Add"), From 5bf8537a77f545b7c64ec0fca89857f911f86aca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20B=20M=C3=A5rtensson?= <53905247+Jon-b-m@users.noreply.github.com> Date: Wed, 14 Jun 2023 23:36:48 +0200 Subject: [PATCH 40/45] Merge fix --- FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift b/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift index 67f8b4676a..cc4602e4f9 100644 --- a/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift +++ b/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift @@ -231,6 +231,7 @@ extension Bolus { Divider() }.padding(.horizontal, 10) } + // Footer if !(state.error && state.insulinRecommended > 0) { VStack { Text( From 8c487bd38a886e62a6ff04a0358dcdc76651a811 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Wed, 14 Jun 2023 23:54:39 +0200 Subject: [PATCH 41/45] More clean up --- FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift | 1 - FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift | 2 -- 2 files changed, 3 deletions(-) diff --git a/FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift b/FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift index b2aa6351b8..cb0ba4e7fe 100644 --- a/FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift +++ b/FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift @@ -12,7 +12,6 @@ extension Bolus { @Published var insulinRecommended: Decimal = 0 @Published var insulinRequired: Decimal = 0 @Published var waitForSuggestion: Bool = false - @Published var manual: Bool = false @Published var error: Bool = false @Published var errorString: Decimal = 0 @Published var evBG: Int = 0 diff --git a/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift b/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift index cc4602e4f9..890a70e5c5 100644 --- a/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift +++ b/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift @@ -5,7 +5,6 @@ extension Bolus { struct RootView: BaseView { let resolver: Resolver let waitForSuggestion: Bool - let manualBolus: Bool @StateObject var state = StateModel() @State private var isAddInsulinAlertPresented = false @@ -150,7 +149,6 @@ extension Bolus { configureView { state.waitForSuggestionInitial = waitForSuggestion state.waitForSuggestion = waitForSuggestion - state.manual = manualBolus } } .navigationTitle("Enact Bolus") From cfef393f279ddc87ecb158d372f354f8d3ca6f91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Wed, 14 Jun 2023 23:56:36 +0200 Subject: [PATCH 42/45] Comment --- FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift b/FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift index cb0ba4e7fe..afdadd9865 100644 --- a/FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift +++ b/FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift @@ -95,7 +95,7 @@ extension Bolus { DispatchQueue.main.async { self.insulinRequired = self.provider.suggestion?.insulinReq ?? 0 - // Manual Bolus recommendation screen after a carb entry (normally) yields a higher amount than the insulin reqiured amount computed for SMBs (auto boluses). Carbs combined with a manual bolus threfore now (test) uses the Eventual BG for glucose prediction, whereas the insulinReg for SMBs uses the minPredBG for glucose prediction (typically lower than Eventual BG). + // Manual Bolus recommendation (normally) yields a higher amount than the insulin reqiured amount computed for SMBs (auto boluses). A manual bolus threfore now (test) uses the Eventual BG for glucose prediction, whereas the insulinReg for SMBs uses the minPredBG for glucose prediction (typically lower than Eventual BG). var conversion: Decimal = 1.0 if self.units == .mmolL { From e948323fe56d2a445f228af899c089c335c5c2d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Thu, 15 Jun 2023 08:44:52 +0200 Subject: [PATCH 43/45] Bug fixes. Remove unused argument. Remove old string variable. --- FreeAPS/Sources/Modules/AddCarbs/AddCarbsStateModel.swift | 4 +--- FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift | 2 +- FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift | 2 +- FreeAPS/Sources/Modules/Home/View/HomeRootView.swift | 2 +- FreeAPS/Sources/Router/Screen.swift | 6 +++--- 5 files changed, 7 insertions(+), 9 deletions(-) diff --git a/FreeAPS/Sources/Modules/AddCarbs/AddCarbsStateModel.swift b/FreeAPS/Sources/Modules/AddCarbs/AddCarbsStateModel.swift index bff66a5723..a18f8417b0 100644 --- a/FreeAPS/Sources/Modules/AddCarbs/AddCarbsStateModel.swift +++ b/FreeAPS/Sources/Modules/AddCarbs/AddCarbsStateModel.swift @@ -16,7 +16,6 @@ extension AddCarbs { @Published var dish: String = "" @Published var selection: Presets? @Published var summation: [String] = [] - @Published var manualBolus: Bool = false let coredataContext = CoreDataStack.shared.persistentContainer.viewContext @@ -109,8 +108,7 @@ extension AddCarbs { apsManager.determineBasalSync() showModal(for: nil) } else { - manualBolus.toggle() - showModal(for: .bolus(waitForSuggestion: true, manualBolus: manualBolus)) + showModal(for: .bolus(waitForSuggestion: true)) } } diff --git a/FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift b/FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift index afdadd9865..59d2651f21 100644 --- a/FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift +++ b/FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift @@ -7,7 +7,7 @@ extension Bolus { @Injected() var apsManager: APSManager! @Injected() var broadcaster: Broadcaster! @Injected() var pumpHistoryStorage: PumpHistoryStorage! - + @Published var amount: Decimal = 0 @Published var insulinRecommended: Decimal = 0 @Published var insulinRequired: Decimal = 0 diff --git a/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift b/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift index 890a70e5c5..8968c89d6f 100644 --- a/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift +++ b/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift @@ -131,7 +131,7 @@ extension Bolus { .alert(isPresented: $displayError) { Alert( title: Text("Warning!"), - message: Text("\n" + NSLocalizedString(state.errorString, comment: "") + NSLocalizedString( + message: Text("\n" + alertString() + NSLocalizedString( "\n\nTap 'Add' to continue with selected amount.", comment: "Alert text to confirm bolus amount to add" )), diff --git a/FreeAPS/Sources/Modules/Home/View/HomeRootView.swift b/FreeAPS/Sources/Modules/Home/View/HomeRootView.swift index b6912144e4..60806f8fab 100644 --- a/FreeAPS/Sources/Modules/Home/View/HomeRootView.swift +++ b/FreeAPS/Sources/Modules/Home/View/HomeRootView.swift @@ -502,7 +502,7 @@ extension Home { .padding(8) }.foregroundColor(.loopGreen) Spacer() - Button { state.showModal(for: .bolus(waitForSuggestion: false, manualBolus: false)) } + Button { state.showModal(for: .bolus(waitForSuggestion: false)) } label: { Image("bolus") .renderingMode(.template) diff --git a/FreeAPS/Sources/Router/Screen.swift b/FreeAPS/Sources/Router/Screen.swift index 76fb42131e..af152733c9 100644 --- a/FreeAPS/Sources/Router/Screen.swift +++ b/FreeAPS/Sources/Router/Screen.swift @@ -16,7 +16,7 @@ enum Screen: Identifiable, Hashable { case preferencesEditor case addCarbs case addTempTarget - case bolus(waitForSuggestion: Bool, manualBolus: Bool) + case bolus(waitForSuggestion: Bool) case manualTempBasal case autotuneConfig case dataTable @@ -67,8 +67,8 @@ extension Screen { AddCarbs.RootView(resolver: resolver) case .addTempTarget: AddTempTarget.RootView(resolver: resolver) - case let .bolus(waitForSuggestion, manualBolus): - Bolus.RootView(resolver: resolver, waitForSuggestion: waitForSuggestion, manualBolus: manualBolus) + case let .bolus(waitForSuggestion): + Bolus.RootView(resolver: resolver, waitForSuggestion: waitForSuggestion) case .manualTempBasal: ManualTempBasal.RootView(resolver: resolver) case .autotuneConfig: From 9a5010a1664e85df2933b63e0405486fc7871e70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Thu, 15 Jun 2023 10:07:27 +0200 Subject: [PATCH 44/45] Describe better... and missing localization commit --- .../Resources/javascript/bundle/determine-basal.js | 2 +- .../Main/en.lproj/Localizable.strings | 11 ++++------- .../Main/sv.lproj/Localizable.strings | 6 +++--- .../Sources/Modules/Bolus/View/BolusRootView.swift | 14 +++++++------- 4 files changed, 15 insertions(+), 18 deletions(-) diff --git a/FreeAPS/Resources/javascript/bundle/determine-basal.js b/FreeAPS/Resources/javascript/bundle/determine-basal.js index d1f10ddceb..afb40d94e2 100644 --- a/FreeAPS/Resources/javascript/bundle/determine-basal.js +++ b/FreeAPS/Resources/javascript/bundle/determine-basal.js @@ -1 +1 @@ -var freeaps_determineBasal;(()=>{var e={5546:(e,t,a)=>{var r=a(6880);function o(e,t){t||(t=0);var a=Math.pow(10,t);return Math.round(e*a)/a}function n(e,t){return"mmol/L"===t.out_units?o(.0555*e,1):Math.round(e)}e.exports=function(e,t,a,i,s,l,u,m,d,c,g,h,p,v){var f=i.min_bg,B=v.overrideTarget;const b=v.smbIsOff,M=v.advancedSettings,_=v.isfAndCr,y=v.isf,x=v.cr,S=v.smbIsAlwaysOff,D=v.start,w=v.end,G=v.smbMinutes,T=v.uamMinutes;var C=0,U=0,O="",R="",A="",I="",F="",j=0,P=0,E=0,q=0,W=0,k=0;const L=v.weightedAverage;var z=1,N=i.sens,H=i.carb_ratio;v.useOverride&&(z=v.overridePercentage/100,_?(N/=z,H/=z):(x&&(H/=z),y&&(N/=z)));const Z=i.weightPercentage,$=v.average_total_data;function J(e,t){var a=e.getTime();return new Date(a+36e5*t)}function K(e){var t=i.bolus_increment;.025!=t&&(t=.05);var a=e/t;return a>=1?o(Math.floor(a)*t,5):0}function Q(e){function t(e){return e<10&&(e="0"+e),e}return t(e.getHours())+":"+t(e.getMinutes())+":00"}function V(e,t){var a=new Date("1/1/1999 "+e),r=new Date("1/1/1999 "+t);return(a.getTime()-r.getTime())/36e5}function X(e,t){var a=0,r=t,o=(e-t)/36e5,n=0,i=o,s=0;do{if(o>0){var l=Q(r),u=p[0].rate;for(let e=0;e=(s=V(p[e+1].start,p[e].start))?n=s:o=s?n=s:om)if(e+1=(s=V(d,l))?n=s:o=(s=V("23:59:59",l))?n=s:o0&&o21)W=X(Y,(te=24-U,ae=Y.getTime(),new Date(ae-36e5*te))),I="24 hours of data is required for an accurate tdd calculation. Currently only "+U.toPrecision(3)+" hours of pump history data are available. Using your pump scheduled basals to fill in the missing hours. Scheduled basals added: "+W.toPrecision(5)+" U. ";else U<21?(he=!1,enableDynamicCR=!1):I=""}else console.log("Pumphistory is empty!"),he=!1,enableDynamicCR=!1;var te,ae;for(let e=0;e0){j=e,k=g[e].rate;var re=g[e-1]["duration (min)"]/60,oe=re,ne=new Date(g[e-1].timestamp),ie=ne,se=0;do{if(e--,0==e){ie=new Date;break}if("TempBasal"==g[e]._type||"PumpSuspend"==g[e]._type){ie=new Date(g[e].timestamp);break}var le=e-2;if(le>=0&&"Rewind"==g[le]._type){let e=g[le].timestamp;for(;le-1>=0&&"Prime"==g[le-=1]._type;)se=(g[le].timestamp-e)/36e5;se>=re&&(ie=e,se=0)}}while(e>0);var ue=(ie-ne)/36e5;ue0&&(--r,"TempBasal"==g[r]._type)){a=new Date(g[r].timestamp);break}}while(r>0);(a-t)/36e5>0&&(W+=X(a,t))}for(let e=g.length-1;e>0;e--)if("TempBasalDuration"==g[e]._type){let t=g[e]["duration (min)"]/60,a=new Date(g[e].timestamp);var me=a;let r=e;do{if(--r,r>=0&&("TempBasal"==g[r]._type||"PumpSuspend"==g[r]._type)){me=new Date(g[r].timestamp);break}}while(r>0);if(0==e&&"TempBasalDuration"==g[0]._type&&(me=new Date,t=g[e]["duration (min)"]/60),(me-a)/36e5-t>0){W+=X(me,J(a,t))}}var de,ce={TDD:o(P=q+E+W,5),bolus:o(q,5),temp_basal:o(E,5),scheduled_basal:o(W,5)};U>21?(R=". Bolus insulin: "+q.toPrecision(5)+" U",A=". Temporary basal insulin: "+E.toPrecision(5)+" U",O=". Insulin with scheduled basal rate: "+W.toPrecision(5)+" U",F=I+(" TDD past 24h is: "+P.toPrecision(5)+" U")+R+A+O,tddReason=", Total insulin: "+o(P,2)+" U, "+o(q/P*100,0)+"% Bolus "+o((E+W)/P*100,0)+"% Basal"):tddReason=", TDD: Not enough pumpData (< 21h)";const ge=e.glucose;var he=h.useNewFormula;const pe=h.enableDynamicCR,ve=Math.min(i.autosens_min,i.autosens_max),fe=Math.max(i.autosens_min,i.autosens_max);(fe==ve||fe<1||ve>1)&&(he=!1,console.log("Dynamic ISF disabled due to current autosens settings"));const Be=h.adjustmentFactor,be=i.min_bg;var Me=!1,_e="",ye=1,xe="";$>0&&(ye=L/$),xe=ye>1?"Basal adjustment with a 24 hour to total average (up to 14 days of data) TDD ratio (limited by Autosens max setting). Basal Ratio: "+(ye=o(ye=Math.min(ye,i.autosens_max),2))+". Upper limit = Autosens max ("+i.autosens_max+")":ye<1?"Basal adjustment with a 24 hour to to total average (up to 14 days of data) TDD ratio (limited by Autosens min setting). Basal Ratio: "+(ye=o(ye=Math.max(ye,i.autosens_min),2))+". Lower limit = Autosens min ("+i.autosens_min+")":"Basal adjusted with a 24 hour to total average (up to 14 days of data) TDD ratio: "+ye,xe=", Basal ratio: "+ye,(i.high_temptarget_raises_sensitivity||i.exercise_mode||v.isEnabled)&&(Me=!0),be>=118&&Me&&(he=!1,_e="Dynamic ISF temporarily off due to a high temp target/exercising. Current min target: "+be);var Se=", Dynamic ratios log: ",De=", AF: "+Be,we="BG: "+ge+" mg/dl ("+(.0555*ge).toPrecision(2)+" mmol/l)",Ge="",Te="";const Ce=h.curve,Ue=h.insulinPeakTime,Oe=h.useCustomPeakTime;var Re=55,Ae=65;switch(Ce){case"rapid-acting":Ae=65;break;case"ultra-rapid":Ae=50}Oe?(Re=120-Ue,console.log("Custom insulinpeakTime set to :"+Ue+", insulinFactor: "+Re)):(Re=120-Ae,console.log("insulinFactor set to : "+Re)),de=P,Z<1&&L>0&&(P=L,console.log("Using weighted TDD average: "+o(P,2)+" U, instead of past 24 h ("+o(de,2)+" U), weight: "+Z),Te=", Weighted TDD: "+o(P,2)+" U");const Ie=h.sigmoid;var Fe="";if(he){var je=N*Be*P*Math.log(ge/Re+1)/1800;Ge=", Logarithmic formula"}if(he&&Ie){const e=ve,t=fe-e,a=.0555*(ge-i.min_bg);var Pe=ye,Ee=fe-1;1==fe&&(Ee=fe+.01-1);const r=Math.log10(1/Ee-e/Ee)/Math.log10(Math.E),o=a*Be*Pe+r;je=t/(1+Math.exp(-o))+e,Ge=", Sigmoid function"}var qe=H;const We=o(H,1);var ke="",Le="";if(he&&P>0){if(ke=", Dynamic ISF/CR: On/",je>fe?(_e=", Dynamic ISF limited by autosens_max setting: "+fe+" ("+o(je,2)+"), ",Le=", Autosens/Dynamic Limit: "+fe+" ("+o(je,2)+")",je=fe):je-.5?"+"+o(e.delta,0):o(e.delta,0);var et=Math.min(e.delta,e.short_avgdelta),tt=Math.min(e.short_avgdelta,e.long_avgdelta),at=Math.max(e.delta,e.short_avgdelta,e.long_avgdelta);(Xe<=10||38===Xe||Ye>=3)&&(Ne.reason="CGM is calibrating, in ??? state, or noise is high");if(Xe>60&&0==e.delta&&e.short_avgdelta>-1&&e.short_avgdelta<1&&e.long_avgdelta>-1&&e.long_avgdelta<1&&("fakecgm"==e.device?(console.error("CGM data is unchanged ("+n(Xe,i)+"+"+n(e.delta,i)+") for 5m w/ "+n(e.short_avgdelta,i)+" mg/dL ~15m change & "+n(e.long_avgdelta,2)+" mg/dL ~45m change"),console.error("Simulator mode detected ("+e.device+"): continuing anyway")):!0),Ve>12||Ve<-5?Ne.reason="If current system time "+Je+" is correct, then BG data is too old. The last BG data was read "+Ve+"m ago at "+Qe:0===e.short_avgdelta&&0===e.long_avgdelta&&(e.last_cal&&e.last_cal<3?Ne.reason="CGM was just calibrated":Ne.reason="CGM data is unchanged ("+n(Xe,i)+"+"+n(e.delta,i)+") for 5m w/ "+n(e.short_avgdelta,i)+" mg/dL ~15m change & "+n(e.long_avgdelta,i)+" mg/dL ~45m change"),Xe<=10||38===Xe||Ye>=3||Ve>12||Ve<-5||0===e.short_avgdelta&&0===e.long_avgdelta)return t.rate>=$e?(Ne.reason+=". Canceling high temp basal of "+t.rate,Ne.deliverAt=He,Ne.temp="absolute",Ne.duration=0,Ne.rate=0,Ne):0===t.rate&&t.duration>30?(Ne.reason+=". Shortening "+t.duration+"m long zero temp to 30m. ",Ne.deliverAt=He,Ne.temp="absolute",Ne.duration=30,Ne.rate=0,Ne):(Ne.reason+=". Temp "+t.rate+" <= current basal "+$e+"U/hr; doing nothing. ",Ne);var rt,ot,nt,it,st=i.max_iob;if(void 0!==i.min_bg&&(ot=i.min_bg),void 0!==i.max_bg&&(nt=i.max_bg),void 0!==i.enableSMB_high_bg_target&&(it=i.enableSMB_high_bg_target),void 0===i.min_bg||void 0===i.max_bg)return Ne.error="Error: could not determine target_bg. ",Ne;rt=(i.min_bg+i.max_bg)/2;var lt=i.exercise_mode||i.high_temptarget_raises_sensitivity||v.isEnabled,ut=100,mt=160;if(mt=i.half_basal_exercise_target,v.isEnabled){const e=v.hbt;console.log("Half Basal Target used: "+n(e,i)+" "+i.out_units),mt=e}else console.log("Default Half Basal Target used: "+n(mt,i)+" "+i.out_units);if(lt&&i.temptargetSet&&rt>ut||i.low_temptarget_lowers_sensitivity&&i.temptargetSet&&rt=rt&&sensitivityRatio0&&(process.stderr.write("TDD-adjustment of basals activated, using tdd24h_14d_Ratio "+o(ye,2)+", TDD 24h = "+o(de,2)+"U, Weighted average TDD = "+o(L,2)+"U, (Weight percentage = "+Z+"), Total data of TDDs (up to 14 days) average = "+o($,2)+"U. "),$e!==Ze*z?process.stderr.write("Adjusting basal from "+Ze*z+" U/h to "+$e+" U/h; "):process.stderr.write("Basal unchanged: "+$e+" U/h; "))),i.temptargetSet);else if(void 0!==s&&s&&(i.sensitivity_raises_target&&s.ratio<1||i.resistance_lowers_target&&s.ratio>1)){ot=o((ot-60)/s.ratio)+60,nt=o((nt-60)/s.ratio)+60;var ct=o((rt-60)/s.ratio)+60;rt===(ct=Math.max(80,ct))?process.stderr.write("target_bg unchanged: "+n(ct,i)+"; "):process.stderr.write("target_bg from "+n(ct,i)+" to "+n(ct,i)+"; "),rt=ct}var gt=n(rt,i);rt!=f&&(gt=0!==B&&B!==rt?n(f,i)+"→"+n(B,i)+"→"+n(rt,i):n(f,i)+"→"+n(rt,i));var ht=200,pt=200,vt=200;if(e.noise>=2){var ft=Math.max(1.1,i.noisyCGMTargetMultiplier);Math.min(250,i.maxRaw);ht=o(Math.min(200,ot*ft)),pt=o(Math.min(200,rt*ft)),vt=o(Math.min(200,nt*ft)),process.stderr.write("Raising target_bg for noisy / raw CGM data, from "+n(ct,i)+" to "+n(pt,i)+"; "),ot=ht,rt=pt,nt=vt}var Bt=ot-.5*(ot-40),bt=i.threshold_setting;bt>Bt&&bt<=120&&bt>=65?(console.error("Threshold changed in settings from "+n(Bt,i)+" to "+n(bt,i)+". "),Bt=bt):console.error("Current threshold: "+n(Bt,i));var Mt="",_t=(o(N,1),N);if(void 0!==s&&s&&((_t=o(_t=N/sensitivityRatio,1))!==N?process.stderr.write("ISF from "+n(N,i)+" to "+n(_t,i)):process.stderr.write("ISF unchanged: "+n(_t,i)),Mt+="Autosens ratio: "+o(sensitivityRatio,2)+", ISF: "+n(N,i)+"→"+n(_t,i)),console.error("CR:"+H),void 0===a)return Ne.error="Error: iob_data undefined. ",Ne;var yt,xt=a;if(a.length,a.length>1&&(a=xt[0]),void 0===a.activity||void 0===a.iob)return Ne.error="Error: iob_data missing some property. ",Ne;var St=((yt=void 0!==a.lastTemp?o((new Date(Je).getTime()-a.lastTemp.date)/6e4):0)+t.duration)%30;if(console.error("currenttemp:"+t.rate+" lastTempAge:"+yt+"m, tempModulus:"+St+"m"),Ne.temp="absolute",Ne.deliverAt=He,m&&t&&a.lastTemp&&t.rate!==a.lastTemp.rate&&yt>10&&t.duration)return Ne.reason="Warning: currenttemp rate "+t.rate+" != lastTemp rate "+a.lastTemp.rate+" from pumphistory; canceling temp",u.setTempBasal(0,0,i,Ne,t);if(t&&a.lastTemp&&t.duration>0){var Dt=yt-a.lastTemp.duration;if(Dt>5&&yt>10)return Ne.reason="Warning: currenttemp running but lastTemp from pumphistory ended "+Dt+"m ago; canceling temp",u.setTempBasal(0,0,i,Ne,t)}var wt=o(-a.activity*_t*5,2),Gt=o(6*(et-wt));Gt<0&&(Gt=o(6*(tt-wt)))<0&&(Gt=o(6*(e.long_avgdelta-wt)));var Tt=Xe,Ct=(Tt=a.iob>0?o(Xe-a.iob*_t):o(Xe-a.iob*Math.min(_t,N)))+Gt;if(void 0===Ct||isNaN(Ct))return Ne.error="Error: could not calculate eventualBG. Sensitivity: "+_t+" Deviation: "+Gt,Ne;var Ut,Ot,Rt=function(e,t,a){return o(a+(e-t)/24,1)}(rt,Ct,wt);Ne={temp:"absolute",bg:Xe,tick:Ke,eventualBG:Ct,insulinReq:0,reservoir:d,deliverAt:He,sensitivityRatio,TDD:de,insulin:ce,current_target:rt,insulinForManualBolus:C,manualBolusErrorString:0,minDelta:et,expectedDelta:Rt,minGuardBG:Ot,minPredBG:Ut};var At=[],It=[],Ft=[],jt=[];At.push(Xe),It.push(Xe),jt.push(Xe),Ft.push(Xe);var Pt=function(e,t,a,r,o,i){return t?!e.allowSMB_with_high_temptarget&&e.temptargetSet&&o>100?(console.error("SMB disabled due to high temptarget of "+o),!1):!0===a.bwFound&&!1===e.A52_risk_enable?(console.error("SMB disabled due to Bolus Wizard activity in the last 6 hours."),!1):!0===e.enableSMB_always?(a.bwFound?console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled due to enableSMB_always"),!0):!0===e.enableSMB_with_COB&&a.mealCOB?(a.bwCarbs?console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for COB of "+a.mealCOB),!0):!0===e.enableSMB_after_carbs&&a.carbs?(a.bwCarbs?console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for 6h after carb entry"),!0):!0===e.enableSMB_with_temptarget&&e.temptargetSet&&o<100?(a.bwFound?console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for temptarget of "+n(o,e)),!0):!0===e.enableSMB_high_bg&&null!==i&&r>=i?(console.error("Checking BG to see if High for SMB enablement."),console.error("Current BG",r," | High BG ",i),a.bwFound?console.error("Warning: High BG SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("High BG detected. Enabling SMB."),!0):(console.error("SMB disabled (no enableSMB preferences active or no condition satisfied)"),!1):(console.error("SMB disabled (!microBolusAllowed)"),!1)}(i,m,l,Xe,rt,it);if(b)if(S){let e=c.getHours();e>=D&&e<=w&&(console.error("SMB disabled by schedule (a Profile is active with SMBs disabled)"),Pt=!1)}else console.error("SMBs are disabled (a Profile is active with SMBs disabled)"),Pt=!1;var Et=i.enableUAM,qt=0,Wt=0;qt=o(et-wt,1);var kt=o(et-wt,1);csf=_t/H,console.error("profile.sens:"+n(N,i)+", sens:"+n(_t,i)+", CSF:"+o(csf,1));var Lt=o(30*csf*5/60,1);qt>Lt&&(console.error("Limiting carb impact from "+qt+" to "+Lt+"mg/dL/5m (30g/h)"),qt=Lt);var zt=3;sensitivityRatio&&(zt/=sensitivityRatio);var Nt=zt;if(l.carbs){zt=Math.max(zt,l.mealCOB/20);var Ht=o((new Date(Je).getTime()-l.lastCarbTime)/6e4),Zt=(l.carbs-l.mealCOB)/l.carbs;Nt=o(Nt=zt+1.5*Ht/60,1),console.error("Last carbs "+Ht+" minutes ago; remainingCATime:"+Nt+"hours; "+o(100*Zt,1)+"% carbs absorbed")}var $t=Math.max(0,qt/5*60*Nt/2)/csf,Jt=90,Kt=1;i.remainingCarbsCap&&(Jt=Math.min(90,i.remainingCarbsCap)),i.remainingCarbsFraction&&(Kt=Math.min(1,i.remainingCarbsFraction));var Qt=1-Kt,Vt=Math.max(0,l.mealCOB-$t-l.carbs*Qt),Xt=(Vt=Math.min(Jt,Vt))*csf*5/60/(Nt/2),Yt=o(l.slopeFromMaxDeviation,2),ea=o(l.slopeFromMinDeviation,2),ta=Math.min(Yt,-ea/3);Wt=0===qt?0:Math.min(60*Nt/5/2,Math.max(0,l.mealCOB*csf/qt)),console.error("Carb Impact:"+qt+"mg/dL per 5m; CI Duration:"+o(5*Wt/60*2,1)+"hours; remaining CI ("+Nt/2+"h peak):"+o(Xt,1)+"mg/dL per 5m");var aa,ra,oa,na,ia=999,sa=999,la=999,ua=999,ma=999,da=999,ca=999,ga=Ct,ha=Xe,pa=Xe,va=0,fa=[],Ba=[];try{xt.forEach((function(e){var t=o(-e.activity*_t*5,2),a=o(-e.iobWithZeroTemp.activity*_t*5,2),r=Tt,n=qt*(1-Math.min(1,It.length/12));if(!0===(he&&!Ie))ga=It[It.length-1]+o(-e.activity*(1800/(P*Be*Math.log(Math.max(It[It.length-1],39)/Re+1)))*5,2)+n,r=jt[jt.length-1]+o(-e.iobWithZeroTemp.activity*(1800/(P*Be*Math.log(Math.max(jt[jt.length-1],39)/Re+1)))*5,2),console.log("Dynamic ISF (Logarithmic Formula) )adjusted predictions for IOB and ZT: IOBpredBG: "+o(ga,2)+" , ZTpredBG: "+o(r,2));else ga=It[It.length-1]+t+n,r=jt[jt.length-1]+a;var i=Math.max(0,Math.max(0,qt)*(1-At.length/Math.max(2*Wt,1))),s=Math.min(At.length,12*Nt-At.length),l=Math.max(0,s/(Nt/2*12)*Xt);i+l,fa.push(o(l,0)),Ba.push(o(i,0)),COBpredBG=At[At.length-1]+t+Math.min(0,n)+i+l;var u=Math.max(0,kt+Ft.length*ta),m=Math.max(0,kt*(1-Ft.length/Math.max(36,1))),d=Math.min(u,m);if(d>0&&(va=o(5*(Ft.length+1)/60,1)),!0===(he&&!Ie))UAMpredBG=Ft[Ft.length-1]+o(-e.activity*(1800/(P*Be*Math.log(Math.max(Ft[Ft.length-1],39)/Re+1)))*5,2)+Math.min(0,n)+d,console.log("Dynamic ISF (Logarithmic Formula) adjusted prediction for UAM: UAMpredBG: "+o(UAMpredBG,2));else UAMpredBG=Ft[Ft.length-1]+t+Math.min(0,n)+d;It.length<48&&It.push(ga),At.length<48&&At.push(COBpredBG),Ft.length<48&&Ft.push(UAMpredBG),jt.length<48&&jt.push(r),COBpredBG18&&gaha&&(ha=ga),(Wt||Xt>0)&&At.length>18&&COBpredBG0)&&COBpredBG>ha&&(pa=COBpredBG),Et&&Ft.length>12&&UAMpredBGha&&UAMpredBG}))}catch(e){console.error("Problem with iobArray. Optional feature Advanced Meal Assist disabled")}l.mealCOB&&(console.error("predCIs (mg/dL/5m):"+Ba.join(" ")),console.error("remainingCIs: "+fa.join(" "))),Ne.predBGs={},It.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))}));for(var ba=It.length-1;ba>12&&It[ba-1]===It[ba];ba--)It.pop();for(Ne.predBGs.IOB=It,ra=o(It[It.length-1]),jt.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),ba=jt.length-1;ba>6&&!(jt[ba-1]>=jt[ba]||jt[ba]<=rt);ba--)jt.pop();if(Ne.predBGs.ZT=jt,o(jt[jt.length-1]),l.mealCOB>0&&(qt>0||Xt>0)){for(At.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),ba=At.length-1;ba>12&&At[ba-1]===At[ba];ba--)At.pop();Ne.predBGs.COB=At,oa=o(At[At.length-1]),Ct=Math.max(Ct,o(At[At.length-1]))}if(qt>0||Xt>0){if(Et){for(Ft.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),ba=Ft.length-1;ba>12&&Ft[ba-1]===Ft[ba];ba--)Ft.pop();Ne.predBGs.UAM=Ft,na=o(Ft[Ft.length-1]),Ft[Ft.length-1]&&(Ct=Math.max(Ct,o(Ft[Ft.length-1])))}Ne.eventualBG=Ct}console.error("UAM Impact:"+kt+"mg/dL per 5m; UAM Duration:"+va+"hours"),ia=Math.max(39,ia),sa=Math.max(39,sa),la=Math.max(39,la),Ut=o(ia);var Ma=l.mealCOB/l.carbs;aa=o(la<999&&sa<999?(1-Ma)*UAMpredBG+Ma*COBpredBG:sa<999?(ga+COBpredBG)/2:la<999?(ga+UAMpredBG)/2:ga),ca>aa&&(aa=ca),Ot=o(Ot=Wt||Xt>0?Et?Ma*ua+(1-Ma)*ma:ua:Et?ma:da);var _a=la;if(cala&&(_a=(la+ca)/2);if(_a=o(_a),l.carbs)if(!Et&&sa<999)Ut=o(Math.max(ia,sa));else if(sa<999){var xa=Ma*sa+(1-Ma)*_a;Ut=o(Math.max(ia,sa,xa))}else Ut=Et?_a:Ot;else Et&&(Ut=o(Math.max(ia,_a)));Ut=Math.min(Ut,aa),process.stderr.write("minPredBG: "+Ut+" minIOBPredBG: "+ia+" minZTGuardBG: "+ca),sa<999&&process.stderr.write(" minCOBPredBG: "+sa),la<999&&process.stderr.write(" minUAMPredBG: "+la),console.error(" avgPredBG:"+aa+" COB/Carbs:"+l.mealCOB+"/"+l.carbs),pa>Xe&&(Ut=Math.min(Ut,pa)),Ne.COB=l.mealCOB,Ne.IOB=a.iob,Ne.BGI=n(wt,i),Ne.deviation=n(Gt,i),Ne.ISF=n(_t,i),Ne.CR=o(H,1),Ne.target_bg=n(rt,i),Ne.TDD=o(de,2),Ne.current_target=o(rt,0);var Sa=Ne.CR;We!=Ne.CR&&(Sa=We+"→"+Ne.CR),Ne.reason=Mt+", COB: "+Ne.COB+", Dev: "+Ne.deviation+", BGI: "+Ne.BGI+", CR: "+Sa+", Target: "+gt+", minPredBG "+n(Ut,i)+", minGuardBG "+n(Ot,i)+", IOBpredBG "+n(ra,i),oa>0&&(Ne.reason+=", COBpredBG "+n(oa,i)),na>0&&(Ne.reason+=", UAMpredBG "+n(na,i)),Ne.reason+=tddReason,Ne.reason+="; ";var Da=Tt;Da<40&&(Da=Math.min(Ot,Da));var wa,Ga=Bt-Da,Ta=240,Ca=240;if(l.mealCOB>0&&(qt>0||Xt>0)){for(ba=0;bawa*Xe&&(console.error("maxDelta "+n(at,i)+" > "+100*wa+"% of BG "+n(Xe,i)+" - disabling SMB"),Ne.reason+="maxDelta "+n(at,i)+" > "+100*wa+"% of BG "+n(Xe,i)+" - SMB disabled!, ",Pt=!1),console.error("BG projected to remain above "+n(ot,i)+" for "+Ta+"minutes"),(Ca<240||Ta<60)&&console.error("BG projected to remain above "+n(Bt,i)+" for "+Ca+"minutes");var Ua=Ca,Oa=i.current_basal*z*_t*Ua/60,Ra=Math.max(0,l.mealCOB-.25*l.carbs),Aa=(Ga-Oa)/csf-Ra;Oa=o(Oa),Aa=o(Aa),console.error("naive_eventualBG:",Tt,"bgUndershoot:",Ga,"zeroTempDuration:",Ua,"zeroTempEffect:",Oa,"carbsReq:",Aa),"Could not parse clock data"==l.reason?console.error("carbsReq unknown: Could not parse clock data"):Aa>=i.carbsReqThreshold&&Ca<=45&&(Ne.carbsReq=Aa,Ne.reason+=Aa+" add'l carbs req w/in "+Ca+"m; ");var Ia=0;if(Xe0&&et>Rt)Ne.reason+="IOB "+a.iob+" < "+o(-i.current_basal*z*20/60,2),Ne.reason+=" and minDelta "+n(et,i)+" > expectedDelta "+n(Rt,i)+"; ";else if(Xe=55)return Ne.reason+="; Canceling temp at "+Ne.deliverAt.getMinutes()+"m past the hour. ",u.setTempBasal(0,0,i,Ne,t);var Fa=0,ja=$e,Pa=0;if(CtRt&&et>0&&!Aa)return Tt<40?(Ne.reason+=", naive_eventualBG < 40. ",u.setTempBasal(0,30,i,Ne,t)):(e.delta>et?Ne.reason+=", but Delta "+n(Ke,i)+" > expectedDelta "+n(Rt,i):Ne.reason+=", but Min. Delta "+et.toFixed(2)+" > Exp. Delta "+n(Rt,i),t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",u.setTempBasal($e,30,i,Ne,t)));Fa=o(Fa=2*Math.min(0,(Ct-rt)/_t),2);var Ea=Math.min(0,(Tt-rt)/_t);if(Ea=o(Ea,2),et<0&&et>Rt)Fa=o(Fa*(et/Rt),2);ja=r(ja=$e+2*Fa,i),Pa=t.duration*(t.rate-$e)/60;var qa=Math.min(Fa,Ea);if(console.log("naiveInsulinReq:"+Ea),Pa5&&ja>=.8*t.rate)return Ne.reason+=", temp "+t.rate+" ~< req "+ja+"U/hr. ",Ne;if(ja<=0){if((Ia=o(60*((Ga=rt-Tt)/_t)/i.current_basal*z))<0?Ia=0:(Ia=30*o(Ia/30),Ia=Math.min(120,Math.max(0,Ia))),Ia>0)return Ne.reason+=", setting "+Ia+"m zero temp. ",u.setTempBasal(ja,Ia,i,Ne,t)}else Ne.reason+=", setting "+ja+"U/hr. ";return u.setTempBasal(ja,30,i,Ne,t)}if(et=0&&Rt>=0?3:et<=0&&Rt<=0?4:5,Ne.insulinForManualBolus=o((Ne.eventualBG-Ne.target_bg)/_t,2),!m||!Pt))return e.delta "+n(ot,i)+" but Delta "+n(Ke,i)+" < Exp. Delta "+n(Rt,i):Ne.reason+="Eventual BG "+n(Ct,i)+" > "+n(ot,i)+" but Min. Delta "+et.toFixed(2)+" < Exp. Delta "+n(Rt,i),t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",u.setTempBasal($e,30,i,Ne,t));if(Math.min(Ct,Ut)ot&&(Ne.manualBolusErrorString=6,Ne.insulinForManualBolus=o((Ne.eventualBG-Ne.target_bg)/_t,2),Ne.minPredBG=Ut),!m||!Pt))return Ne.reason+=n(Ct,i)+"-"+n(Ut,i)+" in range: no temp required",t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",u.setTempBasal($e,30,i,Ne,t));if(Ct>=nt&&(Ne.reason+="Eventual BG "+n(Ct,i)+" >= "+n(nt,i)+", "),a.iob>st)return Ne.reason+="IOB "+o(a.iob,2)+" > max_iob "+st,t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",u.setTempBasal($e,30,i,Ne,t));Fa=o((Math.min(Ut,Ct)-rt)/_t,2),C=o((Ct-rt)/_t,2),Fa>st-a.iob?(console.error("SMB limited by maxIOB: "+st-a.iob+" (. insulinReq: "+Fa+" U)"),Ne.reason+="max_iob "+st+", ",Fa=st-a.iob):console.error("SMB not limited by maxIOB ( insulinReq: "+Fa+" U)."),C>st-a.iob?(console.error("Ev. Bolus limited by maxIOB: "+st-a.iob+" (. insulinForManualBolus: "+C+" U)"),Ne.reason+="max_iob "+st+", "):console.error("Ev. Bolus would not be limited by maxIOB ( insulinForManualBolus: "+C+" U)."),ja=r(ja=$e+2*Fa,i),Fa=o(Fa,3),Ne.insulinReq=Fa,Ne.insulinForManualBolus=o(C,3);var Wa=o((new Date(Je).getTime()-a.lastBolusTime)/6e4,1);if(m&&Pt&&Xe>Bt){var ka=30;void 0!==i.maxSMBBasalMinutes&&(ka=i.maxSMBBasalMinutes);var La=30;void 0!==i.maxUAMSMBBasalMinutes&&(La=i.maxUAMSMBBasalMinutes),v.useOverride&&M&&G!==ka&&(console.error("SMB Max Minutes - setting overriden from "+ka+" to "+G),ka=G),v.useOverride&&M&&T!==La&&(console.error("UAM Max Minutes - setting overriden from "+La+" to "+T),La=T);var za=o(l.mealCOB/H,3),Na=0;void 0===ka?(Na=o(i.current_basal*z*30/60,1),console.error("smbMinutesSetting undefined: defaulting to 30m"),Fa>Na&&console.error("SMB limited by maxBolus: "+Na+" ( "+Fa+" U)")):a.iob>za&&a.iob>0?(console.error("IOB"+a.iob+"> COB"+l.mealCOB+"; mealInsulinReq ="+za),La?(console.error("maxUAMSMBBasalMinutes: "+La+", profile.current_basal: "+i.current_basal*z),Na=o(i.current_basal*z*La/60,1)):(console.error("maxUAMSMBBasalMinutes undefined: defaulting to 30m"),Na=o(i.current_basal*z*30/60,1)),Fa>Na?console.error("SMB limited by maxUAMSMBBasalMinutes [ "+La+"m ]: "+Na+"U ( "+Fa+"U )"):console.error("SMB is not limited by maxUAMSMBBasalMinutes. ( insulinReq: "+Fa+"U )")):(console.error(".maxSMBBasalMinutes: "+ka+", profile.current_basal: "+i.current_basal*z),Fa>(Na=o(i.current_basal*ka/60,1))?console.error("SMB limited by maxSMBBasalMinutes: "+ka+"m ]: "+Na+"U ( insulinReq: "+Fa+"U )"):console.error("SMB is not limited by maxSMBBasalMinutes. ( insulinReq: "+Fa+"U )"));var Ha=i.bolus_increment,Za=1/Ha,$a=i.smb_delivery_ratio;$a>.5&&console.error("SMB Delivery Ratio increased from default 0.5 to "+o($a,2));var Ja=Math.min(Fa*$a,Na);Ja=Math.floor(Ja*Za)/Za,Ia=o(60*((rt-(Tt+ia)/2)/_t)/i.current_basal*z),Fa>0&&Ja=30?(Ia=30*o(Ia/30),Ia=Math.min(60,Math.max(0,Ia))):(Ka=o($e*Ia/30,2),Ia=30),Ne.reason+=" insulinReq "+Fa,Ja>=Na&&(Ne.reason+="; maxBolus "+Na),Ia>0&&(Ne.reason+="; setting "+Ia+"m low temp of "+Ka+"U/h"),Ne.reason+=". ";var Qa=3;i.SMBInterval&&(Qa=Math.min(10,Math.max(1,i.SMBInterval)));var Va=o(Qa-Wa,0),Xa=o(60*(Qa-Wa),0)%60;if(console.error("naive_eventualBG "+Tt+","+Ia+"m "+Ka+"U/h temp needed; last bolus "+Wa+"m ago; maxBolus: "+Na),Wa>Qa?Ja>0&&(Ne.units=Ja,Ne.reason+="Microbolusing "+Ja+"U. "):Ne.reason+="Waiting "+Va+"m "+Xa+"s to microbolus again. ",Ia>0)return Ne.rate=Ka,Ne.duration=Ia,Ne}var Ya=u.getMaxSafeBasal(i);return ja>Ya&&(Ne.reason+="adj. req. rate: "+ja+" to maxSafeBasal: "+o(Ya,2)+", ",ja=r(Ya,i)),(Pa=t.duration*(t.rate-$e)/60)>=2*Fa?(Ne.reason+=t.duration+"m@"+t.rate.toFixed(2)+" > 2 * insulinReq. Setting temp basal of "+ja+"U/hr. ",u.setTempBasal(ja,30,i,Ne,t)):void 0===t.duration||0===t.duration?(Ne.reason+="no temp, setting "+ja+"U/hr. ",u.setTempBasal(ja,30,i,Ne,t)):t.duration>5&&r(ja,i)<=r(t.rate,i)?(Ne.reason+="temp "+t.rate+" >~ req "+ja+"U/hr. ",Ne):(Ne.reason+="temp "+t.rate+"<"+ja+"U/hr. ",u.setTempBasal(ja,30,i,Ne,t))}},6880:(e,t,a)=>{var r=a(6654);e.exports=function(e,t){var a=20;void 0!==t&&"string"==typeof t.model&&(r(t.model,"54")||r(t.model,"23"))&&(a=40);return e<1?Math.round(e*a)/a:e<10?Math.round(20*e)/20:Math.round(10*e)/10}},2705:(e,t,a)=>{var r=a(5639).Symbol;e.exports=r},9932:e=>{e.exports=function(e,t){for(var a=-1,r=null==e?0:e.length,o=Array(r);++a{e.exports=function(e,t,a){return e==e&&(void 0!==a&&(e=e<=a?e:a),void 0!==t&&(e=e>=t?e:t)),e}},4239:(e,t,a)=>{var r=a(2705),o=a(9607),n=a(2333),i=r?r.toStringTag:void 0;e.exports=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":i&&i in Object(e)?o(e):n(e)}},531:(e,t,a)=>{var r=a(2705),o=a(9932),n=a(1469),i=a(3448),s=r?r.prototype:void 0,l=s?s.toString:void 0;e.exports=function e(t){if("string"==typeof t)return t;if(n(t))return o(t,e)+"";if(i(t))return l?l.call(t):"";var a=t+"";return"0"==a&&1/t==-Infinity?"-0":a}},7561:(e,t,a)=>{var r=a(7990),o=/^\s+/;e.exports=function(e){return e?e.slice(0,r(e)+1).replace(o,""):e}},1957:(e,t,a)=>{var r="object"==typeof a.g&&a.g&&a.g.Object===Object&&a.g;e.exports=r},9607:(e,t,a)=>{var r=a(2705),o=Object.prototype,n=o.hasOwnProperty,i=o.toString,s=r?r.toStringTag:void 0;e.exports=function(e){var t=n.call(e,s),a=e[s];try{e[s]=void 0;var r=!0}catch(e){}var o=i.call(e);return r&&(t?e[s]=a:delete e[s]),o}},2333:e=>{var t=Object.prototype.toString;e.exports=function(e){return t.call(e)}},5639:(e,t,a)=>{var r=a(1957),o="object"==typeof self&&self&&self.Object===Object&&self,n=r||o||Function("return this")();e.exports=n},7990:e=>{var t=/\s/;e.exports=function(e){for(var a=e.length;a--&&t.test(e.charAt(a)););return a}},6654:(e,t,a)=>{var r=a(9750),o=a(531),n=a(554),i=a(9833);e.exports=function(e,t,a){e=i(e),t=o(t);var s=e.length,l=a=void 0===a?s:r(n(a),0,s);return(a-=t.length)>=0&&e.slice(a,l)==t}},1469:e=>{var t=Array.isArray;e.exports=t},3218:e=>{e.exports=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}},7005:e=>{e.exports=function(e){return null!=e&&"object"==typeof e}},3448:(e,t,a)=>{var r=a(4239),o=a(7005);e.exports=function(e){return"symbol"==typeof e||o(e)&&"[object Symbol]"==r(e)}},8601:(e,t,a)=>{var r=a(4841),o=1/0;e.exports=function(e){return e?(e=r(e))===o||e===-1/0?17976931348623157e292*(e<0?-1:1):e==e?e:0:0===e?e:0}},554:(e,t,a)=>{var r=a(8601);e.exports=function(e){var t=r(e),a=t%1;return t==t?a?t-a:t:0}},4841:(e,t,a)=>{var r=a(7561),o=a(3218),n=a(3448),i=/^[-+]0x[0-9a-f]+$/i,s=/^0b[01]+$/i,l=/^0o[0-7]+$/i,u=parseInt;e.exports=function(e){if("number"==typeof e)return e;if(n(e))return NaN;if(o(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=o(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=r(e);var a=s.test(e);return a||l.test(e)?u(e.slice(2),a?2:8):i.test(e)?NaN:+e}},9833:(e,t,a)=>{var r=a(531);e.exports=function(e){return null==e?"":r(e)}}},t={};function a(r){var o=t[r];if(void 0!==o)return o.exports;var n=t[r]={exports:{}};return e[r](n,n.exports,a),n.exports}a.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}();var r=a(5546);freeaps_determineBasal=r})(); +var freeaps_determineBasal;(()=>{var e={5546:(e,t,a)=>{var r=a(6880);function o(e,t){t||(t=0);var a=Math.pow(10,t);return Math.round(e*a)/a}function n(e,t){return"mmol/L"===t.out_units?o(.0555*e,1):Math.round(e)}e.exports=function(e,t,a,i,s,l,u,m,d,c,g,h,p,v){var f=i.min_bg,B=v.overrideTarget;const b=v.smbIsOff,M=v.advancedSettings,_=v.isfAndCr,y=v.isf,x=v.cr,S=v.smbIsAlwaysOff,D=v.start,w=v.end,G=v.smbMinutes,T=v.uamMinutes;var C=0,U=0,O="",R="",A="",I="",F="",j=0,P=0,E=0,q=0,W=0,k=0;const L=v.weightedAverage;var z=1,N=i.sens,H=i.carb_ratio;v.useOverride&&(z=v.overridePercentage/100,_?(N/=z,H/=z):(x&&(H/=z),y&&(N/=z)));const Z=i.weightPercentage,$=v.average_total_data;function J(e,t){var a=e.getTime();return new Date(a+36e5*t)}function K(e){var t=i.bolus_increment;.025!=t&&(t=.05);var a=e/t;return a>=1?o(Math.floor(a)*t,5):0}function Q(e){function t(e){return e<10&&(e="0"+e),e}return t(e.getHours())+":"+t(e.getMinutes())+":00"}function V(e,t){var a=new Date("1/1/1999 "+e),r=new Date("1/1/1999 "+t);return(a.getTime()-r.getTime())/36e5}function X(e,t){var a=0,r=t,o=(e-t)/36e5,n=0,i=o,s=0;do{if(o>0){var l=Q(r),u=p[0].rate;for(let e=0;e=(s=V(p[e+1].start,p[e].start))?n=s:o=s?n=s:om)if(e+1=(s=V(d,l))?n=s:o=(s=V("23:59:59",l))?n=s:o0&&o21)W=X(Y,(te=24-U,ae=Y.getTime(),new Date(ae-36e5*te))),I="24 hours of data is required for an accurate tdd calculation. Currently only "+U.toPrecision(3)+" hours of pump history data are available. Using your pump scheduled basals to fill in the missing hours. Scheduled basals added: "+W.toPrecision(5)+" U. ";else U<21?(he=!1,enableDynamicCR=!1):I=""}else console.log("Pumphistory is empty!"),he=!1,enableDynamicCR=!1;var te,ae;for(let e=0;e0){j=e,k=g[e].rate;var re=g[e-1]["duration (min)"]/60,oe=re,ne=new Date(g[e-1].timestamp),ie=ne,se=0;do{if(e--,0==e){ie=new Date;break}if("TempBasal"==g[e]._type||"PumpSuspend"==g[e]._type){ie=new Date(g[e].timestamp);break}var le=e-2;if(le>=0&&"Rewind"==g[le]._type){let e=g[le].timestamp;for(;le-1>=0&&"Prime"==g[le-=1]._type;)se=(g[le].timestamp-e)/36e5;se>=re&&(ie=e,se=0)}}while(e>0);var ue=(ie-ne)/36e5;ue0&&(--r,"TempBasal"==g[r]._type)){a=new Date(g[r].timestamp);break}}while(r>0);(a-t)/36e5>0&&(W+=X(a,t))}for(let e=g.length-1;e>0;e--)if("TempBasalDuration"==g[e]._type){let t=g[e]["duration (min)"]/60,a=new Date(g[e].timestamp);var me=a;let r=e;do{if(--r,r>=0&&("TempBasal"==g[r]._type||"PumpSuspend"==g[r]._type)){me=new Date(g[r].timestamp);break}}while(r>0);if(0==e&&"TempBasalDuration"==g[0]._type&&(me=new Date,t=g[e]["duration (min)"]/60),(me-a)/36e5-t>0){W+=X(me,J(a,t))}}var de,ce={TDD:o(P=q+E+W,5),bolus:o(q,5),temp_basal:o(E,5),scheduled_basal:o(W,5)};U>21?(R=". Bolus insulin: "+q.toPrecision(5)+" U",A=". Temporary basal insulin: "+E.toPrecision(5)+" U",O=". Insulin with scheduled basal rate: "+W.toPrecision(5)+" U",F=I+(" TDD past 24h is: "+P.toPrecision(5)+" U")+R+A+O,tddReason=", Total insulin: "+o(P,2)+" U, "+o(q/P*100,0)+"% Bolus "+o((E+W)/P*100,0)+"% Basal"):tddReason=", TDD: Not enough pumpData (< 21h)";const ge=e.glucose;var he=h.useNewFormula;const pe=h.enableDynamicCR,ve=Math.min(i.autosens_min,i.autosens_max),fe=Math.max(i.autosens_min,i.autosens_max);(fe==ve||fe<1||ve>1)&&(he=!1,console.log("Dynamic ISF disabled due to current autosens settings"));const Be=h.adjustmentFactor,be=i.min_bg;var Me=!1,_e="",ye=1,xe="";$>0&&(ye=L/$),xe=ye>1?"Basal adjustment with a 24 hour to total average (up to 14 days of data) TDD ratio (limited by Autosens max setting). Basal Ratio: "+(ye=o(ye=Math.min(ye,i.autosens_max),2))+". Upper limit = Autosens max ("+i.autosens_max+")":ye<1?"Basal adjustment with a 24 hour to to total average (up to 14 days of data) TDD ratio (limited by Autosens min setting). Basal Ratio: "+(ye=o(ye=Math.max(ye,i.autosens_min),2))+". Lower limit = Autosens min ("+i.autosens_min+")":"Basal adjusted with a 24 hour to total average (up to 14 days of data) TDD ratio: "+ye,xe=", Basal ratio: "+ye,(i.high_temptarget_raises_sensitivity||i.exercise_mode||v.isEnabled)&&(Me=!0),be>=118&&Me&&(he=!1,_e="Dynamic ISF temporarily off due to a high temp target/exercising. Current min target: "+be);var Se=", Dynamic ratios log: ",De=", AF: "+Be,we="BG: "+ge+" mg/dl ("+(.0555*ge).toPrecision(2)+" mmol/l)",Ge="",Te="";const Ce=h.curve,Ue=h.insulinPeakTime,Oe=h.useCustomPeakTime;var Re=55,Ae=65;switch(Ce){case"rapid-acting":Ae=65;break;case"ultra-rapid":Ae=50}Oe?(Re=120-Ue,console.log("Custom insulinpeakTime set to :"+Ue+", insulinFactor: "+Re)):(Re=120-Ae,console.log("insulinFactor set to : "+Re)),de=P,Z<1&&L>0&&(P=L,console.log("Using weighted TDD average: "+o(P,2)+" U, instead of past 24 h ("+o(de,2)+" U), weight: "+Z),Te=", Weighted TDD: "+o(P,2)+" U");const Ie=h.sigmoid;var Fe="";if(he){var je=N*Be*P*Math.log(ge/Re+1)/1800;Ge=", Logarithmic formula"}if(he&&Ie){const e=ve,t=fe-e,a=.0555*(ge-i.min_bg);var Pe=ye,Ee=fe-1;1==fe&&(Ee=fe+.01-1);const r=Math.log10(1/Ee-e/Ee)/Math.log10(Math.E),o=a*Be*Pe+r;je=t/(1+Math.exp(-o))+e,Ge=", Sigmoid function"}var qe=H;const We=o(H,1);var ke="",Le="";if(he&&P>0){if(ke=", Dynamic ISF/CR: On/",je>fe?(_e=", Dynamic ISF limited by autosens_max setting: "+fe+" ("+o(je,2)+"), ",Le=", Autosens/Dynamic Limit: "+fe+" ("+o(je,2)+")",je=fe):je-.5?"+"+o(e.delta,0):o(e.delta,0);var et=Math.min(e.delta,e.short_avgdelta),tt=Math.min(e.short_avgdelta,e.long_avgdelta),at=Math.max(e.delta,e.short_avgdelta,e.long_avgdelta);(Xe<=10||38===Xe||Ye>=3)&&(Ne.reason="CGM is calibrating, in ??? state, or noise is high");if(Xe>60&&0==e.delta&&e.short_avgdelta>-1&&e.short_avgdelta<1&&e.long_avgdelta>-1&&e.long_avgdelta<1&&("fakecgm"==e.device?(console.error("CGM data is unchanged ("+n(Xe,i)+"+"+n(e.delta,i)+") for 5m w/ "+n(e.short_avgdelta,i)+" mg/dL ~15m change & "+n(e.long_avgdelta,2)+" mg/dL ~45m change"),console.error("Simulator mode detected ("+e.device+"): continuing anyway")):!0),Ve>12||Ve<-5?Ne.reason="If current system time "+Je+" is correct, then BG data is too old. The last BG data was read "+Ve+"m ago at "+Qe:0===e.short_avgdelta&&0===e.long_avgdelta&&(e.last_cal&&e.last_cal<3?Ne.reason="CGM was just calibrated":Ne.reason="CGM data is unchanged ("+n(Xe,i)+"+"+n(e.delta,i)+") for 5m w/ "+n(e.short_avgdelta,i)+" mg/dL ~15m change & "+n(e.long_avgdelta,i)+" mg/dL ~45m change"),Xe<=10||38===Xe||Ye>=3||Ve>12||Ve<-5||0===e.short_avgdelta&&0===e.long_avgdelta)return t.rate>=$e?(Ne.reason+=". Canceling high temp basal of "+t.rate,Ne.deliverAt=He,Ne.temp="absolute",Ne.duration=0,Ne.rate=0,Ne):0===t.rate&&t.duration>30?(Ne.reason+=". Shortening "+t.duration+"m long zero temp to 30m. ",Ne.deliverAt=He,Ne.temp="absolute",Ne.duration=30,Ne.rate=0,Ne):(Ne.reason+=". Temp "+t.rate+" <= current basal "+$e+"U/hr; doing nothing. ",Ne);var rt,ot,nt,it,st=i.max_iob;if(void 0!==i.min_bg&&(ot=i.min_bg),void 0!==i.max_bg&&(nt=i.max_bg),void 0!==i.enableSMB_high_bg_target&&(it=i.enableSMB_high_bg_target),void 0===i.min_bg||void 0===i.max_bg)return Ne.error="Error: could not determine target_bg. ",Ne;rt=(i.min_bg+i.max_bg)/2;var lt=i.exercise_mode||i.high_temptarget_raises_sensitivity||v.isEnabled,ut=100,mt=160;if(mt=i.half_basal_exercise_target,v.isEnabled){const e=v.hbt;console.log("Half Basal Target used: "+n(e,i)+" "+i.out_units),mt=e}else console.log("Default Half Basal Target used: "+n(mt,i)+" "+i.out_units);if(lt&&i.temptargetSet&&rt>ut||i.low_temptarget_lowers_sensitivity&&i.temptargetSet&&rt=rt&&sensitivityRatio0&&(process.stderr.write("TDD-adjustment of basals activated, using tdd24h_14d_Ratio "+o(ye,2)+", TDD 24h = "+o(de,2)+"U, Weighted average TDD = "+o(L,2)+"U, (Weight percentage = "+Z+"), Total data of TDDs (up to 14 days) average = "+o($,2)+"U. "),$e!==Ze*z?process.stderr.write("Adjusting basal from "+Ze*z+" U/h to "+$e+" U/h; "):process.stderr.write("Basal unchanged: "+$e+" U/h; "))),i.temptargetSet);else if(void 0!==s&&s&&(i.sensitivity_raises_target&&s.ratio<1||i.resistance_lowers_target&&s.ratio>1)){ot=o((ot-60)/s.ratio)+60,nt=o((nt-60)/s.ratio)+60;var ct=o((rt-60)/s.ratio)+60;rt===(ct=Math.max(80,ct))?process.stderr.write("target_bg unchanged: "+n(ct,i)+"; "):process.stderr.write("target_bg from "+n(ct,i)+" to "+n(ct,i)+"; "),rt=ct}var gt=n(rt,i);rt!=f&&(gt=0!==B&&B!==rt?n(f,i)+"→"+n(B,i)+"→"+n(rt,i):n(f,i)+"→"+n(rt,i));var ht=200,pt=200,vt=200;if(e.noise>=2){var ft=Math.max(1.1,i.noisyCGMTargetMultiplier);Math.min(250,i.maxRaw);ht=o(Math.min(200,ot*ft)),pt=o(Math.min(200,rt*ft)),vt=o(Math.min(200,nt*ft)),process.stderr.write("Raising target_bg for noisy / raw CGM data, from "+n(ct,i)+" to "+n(pt,i)+"; "),ot=ht,rt=pt,nt=vt}var Bt=ot-.5*(ot-40),bt=i.threshold_setting;bt>Bt&&bt<=120&&bt>=65?(console.error("Threshold changed in settings from "+n(Bt,i)+" to "+n(bt,i)+". "),Bt=bt):console.error("Current threshold: "+n(Bt,i));var Mt="",_t=(o(N,1),N);if(void 0!==s&&s&&((_t=o(_t=N/sensitivityRatio,1))!==N?process.stderr.write("ISF from "+n(N,i)+" to "+n(_t,i)):process.stderr.write("ISF unchanged: "+n(_t,i)),Mt+="Autosens ratio: "+o(sensitivityRatio,2)+", ISF: "+n(N,i)+"→"+n(_t,i)),console.error("CR:"+H),void 0===a)return Ne.error="Error: iob_data undefined. ",Ne;var yt,xt=a;if(a.length,a.length>1&&(a=xt[0]),void 0===a.activity||void 0===a.iob)return Ne.error="Error: iob_data missing some property. ",Ne;var St=((yt=void 0!==a.lastTemp?o((new Date(Je).getTime()-a.lastTemp.date)/6e4):0)+t.duration)%30;if(console.error("currenttemp:"+t.rate+" lastTempAge:"+yt+"m, tempModulus:"+St+"m"),Ne.temp="absolute",Ne.deliverAt=He,m&&t&&a.lastTemp&&t.rate!==a.lastTemp.rate&&yt>10&&t.duration)return Ne.reason="Warning: currenttemp rate "+t.rate+" != lastTemp rate "+a.lastTemp.rate+" from pumphistory; canceling temp",u.setTempBasal(0,0,i,Ne,t);if(t&&a.lastTemp&&t.duration>0){var Dt=yt-a.lastTemp.duration;if(Dt>5&&yt>10)return Ne.reason="Warning: currenttemp running but lastTemp from pumphistory ended "+Dt+"m ago; canceling temp",u.setTempBasal(0,0,i,Ne,t)}var wt=o(-a.activity*_t*5,2),Gt=o(6*(et-wt));Gt<0&&(Gt=o(6*(tt-wt)))<0&&(Gt=o(6*(e.long_avgdelta-wt)));var Tt=Xe,Ct=(Tt=a.iob>0?o(Xe-a.iob*_t):o(Xe-a.iob*Math.min(_t,N)))+Gt;if(void 0===Ct||isNaN(Ct))return Ne.error="Error: could not calculate eventualBG. Sensitivity: "+_t+" Deviation: "+Gt,Ne;var Ut,Ot,Rt=function(e,t,a){return o(a+(e-t)/24,1)}(rt,Ct,wt);Ne={temp:"absolute",bg:Xe,tick:Ke,eventualBG:Ct,insulinReq:0,reservoir:d,deliverAt:He,sensitivityRatio,TDD:de,insulin:ce,current_target:rt,insulinForManualBolus:C,manualBolusErrorString:0,minDelta:et,expectedDelta:Rt,minGuardBG:Ot,minPredBG:Ut};var At=[],It=[],Ft=[],jt=[];At.push(Xe),It.push(Xe),jt.push(Xe),Ft.push(Xe);var Pt=function(e,t,a,r,o,i){return t?!e.allowSMB_with_high_temptarget&&e.temptargetSet&&o>100?(console.error("SMB disabled due to high temptarget of "+o),!1):!0===a.bwFound&&!1===e.A52_risk_enable?(console.error("SMB disabled due to Bolus Wizard activity in the last 6 hours."),!1):!0===e.enableSMB_always?(a.bwFound?console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled due to enableSMB_always"),!0):!0===e.enableSMB_with_COB&&a.mealCOB?(a.bwCarbs?console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for COB of "+a.mealCOB),!0):!0===e.enableSMB_after_carbs&&a.carbs?(a.bwCarbs?console.error("Warning: SMB enabled with Bolus Wizard carbs: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for 6h after carb entry"),!0):!0===e.enableSMB_with_temptarget&&e.temptargetSet&&o<100?(a.bwFound?console.error("Warning: SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("SMB enabled for temptarget of "+n(o,e)),!0):!0===e.enableSMB_high_bg&&null!==i&&r>=i?(console.error("Checking BG to see if High for SMB enablement."),console.error("Current BG",r," | High BG ",i),a.bwFound?console.error("Warning: High BG SMB enabled within 6h of using Bolus Wizard: be sure to easy bolus 30s before using Bolus Wizard"):console.error("High BG detected. Enabling SMB."),!0):(console.error("SMB disabled (no enableSMB preferences active or no condition satisfied)"),!1):(console.error("SMB disabled (!microBolusAllowed)"),!1)}(i,m,l,Xe,rt,it);if(b)if(S){let e=c.getHours();e>=D&&e<=w&&(console.error("SMB disabled by schedule (a Profile is active with SMBs disabled)"),Pt=!1)}else console.error("SMBs are disabled (a Profile is active with SMBs disabled)"),Pt=!1;var Et=i.enableUAM,qt=0,Wt=0;qt=o(et-wt,1);var kt=o(et-wt,1);csf=_t/H,console.error("profile.sens:"+n(N,i)+", sens:"+n(_t,i)+", CSF:"+o(csf,1));var Lt=o(30*csf*5/60,1);qt>Lt&&(console.error("Limiting carb impact from "+qt+" to "+Lt+"mg/dL/5m (30g/h)"),qt=Lt);var zt=3;sensitivityRatio&&(zt/=sensitivityRatio);var Nt=zt;if(l.carbs){zt=Math.max(zt,l.mealCOB/20);var Ht=o((new Date(Je).getTime()-l.lastCarbTime)/6e4),Zt=(l.carbs-l.mealCOB)/l.carbs;Nt=o(Nt=zt+1.5*Ht/60,1),console.error("Last carbs "+Ht+" minutes ago; remainingCATime:"+Nt+"hours; "+o(100*Zt,1)+"% carbs absorbed")}var $t=Math.max(0,qt/5*60*Nt/2)/csf,Jt=90,Kt=1;i.remainingCarbsCap&&(Jt=Math.min(90,i.remainingCarbsCap)),i.remainingCarbsFraction&&(Kt=Math.min(1,i.remainingCarbsFraction));var Qt=1-Kt,Vt=Math.max(0,l.mealCOB-$t-l.carbs*Qt),Xt=(Vt=Math.min(Jt,Vt))*csf*5/60/(Nt/2),Yt=o(l.slopeFromMaxDeviation,2),ea=o(l.slopeFromMinDeviation,2),ta=Math.min(Yt,-ea/3);Wt=0===qt?0:Math.min(60*Nt/5/2,Math.max(0,l.mealCOB*csf/qt)),console.error("Carb Impact:"+qt+"mg/dL per 5m; CI Duration:"+o(5*Wt/60*2,1)+"hours; remaining CI ("+Nt/2+"h peak):"+o(Xt,1)+"mg/dL per 5m");var aa,ra,oa,na,ia=999,sa=999,la=999,ua=999,ma=999,da=999,ca=999,ga=Ct,ha=Xe,pa=Xe,va=0,fa=[],Ba=[];try{xt.forEach((function(e){var t=o(-e.activity*_t*5,2),a=o(-e.iobWithZeroTemp.activity*_t*5,2),r=Tt,n=qt*(1-Math.min(1,It.length/12));if(!0===(he&&!Ie))ga=It[It.length-1]+o(-e.activity*(1800/(P*Be*Math.log(Math.max(It[It.length-1],39)/Re+1)))*5,2)+n,r=jt[jt.length-1]+o(-e.iobWithZeroTemp.activity*(1800/(P*Be*Math.log(Math.max(jt[jt.length-1],39)/Re+1)))*5,2),console.log("Dynamic ISF (Logarithmic Formula) )adjusted predictions for IOB and ZT: IOBpredBG: "+o(ga,2)+" , ZTpredBG: "+o(r,2));else ga=It[It.length-1]+t+n,r=jt[jt.length-1]+a;var i=Math.max(0,Math.max(0,qt)*(1-At.length/Math.max(2*Wt,1))),s=Math.min(At.length,12*Nt-At.length),l=Math.max(0,s/(Nt/2*12)*Xt);i+l,fa.push(o(l,0)),Ba.push(o(i,0)),COBpredBG=At[At.length-1]+t+Math.min(0,n)+i+l;var u=Math.max(0,kt+Ft.length*ta),m=Math.max(0,kt*(1-Ft.length/Math.max(36,1))),d=Math.min(u,m);if(d>0&&(va=o(5*(Ft.length+1)/60,1)),!0===(he&&!Ie))UAMpredBG=Ft[Ft.length-1]+o(-e.activity*(1800/(P*Be*Math.log(Math.max(Ft[Ft.length-1],39)/Re+1)))*5,2)+Math.min(0,n)+d,console.log("Dynamic ISF (Logarithmic Formula) adjusted prediction for UAM: UAMpredBG: "+o(UAMpredBG,2));else UAMpredBG=Ft[Ft.length-1]+t+Math.min(0,n)+d;It.length<48&&It.push(ga),At.length<48&&At.push(COBpredBG),Ft.length<48&&Ft.push(UAMpredBG),jt.length<48&&jt.push(r),COBpredBG18&&gaha&&(ha=ga),(Wt||Xt>0)&&At.length>18&&COBpredBG0)&&COBpredBG>ha&&(pa=COBpredBG),Et&&Ft.length>12&&UAMpredBGha&&UAMpredBG}))}catch(e){console.error("Problem with iobArray. Optional feature Advanced Meal Assist disabled")}l.mealCOB&&(console.error("predCIs (mg/dL/5m):"+Ba.join(" ")),console.error("remainingCIs: "+fa.join(" "))),Ne.predBGs={},It.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))}));for(var ba=It.length-1;ba>12&&It[ba-1]===It[ba];ba--)It.pop();for(Ne.predBGs.IOB=It,ra=o(It[It.length-1]),jt.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),ba=jt.length-1;ba>6&&!(jt[ba-1]>=jt[ba]||jt[ba]<=rt);ba--)jt.pop();if(Ne.predBGs.ZT=jt,o(jt[jt.length-1]),l.mealCOB>0&&(qt>0||Xt>0)){for(At.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),ba=At.length-1;ba>12&&At[ba-1]===At[ba];ba--)At.pop();Ne.predBGs.COB=At,oa=o(At[At.length-1]),Ct=Math.max(Ct,o(At[At.length-1]))}if(qt>0||Xt>0){if(Et){for(Ft.forEach((function(e,t,a){a[t]=o(Math.min(401,Math.max(39,e)))})),ba=Ft.length-1;ba>12&&Ft[ba-1]===Ft[ba];ba--)Ft.pop();Ne.predBGs.UAM=Ft,na=o(Ft[Ft.length-1]),Ft[Ft.length-1]&&(Ct=Math.max(Ct,o(Ft[Ft.length-1])))}Ne.eventualBG=Ct}console.error("UAM Impact:"+kt+"mg/dL per 5m; UAM Duration:"+va+"hours"),ia=Math.max(39,ia),sa=Math.max(39,sa),la=Math.max(39,la),Ut=o(ia);var Ma=l.mealCOB/l.carbs;aa=o(la<999&&sa<999?(1-Ma)*UAMpredBG+Ma*COBpredBG:sa<999?(ga+COBpredBG)/2:la<999?(ga+UAMpredBG)/2:ga),ca>aa&&(aa=ca),Ot=o(Ot=Wt||Xt>0?Et?Ma*ua+(1-Ma)*ma:ua:Et?ma:da);var _a=la;if(cala&&(_a=(la+ca)/2);if(_a=o(_a),l.carbs)if(!Et&&sa<999)Ut=o(Math.max(ia,sa));else if(sa<999){var xa=Ma*sa+(1-Ma)*_a;Ut=o(Math.max(ia,sa,xa))}else Ut=Et?_a:Ot;else Et&&(Ut=o(Math.max(ia,_a)));Ut=Math.min(Ut,aa),process.stderr.write("minPredBG: "+Ut+" minIOBPredBG: "+ia+" minZTGuardBG: "+ca),sa<999&&process.stderr.write(" minCOBPredBG: "+sa),la<999&&process.stderr.write(" minUAMPredBG: "+la),console.error(" avgPredBG:"+aa+" COB/Carbs:"+l.mealCOB+"/"+l.carbs),pa>Xe&&(Ut=Math.min(Ut,pa)),Ne.COB=l.mealCOB,Ne.IOB=a.iob,Ne.BGI=n(wt,i),Ne.deviation=n(Gt,i),Ne.ISF=n(_t,i),Ne.CR=o(H,1),Ne.target_bg=n(rt,i),Ne.TDD=o(de,2),Ne.current_target=o(rt,0);var Sa=Ne.CR;We!=Ne.CR&&(Sa=We+"→"+Ne.CR),Ne.reason=Mt+", COB: "+Ne.COB+", Dev: "+Ne.deviation+", BGI: "+Ne.BGI+", CR: "+Sa+", Target: "+gt+", minPredBG "+n(Ut,i)+", minGuardBG "+n(Ot,i)+", IOBpredBG "+n(ra,i),oa>0&&(Ne.reason+=", COBpredBG "+n(oa,i)),na>0&&(Ne.reason+=", UAMpredBG "+n(na,i)),Ne.reason+=tddReason,Ne.reason+="; ";var Da=Tt;Da<40&&(Da=Math.min(Ot,Da));var wa,Ga=Bt-Da,Ta=240,Ca=240;if(l.mealCOB>0&&(qt>0||Xt>0)){for(ba=0;bawa*Xe&&(console.error("maxDelta "+n(at,i)+" > "+100*wa+"% of BG "+n(Xe,i)+" - disabling SMB"),Ne.reason+="maxDelta "+n(at,i)+" > "+100*wa+"% of BG "+n(Xe,i)+" - SMB disabled!, ",Pt=!1),console.error("BG projected to remain above "+n(ot,i)+" for "+Ta+"minutes"),(Ca<240||Ta<60)&&console.error("BG projected to remain above "+n(Bt,i)+" for "+Ca+"minutes");var Ua=Ca,Oa=i.current_basal*z*_t*Ua/60,Ra=Math.max(0,l.mealCOB-.25*l.carbs),Aa=(Ga-Oa)/csf-Ra;Oa=o(Oa),Aa=o(Aa),console.error("naive_eventualBG:",Tt,"bgUndershoot:",Ga,"zeroTempDuration:",Ua,"zeroTempEffect:",Oa,"carbsReq:",Aa),"Could not parse clock data"==l.reason?console.error("carbsReq unknown: Could not parse clock data"):Aa>=i.carbsReqThreshold&&Ca<=45&&(Ne.carbsReq=Aa,Ne.reason+=Aa+" add'l carbs req w/in "+Ca+"m; ");var Ia=0;if(Xe0&&et>Rt)Ne.reason+="IOB "+a.iob+" < "+o(-i.current_basal*z*20/60,2),Ne.reason+=" and minDelta "+n(et,i)+" > expectedDelta "+n(Rt,i)+"; ";else if(Xe=55)return Ne.reason+="; Canceling temp at "+Ne.deliverAt.getMinutes()+"m past the hour. ",u.setTempBasal(0,0,i,Ne,t);var Fa=0,ja=$e,Pa=0;if(CtRt&&et>0&&!Aa)return Tt<40?(Ne.reason+=", naive_eventualBG < 40. ",u.setTempBasal(0,30,i,Ne,t)):(e.delta>et?Ne.reason+=", but Delta "+n(Ke,i)+" > expectedDelta "+n(Rt,i):Ne.reason+=", but Min. Delta "+et.toFixed(2)+" > Exp. Delta "+n(Rt,i),t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",u.setTempBasal($e,30,i,Ne,t)));Fa=o(Fa=2*Math.min(0,(Ct-rt)/_t),2);var Ea=Math.min(0,(Tt-rt)/_t);if(Ea=o(Ea,2),et<0&&et>Rt)Fa=o(Fa*(et/Rt),2);ja=r(ja=$e+2*Fa,i),Pa=t.duration*(t.rate-$e)/60;var qa=Math.min(Fa,Ea);if(console.log("naiveInsulinReq:"+Ea),Pa5&&ja>=.8*t.rate)return Ne.reason+=", temp "+t.rate+" ~< req "+ja+"U/hr. ",Ne;if(ja<=0){if((Ia=o(60*((Ga=rt-Tt)/_t)/i.current_basal*z))<0?Ia=0:(Ia=30*o(Ia/30),Ia=Math.min(120,Math.max(0,Ia))),Ia>0)return Ne.reason+=", setting "+Ia+"m zero temp. ",u.setTempBasal(ja,Ia,i,Ne,t)}else Ne.reason+=", setting "+ja+"U/hr. ";return u.setTempBasal(ja,30,i,Ne,t)}if(et=0&&Rt>0?3:et<0&&Rt<=0||et<0&&Rt>=0?4:5,Ne.insulinForManualBolus=o((Ne.eventualBG-Ne.target_bg)/_t,2),!m||!Pt))return e.delta "+n(ot,i)+" but Delta "+n(Ke,i)+" < Exp. Delta "+n(Rt,i):Ne.reason+="Eventual BG "+n(Ct,i)+" > "+n(ot,i)+" but Min. Delta "+et.toFixed(2)+" < Exp. Delta "+n(Rt,i),t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",u.setTempBasal($e,30,i,Ne,t));if(Math.min(Ct,Ut)ot&&(Ne.manualBolusErrorString=6,Ne.insulinForManualBolus=o((Ne.eventualBG-Ne.target_bg)/_t,2),Ne.minPredBG=Ut),!m||!Pt))return Ne.reason+=n(Ct,i)+"-"+n(Ut,i)+" in range: no temp required",t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",u.setTempBasal($e,30,i,Ne,t));if(Ct>=nt&&(Ne.reason+="Eventual BG "+n(Ct,i)+" >= "+n(nt,i)+", "),a.iob>st)return Ne.reason+="IOB "+o(a.iob,2)+" > max_iob "+st,t.duration>15&&r($e,i)===r(t.rate,i)?(Ne.reason+=", temp "+t.rate+" ~ req "+$e+"U/hr. ",Ne):(Ne.reason+="; setting current basal of "+$e+" as temp. ",u.setTempBasal($e,30,i,Ne,t));Fa=o((Math.min(Ut,Ct)-rt)/_t,2),C=o((Ct-rt)/_t,2),Fa>st-a.iob?(console.error("SMB limited by maxIOB: "+st-a.iob+" (. insulinReq: "+Fa+" U)"),Ne.reason+="max_iob "+st+", ",Fa=st-a.iob):console.error("SMB not limited by maxIOB ( insulinReq: "+Fa+" U)."),C>st-a.iob?(console.error("Ev. Bolus limited by maxIOB: "+st-a.iob+" (. insulinForManualBolus: "+C+" U)"),Ne.reason+="max_iob "+st+", "):console.error("Ev. Bolus would not be limited by maxIOB ( insulinForManualBolus: "+C+" U)."),ja=r(ja=$e+2*Fa,i),Fa=o(Fa,3),Ne.insulinReq=Fa,Ne.insulinForManualBolus=o(C,3);var Wa=o((new Date(Je).getTime()-a.lastBolusTime)/6e4,1);if(m&&Pt&&Xe>Bt){var ka=30;void 0!==i.maxSMBBasalMinutes&&(ka=i.maxSMBBasalMinutes);var La=30;void 0!==i.maxUAMSMBBasalMinutes&&(La=i.maxUAMSMBBasalMinutes),v.useOverride&&M&&G!==ka&&(console.error("SMB Max Minutes - setting overriden from "+ka+" to "+G),ka=G),v.useOverride&&M&&T!==La&&(console.error("UAM Max Minutes - setting overriden from "+La+" to "+T),La=T);var za=o(l.mealCOB/H,3),Na=0;void 0===ka?(Na=o(i.current_basal*z*30/60,1),console.error("smbMinutesSetting undefined: defaulting to 30m"),Fa>Na&&console.error("SMB limited by maxBolus: "+Na+" ( "+Fa+" U)")):a.iob>za&&a.iob>0?(console.error("IOB"+a.iob+"> COB"+l.mealCOB+"; mealInsulinReq ="+za),La?(console.error("maxUAMSMBBasalMinutes: "+La+", profile.current_basal: "+i.current_basal*z),Na=o(i.current_basal*z*La/60,1)):(console.error("maxUAMSMBBasalMinutes undefined: defaulting to 30m"),Na=o(i.current_basal*z*30/60,1)),Fa>Na?console.error("SMB limited by maxUAMSMBBasalMinutes [ "+La+"m ]: "+Na+"U ( "+Fa+"U )"):console.error("SMB is not limited by maxUAMSMBBasalMinutes. ( insulinReq: "+Fa+"U )")):(console.error(".maxSMBBasalMinutes: "+ka+", profile.current_basal: "+i.current_basal*z),Fa>(Na=o(i.current_basal*ka/60,1))?console.error("SMB limited by maxSMBBasalMinutes: "+ka+"m ]: "+Na+"U ( insulinReq: "+Fa+"U )"):console.error("SMB is not limited by maxSMBBasalMinutes. ( insulinReq: "+Fa+"U )"));var Ha=i.bolus_increment,Za=1/Ha,$a=i.smb_delivery_ratio;$a>.5&&console.error("SMB Delivery Ratio increased from default 0.5 to "+o($a,2));var Ja=Math.min(Fa*$a,Na);Ja=Math.floor(Ja*Za)/Za,Ia=o(60*((rt-(Tt+ia)/2)/_t)/i.current_basal*z),Fa>0&&Ja=30?(Ia=30*o(Ia/30),Ia=Math.min(60,Math.max(0,Ia))):(Ka=o($e*Ia/30,2),Ia=30),Ne.reason+=" insulinReq "+Fa,Ja>=Na&&(Ne.reason+="; maxBolus "+Na),Ia>0&&(Ne.reason+="; setting "+Ia+"m low temp of "+Ka+"U/h"),Ne.reason+=". ";var Qa=3;i.SMBInterval&&(Qa=Math.min(10,Math.max(1,i.SMBInterval)));var Va=o(Qa-Wa,0),Xa=o(60*(Qa-Wa),0)%60;if(console.error("naive_eventualBG "+Tt+","+Ia+"m "+Ka+"U/h temp needed; last bolus "+Wa+"m ago; maxBolus: "+Na),Wa>Qa?Ja>0&&(Ne.units=Ja,Ne.reason+="Microbolusing "+Ja+"U. "):Ne.reason+="Waiting "+Va+"m "+Xa+"s to microbolus again. ",Ia>0)return Ne.rate=Ka,Ne.duration=Ia,Ne}var Ya=u.getMaxSafeBasal(i);return ja>Ya&&(Ne.reason+="adj. req. rate: "+ja+" to maxSafeBasal: "+o(Ya,2)+", ",ja=r(Ya,i)),(Pa=t.duration*(t.rate-$e)/60)>=2*Fa?(Ne.reason+=t.duration+"m@"+t.rate.toFixed(2)+" > 2 * insulinReq. Setting temp basal of "+ja+"U/hr. ",u.setTempBasal(ja,30,i,Ne,t)):void 0===t.duration||0===t.duration?(Ne.reason+="no temp, setting "+ja+"U/hr. ",u.setTempBasal(ja,30,i,Ne,t)):t.duration>5&&r(ja,i)<=r(t.rate,i)?(Ne.reason+="temp "+t.rate+" >~ req "+ja+"U/hr. ",Ne):(Ne.reason+="temp "+t.rate+"<"+ja+"U/hr. ",u.setTempBasal(ja,30,i,Ne,t))}},6880:(e,t,a)=>{var r=a(6654);e.exports=function(e,t){var a=20;void 0!==t&&"string"==typeof t.model&&(r(t.model,"54")||r(t.model,"23"))&&(a=40);return e<1?Math.round(e*a)/a:e<10?Math.round(20*e)/20:Math.round(10*e)/10}},2705:(e,t,a)=>{var r=a(5639).Symbol;e.exports=r},9932:e=>{e.exports=function(e,t){for(var a=-1,r=null==e?0:e.length,o=Array(r);++a{e.exports=function(e,t,a){return e==e&&(void 0!==a&&(e=e<=a?e:a),void 0!==t&&(e=e>=t?e:t)),e}},4239:(e,t,a)=>{var r=a(2705),o=a(9607),n=a(2333),i=r?r.toStringTag:void 0;e.exports=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":i&&i in Object(e)?o(e):n(e)}},531:(e,t,a)=>{var r=a(2705),o=a(9932),n=a(1469),i=a(3448),s=r?r.prototype:void 0,l=s?s.toString:void 0;e.exports=function e(t){if("string"==typeof t)return t;if(n(t))return o(t,e)+"";if(i(t))return l?l.call(t):"";var a=t+"";return"0"==a&&1/t==-Infinity?"-0":a}},7561:(e,t,a)=>{var r=a(7990),o=/^\s+/;e.exports=function(e){return e?e.slice(0,r(e)+1).replace(o,""):e}},1957:(e,t,a)=>{var r="object"==typeof a.g&&a.g&&a.g.Object===Object&&a.g;e.exports=r},9607:(e,t,a)=>{var r=a(2705),o=Object.prototype,n=o.hasOwnProperty,i=o.toString,s=r?r.toStringTag:void 0;e.exports=function(e){var t=n.call(e,s),a=e[s];try{e[s]=void 0;var r=!0}catch(e){}var o=i.call(e);return r&&(t?e[s]=a:delete e[s]),o}},2333:e=>{var t=Object.prototype.toString;e.exports=function(e){return t.call(e)}},5639:(e,t,a)=>{var r=a(1957),o="object"==typeof self&&self&&self.Object===Object&&self,n=r||o||Function("return this")();e.exports=n},7990:e=>{var t=/\s/;e.exports=function(e){for(var a=e.length;a--&&t.test(e.charAt(a)););return a}},6654:(e,t,a)=>{var r=a(9750),o=a(531),n=a(554),i=a(9833);e.exports=function(e,t,a){e=i(e),t=o(t);var s=e.length,l=a=void 0===a?s:r(n(a),0,s);return(a-=t.length)>=0&&e.slice(a,l)==t}},1469:e=>{var t=Array.isArray;e.exports=t},3218:e=>{e.exports=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}},7005:e=>{e.exports=function(e){return null!=e&&"object"==typeof e}},3448:(e,t,a)=>{var r=a(4239),o=a(7005);e.exports=function(e){return"symbol"==typeof e||o(e)&&"[object Symbol]"==r(e)}},8601:(e,t,a)=>{var r=a(4841),o=1/0;e.exports=function(e){return e?(e=r(e))===o||e===-1/0?17976931348623157e292*(e<0?-1:1):e==e?e:0:0===e?e:0}},554:(e,t,a)=>{var r=a(8601);e.exports=function(e){var t=r(e),a=t%1;return t==t?a?t-a:t:0}},4841:(e,t,a)=>{var r=a(7561),o=a(3218),n=a(3448),i=/^[-+]0x[0-9a-f]+$/i,s=/^0b[01]+$/i,l=/^0o[0-7]+$/i,u=parseInt;e.exports=function(e){if("number"==typeof e)return e;if(n(e))return NaN;if(o(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=o(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=r(e);var a=s.test(e);return a||l.test(e)?u(e.slice(2),a?2:8):i.test(e)?NaN:+e}},9833:(e,t,a)=>{var r=a(531);e.exports=function(e){return null==e?"":r(e)}}},t={};function a(r){var o=t[r];if(void 0!==o)return o.exports;var n=t[r]={exports:{}};return e[r](n,n.exports,a),n.exports}a.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}();var r=a(5546);freeaps_determineBasal=r})(); \ No newline at end of file diff --git a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings index 4fa2fc5635..ade59122a0 100644 --- a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings @@ -1308,13 +1308,10 @@ Enact a temp Basal or a temp target */ "Hide" = "Hide"; /* Bolus pop-up / Alert string. Make translations concise! */ -"Predicted Glucose, " = "Predicted Glucose, "; +"Eventual Glucose > Target Glucose, but glucose, " = "Predicted Glucose, "; /* Bolus pop-up / Alert string. Make translations concise! */ -"is predicted below threshold " = "is predicted below threshold "; - -/* Bolus pop-up / Alert string. Make translations concise! */ -"is below Threshold of " = "is below Threshold of "; +"is predicted below Threshold of " = "is below Threshold of "; /* Bolus pop-up / Alert string. Make translations concise! */ "Eventual Glucose > Target Glucose, but glucose is climbing slower than expected. Expected: " = "Eventual Glucose > Target Glucose, but glucose is climbing slower than expected. Expected: "; @@ -1323,7 +1320,7 @@ Enact a temp Basal or a temp target */ ". Climbing: " = ". Climbing: "; /* Bolus pop-up / Alert string. Make translations concise! */ -"Eventual Glucose > Target Glucose, but glucose is falling slower than expected. Expected: " = "Eventual Glucose > Target Glucose, but glucose is falling slower than expected. Expected: "; +"Eventual Glucose > Target Glucose, but glucose is falling faster than expected. Expected: " = "Eventual Glucose > Target Glucose, but glucose is falling faster than expected. Expected: "; /* Bolus pop-up / Alert string. Make translations concise! */ ". Falling: " = ". Falling: "; @@ -1335,7 +1332,7 @@ Enact a temp Basal or a temp target */ ". Changing: " = ". Changing: "; /* Bolus pop-up / Alert string. Make translations concise! */ -"Minimum predicted Glucose is " = "Minimum predicted Glucose is "; +"Eventual Glucose > Target Glucose, but glucose is predicted to drop down to " = "Glucose is predicted to drop to"; /* Add insulin without bolusing alert */ " without bolusing" = " without bolusing"; diff --git a/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings index 4926f659a6..e68a2fd52a 100644 --- a/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings @@ -1351,13 +1351,13 @@ Enact a temp Basal or a temp target */ "is below Threshold of " = "är under tröskelvärde "; /* Bolus pop-up / Alert string. Make translations concise! */ -"Eventual Glucose > Target Glucose, but glucose is climbing slower than expected. Expected: " = "Prognos > Målvärde, men blodsocker stiger snabbare än väntat. Förväntat: "; +"Eventual Glucose > Target Glucose, but glucose is climbing slower than expected. Expected: " = "Prognos > Målvärde, men blodsocker stiger långsammare än väntat. Förväntat: "; //* Bolus pop-up / Alert string. Make translations concise! */ ". Climbing: " = ". Stiger: "; /* Bolus pop-up / Alert string. Make translations concise! */ -"Eventual Glucose > Target Glucose, but glucose is falling slower than expected. Expected: " = "Prognos > Målvärde, men blodsocker sjunker snabbare än väntat. Förväntat: "; +"Eventual Glucose > Target Glucose, but glucose is falling faster than expected. Expected: " = "Prognos > Målvärde, men blodsocker sjunker snabbare än väntat. Förväntat: "; /* Bolus pop-up / Alert string. Make translations concise! */ ". Falling: " = ". Sjunker: "; @@ -1369,7 +1369,7 @@ Enact a temp Basal or a temp target */ ". Changing: " = ". Ändras: "; /* Bolus pop-up / Alert string. Make translations concise! */ -"Minimum predicted Glucose is " = "Lägsta prognos är "; +"Eventual Glucose > Target Glucose, but glucose is predicted to drop down to " = "Prognos är > målvärde, men blodsocker väntas ev sjunka till "; /* Add insulin without bolusing alert */ " without bolusing" = " utan att ge insulin"; diff --git a/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift b/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift index 8968c89d6f..e3cdae66e9 100644 --- a/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift +++ b/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift @@ -95,7 +95,7 @@ extension Bolus { Alert( title: Text("Are you sure?"), message: Text( - "Add " + formatter + NSLocalizedString("Add", comment: "Add insulin without bolusing alert") + " " + formatter .string(from: state.amount as NSNumber)! + NSLocalizedString(" U", comment: "Insulin unit") + NSLocalizedString(" without bolusing", comment: "Add insulin without bolusing alert") ), @@ -256,25 +256,25 @@ extension Bolus { switch state.errorString { case 1: return NSLocalizedString( - "Predicted Glucose, ", + "Eventual Glucose > Target Glucose, but glucose, ", comment: "Bolus pop-up / Alert string. Make translations concise!" ) + state.minGuardBG .formatted(.number.grouping(.never).rounded().precision(.fractionLength(fractionDigits))) + " " + state.units .rawValue + ", " + NSLocalizedString( - "is predicted below threshold ", + "is predicted below threshold of ", comment: "Bolus pop-up / Alert string. Make translations concise!" ) + state .threshold.formatted(.number.grouping(.never).rounded().precision(.fractionLength(fractionDigits))) + "!" case 2: return NSLocalizedString( - "Predicted Glucose, ", + "Eventual Glucose > Target Glucose, but glucose, ", comment: "Bolus pop-up / Alert string. Make translations concise!" ) + state.minGuardBG .formatted(.number.grouping(.never).rounded().precision(.fractionLength(fractionDigits))) + " " + state.units .rawValue + ", " + NSLocalizedString( - "is below Threshold of ", + "is predicted below Threshold of ", comment: "Bolus pop-up / Alert string. Make translations concise!" ) + state .threshold.formatted(.number.grouping(.never).rounded().precision(.fractionLength(fractionDigits))) @@ -289,7 +289,7 @@ extension Bolus { .minDelta.formatted(.number.grouping(.never).rounded().precision(.fractionLength(fractionDigits))) case 4: return NSLocalizedString( - "Eventual Glucose > Target Glucose, but glucose is falling slower than expected. Expected: ", + "Eventual Glucose > Target Glucose, but glucose is falling faster than expected. Expected: ", comment: "Bolus pop-up / Alert string. Make translations concise!" ) + state.expectedDelta @@ -307,7 +307,7 @@ extension Bolus { .minDelta.formatted(.number.grouping(.never).rounded().precision(.fractionLength(fractionDigits))) case 6: return NSLocalizedString( - "Minimum predicted Glucose is ", + "Eventual Glucose > Target Glucose, but glucose is predicted to drop down to ", comment: "Bolus pop-up / Alert string. Make translations concise!" ) + state .minPredBG From cb5cdef74897c914fd6200837d4b761c9dd05ed2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20M=C3=A5rtensson?= Date: Thu, 15 Jun 2023 10:47:34 +0200 Subject: [PATCH 45/45] Formatting and more missing localization (cherry picked from commit fcd491a3120e93ae9933382bef40e65197177b0d) --- .../Main/en.lproj/Localizable.strings | 11 ++++++---- .../Main/sv.lproj/Localizable.strings | 20 +++++++++---------- .../Modules/Bolus/View/BolusRootView.swift | 9 ++++++--- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings index ade59122a0..a45f352b96 100644 --- a/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/en.lproj/Localizable.strings @@ -1298,8 +1298,11 @@ Enact a temp Basal or a temp target */ /* */ "Insulin Sensitivity" = "Insulin Sensitivity"; -/* Formuala displayed in Bolus info pop-up*/ -"(Eventual Glucose - Target) / ISF =" = "(Eventual Glucose - Target) / ISF ="; +/* Formula displayed in Bolus info pop-up. Make translation short! */ +"(Eventual Glucose - Target) / ISF" = "(Eventual Glucose - Target) / ISF"; + +/* */ +"Formula =" = "Formula ="; /* Bolus pop-up footer */ "Carbs and previous insulin are included in the glucose prediction, but if the Eventual Glucose is lower than the Target Glucose, a bolus will not be recommended." = "Carbs and previous insulin are included in the glucose prediction, but if the Eventual Glucose is lower than the Target Glucose, a bolus will not be recommended."; @@ -1308,10 +1311,10 @@ Enact a temp Basal or a temp target */ "Hide" = "Hide"; /* Bolus pop-up / Alert string. Make translations concise! */ -"Eventual Glucose > Target Glucose, but glucose, " = "Predicted Glucose, "; +"Eventual Glucose > Target Glucose, but glucose, " = "Eventual Glucose > Target Glucose, but glucose, "; /* Bolus pop-up / Alert string. Make translations concise! */ -"is predicted below Threshold of " = "is below Threshold of "; +"is predicted below Threshold of " = "is predicted below Threshold of "; /* Bolus pop-up / Alert string. Make translations concise! */ "Eventual Glucose > Target Glucose, but glucose is climbing slower than expected. Expected: " = "Eventual Glucose > Target Glucose, but glucose is climbing slower than expected. Expected: "; diff --git a/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings b/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings index e68a2fd52a..47244446bc 100644 --- a/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings +++ b/FreeAPS/Sources/Localizations/Main/sv.lproj/Localizable.strings @@ -1332,8 +1332,11 @@ Enact a temp Basal or a temp target */ /* */ "Insulin Sensitivity" = "Insulinkänslighet"; -/* Formuala displayed in Bolus info pop-up. Make translation short! */ -"(Eventual Glucose - Target) / ISF =" = "(Blodsockerprognos - Målvärde) / ISF ="; +/* Formula displayed in Bolus info pop-up. Make translation short! */ +"(Eventual Glucose - Target) / ISF" = "(Blodsockerprognos - Målvärde) / ISF"; + +/* */ +"Formula =" = "Formel ="; /* Bolus pop-up footer */ "Carbs and previous insulin are included in the glucose prediction, but if the Eventual Glucose is lower than the Target Glucose, a bolus will not be recommended." = "Kolhydrater och tidigare insulin ingår i prognos, men om prognos är lägre än målvärde kommer ingen bolus att föreslås."; @@ -1342,28 +1345,25 @@ Enact a temp Basal or a temp target */ "Hide" = "Göm"; /* Bolus pop-up / Alert string. Make translations concise! */ -"Predicted Glucose, " = "Prognos, "; - -/* Bolus pop-up / Alert string. Make translations concise! */ -"is predicted below threshold " = "är under tröskelvärde "; +"Eventual Glucose > Target Glucose, but glucose, " = "Prognos > målvärde, men ditt blodsocker, "; /* Bolus pop-up / Alert string. Make translations concise! */ -"is below Threshold of " = "är under tröskelvärde "; +"is predicted below Threshold of " = "beräknas sjunka under tröskelvärde "; /* Bolus pop-up / Alert string. Make translations concise! */ -"Eventual Glucose > Target Glucose, but glucose is climbing slower than expected. Expected: " = "Prognos > Målvärde, men blodsocker stiger långsammare än väntat. Förväntat: "; +"Eventual Glucose > Target Glucose, but glucose is climbing slower than expected. Expected: " = "Prognos > Målvärde, men ditt blodsocker stiger långsammare än väntat. Förväntat: "; //* Bolus pop-up / Alert string. Make translations concise! */ ". Climbing: " = ". Stiger: "; /* Bolus pop-up / Alert string. Make translations concise! */ -"Eventual Glucose > Target Glucose, but glucose is falling faster than expected. Expected: " = "Prognos > Målvärde, men blodsocker sjunker snabbare än väntat. Förväntat: "; +"Eventual Glucose > Target Glucose, but glucose is falling faster than expected. Expected: " = "Prognos > målvärde, men blodsocker sjunker snabbare än väntat. Förväntat: "; /* Bolus pop-up / Alert string. Make translations concise! */ ". Falling: " = ". Sjunker: "; /* Bolus pop-up / Alert string. Make translations concise! */ -"Eventual Glucose > Target Glucose, but glucose is changing faster than expected. Expected: " = "Prognos > Målvärde, men blodsocker ändras snabbare än väntat. Förväntat: "; +"Eventual Glucose > Target Glucose, but glucose is changing faster than expected. Expected: " = "Prognos > målvärde, men blodsocker ändras snabbare än väntat. Förväntat: "; /* Bolus pop-up / Alert string. Make translations concise! */ ". Changing: " = ". Ändras: "; diff --git a/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift b/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift index e3cdae66e9..c9b92fa7a2 100644 --- a/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift +++ b/FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift @@ -194,6 +194,10 @@ extension Bolus { Text("%").foregroundColor(.secondary) } } + HStack { + Text("Formula =") + Text("(Eventual Glucose - Target) / ISF") + }.foregroundColor(.secondary).italic().padding(.top, 5) } .font(.footnote) .padding(.top, 10) @@ -204,11 +208,10 @@ extension Bolus { " U", comment: "Unit in number of units delivered (keep the space character!)" ) - Text("(Eventual Glucose - Target) / ISF =").font(.callout).italic() let color: Color = (state.percentage != 100 && state.insulin > 0) ? .secondary : .blue let fontWeight: Font.Weight = (state.percentage != 100 && state.insulin > 0) ? .regular : .bold HStack { - Text(" = ").font(.callout) + Text(NSLocalizedString("Insulin recommended", comment: "") + ":").font(.callout) Text(state.insulin.formatted() + unit).font(.callout).foregroundColor(color).fontWeight(fontWeight) } if state.percentage != 100, state.insulin > 0 { @@ -262,7 +265,7 @@ extension Bolus { .formatted(.number.grouping(.never).rounded().precision(.fractionLength(fractionDigits))) + " " + state.units .rawValue + ", " + NSLocalizedString( - "is predicted below threshold of ", + "is predicted below Threshold of ", comment: "Bolus pop-up / Alert string. Make translations concise!" ) + state .threshold.formatted(.number.grouping(.never).rounded().precision(.fractionLength(fractionDigits))) + "!"