This commit is contained in:
Milos Kozak 2021-11-10 17:10:48 +01:00
commit 3dc2f073fe
11 changed files with 67 additions and 18 deletions

View file

@ -558,10 +558,7 @@ class IobCobCalculatorPlugin @Inject constructor(
return null
}
override fun getTempBasalIncludingConvertedExtended(timestamp: Long): TemporaryBasal? {
val tb = repository.getTemporaryBasalActiveAt(timestamp).blockingGet()
if (tb is ValueWrapper.Existing) return tb.value
private fun getConvertedExtended(timestamp: Long): TemporaryBasal? {
if (activePlugin.activePump.isFakingTempsByExtendedBoluses) {
val eb = repository.getExtendedBolusActiveAt(timestamp).blockingGet()
val profile = profileFunction.getProfile(timestamp) ?: return null
@ -570,6 +567,22 @@ class IobCobCalculatorPlugin @Inject constructor(
return null
}
override fun getTempBasalIncludingConvertedExtended(timestamp: Long): TemporaryBasal? {
val tb = repository.getTemporaryBasalActiveAt(timestamp).blockingGet()
if (tb is ValueWrapper.Existing) return tb.value
return getConvertedExtended(timestamp);
}
override fun getTempBasalIncludingConvertedExtendedForRange(startTime: Long, endTime: Long, calculationStep: Long): Map<Long, TemporaryBasal?> {
val tempBasals = HashMap<Long, TemporaryBasal?>();
val tbs = repository.getTemporaryBasalsDataActiveBetweenTimeAndTime(startTime, endTime).blockingGet()
for (t in startTime until endTime step calculationStep) {
val tb = tbs.firstOrNull { basal -> basal.timestamp <= t && (basal.timestamp + basal.duration) > t }
tempBasals[t] = tb ?: getConvertedExtended(t)
}
return tempBasals;
}
override fun calculateAbsoluteIobFromBaseBasals(toTime: Long): IobTotal {
val total = IobTotal(toTime)
var i = toTime - range()

View file

@ -50,10 +50,12 @@ class TddCalculator @Inject constructor(
result.put(midnight, tdd)
}
for (t in startTime until endTime step T.mins(5).msecs()) {
val calculationStep = T.mins(5).msecs()
val tempBasals = iobCobCalculator.getTempBasalIncludingConvertedExtendedForRange(startTime, endTime, calculationStep)
for (t in startTime until endTime step calculationStep) {
val midnight = MidnightTime.calc(t)
val tdd = result[midnight] ?: TotalDailyDose(timestamp = midnight)
val tbr = iobCobCalculator.getTempBasalIncludingConvertedExtended(t)
val tbr = tempBasals[t]
val profile = profileFunction.getProfile(t) ?: continue
val absoluteRate = tbr?.convertedToAbsolute(t, profile) ?: profile.getBasal(t)
tdd.basalAmount += absoluteRate / 60.0 * 5.0

View file

@ -44,7 +44,9 @@ open class TestBaseWithProfile : TestBase() {
@Before
fun prepareMock() {
validProfileJSON = "{\"dia\":\"3\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"},{\"time\":\"2:00\",\"value\":\"110\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"
validProfileJSON = "{\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"3\"}," +
"{\"time\":\"2:00\",\"value\":\"3.4\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4.5\"}]," +
"\"target_high\":[{\"time\":\"00:00\",\"value\":\"7\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"
dateUtil = DateUtil(context)
validProfile = ProfileSealed.Pure(pureProfileFromJson(JSONObject(validProfileJSON), dateUtil)!!)
effectiveProfileSwitch = EffectiveProfileSwitch(
@ -72,4 +74,4 @@ open class TestBaseWithProfile : TestBase() {
json.put("store", store)
return ProfileStore(profileInjector, json, dateUtil)
}
}
}

View file

@ -45,7 +45,9 @@ open class TestBaseWithProfile : TestBase() {
@Before
fun prepareMock() {
validProfileJSON = "{\"dia\":\"3\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"},{\"time\":\"2:00\",\"value\":\"110\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"
validProfileJSON = "{\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"3\"}," +
"{\"time\":\"2:00\",\"value\":\"3.4\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4.5\"}]," +
"\"target_high\":[{\"time\":\"00:00\",\"value\":\"7\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"
validProfile = ProfileSealed.Pure(pureProfileFromJson(JSONObject(validProfileJSON), dateUtil)!!)
}
@ -57,4 +59,4 @@ open class TestBaseWithProfile : TestBase() {
json.put("store", store)
return ProfileStore(profileInjector, json, dateUtil)
}
}
}

View file

@ -64,6 +64,17 @@ interface IobCobCalculator {
*/
fun getTempBasalIncludingConvertedExtended(timestamp: Long): TemporaryBasal?
/**
* Get running temporary basals for given time range, sliced by calculationStep.
* For each step between given range it calculates equivalent of getTempBasalIncludingConvertedExtended
*
* @param startTime start of calculated period, timestamp
* @param endTime end of calculated period, timestamp
* @param calculationStep calculation step, in millisecond
* @return map where for each step, its timestamp is a key and calculated optional temporary basal is a value
*/
fun getTempBasalIncludingConvertedExtendedForRange(startTime: Long, endTime: Long, calculationStep: Long): Map<Long, TemporaryBasal?>
/**
* Get running extended bolus at time
*

View file

@ -42,7 +42,9 @@ open class TestBaseWithProfile : TestBase() {
@Before
fun prepareMock() {
validProfileJSON = "{\"dia\":\"3\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"},{\"time\":\"2:00\",\"value\":\"110\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"
validProfileJSON = "{\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"3\"}," +
"{\"time\":\"2:00\",\"value\":\"3.4\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4.5\"}]," +
"\"target_high\":[{\"time\":\"00:00\",\"value\":\"7\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"
validProfile = ProfileSealed.Pure(pureProfileFromJson(JSONObject(validProfileJSON), dateUtil)!!)
}
@ -54,4 +56,4 @@ open class TestBaseWithProfile : TestBase() {
json.put("store", store)
return ProfileStore(profileInjector, json, dateUtil)
}
}
}

View file

@ -42,11 +42,17 @@ open class TestBaseWithProfile : TestBase() {
@Before
fun prepareMock() {
validProfileJSON = "{\"dia\":\"3\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"},{\"time\":\"2:00\",\"value\":\"110\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"
validProfileJSON = "{\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"3\"}," +
"{\"time\":\"2:00\",\"value\":\"3.4\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4.5\"}]," +
"\"target_high\":[{\"time\":\"00:00\",\"value\":\"7\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"
validProfile = ProfileSealed.Pure(pureProfileFromJson(JSONObject(validProfileJSON), dateUtil)!!)
}
fun getValidProfileStore(): ProfileStore {
validProfileJSON = "{\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"3\"}," +
"{\"time\":\"2:00\",\"value\":\"3.4\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4.5\"}]," +
"\"target_high\":[{\"time\":\"00:00\",\"value\":\"7\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"
val json = JSONObject()
val store = JSONObject()
store.put(TESTPROFILENAME, JSONObject(validProfileJSON))
@ -54,4 +60,4 @@ open class TestBaseWithProfile : TestBase() {
json.put("store", store)
return ProfileStore(profileInjector, json, dateUtil)
}
}
}

View file

@ -42,7 +42,9 @@ open class TestBaseWithProfile : TestBase() {
@Before
fun prepareMock() {
validProfileJSON = "{\"dia\":\"3\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"},{\"time\":\"2:00\",\"value\":\"110\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"
validProfileJSON = "{\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"3\"}," +
"{\"time\":\"2:00\",\"value\":\"3.4\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4.5\"}]," +
"\"target_high\":[{\"time\":\"00:00\",\"value\":\"7\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"
validProfile = ProfileSealed.Pure(pureProfileFromJson(JSONObject(validProfileJSON), dateUtil)!!)
}
@ -54,4 +56,4 @@ open class TestBaseWithProfile : TestBase() {
json.put("store", store)
return ProfileStore(profileInjector, json, dateUtil)
}
}
}

View file

@ -42,7 +42,9 @@ open class TestBaseWithProfile : TestBase() {
@Before
fun prepareMock() {
validProfileJSON = "{\"dia\":\"3\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"},{\"time\":\"2:00\",\"value\":\"110\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"
validProfileJSON = "{\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"3\"}," +
"{\"time\":\"2:00\",\"value\":\"3.4\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4.5\"}]," +
"\"target_high\":[{\"time\":\"00:00\",\"value\":\"7\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"
validProfile = ProfileSealed.Pure(pureProfileFromJson(JSONObject(validProfileJSON), dateUtil)!!)
}
@ -54,4 +56,4 @@ open class TestBaseWithProfile : TestBase() {
json.put("store", store)
return ProfileStore(profileInjector, json, dateUtil)
}
}
}

View file

@ -685,6 +685,10 @@ import kotlin.math.roundToInt
.subscribeOn(Schedulers.io())
.toWrappedSingle()
fun getTemporaryBasalsDataActiveBetweenTimeAndTime(from: Long, to: Long): Single<List<TemporaryBasal>> =
database.temporaryBasalDao.getTemporaryBasalActiveBetweenTimeAndTime(from, to)
.subscribeOn(Schedulers.io())
fun getTemporaryBasalsDataFromTime(timestamp: Long, ascending: Boolean): Single<List<TemporaryBasal>> =
database.temporaryBasalDao.getTemporaryBasalDataFromTime(timestamp)
.map { if (!ascending) it.reversed() else it }

View file

@ -47,6 +47,9 @@ internal interface TemporaryBasalDao : TraceableDao<TemporaryBasal> {
@Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE timestamp <= :timestamp AND (timestamp + duration) > :timestamp AND referenceId IS NULL AND isValid = 1 ORDER BY timestamp DESC LIMIT 1")
fun getTemporaryBasalActiveAt(timestamp: Long): Maybe<TemporaryBasal>
@Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE timestamp <= :to AND (timestamp + duration) > :from AND referenceId IS NULL AND isValid = 1 ORDER BY timestamp DESC")
fun getTemporaryBasalActiveBetweenTimeAndTime(from: Long, to: Long): Single<List<TemporaryBasal>>
@Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE timestamp >= :timestamp AND isValid = 1 AND referenceId IS NULL ORDER BY timestamp ASC")
fun getTemporaryBasalDataFromTime(timestamp: Long): Single<List<TemporaryBasal>>