diff --git a/Sources/LoopAlgorithm/SampleValue.swift b/Sources/LoopAlgorithm/SampleValue.swift index fb978b2..28929e2 100644 --- a/Sources/LoopAlgorithm/SampleValue.swift +++ b/Sources/LoopAlgorithm/SampleValue.swift @@ -111,6 +111,13 @@ public extension Sequence where Element: TimelineValue { public extension RandomAccessCollection where Element: TimelineValue, Index == Int { func filterDateRange(_ startDate: Date?, _ endDate: Date?) -> [Element] { guard !isEmpty else { return [] } + // This binary-search filter is only correct when the elements are sorted + // ascending by startDate. Catch contract violations in debug builds; the + // check is compiled out of release builds, so there is no runtime cost. + assert( + zip(self, dropFirst()).allSatisfy { $0.startDate <= $1.startDate }, + "filterDateRange requires elements sorted ascending by startDate" + ) // Lower bound: first index where element.endDate >= startDate var lo = startIndex if let startDate { diff --git a/Tests/LoopAlgorithmTests/Fixtures/effect_from_history_output.json b/Tests/LoopAlgorithmTests/Fixtures/effect_from_history_output.json index 26aabee..9f5feaa 100644 --- a/Tests/LoopAlgorithmTests/Fixtures/effect_from_history_output.json +++ b/Tests/LoopAlgorithmTests/Fixtures/effect_from_history_output.json @@ -155,489 +155,488 @@ "unit" : "mg/dL" }, { - "amount" : -52.264027741079879, + "amount" : -52.2640280422766, "date" : "2015-10-15T20:40:00", "unit" : "mg/dL" }, { - "amount" : -61.76646699369725, + "amount" : -61.7677478059354, "date" : "2015-10-15T20:45:00", "unit" : "mg/dL" }, { - "amount" : -71.680918819657265, + "amount" : -71.687637842502099, "date" : "2015-10-15T20:50:00", "unit" : "mg/dL" }, { - "amount" : -81.900465930344126, + "amount" : -81.919234933234577, "date" : "2015-10-15T20:55:00", "unit" : "mg/dL" }, { - "amount" : -92.328165568362309, + "amount" : -92.367908821205617, "date" : "2015-10-15T21:00:00", "unit" : "mg/dL" }, { - "amount" : -102.87748849853307, + "amount" : -102.94913050298391, "date" : "2015-10-15T21:05:00", "unit" : "mg/dL" }, { - "amount" : -113.47146208796229, + "amount" : -113.58764235562131, "date" : "2015-10-15T21:10:00", "unit" : "mg/dL" }, { - "amount" : -124.06101315660501, + "amount" : -124.23414028175458, "date" : "2015-10-15T21:15:00", "unit" : "mg/dL" }, { - "amount" : -134.62009905018957, + "amount" : -134.86086625464586, "date" : "2015-10-15T21:20:00", "unit" : "mg/dL" }, { - "amount" : -145.1217841778539, + "amount" : -145.43932554945283, "date" : "2015-10-15T21:25:00", "unit" : "mg/dL" }, { - "amount" : -155.53243783066668, + "amount" : -155.93447255166663, "date" : "2015-10-15T21:30:00", "unit" : "mg/dL" }, { - "amount" : -165.81576158842529, + "amount" : -166.30872699287778, "date" : "2015-10-15T21:35:00", "unit" : "mg/dL" }, { - "amount" : -175.94014779129205, + "amount" : -176.52932203535278, "date" : "2015-10-15T21:40:00", "unit" : "mg/dL" }, { - "amount" : -185.87826522474734, + "amount" : -186.56788030227949, "date" : "2015-10-15T21:45:00", "unit" : "mg/dL" }, { - "amount" : -195.96262752949394, + "amount" : -196.75597331694593, "date" : "2015-10-15T21:50:00", "unit" : "mg/dL" }, { - "amount" : -206.52914016717139, + "amount" : -207.42866013639221, "date" : "2015-10-15T21:55:00", "unit" : "mg/dL" }, { - "amount" : -217.47340056280586, + "amount" : -218.48077975800794, "date" : "2015-10-15T22:00:00", "unit" : "mg/dL" }, { - "amount" : -228.70047046491561, + "amount" : -229.81671630023288, "date" : "2015-10-15T22:05:00", "unit" : "mg/dL" }, { - "amount" : -240.12529726332727, + "amount" : -241.35081366017906, "date" : "2015-10-15T22:10:00", "unit" : "mg/dL" }, { - "amount" : -251.690438990204, + "amount" : -253.02509433881008, "date" : "2015-10-15T22:15:00", "unit" : "mg/dL" }, { - "amount" : -263.36153925216848, + "amount" : -264.80472864892096, "date" : "2015-10-15T22:20:00", "unit" : "mg/dL" }, { - "amount" : -275.10715080098271, + "amount" : -276.65785298282833, "date" : "2015-10-15T22:25:00", "unit" : "mg/dL" }, { - "amount" : -286.89908382548953, + "amount" : -288.55591319388481, "date" : "2015-10-15T22:30:00", "unit" : "mg/dL" }, { - "amount" : -298.71214261916953, + "amount" : -300.47339671941916, "date" : "2015-10-15T22:35:00", "unit" : "mg/dL" }, { - "amount" : -310.52328534383491, + "amount" : -312.38698814059592, "date" : "2015-10-15T22:40:00", "unit" : "mg/dL" }, { - "amount" : -322.29421713089812, + "amount" : -324.25815839722361, "date" : "2015-10-15T22:45:00", "unit" : "mg/dL" }, { - "amount" : -333.97464519098088, + "amount" : -336.03641630638566, "date" : "2015-10-15T22:50:00", "unit" : "mg/dL" }, { - "amount" : -345.52048542110253, + "amount" : -347.67751185366495, "date" : "2015-10-15T22:55:00", "unit" : "mg/dL" }, { - "amount" : -356.8933206733189, + "amount" : -359.14289140170098, "date" : "2015-10-15T23:00:00", "unit" : "mg/dL" }, { - "amount" : -368.05989966830873, + "amount" : -370.39919378169293, "date" : "2015-10-15T23:05:00", "unit" : "mg/dL" }, { - "amount" : -378.99167375942488, + "amount" : -381.41778445665733, "date" : "2015-10-15T23:10:00", "unit" : "mg/dL" }, { - "amount" : -389.66436893407285, + "amount" : -392.17432512769443, "date" : "2015-10-15T23:15:00", "unit" : "mg/dL" }, { - "amount" : -400.05759060934326, + "amount" : -402.64837632560784, "date" : "2015-10-15T23:20:00", "unit" : "mg/dL" }, { - "amount" : -410.15445893826853, + "amount" : -412.82303069063533, "date" : "2015-10-15T23:25:00", "unit" : "mg/dL" }, { - "amount" : -419.94127249255814, + "amount" : -422.68457479343311, "date" : "2015-10-15T23:30:00", "unit" : "mg/dL" }, { - "amount" : -429.40719832776898, + "amount" : -432.22217749140992, "date" : "2015-10-15T23:35:00", "unit" : "mg/dL" }, { - "amount" : -438.54398656819569, + "amount" : -441.42760294662321, "date" : "2015-10-15T23:40:00", "unit" : "mg/dL" }, { - "amount" : -447.34570777179891, + "amount" : -450.2949465552303, "date" : "2015-10-15T23:45:00", "unit" : "mg/dL" }, { - "amount" : -455.80851145079703, + "amount" : -458.82039215448776, "date" : "2015-10-15T23:50:00", "unit" : "mg/dL" }, { - "amount" : -463.93040423153343, + "amount" : -467.00198898193264, "date" : "2015-10-15T23:55:00", "unit" : "mg/dL" }, { - "amount" : -471.71104623839892, + "amount" : -474.83944696315064, "date" : "2015-10-16T00:00:00", "unit" : "mg/dL" }, { - "amount" : -479.15156438132186, + "amount" : -482.33394899984762, "date" : "2015-10-16T00:05:00", "unit" : "mg/dL" }, { - "amount" : -486.2543813150387, + "amount" : -489.48797901916589, "date" : "2015-10-16T00:10:00", "unit" : "mg/dL" }, { - "amount" : -493.023058921406, + "amount" : -496.3051646287397, "date" : "2015-10-16T00:15:00", "unit" : "mg/dL" }, { - "amount" : -499.46215486351923, + "amount" : -502.79013291995432, "date" : "2015-10-16T00:20:00", "unit" : "mg/dL" }, { - "amount" : -505.5770310131204, + "amount" : -508.94831821502453, "date" : "2015-10-16T00:25:00", "unit" : "mg/dL" }, { - "amount" : -511.37357039402116, + "amount" : -514.78567839516109, "date" : "2015-10-16T00:30:00", "unit" : "mg/dL" }, { - "amount" : -516.85813478586385, + "amount" : -520.30865194907335, "date" : "2015-10-16T00:35:00", "unit" : "mg/dL" }, { - "amount" : -522.03765726190443, + "amount" : -525.52425001077142, "date" : "2015-10-16T00:40:00", "unit" : "mg/dL" }, { - "amount" : -526.91960305812609, + "amount" : -530.44001677959045, "date" : "2015-10-16T00:45:00", "unit" : "mg/dL" }, { - "amount" : -531.51186924154661, + "amount" : -535.0639287862225, "date" : "2015-10-16T00:50:00", "unit" : "mg/dL" }, { - "amount" : -535.82267812482121, + "amount" : -539.40428794807474, "date" : "2015-10-16T00:55:00", "unit" : "mg/dL" }, { - "amount" : -539.86069160301474, + "amount" : -543.46983558631189, "date" : "2015-10-16T01:00:00", "unit" : "mg/dL" }, { - "amount" : -543.63492920431247, + "amount" : -547.26967019309222, "date" : "2015-10-16T01:05:00", "unit" : "mg/dL" }, { - "amount" : -547.15451907267538, + "amount" : -550.81299816397518, "date" : "2015-10-16T01:10:00", "unit" : "mg/dL" }, { - "amount" : -550.42846838462219, + "amount" : -554.1089039948821, "date" : "2015-10-16T01:15:00", "unit" : "mg/dL" }, { - "amount" : -553.46562056285904, + "amount" : -557.16630730372844, "date" : "2015-10-16T01:20:00", "unit" : "mg/dL" }, { - "amount" : -556.27482496187201, + "amount" : -559.994132349437, "date" : "2015-10-16T01:25:00", "unit" : "mg/dL" }, { - "amount" : -558.86493785268158, + "amount" : -562.60130887330024, "date" : "2015-10-16T01:30:00", "unit" : "mg/dL" }, { - "amount" : -561.24477785349723, + "amount" : -564.99672740737037, "date" : "2015-10-16T01:35:00", "unit" : "mg/dL" }, { - "amount" : -563.43359411530798, + "amount" : -567.19970735700224, "date" : "2015-10-16T01:40:00", "unit" : "mg/dL" }, { - "amount" : -565.45900786932339, + "amount" : -569.23793846270314, "date" : "2015-10-16T01:45:00", "unit" : "mg/dL" }, { - "amount" : -567.32945007449439, + "amount" : -571.11991837788901, "date" : "2015-10-16T01:50:00", "unit" : "mg/dL" }, { - "amount" : -569.05270789672886, + "amount" : -572.85349909266051, "date" : "2015-10-16T01:55:00", "unit" : "mg/dL" }, { - "amount" : -570.6363878436191, + "amount" : -574.44635002602649, "date" : "2015-10-16T02:00:00", "unit" : "mg/dL" }, { - "amount" : -572.0877702437632, + "amount" : -575.9058124743799, "date" : "2015-10-16T02:05:00", "unit" : "mg/dL" }, { - "amount" : -573.41396516542841, + "amount" : -577.23905550979885, "date" : "2015-10-16T02:10:00", "unit" : "mg/dL" }, { - "amount" : -574.6219981579759, + "amount" : -578.45316171050558, "date" : "2015-10-16T02:15:00", "unit" : "mg/dL" }, { - "amount" : -575.7275007450005, + "amount" : -579.56381765143828, "date" : "2015-10-16T02:20:00", "unit" : "mg/dL" }, { - "amount" : -576.74580130146126, + "amount" : -580.5864047863015, "date" : "2015-10-16T02:25:00", "unit" : "mg/dL" }, { - "amount" : -577.68106518094305, + "amount" : -581.52513958638849, "date" : "2015-10-16T02:30:00", "unit" : "mg/dL" }, { - "amount" : -578.53713343337517, + "amount" : -582.38391227573231, "date" : "2015-10-16T02:35:00", "unit" : "mg/dL" }, { - "amount" : -579.31768623633491, + "amount" : -583.16645029377958, "date" : "2015-10-16T02:40:00", "unit" : "mg/dL" }, { - "amount" : -580.02630527022711, + "amount" : -583.87641862524356, "date" : "2015-10-16T02:45:00", "unit" : "mg/dL" }, { - "amount" : -580.66622392121678, + "amount" : -584.51718221441229, "date" : "2015-10-16T02:50:00", "unit" : "mg/dL" }, { - "amount" : -581.24043672229402, + "amount" : -585.09185723978885, "date" : "2015-10-16T02:55:00", "unit" : "mg/dL" }, { - "amount" : -581.7518346710234, + "amount" : -585.60345407259592, "date" : "2015-10-16T03:00:00", "unit" : "mg/dL" }, { - "amount" : -582.20324063049941, + "amount" : -586.05490729716598, "date" : "2015-10-16T03:05:00", "unit" : "mg/dL" }, { - "amount" : -582.59740660912655, + "amount" : -586.44907327579324, "date" : "2015-10-16T03:10:00", "unit" : "mg/dL" }, { - "amount" : -582.93757898138779, + "amount" : -586.78924564805448, "date" : "2015-10-16T03:15:00", "unit" : "mg/dL" }, { - "amount" : -583.22741489495911, + "amount" : -587.0790815616258, "date" : "2015-10-16T03:20:00", "unit" : "mg/dL" }, { - "amount" : -583.47030192860075, + "amount" : -587.32196859526744, "date" : "2015-10-16T03:25:00", "unit" : "mg/dL" }, { - "amount" : -583.66919134980412, + "amount" : -587.52085801647081, "date" : "2015-10-16T03:30:00", "unit" : "mg/dL" }, { - "amount" : -583.8267089590006, + "amount" : -587.67837562566717, "date" : "2015-10-16T03:35:00", "unit" : "mg/dL" }, { - "amount" : -583.94537949189805, + "amount" : -587.79704615856474, "date" : "2015-10-16T03:40:00", "unit" : "mg/dL" }, { - "amount" : -584.02762789860844, + "amount" : -587.87929456527513, "date" : "2015-10-16T03:45:00", "unit" : "mg/dL" }, { - "amount" : -584.08632593727748, + "amount" : -587.93799260394417, "date" : "2015-10-16T03:50:00", "unit" : "mg/dL" }, { - "amount" : -584.13502294212412, + "amount" : -587.98668960879081, "date" : "2015-10-16T03:55:00", "unit" : "mg/dL" }, { - "amount" : -584.17434487516277, + "amount" : -588.02601154182946, "date" : "2015-10-16T04:00:00", "unit" : "mg/dL" }, { - "amount" : -584.20485800454787, + "amount" : -588.05652467121456, "date" : "2015-10-16T04:05:00", "unit" : "mg/dL" }, { - "amount" : -584.22710644921244, + "amount" : -588.07877311587902, "date" : "2015-10-16T04:10:00", "unit" : "mg/dL" }, { - "amount" : -584.24216197536089, + "amount" : -588.09382864202757, "date" : "2015-10-16T04:15:00", "unit" : "mg/dL" }, { - "amount" : -584.25155129938207, + "amount" : -588.10321796604876, "date" : "2015-10-16T04:20:00", "unit" : "mg/dL" }, { - "amount" : -584.2566906636182, + "amount" : -588.10835733028489, "date" : "2015-10-16T04:25:00", "unit" : "mg/dL" }, { - "amount" : -584.2589075785753, + "amount" : -588.11057424524188, "date" : "2015-10-16T04:30:00", "unit" : "mg/dL" }, { - "amount" : -584.2594444444444, + "amount" : -588.11111111111109, "date" : "2015-10-16T04:35:00", "unit" : "mg/dL" }, { - "amount" : -584.2594444444444, + "amount" : -588.11111111111109, "date" : "2015-10-16T04:40:00", "unit" : "mg/dL" } -] - +] \ No newline at end of file diff --git a/Tests/LoopAlgorithmTests/InsulinMathTests.swift b/Tests/LoopAlgorithmTests/InsulinMathTests.swift index 04b74c2..bc5b47a 100644 --- a/Tests/LoopAlgorithmTests/InsulinMathTests.swift +++ b/Tests/LoopAlgorithmTests/InsulinMathTests.swift @@ -237,17 +237,10 @@ class InsulinMathTests: XCTestCase { ) ] + // A well-formed basal schedule: sorted ascending, contiguous, and non-overlapping. let basal = [ AbsoluteScheduleValue( startDate: startDate, - endDate: dateFormatter.date(from: "2015-10-15T20:30:00")!, - value: 1.0), - AbsoluteScheduleValue( - startDate: dateFormatter.date(from: "2015-10-15T20:30:00")!, - endDate: dateFormatter.date(from: "2015-10-15T21:00:00")!, - value: 0.8), - AbsoluteScheduleValue( - startDate: dateFormatter.date(from: "2015-10-15T21:00:00")!, endDate: dateFormatter.date(from: "2015-10-15T18:30:00")!, value: 1.0), AbsoluteScheduleValue( @@ -256,6 +249,14 @@ class InsulinMathTests: XCTestCase { value: 0.8), AbsoluteScheduleValue( startDate: dateFormatter.date(from: "2015-10-15T19:00:00")!, + endDate: dateFormatter.date(from: "2015-10-15T20:30:00")!, + value: 1.0), + AbsoluteScheduleValue( + startDate: dateFormatter.date(from: "2015-10-15T20:30:00")!, + endDate: dateFormatter.date(from: "2015-10-15T21:00:00")!, + value: 0.8), + AbsoluteScheduleValue( + startDate: dateFormatter.date(from: "2015-10-15T21:00:00")!, endDate: endDate, value: 1.0), ]