Unit test for AutotuneCore
This commit is contained in:
parent
73e4933251
commit
a7c2dbc850
1 changed files with 138 additions and 0 deletions
|
@ -0,0 +1,138 @@
|
|||
package info.nightscout.androidaps.plugins.general.autotune
|
||||
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.TestBaseWithProfile
|
||||
import info.nightscout.androidaps.data.LocalInsulin
|
||||
import info.nightscout.androidaps.data.ProfileSealed
|
||||
import info.nightscout.androidaps.data.PureProfile
|
||||
import info.nightscout.androidaps.database.data.Block
|
||||
import info.nightscout.androidaps.database.data.TargetBlock
|
||||
import info.nightscout.androidaps.interfaces.*
|
||||
import info.nightscout.androidaps.plugins.general.autotune.data.*
|
||||
import info.nightscout.androidaps.utils.DateUtil
|
||||
import info.nightscout.androidaps.utils.JsonHelper
|
||||
import info.nightscout.androidaps.utils.T
|
||||
import info.nightscout.shared.sharedPreferences.SP
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import org.junit.Assert
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.`when`
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
class AutotuneCoreTest : TestBaseWithProfile() {
|
||||
@Mock lateinit var sp: SP
|
||||
@Mock lateinit var autotuneFS: AutotuneFS
|
||||
@Mock lateinit var injector: HasAndroidInjector
|
||||
@Mock lateinit var activePlugin: ActivePlugin
|
||||
lateinit var autotuneCore: AutotuneCore
|
||||
lateinit var prep: PreppedGlucose
|
||||
lateinit var prepjson: String
|
||||
lateinit var inputProfile: ATProfile
|
||||
var min5mCarbImpact = 0.0
|
||||
var autotuneMin = 0.0
|
||||
var autotuneMax = 0.0
|
||||
|
||||
@Before
|
||||
fun initData() {
|
||||
autotuneCore = AutotuneCore(sp,autotuneFS)
|
||||
prepjson = File("src/test/res/autotune/test1/autotune.2022-05-21.json").readText()
|
||||
val inputProfileJson = File("src/test/res/autotune/test1/profile.pump.json").readText()
|
||||
inputProfile = atProfileFromOapsJson(JSONObject(inputProfileJson), dateUtil)!!
|
||||
prep = PreppedGlucose(JSONObject(prepjson), dateUtil)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun autotuneCoreTest() { // Test if load from file of OpenAPS categorisation is Ok
|
||||
`when`(sp.getDouble(R.string.key_openapsama_autosens_max, 1.2)).thenReturn(autotuneMax)
|
||||
`when`(sp.getDouble(R.string.key_openapsama_autosens_min, 0.7)).thenReturn(autotuneMin)
|
||||
`when`(sp.getDouble(R.string.key_openapsama_min_5m_carbimpact, 3.0)).thenReturn(min5mCarbImpact)
|
||||
val OapsOutputProfileJson = File("src/test/res/autotune/test1/aapsorefprofile.json").readText()
|
||||
val OapsOutputProfile = atProfileFromOapsJson(JSONObject(OapsOutputProfileJson),dateUtil)
|
||||
val outProfile = autotuneCore.tuneAllTheThings(prep, inputProfile, inputProfile)
|
||||
OapsOutputProfile?.let {
|
||||
Assert.assertEquals(OapsOutputProfile.isf, outProfile.isf, 0.0)
|
||||
Assert.assertEquals(OapsOutputProfile.ic, outProfile.ic, 0.0)
|
||||
for (i in 0..23)
|
||||
Assert.assertEquals(OapsOutputProfile.basal[i], outProfile.basal[i], 0.0)
|
||||
}
|
||||
?:Assert.fail()
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* OpenAPS profile for Autotune only have one ISF value and one IC value
|
||||
*/
|
||||
fun atProfileFromOapsJson(jsonObject: JSONObject, dateUtil: DateUtil, defaultUnits: String? = null): ATProfile? {
|
||||
try {
|
||||
min5mCarbImpact = JsonHelper.safeGetDoubleAllowNull(jsonObject, "min_5m_carbimpact") ?: return null
|
||||
autotuneMin = JsonHelper.safeGetDoubleAllowNull(jsonObject, "autosens_min") ?: return null
|
||||
autotuneMax = JsonHelper.safeGetDoubleAllowNull(jsonObject, "autosens_max") ?: return null
|
||||
val txtUnits = JsonHelper.safeGetStringAllowNull(jsonObject, "units", defaultUnits) ?: return null
|
||||
val units = GlucoseUnit.fromText(txtUnits)
|
||||
val dia = JsonHelper.safeGetDoubleAllowNull(jsonObject, "dia") ?: return null
|
||||
val peak = JsonHelper.safeGetIntAllowNull(jsonObject, "insulinPeakTime") ?: return null
|
||||
val localInsulin = LocalInsulin("insulin", peak, dia)
|
||||
val timezone = TimeZone.getTimeZone(JsonHelper.safeGetString(jsonObject, "timezone", "UTC"))
|
||||
val isfJson = jsonObject.getJSONObject("isfProfile")
|
||||
val isfBlocks = ArrayList<Block>(1).also {
|
||||
val isfJsonArray = isfJson.getJSONArray("sensitivities")
|
||||
val value = isfJsonArray.getJSONObject(0).getDouble("sensitivity")
|
||||
it.add(0,Block((T.hours(24).secs()) * 1000L, value))
|
||||
}
|
||||
val icBlocks = ArrayList<Block>(1).also {
|
||||
val value = jsonObject.getDouble("carb_ratio")
|
||||
it.add(0,Block((T.hours(24).secs()) * 1000L, value))
|
||||
}
|
||||
val basalBlocks = blockFromJsonArray(jsonObject.getJSONArray("basalprofile"), dateUtil)
|
||||
?: return null
|
||||
val targetBlocks = ArrayList<TargetBlock>(1).also {
|
||||
it.add(0, TargetBlock((T.hours(24).secs()) * 1000L, 100.0, 100.0))
|
||||
}
|
||||
|
||||
val pure = PureProfile(
|
||||
jsonObject = jsonObject,
|
||||
basalBlocks = basalBlocks,
|
||||
isfBlocks = isfBlocks,
|
||||
icBlocks = icBlocks,
|
||||
targetBlocks = targetBlocks,
|
||||
glucoseUnit = units,
|
||||
timeZone = timezone,
|
||||
dia = dia
|
||||
)
|
||||
return ATProfile(ProfileSealed.Pure(pure), localInsulin, profileInjector).also { it.dateUtil = dateUtil}
|
||||
} catch (ignored: Exception) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun blockFromJsonArray(jsonArray: JSONArray?, dateUtil: DateUtil): List<Block>? {
|
||||
val size = jsonArray?.length() ?: return null
|
||||
val ret = ArrayList<Block>(size)
|
||||
try {
|
||||
for (index in 0 until jsonArray.length() - 1) {
|
||||
val o = jsonArray.getJSONObject(index)
|
||||
val tas = o.getInt("minutes") * 60
|
||||
val next = jsonArray.getJSONObject(index + 1)
|
||||
val nextTas = next.getInt("minutes") * 60
|
||||
val value = o.getDouble("rate")
|
||||
if (tas % 3600 != 0) return null
|
||||
if (nextTas % 3600 != 0) return null
|
||||
ret.add(index, Block((nextTas - tas) * 1000L, value))
|
||||
}
|
||||
val last: JSONObject = jsonArray.getJSONObject(jsonArray.length() - 1)
|
||||
val lastTas = last.getInt("minutes") * 60
|
||||
val value = last.getDouble("rate")
|
||||
ret.add(jsonArray.length() - 1, Block((T.hours(24).secs() - lastTas) * 1000L, value))
|
||||
} catch (e: Exception) {
|
||||
return null
|
||||
}
|
||||
return ret
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue