Enable DynISF, fallback to SMB with no tdd data, new objective to enable DynISF

This commit is contained in:
Milos Kozak 2023-08-17 15:51:17 +02:00
parent f870fbc618
commit 8d05588f11
17 changed files with 145 additions and 66 deletions

View file

@ -11,8 +11,8 @@ import info.nightscout.androidaps.insight.database.InsightDatabaseDao
import info.nightscout.androidaps.insight.database.InsightDbHelper
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin
import info.nightscout.database.impl.AppRepository
import info.nightscout.interfaces.ApsMode
import info.nightscout.implementation.iob.GlucoseStatusProviderImpl
import info.nightscout.interfaces.ApsMode
import info.nightscout.interfaces.bgQualityCheck.BgQualityCheck
import info.nightscout.interfaces.constraints.Constraint
import info.nightscout.interfaces.constraints.Constraints
@ -29,6 +29,7 @@ import info.nightscout.interfaces.pump.PumpSync
import info.nightscout.interfaces.pump.TemporaryBasalStorage
import info.nightscout.interfaces.pump.defs.PumpDescription
import info.nightscout.interfaces.queue.CommandQueue
import info.nightscout.interfaces.stats.TddCalculator
import info.nightscout.interfaces.ui.UiInteraction
import info.nightscout.interfaces.utils.HardLimits
import info.nightscout.plugins.aps.openAPSAMA.OpenAPSAMAPlugin
@ -75,6 +76,7 @@ class ConstraintsCheckerTest : TestBaseWithProfile() {
@Mock lateinit var danaHistoryDatabase: DanaHistoryDatabase
@Mock lateinit var insightDatabase: InsightDatabase
@Mock lateinit var bgQualityCheck: BgQualityCheck
@Mock lateinit var tddCalculator: TddCalculator
private lateinit var hardLimits: HardLimits
private lateinit var danaPump: DanaPump
@ -190,7 +192,8 @@ class ConstraintsCheckerTest : TestBaseWithProfile() {
dateUtil,
repository,
glucoseStatusProvider,
bgQualityCheck
bgQualityCheck,
tddCalculator
)
openAPSSMBDynamicISFPlugin =
OpenAPSSMBDynamicISFPlugin(
@ -209,8 +212,8 @@ class ConstraintsCheckerTest : TestBaseWithProfile() {
dateUtil,
repository,
glucoseStatusProvider,
config,
bgQualityCheck
bgQualityCheck,
tddCalculator
)
openAPSAMAPlugin =
OpenAPSAMAPlugin(

View file

@ -15,6 +15,7 @@ import info.nightscout.interfaces.plugin.ActivePlugin
import info.nightscout.interfaces.plugin.PluginType
import info.nightscout.interfaces.profiling.Profiler
import info.nightscout.interfaces.pump.defs.PumpDescription
import info.nightscout.interfaces.stats.TddCalculator
import info.nightscout.interfaces.ui.UiInteraction
import info.nightscout.interfaces.utils.HardLimits
import info.nightscout.plugins.aps.openAPSAMA.OpenAPSAMAPlugin
@ -41,6 +42,7 @@ class SafetyPluginTest : TestBaseWithProfile() {
@Mock lateinit var glucoseStatusProvider: GlucoseStatusProvider
@Mock lateinit var bgQualityCheck: BgQualityCheck
@Mock lateinit var uiInteraction: UiInteraction
@Mock lateinit var tddCalculator: TddCalculator
private lateinit var hardLimits: HardLimits
private lateinit var safetyPlugin: SafetyPlugin
@ -84,7 +86,7 @@ class SafetyPluginTest : TestBaseWithProfile() {
)
openAPSSMBPlugin = OpenAPSSMBPlugin(
injector, aapsLogger, rxBus, constraintChecker, rh, profileFunction, context, activePlugin, iobCobCalculator, hardLimits, profiler, sp,
dateUtil, repository, glucoseStatusProvider, bgQualityCheck
dateUtil, repository, glucoseStatusProvider, bgQualityCheck, tddCalculator
)
}

View file

@ -30,7 +30,12 @@ interface DetermineBasalAdapter {
microBolusAllowed: Boolean = false,
uamAllowed: Boolean = false,
advancedFiltering: Boolean = false,
flatBGsDetected: Boolean = false
flatBGsDetected: Boolean = false,
tdd1D: Double?,
tdd7D: Double?,
tddLast24H: Double?,
tddLast4H: Double?,
tddLast8to4H: Double?
)
operator fun invoke(): APSResult?

View file

@ -21,6 +21,7 @@ interface Constraints {
fun isLgsAllowed(value: Constraint<Boolean> = Constraint(true)): Constraint<Boolean> = value
fun isAutosensModeEnabled(value: Constraint<Boolean> = Constraint(true)): Constraint<Boolean> = value
fun isSMBModeEnabled(value: Constraint<Boolean> = Constraint(true)): Constraint<Boolean> = value
fun isDynIsfModeEnabled(value: Constraint<Boolean> = Constraint(true)): Constraint<Boolean> = value
fun isUAMEnabled(value: Constraint<Boolean> = Constraint(true)): Constraint<Boolean> = value
fun isAdvancedFilteringEnabled(value: Constraint<Boolean> = Constraint(true)): Constraint<Boolean> = value
fun isSuperBolusEnabled(value: Constraint<Boolean> = Constraint(true)): Constraint<Boolean> = value

View file

@ -13,6 +13,7 @@ interface Objectives {
const val AUTOSENS_OBJECTIVE = 7
const val SMB_OBJECTIVE = 8
const val AUTO_OBJECTIVE = 9
const val DYN_ISF_OBJECTIVE = 10
}
fun isAccomplished(index: Int): Boolean

View file

@ -1,7 +1,6 @@
package info.nightscout.plugins.aps.openAPSAMA
import dagger.android.HasAndroidInjector
import info.nightscout.plugins.aps.APSResultObject
import info.nightscout.core.extensions.convertedToAbsolute
import info.nightscout.core.extensions.getPassedDurationToTimeInMinutes
import info.nightscout.core.extensions.plannedRemainingMinutes
@ -15,6 +14,7 @@ import info.nightscout.interfaces.iob.IobTotal
import info.nightscout.interfaces.iob.MealData
import info.nightscout.interfaces.profile.Profile
import info.nightscout.interfaces.profile.ProfileFunction
import info.nightscout.plugins.aps.APSResultObject
import info.nightscout.plugins.aps.R
import info.nightscout.plugins.aps.logger.LoggerCallback
import info.nightscout.plugins.aps.utils.ScriptReader
@ -162,7 +162,12 @@ class DetermineBasalAdapterAMAJS internal constructor(scriptReader: ScriptReader
microBolusAllowed: Boolean,
uamAllowed: Boolean,
advancedFiltering: Boolean,
flatBGsDetected: Boolean
flatBGsDetected: Boolean,
tdd1D: Double?,
tdd7D: Double?,
tddLast24H: Double?,
tddLast4H: Double?,
tddLast8to4H: Double?
) {
this.profile = JSONObject()
this.profile.put("max_iob", maxIob)

View file

@ -181,7 +181,12 @@ class OpenAPSAMAPlugin @Inject constructor(
determineBasalAdapterAMAJS.setData(
profile, maxIob, maxBasal, minBg, maxBg, targetBg, activePlugin.activePump.baseBasalRate, iobArray, glucoseStatus, mealData,
lastAutosensResult.ratio,
isTempTarget
isTempTarget,
tdd1D = null,
tdd7D = null,
tddLast4H = null,
tddLast8to4H = null,
tddLast24H = null,
)
} catch (e: JSONException) {
fabricPrivacy.logException(e)

View file

@ -1,7 +1,6 @@
package info.nightscout.plugins.aps.openAPSSMB
import dagger.android.HasAndroidInjector
import info.nightscout.plugins.aps.APSResultObject
import info.nightscout.core.extensions.convertedToAbsolute
import info.nightscout.core.extensions.getPassedDurationToTimeInMinutes
import info.nightscout.core.extensions.plannedRemainingMinutes
@ -16,6 +15,7 @@ import info.nightscout.interfaces.iob.MealData
import info.nightscout.interfaces.plugin.ActivePlugin
import info.nightscout.interfaces.profile.Profile
import info.nightscout.interfaces.profile.ProfileFunction
import info.nightscout.plugins.aps.APSResultObject
import info.nightscout.plugins.aps.R
import info.nightscout.plugins.aps.logger.LoggerCallback
import info.nightscout.plugins.aps.utils.ScriptReader
@ -174,7 +174,12 @@ class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader:
microBolusAllowed: Boolean,
uamAllowed: Boolean,
advancedFiltering: Boolean,
flatBGsDetected: Boolean
flatBGsDetected: Boolean,
tdd1D: Double?,
tdd7D: Double?,
tddLast24H: Double?,
tddLast4H: Double?,
tddLast8to4H: Double?
) {
val pump = activePlugin.activePump
val pumpBolusStep = pump.pumpDescription.bolusStep

View file

@ -25,6 +25,7 @@ import info.nightscout.interfaces.plugin.PluginType
import info.nightscout.interfaces.profile.Profile
import info.nightscout.interfaces.profile.ProfileFunction
import info.nightscout.interfaces.profiling.Profiler
import info.nightscout.interfaces.stats.TddCalculator
import info.nightscout.interfaces.utils.HardLimits
import info.nightscout.interfaces.utils.Round
import info.nightscout.plugins.aps.R
@ -57,7 +58,8 @@ class OpenAPSSMBPlugin @Inject constructor(
private val dateUtil: DateUtil,
private val repository: AppRepository,
private val glucoseStatusProvider: GlucoseStatusProvider,
private val bgQualityCheck: BgQualityCheck
private val bgQualityCheck: BgQualityCheck,
private val tddCalculator: TddCalculator
) : PluginBase(
PluginDescription()
.mainType(PluginType.APS)
@ -71,6 +73,14 @@ class OpenAPSSMBPlugin @Inject constructor(
aapsLogger, rh, injector
), APS, Constraints {
// DynamicISF specific
var tdd1D : Double? = null
var tdd7D : Double? = null
var tddLast24H : Double? = null
var tddLast4H : Double? = null
var tddLast8to4H : Double? = null
var dynIsfEnabled : Constraint<Boolean> = Constraint(false)
// last values
override var lastAPSRun: Long = 0
override var lastAPSResult: DetermineBasalResultSMB? = null
@ -193,11 +203,24 @@ class OpenAPSSMBPlugin @Inject constructor(
constraintChecker.isUAMEnabled(it)
inputConstraints.copyReasons(it)
}
dynIsfEnabled = Constraint(true).also {
constraintChecker.isDynIsfModeEnabled(it)
inputConstraints.copyReasons(it)
}
val flatBGsDetected = bgQualityCheck.state == BgQualityCheck.State.FLAT
profiler.log(LTag.APS, "detectSensitivityAndCarbAbsorption()", startPart)
profiler.log(LTag.APS, "SMB data gathering", start)
start = System.currentTimeMillis()
// DynamicISF specific
// without these values DynISF doesn't work properly
// Current implementation is fallback to SMB if TDD history is not available. Thus calculated here
tdd1D = tddCalculator.averageTDD(tddCalculator.calculate(1, allowMissingDays = false))?.totalAmount
tdd7D = tddCalculator.averageTDD(tddCalculator.calculate(7, allowMissingDays = false))?.totalAmount
tddLast24H = tddCalculator.calculateDaily(-24, 0)?.totalAmount
tddLast4H = tddCalculator.calculateDaily(-4, 0)?.totalAmount
tddLast8to4H = tddCalculator.calculateDaily(-8, -4)?.totalAmount
provideDetermineBasalAdapter().also { determineBasalAdapterSMBJS ->
determineBasalAdapterSMBJS.setData(
profile, maxIob, maxBasal, minBg, maxBg, targetBg,
@ -210,7 +233,12 @@ class OpenAPSSMBPlugin @Inject constructor(
smbAllowed.value(),
uam.value(),
advancedFiltering.value(),
flatBGsDetected
flatBGsDetected,
tdd1D = tdd1D,
tdd7D = tdd7D,
tddLast24H = tddLast24H,
tddLast4H = tddLast4H,
tddLast8to4H = tddLast8to4H
)
val now = System.currentTimeMillis()
val determineBasalResultSMB = determineBasalAdapterSMBJS.invoke()
@ -243,7 +271,7 @@ class OpenAPSSMBPlugin @Inject constructor(
override fun applyMaxIOBConstraints(maxIob: Constraint<Double>): Constraint<Double> {
if (isEnabled()) {
val maxIobPref: Double = sp.getDouble(info.nightscout.plugins.aps.R.string.key_openapssmb_max_iob, 3.0)
val maxIobPref: Double = sp.getDouble(R.string.key_openapssmb_max_iob, 3.0)
maxIob.setIfSmaller(aapsLogger, maxIobPref, rh.gs(R.string.limiting_iob, maxIobPref, rh.gs(R.string.maxvalueinpreferences)), this)
maxIob.setIfSmaller(aapsLogger, hardLimits.maxIobSMB(), rh.gs(R.string.limiting_iob, hardLimits.maxIobSMB(), rh.gs(R.string.hardlimit)), this)
}

View file

@ -14,7 +14,6 @@ import info.nightscout.interfaces.iob.MealData
import info.nightscout.interfaces.plugin.ActivePlugin
import info.nightscout.interfaces.profile.Profile
import info.nightscout.interfaces.profile.ProfileFunction
import info.nightscout.interfaces.stats.TddCalculator
import info.nightscout.interfaces.utils.Round
import info.nightscout.plugins.aps.R
import info.nightscout.plugins.aps.logger.LoggerCallback
@ -38,6 +37,7 @@ import org.mozilla.javascript.Undefined
import java.io.IOException
import java.lang.reflect.InvocationTargetException
import java.nio.charset.StandardCharsets
import java.security.InvalidParameterException
import javax.inject.Inject
import kotlin.math.ln
@ -48,7 +48,6 @@ class DetermineBasalAdapterSMBDynamicISFJS internal constructor(private val scri
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var iobCobCalculator: IobCobCalculator
@Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var tddCalculator: TddCalculator
private var profile = JSONObject()
private var mGlucoseStatus = JSONObject()
@ -176,8 +175,19 @@ class DetermineBasalAdapterSMBDynamicISFJS internal constructor(private val scri
microBolusAllowed: Boolean,
uamAllowed: Boolean,
advancedFiltering: Boolean,
flatBGsDetected: Boolean
flatBGsDetected: Boolean,
tdd1D: Double?,
tdd7D: Double?,
tddLast24H: Double?,
tddLast4H: Double?,
tddLast8to4H: Double?
) {
tdd1D ?: throw InvalidParameterException()
tdd7D ?: throw InvalidParameterException()
tddLast24H ?: throw InvalidParameterException()
tddLast4H ?: throw InvalidParameterException()
tddLast8to4H ?: throw InvalidParameterException()
val pump = activePlugin.activePump
val pumpBolusStep = pump.pumpDescription.bolusStep
this.profile.put("max_iob", maxIob)
@ -262,12 +272,6 @@ class DetermineBasalAdapterSMBDynamicISFJS internal constructor(private val scri
this.mealData.put("lastBolusTime", mealData.lastBolusTime)
this.mealData.put("lastCarbTime", mealData.lastCarbTime)
val tdd1D = tddCalculator.averageTDD(tddCalculator.calculate(1, allowMissingDays = false))?.totalAmount
val tdd7D = tddCalculator.averageTDD(tddCalculator.calculate(7, allowMissingDays = false))?.totalAmount
val tddLast24H = tddCalculator.calculateDaily(-24, 0)?.totalAmount
val tddLast4H = tddCalculator.calculateDaily(-4, 0)?.totalAmount
val tddLast8to4H = tddCalculator.calculateDaily(-8, -4)?.totalAmount
val insulin = activePlugin.activeInsulin
val insulinDivisor = when {
insulin.peak > 65 -> 55 // lyumjev peak: 45
@ -275,34 +279,19 @@ class DetermineBasalAdapterSMBDynamicISFJS internal constructor(private val scri
else -> 75 // rapid peak: 75
}
var tdd: Double? = null
var variableSensitivity: Double
if (tddLast24H != null && tddLast4H != null && tddLast8to4H != null) {
val tddWeightedFromLast8H = ((1.4 * tddLast4H) + (0.6 * tddLast8to4H)) * 3
// console.error("Rolling 8 hours weight average: " + tdd_last8_wt + "; ");
// console.error("1-day average TDD is: " + tdd1 + "; ");
// console.error("7-day average TDD is: " + tdd7 + "; ");
val tddWeightedFromLast8H = ((1.4 * tddLast4H) + (0.6 * tddLast8to4H)) * 3
var tdd = (tddWeightedFromLast8H * 0.33) + (tdd7D * 0.34) + (tdd1D * 0.33)
val dynISFadjust = SafeParse.stringToDouble(sp.getString(R.string.key_DynISFAdjust, "100")) / 100.0
tdd *= dynISFadjust
tdd =
if (tdd1D != null && tdd7D != null) (tddWeightedFromLast8H * 0.33) + (tdd7D * 0.34) + (tdd1D * 0.33)
else tddWeightedFromLast8H
// console.log("TDD = " + TDD + " using average of 7-day, 1-day and weighted 8hr average");
val dynISFadjust = SafeParse.stringToDouble(sp.getString(R.string.key_DynISFAdjust, "100")) / 100.0
tdd *= dynISFadjust
variableSensitivity = 1800 / (tdd * (ln((glucoseStatus.glucose / insulinDivisor) + 1)))
variableSensitivity = Round.roundTo(variableSensitivity, 0.1)
} else {
variableSensitivity = profile.getIsfMgdl()
}
val variableSensitivity = Round.roundTo(1800 / (tdd * (ln((glucoseStatus.glucose / insulinDivisor) + 1))), 0.1)
this.profile.put("variable_sens", variableSensitivity)
this.profile.put("insulinDivisor", insulinDivisor)
tdd?.let { this.profile.put("TDD", tdd) }
this.profile.put("TDD", tdd)
if (sp.getBoolean(R.string.key_adjust_sensitivity, false) && tdd7D != null && tddLast24H != null)
if (sp.getBoolean(R.string.key_adjust_sensitivity, false))
autosensData.put("ratio", tddLast24H / tdd7D)
else
autosensData.put("ratio", 1.0)

View file

@ -4,7 +4,6 @@ import android.content.Context
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.annotations.OpenForTesting
import info.nightscout.database.impl.AppRepository
import info.nightscout.interfaces.Config
import info.nightscout.interfaces.aps.DetermineBasalAdapter
import info.nightscout.interfaces.bgQualityCheck.BgQualityCheck
import info.nightscout.interfaces.constraints.Constraints
@ -13,8 +12,10 @@ import info.nightscout.interfaces.iob.IobCobCalculator
import info.nightscout.interfaces.plugin.ActivePlugin
import info.nightscout.interfaces.profile.ProfileFunction
import info.nightscout.interfaces.profiling.Profiler
import info.nightscout.interfaces.stats.TddCalculator
import info.nightscout.interfaces.utils.HardLimits
import info.nightscout.plugins.aps.R
import info.nightscout.plugins.aps.openAPSSMB.DetermineBasalAdapterSMBJS
import info.nightscout.plugins.aps.openAPSSMB.OpenAPSSMBPlugin
import info.nightscout.plugins.aps.utils.ScriptReader
import info.nightscout.rx.bus.RxBus
@ -43,8 +44,8 @@ class OpenAPSSMBDynamicISFPlugin @Inject constructor(
dateUtil: DateUtil,
repository: AppRepository,
glucoseStatusProvider: GlucoseStatusProvider,
private val config: Config,
private val bgQualityCheck: BgQualityCheck
bgQualityCheck: BgQualityCheck,
tddCalculator: TddCalculator
) : OpenAPSSMBPlugin(
injector,
aapsLogger,
@ -61,7 +62,8 @@ class OpenAPSSMBDynamicISFPlugin @Inject constructor(
dateUtil,
repository,
glucoseStatusProvider,
bgQualityCheck
bgQualityCheck,
tddCalculator
) {
init {
@ -71,10 +73,11 @@ class OpenAPSSMBDynamicISFPlugin @Inject constructor(
.shortName(R.string.dynisf_shortname)
.preferencesId(R.xml.pref_openapssmbdynamicisf)
.setDefault(false)
.showInList(config.isEngineeringMode() && config.isDev())
}
override fun specialEnableCondition(): Boolean = config.isEngineeringMode() && config.isDev()
override fun provideDetermineBasalAdapter(): DetermineBasalAdapter = DetermineBasalAdapterSMBDynamicISFJS(ScriptReader(context), injector)
// If there is no TDD data fallback to SMB as ISF calculation may be really off
override fun provideDetermineBasalAdapter(): DetermineBasalAdapter =
if (tdd1D == null || tdd7D == null || tddLast4H == null || tddLast8to4H == null || tddLast24H == null || !dynIsfEnabled.value())
DetermineBasalAdapterSMBJS(ScriptReader(context), injector)
else DetermineBasalAdapterSMBDynamicISFJS(ScriptReader(context), injector)
}

View file

@ -60,6 +60,16 @@ class ConstraintsImpl @Inject constructor(private val activePlugin: ActivePlugin
return value
}
override fun isDynIsfModeEnabled(value: Constraint<Boolean>): Constraint<Boolean> {
val constraintsPlugins = activePlugin.getSpecificPluginsListByInterface(Constraints::class.java)
for (p in constraintsPlugins) {
val constraint = p as Constraints
if (!p.isEnabled()) continue
constraint.isDynIsfModeEnabled(value)
}
return value
}
override fun isUAMEnabled(value: Constraint<Boolean>): Constraint<Boolean> {
val constraintsPlugins = activePlugin.getSpecificPluginsListByInterface(Constraints::class.java)
for (p in constraintsPlugins) {

View file

@ -9,6 +9,7 @@ import info.nightscout.plugins.constraints.objectives.objectives.Objective
import info.nightscout.plugins.constraints.objectives.objectives.Objective0
import info.nightscout.plugins.constraints.objectives.objectives.Objective1
import info.nightscout.plugins.constraints.objectives.objectives.Objective10
import info.nightscout.plugins.constraints.objectives.objectives.Objective11
import info.nightscout.plugins.constraints.objectives.objectives.Objective2
import info.nightscout.plugins.constraints.objectives.objectives.Objective3
import info.nightscout.plugins.constraints.objectives.objectives.Objective4
@ -36,4 +37,5 @@ abstract class ObjectivesModule {
@ContributesAndroidInjector abstract fun objective7Injector(): Objective7
@ContributesAndroidInjector abstract fun objective9Injector(): Objective9
@ContributesAndroidInjector abstract fun objective10Injector(): Objective10
@ContributesAndroidInjector abstract fun objective11Injector(): Objective11
}

View file

@ -7,6 +7,7 @@ import info.nightscout.interfaces.constraints.Constraints
import info.nightscout.interfaces.constraints.Objectives
import info.nightscout.interfaces.constraints.Objectives.Companion.AUTOSENS_OBJECTIVE
import info.nightscout.interfaces.constraints.Objectives.Companion.AUTO_OBJECTIVE
import info.nightscout.interfaces.constraints.Objectives.Companion.DYN_ISF_OBJECTIVE
import info.nightscout.interfaces.constraints.Objectives.Companion.FIRST_OBJECTIVE
import info.nightscout.interfaces.constraints.Objectives.Companion.MAXBASAL_OBJECTIVE
import info.nightscout.interfaces.constraints.Objectives.Companion.MAXIOB_ZERO_CL_OBJECTIVE
@ -20,6 +21,7 @@ import info.nightscout.plugins.constraints.objectives.objectives.Objective
import info.nightscout.plugins.constraints.objectives.objectives.Objective0
import info.nightscout.plugins.constraints.objectives.objectives.Objective1
import info.nightscout.plugins.constraints.objectives.objectives.Objective10
import info.nightscout.plugins.constraints.objectives.objectives.Objective11
import info.nightscout.plugins.constraints.objectives.objectives.Objective2
import info.nightscout.plugins.constraints.objectives.objectives.Objective3
import info.nightscout.plugins.constraints.objectives.objectives.Objective4
@ -76,6 +78,7 @@ class ObjectivesPlugin @Inject constructor(
objectives.add(Objective7(injector))
objectives.add(Objective9(injector))
objectives.add(Objective10(injector))
objectives.add(Objective11(injector))
// edit companion object if you remove/add Objective
}
@ -137,6 +140,12 @@ class ObjectivesPlugin @Inject constructor(
return value
}
override fun isDynIsfModeEnabled(value: Constraint<Boolean>): Constraint<Boolean> {
if (!objectives[DYN_ISF_OBJECTIVE].isStarted)
value.set(aapsLogger, false, rh.gs(R.string.objectivenotstarted, DYN_ISF_OBJECTIVE + 1), this)
return value
}
override fun applyMaxIOBConstraints(maxIob: Constraint<Double>): Constraint<Double> {
if (objectives[MAXIOB_ZERO_CL_OBJECTIVE].isStarted && !objectives[MAXIOB_ZERO_CL_OBJECTIVE].isAccomplished)
maxIob.set(aapsLogger, 0.0, rh.gs(R.string.objectivenotfinished, MAXIOB_ZERO_CL_OBJECTIVE + 1), this)

View file

@ -46,6 +46,7 @@ abstract class Objective(injector: HasAndroidInjector, spName: String, @StringRe
}
init {
@Suppress("LeakingThis")
injector.androidInjector().inject(this)
this.spName = spName
this.objective = objective
@ -70,10 +71,10 @@ abstract class Objective(injector: HasAndroidInjector, spName: String, @StringRe
val isStarted: Boolean
get() = startedOn != 0L
open fun specialActionEnabled(): Boolean {
return true
}
@Suppress("unused")
open fun specialActionEnabled(): Boolean = true
@Suppress("unused")
open fun specialAction(activity: FragmentActivity, input: String) {}
abstract inner class Task(var objective: Objective, @StringRes val task: Int) {
@ -157,7 +158,7 @@ abstract class Objective(injector: HasAndroidInjector, spName: String, @StringRe
inner class Option internal constructor(@StringRes var option: Int, var isCorrect: Boolean) {
var cb: CheckBox? = null // TODO: change it, this will block releasing memory
private var cb: CheckBox? = null // TODO: change it, this will block releasing memory
fun generate(context: Context): CheckBox {
cb = CheckBox(context)
@ -184,13 +185,5 @@ abstract class Objective(injector: HasAndroidInjector, spName: String, @StringRe
}
}
inner class Learned internal constructor(@StringRes var learned: Int) {
fun generate(context: Context): TextView {
val textView = TextView(context)
textView.setText(learned)
textView.setLinkTextColor(rh.gac(context, com.google.android.material.R.attr.colorSecondary))
return textView
}
}
inner class Learned internal constructor(@StringRes var learned: Int)
}

View file

@ -0,0 +1,15 @@
package info.nightscout.plugins.constraints.objectives.objectives
import dagger.android.HasAndroidInjector
import info.nightscout.plugins.constraints.R
import info.nightscout.shared.utils.T
class Objective11(injector: HasAndroidInjector) : Objective(injector, "dyn_isf", R.string.objectives_dyn_isf_objective, R.string.objectives_dyn_isf_gate) {
init {
tasks.add(
MinimumDurationTask(this, T.days(28).msecs())
.learned(Learned(R.string.objectives_dyn_isf_learned))
)
}
}

View file

@ -28,6 +28,9 @@
<string name="objectives_smb_objective">Enabling additional features for daytime use, such as SMB</string>
<string name="objectives_smb_gate">You must read the wiki and raise maxIOB to get SMBs working fine! A good start is maxIOB=average mealbolus + 3 x max daily basal</string>
<string name="objectives_smb_learned">Using SMB is your goal. Oref1 algorithm was designed to help you with your boluses as well. You should not give full bolus for your food but only part of it and let AAPS give you the rest if needed. This way you have more space for miscalculated carbs. Did you know that you can set a percentage of bolus calculator result to reduce the size of bolus?</string>
<string name="objectives_dyn_isf_objective">Enabling additional features for daytime use, such as Dynamic sensitivity plugin</string>
<string name="objectives_dyn_isf_gate">Make sure SMB is working well. Enable DynamicISF plugin and determine correct strangeness specific to your body. It\'s safer to start with lower value than 100%.</string>
<string name="objectives_dyn_isf_learned">Dynamic sensitivity plugin is based on idea that total insulin income and current glycemia affects actual sensitivity. DynamicISF plugin can adjust ISF passed to the algorithm for you.</string>
<string name="objectives_auto_objective">Enabling automation</string>
<string name="objectives_auto_gate">Read the docs on how automation works. Set up your first simple rules. Instead of action let AAPS display only notification. When you are sure automation is triggered at the right time replace notification by real action. (https://wiki.aaps.app/en/latest/Usage/Automation.html)</string>
<string name="objectives_auto_learned">Automation can be a good servant but a bad master. Don\'t overuse it. Do not try to replace underlying algorithm. Test the rule with message only before use. It depends on order.</string>