clean up unused code
This commit is contained in:
parent
95870fbdee
commit
1317c54c26
|
@ -21,6 +21,7 @@
|
|||
F80610C4222D4E4D00D8F236 /* ActionClosureable-extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F80610C3222D4E4D00D8F236 /* ActionClosureable-extension.swift */; };
|
||||
F80859272364355F00F3829D /* ConstantsGlucoseChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = F80859262364355F00F3829D /* ConstantsGlucoseChart.swift */; };
|
||||
F80859292364D61B00F3829D /* UserDefaults+charts.swift in Sources */ = {isa = PBXBuildFile; fileRef = F80859282364D61B00F3829D /* UserDefaults+charts.swift */; };
|
||||
F808592B23660F4500F3829D /* BidirectionalCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = F808592A23660F4500F3829D /* BidirectionalCollection.swift */; };
|
||||
F81D6D4822BD5F62005EFAE2 /* DexcomShareUploadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F81D6D4722BD5F62005EFAE2 /* DexcomShareUploadManager.swift */; };
|
||||
F81D6D4E22BFC762005EFAE2 /* TextsDexcomShareTestResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = F81D6D4D22BFC762005EFAE2 /* TextsDexcomShareTestResult.swift */; };
|
||||
F81D6D5222C27F18005EFAE2 /* BgReading+DexcomShare.swift in Sources */ = {isa = PBXBuildFile; fileRef = F81D6D5122C27F18005EFAE2 /* BgReading+DexcomShare.swift */; };
|
||||
|
@ -209,26 +210,11 @@
|
|||
F8BDD452221DEAB2006EAB84 /* TextsSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8BDD451221DEAB1006EAB84 /* TextsSettingsView.swift */; };
|
||||
F8BDD455221DEF22006EAB84 /* SettingsViews.strings in Resources */ = {isa = PBXBuildFile; fileRef = F8BDD457221DEF22006EAB84 /* SettingsViews.strings */; };
|
||||
F8BECB02235CE3E20060DAE1 /* BloodGlucoseChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8BECB01235CE3E20060DAE1 /* BloodGlucoseChartView.swift */; };
|
||||
F8BECB05235CE5D80060DAE1 /* StatusChartsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8BECB04235CE5D80060DAE1 /* StatusChartsManager.swift */; };
|
||||
F8BECB0C235CE7220060DAE1 /* ChartLineModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8BECB07235CE7220060DAE1 /* ChartLineModel.swift */; };
|
||||
F8BECB0D235CE7220060DAE1 /* StateColorPalette.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8BECB08235CE7220060DAE1 /* StateColorPalette.swift */; };
|
||||
F8BECB0E235CE7220060DAE1 /* ChartAxisValueDoubleUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8BECB09235CE7220060DAE1 /* ChartAxisValueDoubleUnit.swift */; };
|
||||
F8BECB05235CE5D80060DAE1 /* GlucoseChartManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8BECB04235CE5D80060DAE1 /* GlucoseChartManager.swift */; };
|
||||
F8BECB0F235CE7220060DAE1 /* ChartColorPalette.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8BECB0A235CE7220060DAE1 /* ChartColorPalette.swift */; };
|
||||
F8BECB10235CE7220060DAE1 /* ChartAxisValueDoubleLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8BECB0B235CE7220060DAE1 /* ChartAxisValueDoubleLog.swift */; };
|
||||
F8BECB12235CEA9B0060DAE1 /* TimeInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8BECB11235CEA9B0060DAE1 /* TimeInterval.swift */; };
|
||||
F8BECB14235CF3AA0060DAE1 /* HKUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8BECB13235CF3AA0060DAE1 /* HKUnit.swift */; };
|
||||
F8BECB18235CF7EE0060DAE1 /* GlucoseRangeSchedule.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8BECB17235CF7EE0060DAE1 /* GlucoseRangeSchedule.swift */; };
|
||||
F8BECB1A235CF8480060DAE1 /* DailyQuantitySchedule.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8BECB19235CF8480060DAE1 /* DailyQuantitySchedule.swift */; };
|
||||
F8BECB1C235CFAB20060DAE1 /* DailyValueSchedule.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8BECB1B235CFAB20060DAE1 /* DailyValueSchedule.swift */; };
|
||||
F8BECB1E235CFB1E0060DAE1 /* ChartPointsTouchHighlightLayerViewCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8BECB1D235CFB1E0060DAE1 /* ChartPointsTouchHighlightLayerViewCache.swift */; };
|
||||
F8BECB20235E04910060DAE1 /* ChartPointsContextFillLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8BECB1F235E04910060DAE1 /* ChartPointsContextFillLayer.swift */; };
|
||||
F8BECB22235E0A8E0060DAE1 /* BidirectionalCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8BECB21235E0A8E0060DAE1 /* BidirectionalCollection.swift */; };
|
||||
F8BECB26235E0BB60060DAE1 /* ChartPointsScatterDownTrianglesLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8BECB25235E0BB60060DAE1 /* ChartPointsScatterDownTrianglesLayer.swift */; };
|
||||
F8BECB28235E0C3F0060DAE1 /* ChartPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8BECB27235E0C3F0060DAE1 /* ChartPoint.swift */; };
|
||||
F8BECB2E235E0E060060DAE1 /* SampleValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8BECB2D235E0E060060DAE1 /* SampleValue.swift */; };
|
||||
F8BECB31235E0EBE0060DAE1 /* CGPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8BECB30235E0EBD0060DAE1 /* CGPoint.swift */; };
|
||||
F8BECB33235E64530060DAE1 /* TimeZone.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8BECB32235E64520060DAE1 /* TimeZone.swift */; };
|
||||
F8BECB35235E65FF0060DAE1 /* NumberFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8BECB34235E65FF0060DAE1 /* NumberFormatter.swift */; };
|
||||
F8C5EBE522F297F000563B5F /* LibreSensorSerialNumber.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8C5EBE422F297EF00563B5F /* LibreSensorSerialNumber.swift */; };
|
||||
F8C5EBE722F38F0E00563B5F /* Trace.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8C5EBE622F38F0E00563B5F /* Trace.swift */; };
|
||||
F8C5EBEA22F49AC700563B5F /* CGMDroplet1Transmitter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8C5EBE922F49AC700563B5F /* CGMDroplet1Transmitter.swift */; };
|
||||
|
@ -273,6 +259,7 @@
|
|||
F80610C3222D4E4D00D8F236 /* ActionClosureable-extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ActionClosureable-extension.swift"; sourceTree = "<group>"; };
|
||||
F80859262364355F00F3829D /* ConstantsGlucoseChart.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConstantsGlucoseChart.swift; sourceTree = "<group>"; };
|
||||
F80859282364D61B00F3829D /* UserDefaults+charts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserDefaults+charts.swift"; sourceTree = "<group>"; };
|
||||
F808592A23660F4500F3829D /* BidirectionalCollection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BidirectionalCollection.swift; sourceTree = "<group>"; };
|
||||
F81D6D4522B67F55005EFAE2 /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/SpeakReading.strings; sourceTree = "<group>"; };
|
||||
F81D6D4722BD5F62005EFAE2 /* DexcomShareUploadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DexcomShareUploadManager.swift; sourceTree = "<group>"; };
|
||||
F81D6D4D22BFC762005EFAE2 /* TextsDexcomShareTestResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextsDexcomShareTestResult.swift; sourceTree = "<group>"; };
|
||||
|
@ -581,26 +568,11 @@
|
|||
F8BDD456221DEF22006EAB84 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/SettingsViews.strings; sourceTree = "<group>"; };
|
||||
F8BDD458221DEF24006EAB84 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/SettingsViews.strings; sourceTree = "<group>"; };
|
||||
F8BECB01235CE3E20060DAE1 /* BloodGlucoseChartView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BloodGlucoseChartView.swift; sourceTree = "<group>"; };
|
||||
F8BECB04235CE5D80060DAE1 /* StatusChartsManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusChartsManager.swift; sourceTree = "<group>"; };
|
||||
F8BECB07235CE7220060DAE1 /* ChartLineModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartLineModel.swift; sourceTree = "<group>"; };
|
||||
F8BECB08235CE7220060DAE1 /* StateColorPalette.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StateColorPalette.swift; sourceTree = "<group>"; };
|
||||
F8BECB09235CE7220060DAE1 /* ChartAxisValueDoubleUnit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartAxisValueDoubleUnit.swift; sourceTree = "<group>"; };
|
||||
F8BECB04235CE5D80060DAE1 /* GlucoseChartManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GlucoseChartManager.swift; sourceTree = "<group>"; };
|
||||
F8BECB0A235CE7220060DAE1 /* ChartColorPalette.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartColorPalette.swift; sourceTree = "<group>"; };
|
||||
F8BECB0B235CE7220060DAE1 /* ChartAxisValueDoubleLog.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartAxisValueDoubleLog.swift; sourceTree = "<group>"; };
|
||||
F8BECB11235CEA9B0060DAE1 /* TimeInterval.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeInterval.swift; sourceTree = "<group>"; };
|
||||
F8BECB13235CF3AA0060DAE1 /* HKUnit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HKUnit.swift; sourceTree = "<group>"; };
|
||||
F8BECB17235CF7EE0060DAE1 /* GlucoseRangeSchedule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GlucoseRangeSchedule.swift; sourceTree = "<group>"; };
|
||||
F8BECB19235CF8480060DAE1 /* DailyQuantitySchedule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DailyQuantitySchedule.swift; sourceTree = "<group>"; };
|
||||
F8BECB1B235CFAB20060DAE1 /* DailyValueSchedule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DailyValueSchedule.swift; sourceTree = "<group>"; };
|
||||
F8BECB1D235CFB1E0060DAE1 /* ChartPointsTouchHighlightLayerViewCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChartPointsTouchHighlightLayerViewCache.swift; sourceTree = "<group>"; };
|
||||
F8BECB1F235E04910060DAE1 /* ChartPointsContextFillLayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartPointsContextFillLayer.swift; sourceTree = "<group>"; };
|
||||
F8BECB21235E0A8E0060DAE1 /* BidirectionalCollection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BidirectionalCollection.swift; sourceTree = "<group>"; };
|
||||
F8BECB25235E0BB60060DAE1 /* ChartPointsScatterDownTrianglesLayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartPointsScatterDownTrianglesLayer.swift; sourceTree = "<group>"; };
|
||||
F8BECB27235E0C3F0060DAE1 /* ChartPoint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartPoint.swift; sourceTree = "<group>"; };
|
||||
F8BECB2D235E0E060060DAE1 /* SampleValue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleValue.swift; sourceTree = "<group>"; };
|
||||
F8BECB30235E0EBD0060DAE1 /* CGPoint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CGPoint.swift; sourceTree = "<group>"; };
|
||||
F8BECB32235E64520060DAE1 /* TimeZone.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeZone.swift; sourceTree = "<group>"; };
|
||||
F8BECB34235E65FF0060DAE1 /* NumberFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NumberFormatter.swift; sourceTree = "<group>"; };
|
||||
F8C5EBE422F297EF00563B5F /* LibreSensorSerialNumber.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LibreSensorSerialNumber.swift; sourceTree = "<group>"; };
|
||||
F8C5EBE622F38F0E00563B5F /* Trace.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Trace.swift; sourceTree = "<group>"; };
|
||||
F8C5EBE922F49AC700563B5F /* CGMDroplet1Transmitter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CGMDroplet1Transmitter.swift; sourceTree = "<group>"; };
|
||||
|
@ -684,14 +656,13 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
F80610C3222D4E4D00D8F236 /* ActionClosureable-extension.swift */,
|
||||
F8BECB21235E0A8E0060DAE1 /* BidirectionalCollection.swift */,
|
||||
F808592A23660F4500F3829D /* BidirectionalCollection.swift */,
|
||||
F8025C0921D94FD700ECF0C0 /* CBManagerState.swift */,
|
||||
F897AAF82200F2D200CDDD10 /* CBPeripheralState.swift */,
|
||||
F8BECB30235E0EBD0060DAE1 /* CGPoint.swift */,
|
||||
F8025C1221DA683400ECF0C0 /* Data.swift */,
|
||||
F8EA6C8121B723BC0082976B /* Date.swift */,
|
||||
F8025E4D21ED450300ECF0C0 /* Double.swift */,
|
||||
F8BECB13235CF3AA0060DAE1 /* HKUnit.swift */,
|
||||
F8B3A85C22821BB6004BA588 /* Int.swift */,
|
||||
F8EEDD5322FF685400D2D610 /* NSMutableURLRequest.swift */,
|
||||
F897AAFA2201018800CDDD10 /* String.swift */,
|
||||
|
@ -706,8 +677,6 @@
|
|||
F8025E6A21F7CD7600ECF0C0 /* UIStoryboard.swift */,
|
||||
F8B3A857227F6971004BA588 /* UISwitch.swift */,
|
||||
F8BDD4232218790E006EAB84 /* UserDefaults.swift */,
|
||||
F8BECB32235E64520060DAE1 /* TimeZone.swift */,
|
||||
F8BECB34235E65FF0060DAE1 /* NumberFormatter.swift */,
|
||||
F80859282364D61B00F3829D /* UserDefaults+charts.swift */,
|
||||
);
|
||||
path = Extensions;
|
||||
|
@ -1352,7 +1321,7 @@
|
|||
F8BECB03235CE5970060DAE1 /* Charts */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F8BECB04235CE5D80060DAE1 /* StatusChartsManager.swift */,
|
||||
F8BECB04235CE5D80060DAE1 /* GlucoseChartManager.swift */,
|
||||
);
|
||||
path = Charts;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1360,18 +1329,7 @@
|
|||
F8BECB06235CE6EC0060DAE1 /* Models */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F8BECB27235E0C3F0060DAE1 /* ChartPoint.swift */,
|
||||
F8BECB25235E0BB60060DAE1 /* ChartPointsScatterDownTrianglesLayer.swift */,
|
||||
F8BECB1F235E04910060DAE1 /* ChartPointsContextFillLayer.swift */,
|
||||
F8BECB17235CF7EE0060DAE1 /* GlucoseRangeSchedule.swift */,
|
||||
F8BECB0B235CE7220060DAE1 /* ChartAxisValueDoubleLog.swift */,
|
||||
F8BECB09235CE7220060DAE1 /* ChartAxisValueDoubleUnit.swift */,
|
||||
F8BECB0A235CE7220060DAE1 /* ChartColorPalette.swift */,
|
||||
F8BECB07235CE7220060DAE1 /* ChartLineModel.swift */,
|
||||
F8BECB08235CE7220060DAE1 /* StateColorPalette.swift */,
|
||||
F8BECB19235CF8480060DAE1 /* DailyQuantitySchedule.swift */,
|
||||
F8BECB1B235CFAB20060DAE1 /* DailyValueSchedule.swift */,
|
||||
F8BECB2D235E0E060060DAE1 /* SampleValue.swift */,
|
||||
);
|
||||
path = Models;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1664,7 +1622,6 @@
|
|||
F8A54ABA22D9111900934E7A /* GlucoseData.swift in Sources */,
|
||||
F8B3A84A227F090E004BA588 /* SettingsViewGeneralSettingsViewModel.swift in Sources */,
|
||||
F8B3A85B2280CCD1004BA588 /* AlertSettingsViewController.swift in Sources */,
|
||||
F8BECB1A235CF8480060DAE1 /* DailyQuantitySchedule.swift in Sources */,
|
||||
F8B3A81B227DEC92004BA588 /* SensorsAccessor.swift in Sources */,
|
||||
F8B3A85D22821BB6004BA588 /* Int.swift in Sources */,
|
||||
F898EDF6234A8A5700BFB79B /* UInt32.swift in Sources */,
|
||||
|
@ -1679,8 +1636,8 @@
|
|||
F85DC2F521CFE3D400B9F74A /* BgReading+CoreDataClass.swift in Sources */,
|
||||
F8A54AEA22D911BA00934E7A /* PairRequestTxMessage.swift in Sources */,
|
||||
F8C5EBEA22F49AC700563B5F /* CGMDroplet1Transmitter.swift in Sources */,
|
||||
F808592B23660F4500F3829D /* BidirectionalCollection.swift in Sources */,
|
||||
F8EEDD4422FD80A600D2D610 /* LibreOOPResponse.swift in Sources */,
|
||||
F8BECB28235E0C3F0060DAE1 /* ChartPoint.swift in Sources */,
|
||||
F821CF56229BF43A005C1E43 /* AlertKind.swift in Sources */,
|
||||
F85DC2ED21CFE2F500B9F74A /* BgReading+CoreDataProperties.swift in Sources */,
|
||||
F8A54AE422D911BA00934E7A /* NSData+CRC.swift in Sources */,
|
||||
|
@ -1689,7 +1646,6 @@
|
|||
F8A54AE022D911BA00934E7A /* SensorDataRxMessage.swift in Sources */,
|
||||
F8A389F0233575DE0010F405 /* M5StackNavigationController.swift in Sources */,
|
||||
F821CF8122A5C814005C1E43 /* RepeatingTimer.swift in Sources */,
|
||||
F8BECB18235CF7EE0060DAE1 /* GlucoseRangeSchedule.swift in Sources */,
|
||||
F821CF6F229FC280005C1E43 /* Endpoint+NightScout.swift in Sources */,
|
||||
F821CF5D229BF43A005C1E43 /* NSDateFormatter.swift in Sources */,
|
||||
F8AC42A121B31F170078C348 /* xdrip.xcdatamodeld in Sources */,
|
||||
|
@ -1700,7 +1656,6 @@
|
|||
F8A7406E22D9C0E700967CFC /* CGMBluconTransmitter.swift in Sources */,
|
||||
F8A1586B22EDB967007F5B5D /* ConstantsMaster.swift in Sources */,
|
||||
F80859292364D61B00F3829D /* UserDefaults+charts.swift in Sources */,
|
||||
F8BECB10235CE7220060DAE1 /* ChartAxisValueDoubleLog.swift in Sources */,
|
||||
F8A389C3231F1A4B0010F405 /* M5StackReadBlePassWordTxMessage.swift in Sources */,
|
||||
F8B3A7B2226A0878004BA588 /* TextsAlerts.swift in Sources */,
|
||||
F8A54B0022D9179100934E7A /* LibreDataParser.swift in Sources */,
|
||||
|
@ -1710,9 +1665,6 @@
|
|||
F821CF61229BF4A2005C1E43 /* NightScoutUploadManager.swift in Sources */,
|
||||
F8A1587122EDC865007F5B5D /* ConstantsSpeakReadingLanguages.swift in Sources */,
|
||||
F8A54ADD22D911BA00934E7A /* BatteryStatusTxMessage.swift in Sources */,
|
||||
F8BECB22235E0A8E0060DAE1 /* BidirectionalCollection.swift in Sources */,
|
||||
F8BECB20235E04910060DAE1 /* ChartPointsContextFillLayer.swift in Sources */,
|
||||
F8BECB35235E65FF0060DAE1 /* NumberFormatter.swift in Sources */,
|
||||
F8EEDD5022FE25D400D2D610 /* LibreGlucoseSmoothing.swift in Sources */,
|
||||
F8A389E2232D3E070010F405 /* SettingsViewM5StackBluetoothSettingsViewModel.swift in Sources */,
|
||||
F8A1585522EDB706007F5B5D /* ConstantsCalibrationAlgorithms.swift in Sources */,
|
||||
|
@ -1721,7 +1673,6 @@
|
|||
F8A54AE522D911BA00934E7A /* TransmitterVersionRxMessage.swift in Sources */,
|
||||
F821CF57229BF43A005C1E43 /* SnoozeParameters.swift in Sources */,
|
||||
F8F62278233D1CED00BE8796 /* TextsM5StackView.swift in Sources */,
|
||||
F8BECB0E235CE7220060DAE1 /* ChartAxisValueDoubleUnit.swift in Sources */,
|
||||
F8A54AFF22D9179100934E7A /* CRC.swift in Sources */,
|
||||
F8B3A79722635A25004BA588 /* AlertEntry+CoreDataProperties.swift in Sources */,
|
||||
F80610C4222D4E4D00D8F236 /* ActionClosureable-extension.swift in Sources */,
|
||||
|
@ -1746,16 +1697,14 @@
|
|||
F8A1587322EDC893007F5B5D /* ConstantsDexcomShare.swift in Sources */,
|
||||
F8A1586F22EDC7EE007F5B5D /* ConstantsSuspensionPrevention.swift in Sources */,
|
||||
F8A54AB822D9111900934E7A /* TransmitterBatteryInfo.swift in Sources */,
|
||||
F8BECB0D235CE7220060DAE1 /* StateColorPalette.swift in Sources */,
|
||||
F8B3A82D227F07D6004BA588 /* SettingsNavigationController.swift in Sources */,
|
||||
F8A54AB722D9111900934E7A /* CGMTransmitter.swift in Sources */,
|
||||
F8BECB05235CE5D80060DAE1 /* StatusChartsManager.swift in Sources */,
|
||||
F8BECB05235CE5D80060DAE1 /* GlucoseChartManager.swift in Sources */,
|
||||
EE9947E822EEDD2E00DCB876 /* CGMBubbleTransmitter.swift in Sources */,
|
||||
F8B3A830227F085A004BA588 /* SettingsTableViewCell.swift in Sources */,
|
||||
F8F62270233AA3B200BE8796 /* M5StackAccessor.swift in Sources */,
|
||||
F8A389E3232D3E070010F405 /* SettingsViewM5StackGeneralSettingsViewModel.swift in Sources */,
|
||||
F8A1586122EDB844007F5B5D /* ConstantsNotifications.swift in Sources */,
|
||||
F8BECB26235E0BB60060DAE1 /* ChartPointsScatterDownTrianglesLayer.swift in Sources */,
|
||||
F8B3A81C227DEC92004BA588 /* AlertEntriesAccessor.swift in Sources */,
|
||||
F8A1585B22EDB7EA007F5B5D /* ConstantsDexcomG5.swift in Sources */,
|
||||
F898EDF4234A8A3200BFB79B /* UInt16.swift in Sources */,
|
||||
|
@ -1792,7 +1741,6 @@
|
|||
F8B3A850227F26F8004BA588 /* AlertTypesSettingsViewController.swift in Sources */,
|
||||
F8A7407022DBB24800967CFC /* BluconTransmitterOpCode.swift in Sources */,
|
||||
F8EA6CAD21BC2CA40082976B /* BluetoothTransmitter.swift in Sources */,
|
||||
F8BECB2E235E0E060060DAE1 /* SampleValue.swift in Sources */,
|
||||
F8B3A808227A2933004BA588 /* SettingsSelectedRowAction.swift in Sources */,
|
||||
F8E3C3AB21FE17B700907A04 /* StringProtocol.swift in Sources */,
|
||||
F8B3A78E22622954004BA588 /* AlertType+CoreDataClass.swift in Sources */,
|
||||
|
@ -1807,7 +1755,6 @@
|
|||
F856CE5B22EDC8E50083E436 /* ConstantsBluetoothPairing.swift in Sources */,
|
||||
F8C5EBE722F38F0E00563B5F /* Trace.swift in Sources */,
|
||||
F8B48A9422B2A705009BCC01 /* TextsSpeakReading.swift in Sources */,
|
||||
F8BECB14235CF3AA0060DAE1 /* HKUnit.swift in Sources */,
|
||||
F8A54AE222D911BA00934E7A /* ResetMessage.swift in Sources */,
|
||||
F821CF5F229BF43A005C1E43 /* ApplicationManager.swift in Sources */,
|
||||
F8B3A834227F08AC004BA588 /* PickerViewData.swift in Sources */,
|
||||
|
@ -1820,9 +1767,7 @@
|
|||
F8B3A78B225D473D004BA588 /* UIAlertController.swift in Sources */,
|
||||
F8A54AEB22D911BA00934E7A /* CGMG4xDripTransmitter.swift in Sources */,
|
||||
F8BDD4242218790E006EAB84 /* UserDefaults.swift in Sources */,
|
||||
F8BECB1C235CFAB20060DAE1 /* DailyValueSchedule.swift in Sources */,
|
||||
F81D6D5222C27F18005EFAE2 /* BgReading+DexcomShare.swift in Sources */,
|
||||
F8BECB0C235CE7220060DAE1 /* ChartLineModel.swift in Sources */,
|
||||
F821CF66229EE68B005C1E43 /* NightScoutFollowManager.swift in Sources */,
|
||||
F8A54AF622D9156600934E7A /* CGMGNSEntryTransmitter.swift in Sources */,
|
||||
F8A389E7232ECE7E0010F405 /* SettingsViewUtilities.swift in Sources */,
|
||||
|
@ -1844,7 +1789,6 @@
|
|||
F85C4A9D2336D05100D6A86F /* M5StackViewController.swift in Sources */,
|
||||
F8A54ADE22D911BA00934E7A /* AESCrypt.m in Sources */,
|
||||
F8A54ADC22D911BA00934E7A /* AuthChallengeTxMessage.swift in Sources */,
|
||||
F8BECB33235E64530060DAE1 /* TimeZone.swift in Sources */,
|
||||
F8025C1321DA683400ECF0C0 /* Data.swift in Sources */,
|
||||
F80859272364355F00F3829D /* ConstantsGlucoseChart.swift in Sources */,
|
||||
F85DC2EF21CFE2F500B9F74A /* Sensor+CoreDataProperties.swift in Sources */,
|
||||
|
|
|
@ -65,5 +65,8 @@ enum ConstantsGlucoseChart {
|
|||
|
||||
/// The spacing in points between axis title labels and axis labels
|
||||
static let axisTitleLabelsToLabelsSpacing: CGFloat = 0
|
||||
|
||||
/// diameter of the circle for blood glucose readings
|
||||
static let glucoseCircleDiameter: CGFloat = 7
|
||||
|
||||
}
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
//
|
||||
// HKUnit.swift
|
||||
// Loop
|
||||
//
|
||||
// Created by Bharat Mediratta on 12/2/16.
|
||||
// Copyright © 2016 LoopKit Authors. All rights reserved.
|
||||
//
|
||||
// Adapted by Johan Degraeve for loopkit
|
||||
//
|
||||
|
||||
import HealthKit
|
||||
|
||||
// Code in this extension is duplicated from:
|
||||
// https://github.com/LoopKit/LoopKit/blob/master/LoopKit/HKUnit.swift
|
||||
// to avoid pulling in the LoopKit extension since it's not extension-API safe.
|
||||
extension HKUnit {
|
||||
|
||||
static let milligramsPerDeciliter: HKUnit = {
|
||||
return HKUnit.gramUnit(with: .milli).unitDivided(by: HKUnit.literUnit(with: .deci))
|
||||
}()
|
||||
|
||||
static let millimolesPerLiter: HKUnit = {
|
||||
return HKUnit.moleUnit(with: .milli, molarMass: HKUnitMolarMassBloodGlucose).unitDivided(by: HKUnit.liter())
|
||||
}()
|
||||
|
||||
// A formatting helper for determining the preferred decimal style for a given unit
|
||||
var preferredFractionDigits: Int {
|
||||
if self.unitString == "mg/dL" {
|
||||
return 0
|
||||
} else {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
//
|
||||
// NSNumberFormatter.swift
|
||||
// Loop
|
||||
//
|
||||
// Created by Nate Racklyeft on 9/5/16.
|
||||
// Copyright © 2016 Nathan Racklyeft. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import HealthKit
|
||||
|
||||
|
||||
extension NumberFormatter {
|
||||
|
||||
static func glucoseFormatter(for unit: HKUnit) -> NumberFormatter {
|
||||
let numberFormatter = NumberFormatter()
|
||||
|
||||
numberFormatter.numberStyle = .decimal
|
||||
numberFormatter.minimumFractionDigits = unit.preferredFractionDigits
|
||||
numberFormatter.maximumFractionDigits = unit.preferredFractionDigits
|
||||
return numberFormatter
|
||||
}
|
||||
|
||||
|
||||
func string(from number: Double) -> String? {
|
||||
return string(from: NSNumber(value: number))
|
||||
}
|
||||
|
||||
func string(from number: Double, unit: String) -> String? {
|
||||
guard let stringValue = string(from: number) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return String(
|
||||
format: NSLocalizedString(
|
||||
"QUANTITY_VALUE_AND_UNIT",
|
||||
value: "%1$@ %2$@",
|
||||
comment: "Format string for combining localized numeric value and unit. (1: numeric value)(2: unit)"
|
||||
),
|
||||
stringValue,
|
||||
unit
|
||||
)
|
||||
}
|
||||
|
||||
func decibleString(from decibles: Int?) -> String? {
|
||||
if let decibles = decibles {
|
||||
return string(from: Double(decibles), unit: NSLocalizedString("dB", comment: "The short unit display string for decibles"))
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
//
|
||||
// TimeZone.swift
|
||||
// LoopKit
|
||||
//
|
||||
// Created by Nate Racklyeft on 10/2/16.
|
||||
// Copyright © 2016 LoopKit Authors. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
extension TimeZone {
|
||||
static var currentFixed: TimeZone {
|
||||
return TimeZone(secondsFromGMT: TimeZone.current.secondsFromGMT())!
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@ import HealthKit
|
|||
import SwiftCharts
|
||||
import os.log
|
||||
|
||||
public final class StatusChartsManager {
|
||||
public final class GlucoseChartManager {
|
||||
|
||||
// MARK: - public properties
|
||||
|
||||
|
@ -302,7 +302,7 @@ public final class StatusChartsManager {
|
|||
// Grid lines
|
||||
let gridLayer = ChartGuideLinesForValuesLayer(xAxis: xAxisLayer.axis, yAxis: yAxisLayer.axis, settings: chartGuideLinesLayerSettings, axisValuesX: Array(xAxisValues.dropFirst().dropLast()), axisValuesY: yAxisValues)
|
||||
|
||||
let circles = ChartPointsScatterCirclesLayer(xAxis: xAxisLayer.axis, yAxis: yAxisLayer.axis, chartPoints: glucoseChartPoints, displayDelay: 0, itemSize: CGSize(width: 4, height: 4), itemFillColor: colors.glucoseTint, optimized: true)
|
||||
let circles = ChartPointsScatterCirclesLayer(xAxis: xAxisLayer.axis, yAxis: yAxisLayer.axis, chartPoints: glucoseChartPoints, displayDelay: 0, itemSize: CGSize(width: ConstantsGlucoseChart.glucoseCircleDiameter, height: ConstantsGlucoseChart.glucoseCircleDiameter), itemFillColor: colors.glucoseTint, optimized: true)
|
||||
|
||||
if gestureRecognizer != nil {
|
||||
glucoseChartCache = ChartPointsTouchHighlightLayerViewCache(
|
|
@ -1,56 +0,0 @@
|
|||
//
|
||||
// ChartAxisValueDoubleLog.swift
|
||||
// Naterade
|
||||
//
|
||||
// Created by Nathan Racklyeft on 2/29/16.
|
||||
// Copyright © 2016 Nathan Racklyeft. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SwiftCharts
|
||||
|
||||
|
||||
public final class ChartAxisValueDoubleLog: ChartAxisValueDoubleScreenLoc {
|
||||
|
||||
let unitString: String?
|
||||
|
||||
public init(actualDouble: Double, unitString: String? = nil, formatter: NumberFormatter, labelSettings: ChartLabelSettings = ChartLabelSettings()) {
|
||||
let screenLocDouble: Double
|
||||
|
||||
switch actualDouble {
|
||||
case let x where x < 0:
|
||||
screenLocDouble = -log(-x + 1)
|
||||
case let x where x > 0:
|
||||
screenLocDouble = log(x + 1)
|
||||
default: // 0
|
||||
screenLocDouble = 0
|
||||
}
|
||||
|
||||
self.unitString = unitString
|
||||
|
||||
super.init(screenLocDouble: screenLocDouble, actualDouble: actualDouble, formatter: formatter, labelSettings: labelSettings)
|
||||
}
|
||||
|
||||
public init(screenLocDouble: Double, formatter: NumberFormatter, labelSettings: ChartLabelSettings = ChartLabelSettings()) {
|
||||
let actualDouble: Double
|
||||
|
||||
switch screenLocDouble {
|
||||
case let x where x < 0:
|
||||
actualDouble = -pow(M_E, -x) + 1
|
||||
case let x where x > 0:
|
||||
actualDouble = pow(M_E, x) - 1
|
||||
default: // 0
|
||||
actualDouble = 0
|
||||
}
|
||||
|
||||
self.unitString = nil
|
||||
|
||||
super.init(screenLocDouble: screenLocDouble, actualDouble: actualDouble, formatter: formatter, labelSettings: labelSettings)
|
||||
}
|
||||
|
||||
override public var description: String {
|
||||
let suffix = unitString != nil ? " \(unitString!)" : ""
|
||||
|
||||
return super.description + suffix
|
||||
}
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
//
|
||||
// ChartAxisValueDoubleUnit.swift
|
||||
// Loop
|
||||
//
|
||||
// Created by Nate Racklyeft on 7/16/16.
|
||||
// Copyright © 2016 Nathan Racklyeft. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SwiftCharts
|
||||
|
||||
|
||||
public final class ChartAxisValueDoubleUnit: ChartAxisValueDouble {
|
||||
let unitString: String
|
||||
|
||||
public init(_ double: Double, unitString: String, formatter: NumberFormatter) {
|
||||
self.unitString = unitString
|
||||
|
||||
super.init(double, formatter: formatter)
|
||||
}
|
||||
|
||||
init(_ double: Double, unitString: String) {
|
||||
self.unitString = unitString
|
||||
|
||||
super.init(double)
|
||||
}
|
||||
|
||||
override public var description: String {
|
||||
return formatter.string(from: scalar, unit: unitString) ?? ""
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
//
|
||||
// ChartLineModel.swift
|
||||
// Loop
|
||||
//
|
||||
// Copyright © 2017 LoopKit Authors. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftCharts
|
||||
|
||||
|
||||
extension ChartLineModel {
|
||||
/// Creates a model configured with the dashed prediction line style
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - points: The points to construct the line
|
||||
/// - color: The line color
|
||||
/// - width: The line width
|
||||
/// - Returns: A new line model
|
||||
static func predictionLine(points: [T], color: UIColor, width: CGFloat) -> ChartLineModel {
|
||||
// TODO: Bug in ChartPointsLineLayer requires a non-zero animation to draw the dash pattern
|
||||
return self.init(chartPoints: points, lineColor: color, lineWidth: width, animDuration: 0.0001, animDelay: 0, dashPattern: [6, 5])
|
||||
}
|
||||
}
|
|
@ -1,110 +0,0 @@
|
|||
//
|
||||
// ChartPoint.swift
|
||||
// Naterade
|
||||
//
|
||||
// Created by Nathan Racklyeft on 2/19/16.
|
||||
// Copyright © 2016 Nathan Racklyeft. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import HealthKit
|
||||
import SwiftCharts
|
||||
|
||||
|
||||
extension ChartPoint {
|
||||
static func pointsForGlucoseRangeSchedule(_ glucoseRangeSchedule: GlucoseRangeSchedule, xAxisValues: [ChartAxisValue], chartTableIncrement: Double) -> [ChartPoint] {
|
||||
let targetRanges = glucoseRangeSchedule.between(
|
||||
start: ChartAxisValueDate.dateFromScalar(xAxisValues.first!.scalar),
|
||||
end: ChartAxisValueDate.dateFromScalar(xAxisValues.last!.scalar)
|
||||
)
|
||||
|
||||
let dateFormatter = DateFormatter()
|
||||
|
||||
var maxPoints: [ChartPoint] = []
|
||||
var minPoints: [ChartPoint] = []
|
||||
|
||||
for (index, range) in targetRanges.enumerated() {
|
||||
var startDate = ChartAxisValueDate(date: range.startDate, formatter: dateFormatter)
|
||||
var endDate: ChartAxisValueDate
|
||||
|
||||
if index == targetRanges.startIndex, let firstDate = xAxisValues.first as? ChartAxisValueDate {
|
||||
startDate = firstDate
|
||||
}
|
||||
|
||||
if index == targetRanges.endIndex - 1, let lastDate = xAxisValues.last as? ChartAxisValueDate {
|
||||
endDate = lastDate
|
||||
} else {
|
||||
endDate = ChartAxisValueDate(date: targetRanges[index + 1].startDate, formatter: dateFormatter)
|
||||
}
|
||||
|
||||
let value = range.value.rangeWithMinimumIncremement(chartTableIncrement)
|
||||
let minValue = ChartAxisValueDouble(value.minValue)
|
||||
let maxValue = ChartAxisValueDouble(value.maxValue)
|
||||
|
||||
maxPoints += [
|
||||
ChartPoint(x: startDate, y: maxValue),
|
||||
ChartPoint(x: endDate, y: maxValue)
|
||||
]
|
||||
|
||||
minPoints += [
|
||||
ChartPoint(x: startDate, y: minValue),
|
||||
ChartPoint(x: endDate, y: minValue)
|
||||
]
|
||||
}
|
||||
|
||||
return maxPoints + minPoints.reversed()
|
||||
}
|
||||
|
||||
static func pointsForGlucoseRangeScheduleOverride(_ override: GlucoseRangeSchedule.Override, chartTableIncrement: Double, xAxisValues: [ChartAxisValue], extendEndDateToChart: Bool = false) -> [ChartPoint] {
|
||||
let range = override.value.rangeWithMinimumIncremement(chartTableIncrement)
|
||||
let startDate = Date()
|
||||
let endDate = override.end ?? .distantFuture
|
||||
|
||||
guard endDate.timeIntervalSince(startDate) > 0,
|
||||
let lastXAxisValue = xAxisValues.last as? ChartAxisValueDate
|
||||
else {
|
||||
return []
|
||||
}
|
||||
|
||||
let dateFormatter = DateFormatter()
|
||||
let startDateAxisValue = ChartAxisValueDate(date: startDate, formatter: dateFormatter)
|
||||
let displayEndDate = min(lastXAxisValue.date, extendEndDateToChart ? .distantFuture : endDate)
|
||||
let endDateAxisValue = ChartAxisValueDate(date: displayEndDate, formatter: dateFormatter)
|
||||
let minValue = ChartAxisValueDouble(range.minValue)
|
||||
let maxValue = ChartAxisValueDouble(range.maxValue)
|
||||
|
||||
return [
|
||||
ChartPoint(x: startDateAxisValue, y: maxValue),
|
||||
ChartPoint(x: endDateAxisValue, y: maxValue),
|
||||
ChartPoint(x: endDateAxisValue, y: minValue),
|
||||
ChartPoint(x: startDateAxisValue, y: minValue)
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
extension ChartPoint: TimelineValue {
|
||||
public var startDate: Date {
|
||||
if let dateValue = x as? ChartAxisValueDate {
|
||||
return dateValue.date
|
||||
} else {
|
||||
return Date.distantPast
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private extension DoubleRange {
|
||||
func rangeWithMinimumIncremement(_ increment: Double) -> DoubleRange {
|
||||
var minValue = self.minValue
|
||||
var maxValue = self.maxValue
|
||||
|
||||
if (maxValue - minValue) < .ulpOfOne {
|
||||
minValue -= increment
|
||||
maxValue += increment
|
||||
}
|
||||
|
||||
return DoubleRange(minValue: minValue, maxValue: maxValue)
|
||||
}
|
||||
}
|
|
@ -1,121 +0,0 @@
|
|||
//
|
||||
// ChartPointsContextFillLayer.swift
|
||||
// Loop
|
||||
//
|
||||
// Copyright © 2017 LoopKit Authors. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftCharts
|
||||
|
||||
|
||||
struct ChartPointsFill {
|
||||
let chartPoints: [ChartPoint]
|
||||
let fillColor: UIColor
|
||||
let createContainerPoints: Bool
|
||||
let blendMode: CGBlendMode
|
||||
fileprivate var screenPoints: [CGPoint] = []
|
||||
|
||||
init?(chartPoints: [ChartPoint], fillColor: UIColor, createContainerPoints: Bool = true, blendMode: CGBlendMode = .normal) {
|
||||
guard chartPoints.count > 1 else {
|
||||
return nil;
|
||||
}
|
||||
|
||||
var chartPoints = chartPoints
|
||||
|
||||
if createContainerPoints {
|
||||
// Create a container line at value position 0
|
||||
if let first = chartPoints.first {
|
||||
chartPoints.insert(ChartPoint(x: first.x, y: ChartAxisValueInt(0)), at: 0)
|
||||
}
|
||||
|
||||
if let last = chartPoints.last {
|
||||
chartPoints.append(ChartPoint(x: last.x, y: ChartAxisValueInt(0)))
|
||||
}
|
||||
}
|
||||
|
||||
self.chartPoints = chartPoints
|
||||
self.fillColor = fillColor
|
||||
self.createContainerPoints = createContainerPoints
|
||||
self.blendMode = blendMode
|
||||
}
|
||||
|
||||
var areaPath: UIBezierPath {
|
||||
let path = UIBezierPath()
|
||||
|
||||
if let point = screenPoints.first {
|
||||
path.move(to: point)
|
||||
}
|
||||
|
||||
for point in screenPoints.dropFirst() {
|
||||
path.addLine(to: point)
|
||||
}
|
||||
|
||||
return path
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final class ChartPointsFillsLayer: ChartCoordsSpaceLayer {
|
||||
let fills: [ChartPointsFill]
|
||||
|
||||
init?(xAxis: ChartAxis, yAxis: ChartAxis, fills: [ChartPointsFill?]) {
|
||||
self.fills = fills.compactMap({ $0 })
|
||||
|
||||
guard fills.count > 0 else {
|
||||
return nil
|
||||
}
|
||||
|
||||
super.init(xAxis: xAxis, yAxis: yAxis)
|
||||
}
|
||||
|
||||
override func chartInitialized(chart: Chart) {
|
||||
super.chartInitialized(chart: chart)
|
||||
|
||||
let view = ChartPointsFillsView(
|
||||
frame: chart.bounds,
|
||||
chartPointsFills: fills.map { (fill) -> ChartPointsFill in
|
||||
var fill = fill
|
||||
|
||||
fill.screenPoints = fill.chartPoints.map { (point) -> CGPoint in
|
||||
return modelLocToScreenLoc(x: point.x.scalar, y: point.y.scalar)
|
||||
}
|
||||
|
||||
return fill
|
||||
}
|
||||
)
|
||||
|
||||
chart.addSubview(view)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class ChartPointsFillsView: UIView {
|
||||
let chartPointsFills: [ChartPointsFill]
|
||||
var allowsAntialiasing = false
|
||||
|
||||
init(frame: CGRect, chartPointsFills: [ChartPointsFill]) {
|
||||
self.chartPointsFills = chartPointsFills
|
||||
|
||||
super.init(frame: frame)
|
||||
|
||||
backgroundColor = .clear
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func draw(_ rect: CGRect) {
|
||||
guard let context = UIGraphicsGetCurrentContext() else { return }
|
||||
|
||||
context.saveGState()
|
||||
context.setAllowsAntialiasing(allowsAntialiasing)
|
||||
|
||||
for fill in chartPointsFills {
|
||||
context.setFillColor(fill.fillColor.cgColor)
|
||||
fill.areaPath.fill(with: fill.blendMode, alpha: 1)
|
||||
}
|
||||
|
||||
context.restoreGState()
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
//
|
||||
// ChartPointsScatterDownTrianglesLayer.swift
|
||||
// Loop
|
||||
//
|
||||
// Created by Nate Racklyeft on 9/28/16.
|
||||
// Copyright © 2016 Nathan Racklyeft. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftCharts
|
||||
|
||||
|
||||
public class ChartPointsScatterDownTrianglesLayer<T: ChartPoint>: ChartPointsScatterLayer<T> {
|
||||
public required init(
|
||||
xAxis: ChartAxis,
|
||||
yAxis: ChartAxis,
|
||||
chartPoints: [T],
|
||||
displayDelay: Float,
|
||||
itemSize: CGSize,
|
||||
itemFillColor: UIColor,
|
||||
optimized: Bool = false,
|
||||
tapSettings: ChartPointsTapSettings<T>? = nil
|
||||
) {
|
||||
// optimized must be set to false because `generateCGLayer` isn't public and can't be overridden
|
||||
super.init(
|
||||
xAxis: xAxis,
|
||||
yAxis: yAxis,
|
||||
chartPoints: chartPoints,
|
||||
displayDelay: displayDelay,
|
||||
itemSize: itemSize,
|
||||
itemFillColor: itemFillColor,
|
||||
optimized: false,
|
||||
tapSettings: tapSettings
|
||||
)
|
||||
}
|
||||
|
||||
public override func drawChartPointModel(_ context: CGContext, chartPointModel: ChartPointLayerModel<T>, view: UIView) {
|
||||
let w = self.itemSize.width
|
||||
let h = self.itemSize.height
|
||||
|
||||
let path = CGMutablePath()
|
||||
path.move(to: CGPoint(x: chartPointModel.screenLoc.x, y: chartPointModel.screenLoc.y + h / 2))
|
||||
path.addLine(to: CGPoint(x: chartPointModel.screenLoc.x + w / 2, y: chartPointModel.screenLoc.y - h / 2))
|
||||
path.addLine(to: CGPoint(x: chartPointModel.screenLoc.x - w / 2, y: chartPointModel.screenLoc.y - h / 2))
|
||||
path.closeSubpath()
|
||||
|
||||
context.setFillColor(self.itemFillColor.cgColor)
|
||||
context.addPath(path)
|
||||
context.fillPath()
|
||||
}
|
||||
}
|
|
@ -1,111 +0,0 @@
|
|||
//
|
||||
// DailyQuantitySchedule.swift
|
||||
// Naterade
|
||||
//
|
||||
// Created by Nathan Racklyeft on 2/12/16.
|
||||
// Copyright © 2016 Nathan Racklyeft. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import HealthKit
|
||||
|
||||
|
||||
public struct DailyQuantitySchedule<T: RawRepresentable>: DailySchedule {
|
||||
public typealias RawValue = [String: Any]
|
||||
public let unit: HKUnit
|
||||
var valueSchedule: DailyValueSchedule<T>
|
||||
|
||||
public init?(unit: HKUnit, dailyItems: [RepeatingScheduleValue<T>], timeZone: TimeZone? = nil) {
|
||||
guard let valueSchedule = DailyValueSchedule<T>(dailyItems: dailyItems, timeZone: timeZone) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
self.unit = unit
|
||||
self.valueSchedule = valueSchedule
|
||||
}
|
||||
|
||||
public init?(rawValue: RawValue) {
|
||||
guard let rawUnit = rawValue["unit"] as? String,
|
||||
let valueSchedule = DailyValueSchedule<T>(rawValue: rawValue)
|
||||
else
|
||||
{
|
||||
return nil
|
||||
}
|
||||
|
||||
self.unit = HKUnit(from: rawUnit)
|
||||
self.valueSchedule = valueSchedule
|
||||
}
|
||||
|
||||
public var items: [RepeatingScheduleValue<T>] {
|
||||
return valueSchedule.items
|
||||
}
|
||||
|
||||
public var timeZone: TimeZone {
|
||||
get {
|
||||
return valueSchedule.timeZone
|
||||
}
|
||||
set {
|
||||
valueSchedule.timeZone = newValue
|
||||
}
|
||||
}
|
||||
|
||||
public var rawValue: RawValue {
|
||||
var rawValue = valueSchedule.rawValue
|
||||
|
||||
rawValue["unit"] = unit.unitString
|
||||
|
||||
return rawValue
|
||||
}
|
||||
|
||||
public func between(start startDate: Date, end endDate: Date) -> [AbsoluteScheduleValue<T>] {
|
||||
return valueSchedule.between(start: startDate, end: endDate)
|
||||
}
|
||||
|
||||
public func value(at time: Date) -> T {
|
||||
return valueSchedule.value(at: time)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension DailyQuantitySchedule: CustomDebugStringConvertible {
|
||||
public var debugDescription: String {
|
||||
return String(reflecting: rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public typealias SingleQuantitySchedule = DailyQuantitySchedule<Double>
|
||||
|
||||
|
||||
public extension DailyQuantitySchedule where T == Double {
|
||||
func quantity(at time: Date) -> HKQuantity {
|
||||
return HKQuantity(unit: unit, doubleValue: valueSchedule.value(at: time))
|
||||
}
|
||||
|
||||
func averageValue() -> Double {
|
||||
var total: Double = 0
|
||||
|
||||
for (index, item) in valueSchedule.items.enumerated() {
|
||||
var endTime = valueSchedule.maxTimeInterval
|
||||
|
||||
if index < valueSchedule.items.endIndex - 1 {
|
||||
endTime = valueSchedule.items[index + 1].startTime
|
||||
}
|
||||
|
||||
total += (endTime - item.startTime) * item.value
|
||||
}
|
||||
|
||||
return total / valueSchedule.repeatInterval
|
||||
}
|
||||
|
||||
func averageQuantity() -> HKQuantity {
|
||||
return HKQuantity(unit: unit, doubleValue: averageValue())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension DailyQuantitySchedule where T: Equatable {
|
||||
public static func ==(lhs: DailyQuantitySchedule<T>, rhs: DailyQuantitySchedule<T>) -> Bool {
|
||||
return lhs.valueSchedule == rhs.valueSchedule && lhs.unit.unitString == rhs.unit.unitString
|
||||
}
|
||||
}
|
|
@ -1,218 +0,0 @@
|
|||
//
|
||||
// QuantitySchedule.swift
|
||||
// Naterade
|
||||
//
|
||||
// Created by Nathan Racklyeft on 1/18/16.
|
||||
// Copyright © 2016 Nathan Racklyeft. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import HealthKit
|
||||
|
||||
|
||||
public struct RepeatingScheduleValue<T: RawRepresentable> where T.RawValue: Any {
|
||||
public let startTime: TimeInterval
|
||||
public let value: T
|
||||
|
||||
public init(startTime: TimeInterval, value: T) {
|
||||
self.startTime = startTime
|
||||
self.value = value
|
||||
}
|
||||
}
|
||||
|
||||
extension RepeatingScheduleValue: Equatable where T: Equatable {
|
||||
public static func ==(lhs: RepeatingScheduleValue<T>, rhs: RepeatingScheduleValue<T>) -> Bool {
|
||||
return abs(lhs.startTime - rhs.startTime) < .ulpOfOne && lhs.value == rhs.value
|
||||
}
|
||||
}
|
||||
|
||||
public struct AbsoluteScheduleValue<T>: TimelineValue {
|
||||
public let startDate: Date
|
||||
public let endDate: Date
|
||||
public let value: T
|
||||
}
|
||||
|
||||
extension AbsoluteScheduleValue where T: Equatable {
|
||||
public static func ==(lhs: AbsoluteScheduleValue<T>, rhs: AbsoluteScheduleValue<T>) -> Bool {
|
||||
return lhs.startDate == rhs.startDate && lhs.endDate == rhs.endDate && lhs.value == rhs.value
|
||||
}
|
||||
}
|
||||
|
||||
extension RepeatingScheduleValue: RawRepresentable {
|
||||
public typealias RawValue = [String: Any]
|
||||
|
||||
public init?(rawValue: RawValue) {
|
||||
guard let startTime = rawValue["startTime"] as? Double,
|
||||
let rawValue = rawValue["value"] as? T.RawValue,
|
||||
let value = T(rawValue: rawValue) else
|
||||
{
|
||||
return nil
|
||||
}
|
||||
|
||||
self.init(startTime: startTime, value: value)
|
||||
}
|
||||
|
||||
public var rawValue: RawValue {
|
||||
return [
|
||||
"startTime": startTime,
|
||||
"value": value.rawValue
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public protocol DailySchedule: RawRepresentable, CustomDebugStringConvertible {
|
||||
associatedtype T: RawRepresentable
|
||||
|
||||
var items: [RepeatingScheduleValue<T>] { get }
|
||||
|
||||
var timeZone: TimeZone { get set }
|
||||
|
||||
func between(start startDate: Date, end endDate: Date) -> [AbsoluteScheduleValue<T>]
|
||||
|
||||
func value(at time: Date) -> T
|
||||
}
|
||||
|
||||
|
||||
public extension DailySchedule {
|
||||
func value(at time: Date) -> T {
|
||||
return between(start: time, end: time).first!.value
|
||||
}
|
||||
|
||||
var debugDescription: String {
|
||||
return String(reflecting: rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public struct DailyValueSchedule<T: RawRepresentable>: RawRepresentable, CustomDebugStringConvertible, DailySchedule where T.RawValue: Any {
|
||||
public typealias RawValue = [String: Any]
|
||||
|
||||
private let referenceTimeInterval: TimeInterval
|
||||
let repeatInterval = TimeInterval(hours: 24)
|
||||
|
||||
public let items: [RepeatingScheduleValue<T>]
|
||||
public var timeZone: TimeZone
|
||||
|
||||
public init?(dailyItems: [RepeatingScheduleValue<T>], timeZone: TimeZone? = nil) {
|
||||
self.items = dailyItems.sorted { $0.startTime < $1.startTime }
|
||||
self.timeZone = timeZone ?? TimeZone.currentFixed
|
||||
|
||||
guard let firstItem = self.items.first else {
|
||||
return nil
|
||||
}
|
||||
|
||||
referenceTimeInterval = firstItem.startTime
|
||||
}
|
||||
|
||||
public init?(rawValue: RawValue) {
|
||||
guard let rawItems = rawValue["items"] as? [RepeatingScheduleValue<T>.RawValue] else {
|
||||
return nil
|
||||
}
|
||||
|
||||
var timeZone: TimeZone?
|
||||
|
||||
if let offset = rawValue["timeZone"] as? Int {
|
||||
timeZone = TimeZone(secondsFromGMT: offset)
|
||||
}
|
||||
|
||||
self.init(dailyItems: rawItems.compactMap { RepeatingScheduleValue(rawValue: $0) }, timeZone: timeZone)
|
||||
}
|
||||
|
||||
public var rawValue: RawValue {
|
||||
let rawItems = items.map { $0.rawValue }
|
||||
|
||||
return [
|
||||
"timeZone": timeZone.secondsFromGMT(),
|
||||
"items": rawItems
|
||||
]
|
||||
}
|
||||
|
||||
var maxTimeInterval: TimeInterval {
|
||||
return referenceTimeInterval + repeatInterval
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the time interval for a given date normalized to the span of the schedule items
|
||||
|
||||
- parameter date: The date to convert
|
||||
*/
|
||||
private func scheduleOffset(for date: Date) -> TimeInterval {
|
||||
// The time interval since a reference date in the specified time zone
|
||||
let interval = date.timeIntervalSinceReferenceDate + TimeInterval(timeZone.secondsFromGMT(for: date))
|
||||
|
||||
// The offset of the time interval since the last occurence of the reference time + n * repeatIntervals.
|
||||
// If the repeat interval was 1 day, this is the fractional amount of time since the most recent repeat interval starting at the reference time
|
||||
return ((interval - referenceTimeInterval).truncatingRemainder(dividingBy: repeatInterval)) + referenceTimeInterval
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a slice of schedule items that occur between two dates
|
||||
|
||||
- parameter startDate: The start date of the range
|
||||
- parameter endDate: The end date of the range
|
||||
|
||||
- returns: A slice of `ScheduleItem` values
|
||||
*/
|
||||
public func between(start startDate: Date, end endDate: Date) -> [AbsoluteScheduleValue<T>] {
|
||||
guard startDate <= endDate else {
|
||||
return []
|
||||
}
|
||||
|
||||
let startOffset = scheduleOffset(for: startDate)
|
||||
let endOffset = startOffset + endDate.timeIntervalSince(startDate)
|
||||
|
||||
guard endOffset <= maxTimeInterval else {
|
||||
let boundaryDate = startDate.addingTimeInterval(maxTimeInterval - startOffset)
|
||||
|
||||
return between(start: startDate, end: boundaryDate) + between(start: boundaryDate, end: endDate)
|
||||
}
|
||||
|
||||
var startIndex = 0
|
||||
var endIndex = items.count
|
||||
|
||||
for (index, item) in items.enumerated() {
|
||||
if startOffset >= item.startTime {
|
||||
startIndex = index
|
||||
}
|
||||
if endOffset < item.startTime {
|
||||
endIndex = index
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
let referenceDate = startDate.addingTimeInterval(-startOffset)
|
||||
|
||||
return (startIndex..<endIndex).map { (index) in
|
||||
let item = items[index]
|
||||
let endTime = index + 1 < items.count ? items[index + 1].startTime : maxTimeInterval
|
||||
|
||||
return AbsoluteScheduleValue(
|
||||
startDate: referenceDate.addingTimeInterval(item.startTime),
|
||||
endDate: referenceDate.addingTimeInterval(endTime),
|
||||
value: item.value
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension DailyValueSchedule where T: Equatable {
|
||||
public static func ==(lhs: DailyValueSchedule<T>, rhs: DailyValueSchedule<T>) -> Bool {
|
||||
guard lhs.items.count == rhs.items.count else {
|
||||
return false
|
||||
}
|
||||
|
||||
guard lhs.timeZone == rhs.timeZone else {
|
||||
return false
|
||||
}
|
||||
|
||||
for (a, b) in zip(lhs.items, rhs.items) {
|
||||
guard a == b else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
|
@ -1,306 +0,0 @@
|
|||
//
|
||||
// GlucoseRangeSchedule.swift
|
||||
// Loop
|
||||
//
|
||||
// Copyright © 2017 LoopKit Authors. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import HealthKit
|
||||
|
||||
|
||||
public struct DoubleRange {
|
||||
public let minValue: Double
|
||||
public let maxValue: Double
|
||||
|
||||
public init(minValue: Double, maxValue: Double) {
|
||||
self.minValue = minValue
|
||||
self.maxValue = maxValue
|
||||
}
|
||||
|
||||
public var isZero: Bool {
|
||||
return abs(minValue) < .ulpOfOne && abs(maxValue) < .ulpOfOne
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension DoubleRange: RawRepresentable {
|
||||
public typealias RawValue = [Double]
|
||||
|
||||
public init?(rawValue: RawValue) {
|
||||
guard rawValue.count == 2 else {
|
||||
return nil
|
||||
}
|
||||
|
||||
minValue = rawValue[0]
|
||||
maxValue = rawValue[1]
|
||||
}
|
||||
|
||||
public var rawValue: RawValue {
|
||||
return [minValue, maxValue]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension DoubleRange: Equatable {
|
||||
public static func ==(lhs: DoubleRange, rhs: DoubleRange) -> Bool {
|
||||
return abs(lhs.minValue - rhs.minValue) < .ulpOfOne &&
|
||||
abs(lhs.maxValue - rhs.maxValue) < .ulpOfOne
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Defines a daily schedule of glucose ranges
|
||||
public struct GlucoseRangeSchedule: DailySchedule {
|
||||
public typealias RawValue = [String: Any]
|
||||
|
||||
/// A time-based value overriding the rangeSchedule
|
||||
public struct Override {
|
||||
public enum Context: String {
|
||||
case workout
|
||||
case preMeal
|
||||
}
|
||||
|
||||
public let context: Context
|
||||
public let start: Date
|
||||
public let end: Date?
|
||||
public let value: DoubleRange
|
||||
|
||||
/// Initializes a new override
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - context: The context type of the override
|
||||
/// - start: The date at which the override starts
|
||||
/// - end: The date at which the override ends, or nil for an indefinite override
|
||||
/// - value: The value to return when active
|
||||
public init(context: Context, start: Date, end: Date?, value: DoubleRange) {
|
||||
self.context = context
|
||||
self.start = start
|
||||
self.end = end
|
||||
self.value = value
|
||||
}
|
||||
|
||||
public var activeDates: DateInterval {
|
||||
return DateInterval(start: start, end: end ?? .distantFuture)
|
||||
}
|
||||
|
||||
public func isActive(at date: Date = Date()) -> Bool {
|
||||
return activeDates.contains(date) && !value.isZero
|
||||
}
|
||||
}
|
||||
|
||||
var rangeSchedule: DailyQuantitySchedule<DoubleRange>
|
||||
|
||||
/// Default override values per context type
|
||||
public var overrideRanges: [Override.Context: DoubleRange]
|
||||
|
||||
/// The last-configured override of the range schedule
|
||||
public private(set) var override: Override?
|
||||
|
||||
/// Enables the predefined override value to be active during a specified system date range
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - context: The context type to use for value selection
|
||||
/// - start: The date the override should start
|
||||
/// - end: The date the override should end
|
||||
/// - Returns: Whether the override was successfully enabled
|
||||
public mutating func setOverride(_ context: Override.Context, from start: Date = Date(), until end: Date) -> Bool {
|
||||
guard let value = overrideRanges[context], end > start, !value.isZero else {
|
||||
return false
|
||||
}
|
||||
|
||||
override = Override(context: context, start: start, end: end, value: value)
|
||||
return true
|
||||
}
|
||||
|
||||
/// Removes the specified range override
|
||||
///
|
||||
/// - Parameter matching: The context to remove. If nil, all contexts are removed.
|
||||
public mutating func clearOverride(matching context: Override.Context? = nil) {
|
||||
guard let override = override, context == nil || context! == override.context else {
|
||||
return
|
||||
}
|
||||
|
||||
self.override = nil
|
||||
}
|
||||
|
||||
public init?(unit: HKUnit, dailyItems: [RepeatingScheduleValue<DoubleRange>], timeZone: TimeZone? = nil, overrideRanges: [Override.Context: DoubleRange], override: Override? = nil) {
|
||||
guard let rangeSchedule = DailyQuantitySchedule<DoubleRange>(unit: unit, dailyItems: dailyItems, timeZone: timeZone) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
self.rangeSchedule = rangeSchedule
|
||||
self.overrideRanges = overrideRanges
|
||||
self.override = override
|
||||
}
|
||||
|
||||
public init?(rawValue: RawValue) {
|
||||
guard let rangeSchedule = DailyQuantitySchedule<DoubleRange>(rawValue: rawValue) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
self.rangeSchedule = rangeSchedule
|
||||
|
||||
var overrideRanges: [Override.Context: DoubleRange] = [:]
|
||||
|
||||
if let workoutRangeRawValue = rawValue["workoutRange"] as? DoubleRange.RawValue {
|
||||
overrideRanges[.workout] = DoubleRange(rawValue: workoutRangeRawValue)
|
||||
}
|
||||
|
||||
if let overrideRangesRawValue = rawValue["overrideRanges"] as? [String: DoubleRange.RawValue] {
|
||||
for (key, value) in overrideRangesRawValue {
|
||||
guard let context = Override.Context(rawValue: key),
|
||||
let range = DoubleRange(rawValue: value), !range.isZero
|
||||
else {
|
||||
continue
|
||||
}
|
||||
|
||||
overrideRanges[context] = range
|
||||
}
|
||||
}
|
||||
|
||||
self.overrideRanges = overrideRanges
|
||||
|
||||
if let overrideRawValue = rawValue["override"] as? Override.RawValue {
|
||||
self.override = Override(rawValue: overrideRawValue)
|
||||
}
|
||||
}
|
||||
|
||||
public func between(start startDate: Date, end endDate: Date) -> [AbsoluteScheduleValue<DoubleRange>] {
|
||||
return rangeSchedule.between(start: startDate, end: endDate)
|
||||
}
|
||||
|
||||
public func value(at time: Date) -> DoubleRange {
|
||||
if let override = override, override.isActive() {
|
||||
return override.value
|
||||
}
|
||||
|
||||
return rangeSchedule.value(at: time)
|
||||
}
|
||||
|
||||
public var items: [RepeatingScheduleValue<DoubleRange>] {
|
||||
return rangeSchedule.items
|
||||
}
|
||||
|
||||
public var timeZone: TimeZone {
|
||||
get {
|
||||
return rangeSchedule.timeZone
|
||||
}
|
||||
set {
|
||||
rangeSchedule.timeZone = newValue
|
||||
}
|
||||
}
|
||||
|
||||
public var unit: HKUnit {
|
||||
return rangeSchedule.unit
|
||||
}
|
||||
|
||||
public var rawValue: RawValue {
|
||||
var rawValue = rangeSchedule.rawValue
|
||||
|
||||
var overrideRangesRawValue: [String: DoubleRange.RawValue] = [:]
|
||||
for (key, value) in overrideRanges {
|
||||
overrideRangesRawValue[key.rawValue] = value.rawValue
|
||||
}
|
||||
|
||||
rawValue["overrideRanges"] = overrideRangesRawValue
|
||||
rawValue["override"] = override?.rawValue
|
||||
|
||||
return rawValue
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension GlucoseRangeSchedule.Override: RawRepresentable {
|
||||
public typealias RawValue = [String: Any]
|
||||
|
||||
public init?(rawValue: RawValue) {
|
||||
guard let contextRaw = rawValue["context"] as? Context.RawValue,
|
||||
let context = Context(rawValue: contextRaw),
|
||||
let valueRaw = rawValue["value"] as? DoubleRange.RawValue,
|
||||
let value = DoubleRange(rawValue: valueRaw),
|
||||
let start = rawValue["start"] as? Date
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
|
||||
self.context = context
|
||||
self.start = start
|
||||
self.end = rawValue["end"] as? Date
|
||||
self.value = value
|
||||
}
|
||||
|
||||
public var rawValue: RawValue {
|
||||
var raw: RawValue = [
|
||||
"context": context.rawValue,
|
||||
"start": start,
|
||||
"value": value.rawValue
|
||||
]
|
||||
|
||||
raw["end"] = end
|
||||
|
||||
return raw
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension GlucoseRangeSchedule.Override: Equatable {
|
||||
public static func ==(lhs: GlucoseRangeSchedule.Override, rhs: GlucoseRangeSchedule.Override) -> Bool {
|
||||
return lhs.context == rhs.context &&
|
||||
lhs.start == rhs.start &&
|
||||
lhs.end == rhs.end &&
|
||||
lhs.value == rhs.value
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension GlucoseRangeSchedule: Equatable {
|
||||
public static func ==(lhs: GlucoseRangeSchedule, rhs: GlucoseRangeSchedule) -> Bool {
|
||||
return lhs.rangeSchedule == rhs.rangeSchedule &&
|
||||
lhs.overrideRanges == rhs.overrideRanges &&
|
||||
lhs.override == rhs.override
|
||||
}
|
||||
}
|
||||
|
||||
extension GlucoseRangeSchedule {
|
||||
func overrideEnabledForContext(_ context: Override.Context) -> Bool? {
|
||||
guard let override = override, override.context == context else {
|
||||
guard let value = overrideRanges[context], !value.isZero else {
|
||||
// Unavailable to set
|
||||
return nil
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
return override.isActive()
|
||||
}
|
||||
|
||||
var activeOverrideContext: GlucoseRangeSchedule.Override.Context? {
|
||||
guard let override = override, override.isActive() else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return override.context
|
||||
}
|
||||
|
||||
var configuredOverrideContexts: [GlucoseRangeSchedule.Override.Context] {
|
||||
var contexts: [GlucoseRangeSchedule.Override.Context] = []
|
||||
for (context, range) in overrideRanges where !range.isZero {
|
||||
contexts.append(context)
|
||||
}
|
||||
|
||||
return contexts
|
||||
}
|
||||
|
||||
func minQuantity(at date: Date) -> HKQuantity {
|
||||
return HKQuantity(unit: unit, doubleValue: value(at: date).minValue)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension DoubleRange {
|
||||
var averageValue: Double {
|
||||
return (maxValue + minValue) / 2
|
||||
}
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
//
|
||||
// SampleValue.swift
|
||||
// Naterade
|
||||
//
|
||||
// Created by Nathan Racklyeft on 1/24/16.
|
||||
// Copyright © 2016 Nathan Racklyeft. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import HealthKit
|
||||
|
||||
|
||||
public protocol TimelineValue {
|
||||
var startDate: Date { get }
|
||||
var endDate: Date { get }
|
||||
}
|
||||
|
||||
|
||||
public extension TimelineValue {
|
||||
var endDate: Date {
|
||||
return startDate
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public protocol SampleValue: TimelineValue {
|
||||
var quantity: HKQuantity { get }
|
||||
}
|
||||
|
||||
|
||||
public extension Sequence where Element: TimelineValue {
|
||||
/**
|
||||
Returns the closest element in the sorted sequence prior to the specified date
|
||||
|
||||
- parameter date: The date to use in the search
|
||||
|
||||
- returns: The closest element, if any exist before the specified date
|
||||
*/
|
||||
func closestPriorToDate(_ date: Date) -> Iterator.Element? {
|
||||
var closestElement: Iterator.Element?
|
||||
|
||||
for value in self {
|
||||
if value.startDate <= date {
|
||||
closestElement = value
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return closestElement
|
||||
}
|
||||
|
||||
/**
|
||||
Returns an array of elements filtered by the specified date range.
|
||||
|
||||
This behavior mimics HKQueryOptionNone, where the value must merely overlap the specified range,
|
||||
not strictly exist inside of it.
|
||||
|
||||
- parameter startDate: The earliest date of elements to return
|
||||
- parameter endDate: The latest date of elements to return
|
||||
|
||||
- returns: A new array of elements
|
||||
*/
|
||||
func filterDateRange(_ startDate: Date?, _ endDate: Date?) -> [Iterator.Element] {
|
||||
return filter { (value) -> Bool in
|
||||
if let startDate = startDate, value.endDate < startDate {
|
||||
return false
|
||||
}
|
||||
|
||||
if let endDate = endDate, value.startDate > endDate {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
//
|
||||
// StateColorPalette.swift
|
||||
// Loop
|
||||
//
|
||||
// Copyright © 2017 LoopKit Authors. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
|
||||
/// A collection of colors for displaying state
|
||||
public struct StateColorPalette {
|
||||
public let unknown: UIColor
|
||||
public let normal: UIColor
|
||||
public let warning: UIColor
|
||||
public let error: UIColor
|
||||
|
||||
public init(unknown: UIColor, normal: UIColor, warning: UIColor, error: UIColor) {
|
||||
self.unknown = unknown
|
||||
self.normal = normal
|
||||
self.warning = warning
|
||||
self.error = error
|
||||
}
|
||||
}
|
|
@ -138,7 +138,7 @@ final class RootViewController: UIViewController {
|
|||
private var m5StackManager: M5StackManager?
|
||||
|
||||
/// manage glucose chart
|
||||
private var glucoseChartManager: StatusChartsManager?
|
||||
private var glucoseChartManager: GlucoseChartManager?
|
||||
|
||||
// MARK: - View Life Cycle
|
||||
|
||||
|
@ -310,7 +310,7 @@ final class RootViewController: UIViewController {
|
|||
m5StackManager = M5StackManager(coreDataManager: coreDataManager)
|
||||
|
||||
// setup glucoseChartManager
|
||||
glucoseChartManager = StatusChartsManager()
|
||||
glucoseChartManager = GlucoseChartManager()
|
||||
}
|
||||
|
||||
/// process new glucose data received from transmitter.
|
||||
|
|
Loading…
Reference in New Issue