From 13096f7f26de64d30792aa734064cdfa990dae19 Mon Sep 17 00:00:00 2001 From: Philoul Date: Sun, 26 Jan 2025 22:58:40 +0100 Subject: [PATCH 01/41] Add ICfg methods and Extension --- .../kotlin/app/aaps/core/data/model/ICfg.kt | 32 +++++++++++++++++-- .../objects/extensions/InsulinExtension.kt | 15 +++++++++ .../InsulinConfigurationExtension.kt | 4 +-- .../openhumans/OpenHumansUploaderPlugin.kt | 6 ++-- 4 files changed, 50 insertions(+), 7 deletions(-) create mode 100644 core/objects/src/main/kotlin/app/aaps/core/objects/extensions/InsulinExtension.kt diff --git a/core/data/src/main/kotlin/app/aaps/core/data/model/ICfg.kt b/core/data/src/main/kotlin/app/aaps/core/data/model/ICfg.kt index 9205bb2378f..bbe490b294b 100644 --- a/core/data/src/main/kotlin/app/aaps/core/data/model/ICfg.kt +++ b/core/data/src/main/kotlin/app/aaps/core/data/model/ICfg.kt @@ -3,5 +3,33 @@ package app.aaps.core.data.model data class ICfg( var insulinLabel: String, var insulinEndTime: Long, // DIA before [milliseconds] - var peak: Long // [milliseconds] -) \ No newline at end of file + var insulinPeakTime: Long // [milliseconds] +) { + + constructor(insulinLabel: String, peak: Int, dia: Double) : this(insulinLabel = insulinLabel, insulinEndTime = (dia * 3600 * 1000).toLong(), insulinPeakTime = (peak * 60000).toLong()) + + fun isEqual(iCfg: ICfg?): Boolean { + iCfg?.let { iCfg -> + if (insulinEndTime != iCfg.insulinEndTime) + return false + if (insulinPeakTime != iCfg.insulinPeakTime) + return false + return true + } + return false + } + + fun getDia(): Double = insulinEndTime / 3600.0 / 1000.0 + fun getPeak(): Int = (insulinPeakTime / 60000).toInt() + fun setDia(dia: Double) { + insulinEndTime = (dia * 3600 * 1000).toLong() + } + + fun setPeak(peak: Int) { + this.insulinPeakTime = (peak * 60000).toLong() + } + + fun deepClone(): ICfg = ICfg(insulinLabel, insulinEndTime, insulinPeakTime) + + companion object; +} \ No newline at end of file diff --git a/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/InsulinExtension.kt b/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/InsulinExtension.kt new file mode 100644 index 00000000000..9860aa26aef --- /dev/null +++ b/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/InsulinExtension.kt @@ -0,0 +1,15 @@ +package app.aaps.core.objects.extensions + +import app.aaps.core.data.model.ICfg +import org.json.JSONObject + +fun ICfg.toJson(): JSONObject = JSONObject() + .put("insulinLabel", insulinLabel) + .put("insulinEndTime", insulinEndTime) + .put("peak", insulinPeakTime) + +fun ICfg.Companion.fromJson(json: JSONObject): ICfg = ICfg( + insulinLabel = json.optString("insulinLabel", ""), + insulinEndTime = json.optLong("insulinEndTime", 6 * 3600 * 1000), + insulinPeakTime = json.optLong("peak") +) \ No newline at end of file diff --git a/database/persistence/src/main/kotlin/app/aaps/database/persistence/converters/InsulinConfigurationExtension.kt b/database/persistence/src/main/kotlin/app/aaps/database/persistence/converters/InsulinConfigurationExtension.kt index 6acf3d0f6c9..eba7239d85a 100644 --- a/database/persistence/src/main/kotlin/app/aaps/database/persistence/converters/InsulinConfigurationExtension.kt +++ b/database/persistence/src/main/kotlin/app/aaps/database/persistence/converters/InsulinConfigurationExtension.kt @@ -7,12 +7,12 @@ fun InsulinConfiguration.fromDb(): ICfg = ICfg( insulinLabel = this.insulinLabel, insulinEndTime = this.insulinEndTime, - peak = this.peak + insulinPeakTime = this.peak ) fun ICfg.toDb(): InsulinConfiguration = InsulinConfiguration( insulinLabel = this.insulinLabel, insulinEndTime = this.insulinEndTime, - peak = this.peak + peak = this.insulinPeakTime ) \ No newline at end of file diff --git a/plugins/sync/src/main/kotlin/app/aaps/plugins/sync/openhumans/OpenHumansUploaderPlugin.kt b/plugins/sync/src/main/kotlin/app/aaps/plugins/sync/openhumans/OpenHumansUploaderPlugin.kt index 605dc1e9ce3..92f4d902ae3 100644 --- a/plugins/sync/src/main/kotlin/app/aaps/plugins/sync/openhumans/OpenHumansUploaderPlugin.kt +++ b/plugins/sync/src/main/kotlin/app/aaps/plugins/sync/openhumans/OpenHumansUploaderPlugin.kt @@ -348,7 +348,7 @@ class OpenHumansUploaderPlugin @Inject internal constructor( put("type", it.type.toString()) put("isBasalInsulin", it.isBasalInsulin) put("insulinEndTime", it.icfg?.insulinEndTime) - put("peak", it.icfg?.peak) + put("peak", it.icfg?.insulinPeakTime) } tags.add("Boluses") } @@ -386,7 +386,7 @@ class OpenHumansUploaderPlugin @Inject internal constructor( put("originalDuration", it.originalDuration) put("originalEnd", it.originalEnd) put("insulinEndTime", it.iCfg.insulinEndTime) - put("insulinEndTime", it.iCfg.peak) + put("insulinEndTime", it.iCfg.insulinPeakTime) } tags.add("EffectiveProfileSwitches") } @@ -471,7 +471,7 @@ class OpenHumansUploaderPlugin @Inject internal constructor( put("percentage", it.percentage) put("duration", it.duration) put("insulinEndTime", it.iCfg.insulinEndTime) - put("peak", it.iCfg.peak) + put("peak", it.iCfg.insulinPeakTime) } tags.add("ProfileSwitches") } From 8779927335b01186909d7b984b34d2db2bbe9424 Mon Sep 17 00:00:00 2001 From: Philoul Date: Tue, 11 Feb 2025 20:59:08 +0100 Subject: [PATCH 02/41] Update Insulin Interface --- .../aaps/core/interfaces/insulin/Insulin.kt | 22 ++++++++++++------- .../src/main/res/values/strings.xml | 7 ++++++ .../src/main/res/drawable/ic_insulin.xml | 0 .../plugins/insulin/InsulinLyumjevPlugin.kt | 13 ++++++----- .../plugins/insulin/InsulinOrefBasePlugin.kt | 11 +++++++++- .../insulin/InsulinOrefFreePeakPlugin.kt | 10 +++++---- .../insulin/InsulinOrefRapidActingPlugin.kt | 7 ++++-- .../InsulinOrefUltraRapidActingPlugin.kt | 7 ++++-- .../insulin/src/main/res/values/strings.xml | 4 ---- 9 files changed, 55 insertions(+), 26 deletions(-) rename {plugins/insulin => core/objects}/src/main/res/drawable/ic_insulin.xml (100%) diff --git a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/insulin/Insulin.kt b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/insulin/Insulin.kt index 243f43f431c..b07be4d194a 100644 --- a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/insulin/Insulin.kt +++ b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/insulin/Insulin.kt @@ -1,26 +1,28 @@ package app.aaps.core.interfaces.insulin +import androidx.annotation.StringRes import app.aaps.core.data.iob.Iob import app.aaps.core.data.model.BS import app.aaps.core.data.model.ICfg +import app.aaps.core.interfaces.R import app.aaps.core.interfaces.configuration.ConfigExportImport interface Insulin : ConfigExportImport { - - enum class InsulinType(val value: Int) { - UNKNOWN(-1), + enum class InsulinType(val value: Int, val peak: Int, val dia: Double, @StringRes val label: Int) { + UNKNOWN(-1, -1, 6.0, R.string.unknown), // int FAST_ACTING_INSULIN = 0; // old model no longer available // int FAST_ACTING_INSULIN_PROLONGED = 1; // old model no longer available - OREF_RAPID_ACTING(2), - OREF_ULTRA_RAPID_ACTING(3), - OREF_FREE_PEAK(4), - OREF_LYUMJEV(5); + OREF_RAPID_ACTING(2, 75, 6.0, R.string.rapid_acting_oref), + OREF_ULTRA_RAPID_ACTING(3, 55, 6.0, R.string.ultra_rapid_oref), + OREF_FREE_PEAK(4, 50, 6.0, R.string.free_peak_oref), + OREF_LYUMJEV(5, 45, 6.0, R.string.lyumjev); companion object { private val map = entries.associateBy(InsulinType::value) fun fromInt(type: Int) = map[type] + fun fromPeak(peak: Long) = InsulinType.values().firstOrNull {it.peak == (peak/60000).toInt()} ?:OREF_FREE_PEAK } } @@ -29,8 +31,12 @@ interface Insulin : ConfigExportImport { val comment: String val dia: Double val peak: Int - + fun setDefault(iCfg: ICfg?) + fun insulinList() = ArrayList() + fun getOrCreateInsulin(iCfg: ICfg): ICfg + fun getInsulin(insulinLabel: String): ICfg fun iobCalcForTreatment(bolus: BS, time: Long, dia: Double): Iob + fun iobCalcForTreatment(bolus: BS, time: Long, iCfg: ICfg): Iob val iCfg: ICfg } \ No newline at end of file diff --git a/core/interfaces/src/main/res/values/strings.xml b/core/interfaces/src/main/res/values/strings.xml index 6d54fef4c0f..da518651edd 100644 --- a/core/interfaces/src/main/res/values/strings.xml +++ b/core/interfaces/src/main/res/values/strings.xml @@ -74,4 +74,11 @@ %1$.2f%% @%2$s %3$d/%4$d\' E %1$.2f U/h @%2$s %3$d/%4$d min + + Unknown + Rapid-Acting Oref + Lyumjev + Free-Peak Oref + Ultra-Rapid Oref + diff --git a/plugins/insulin/src/main/res/drawable/ic_insulin.xml b/core/objects/src/main/res/drawable/ic_insulin.xml similarity index 100% rename from plugins/insulin/src/main/res/drawable/ic_insulin.xml rename to core/objects/src/main/res/drawable/ic_insulin.xml diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinLyumjevPlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinLyumjevPlugin.kt index ee8a92437ac..e95715bd6e5 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinLyumjevPlugin.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinLyumjevPlugin.kt @@ -1,5 +1,6 @@ package app.aaps.plugins.insulin +import app.aaps.core.data.model.ICfg import app.aaps.core.interfaces.configuration.Config import app.aaps.core.interfaces.insulin.Insulin import app.aaps.core.interfaces.logging.AAPSLogger @@ -24,19 +25,21 @@ class InsulinLyumjevPlugin @Inject constructor( ) : InsulinOrefBasePlugin(rh, profileFunction, rxBus, aapsLogger, config, hardLimits, uiInteraction) { override val id get(): Insulin.InsulinType = Insulin.InsulinType.OREF_LYUMJEV - override val friendlyName get(): String = rh.gs(R.string.lyumjev) + override val friendlyName get(): String = rh.gs(app.aaps.core.interfaces.R.string.lyumjev) + override fun getOrCreateInsulin(iCfg: ICfg) = ICfg(rh.gs(app.aaps.core.interfaces.R.string.lyumjev), peak, dia) + override fun getInsulin(insulinLabel: String)= ICfg(rh.gs(app.aaps.core.interfaces.R.string.lyumjev), peak, dia) override fun configuration(): JSONObject = JSONObject() - override fun applyConfiguration(configuration: JSONObject) {} + override fun applyConfiguration(configuration: JSONObject) { } - override fun commentStandardText(): String = rh.gs(R.string.lyumjev) + override fun commentStandardText(): String = rh.gs(app.aaps.core.interfaces.R.string.lyumjev) override val peak = 45 init { pluginDescription - .pluginIcon(R.drawable.ic_insulin) - .pluginName(R.string.lyumjev) + .pluginIcon(app.aaps.core.objects.R.drawable.ic_insulin) + .pluginName(app.aaps.core.interfaces.R.string.lyumjev) .description(R.string.description_insulin_lyumjev) } } \ No newline at end of file diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt index c31c103e4ce..02676556831 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt @@ -37,7 +37,7 @@ abstract class InsulinOrefBasePlugin( PluginDescription() .mainType(PluginType.INSULIN) .fragmentClass(InsulinFragment::class.java.name) - .pluginIcon(R.drawable.ic_insulin) + .pluginIcon(app.aaps.core.objects.R.drawable.ic_insulin) .shortName(R.string.insulin_shortname) .visibleByDefault(false) .neverVisible(config.AAPSCLIENT), @@ -55,6 +55,7 @@ abstract class InsulinOrefBasePlugin( hardLimits.minDia() } } + override fun setDefault(iCfg: ICfg?) { } open fun sendShortDiaNotification(dia: Double) { if (System.currentTimeMillis() - lastWarned > 60 * 1000) { @@ -72,7 +73,15 @@ abstract class InsulinOrefBasePlugin( return profile?.dia ?: hardLimits.minDia() } + override fun iobCalcForTreatment(bolus: BS, time: Long, iCfg: ICfg): Iob { + return iobCalcForTreatment(bolus, time, iCfg.getPeak(), iCfg.getDia()) + } + override fun iobCalcForTreatment(bolus: BS, time: Long, dia: Double): Iob { + return iobCalcForTreatment(bolus, time, peak, dia) + } + + private fun iobCalcForTreatment(bolus: BS, time: Long, peak: Int, dia: Double): Iob { assert(dia != 0.0) assert(peak != 0) val result = Iob() diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefFreePeakPlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefFreePeakPlugin.kt index 2569b5ec90f..5648fb625ec 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefFreePeakPlugin.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefFreePeakPlugin.kt @@ -4,6 +4,7 @@ import android.content.Context import androidx.preference.PreferenceCategory import androidx.preference.PreferenceManager import androidx.preference.PreferenceScreen +import app.aaps.core.data.model.ICfg import app.aaps.core.interfaces.configuration.Config import app.aaps.core.interfaces.insulin.Insulin import app.aaps.core.interfaces.logging.AAPSLogger @@ -38,8 +39,9 @@ class InsulinOrefFreePeakPlugin @Inject constructor( ) : InsulinOrefBasePlugin(rh, profileFunction, rxBus, aapsLogger, config, hardLimits, uiInteraction) { override val id get(): Insulin.InsulinType = Insulin.InsulinType.OREF_FREE_PEAK - - override val friendlyName get(): String = rh.gs(R.string.free_peak_oref) + override val friendlyName get(): String = rh.gs(app.aaps.core.interfaces.R.string.free_peak_oref) + override fun getOrCreateInsulin(iCfg: ICfg) = ICfg(rh.gs(app.aaps.core.interfaces.R.string.free_peak_oref), peak, dia) + override fun getInsulin(insulinLabel: String)= ICfg(rh.gs(app.aaps.core.interfaces.R.string.free_peak_oref), peak, dia) override fun configuration(): JSONObject = JSONObject() @@ -59,8 +61,8 @@ class InsulinOrefFreePeakPlugin @Inject constructor( init { pluginDescription - .pluginIcon(R.drawable.ic_insulin) - .pluginName(R.string.free_peak_oref) + .pluginIcon(app.aaps.core.objects.R.drawable.ic_insulin) + .pluginName(app.aaps.core.interfaces.R.string.free_peak_oref) .preferencesId(PluginDescription.PREFERENCE_SCREEN) .description(R.string.description_insulin_free_peak) } diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefRapidActingPlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefRapidActingPlugin.kt index 065694a2be9..bec4e545b38 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefRapidActingPlugin.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefRapidActingPlugin.kt @@ -1,5 +1,6 @@ package app.aaps.plugins.insulin +import app.aaps.core.data.model.ICfg import app.aaps.core.interfaces.configuration.Config import app.aaps.core.interfaces.insulin.Insulin import app.aaps.core.interfaces.logging.AAPSLogger @@ -27,7 +28,9 @@ class InsulinOrefRapidActingPlugin @Inject constructor( ) : InsulinOrefBasePlugin(rh, profileFunction, rxBus, aapsLogger, config, hardLimits, uiInteraction) { override val id get(): Insulin.InsulinType = Insulin.InsulinType.OREF_RAPID_ACTING - override val friendlyName get(): String = rh.gs(R.string.rapid_acting_oref) + override val friendlyName get(): String = rh.gs(app.aaps.core.interfaces.R.string.rapid_acting_oref) + override fun getOrCreateInsulin(iCfg: ICfg) = ICfg(rh.gs(app.aaps.core.interfaces.R.string.rapid_acting_oref), peak, dia) + override fun getInsulin(insulinLabel: String)= ICfg(rh.gs(app.aaps.core.interfaces.R.string.rapid_acting_oref), peak, dia) override fun configuration(): JSONObject = JSONObject() override fun applyConfiguration(configuration: JSONObject) {} @@ -38,7 +41,7 @@ class InsulinOrefRapidActingPlugin @Inject constructor( init { pluginDescription - .pluginName(R.string.rapid_acting_oref) + .pluginName(app.aaps.core.interfaces.R.string.rapid_acting_oref) .description(R.string.description_insulin_rapid) .setDefault() .enableByDefault(true) diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefUltraRapidActingPlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefUltraRapidActingPlugin.kt index a3ae58bfdbe..63fac17caa0 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefUltraRapidActingPlugin.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefUltraRapidActingPlugin.kt @@ -1,5 +1,6 @@ package app.aaps.plugins.insulin +import app.aaps.core.data.model.ICfg import app.aaps.core.interfaces.configuration.Config import app.aaps.core.interfaces.insulin.Insulin import app.aaps.core.interfaces.logging.AAPSLogger @@ -27,7 +28,9 @@ class InsulinOrefUltraRapidActingPlugin @Inject constructor( ) : InsulinOrefBasePlugin(rh, profileFunction, rxBus, aapsLogger, config, hardLimits, uiInteraction) { override val id get(): Insulin.InsulinType = Insulin.InsulinType.OREF_ULTRA_RAPID_ACTING - override val friendlyName get(): String = rh.gs(R.string.ultra_rapid_oref) + override val friendlyName get(): String = rh.gs(app.aaps.core.interfaces.R.string.ultra_rapid_oref) + override fun getOrCreateInsulin(iCfg: ICfg) = ICfg(rh.gs(R.string.ultra_fast_acting_insulin_comment), peak, dia) + override fun getInsulin(insulinLabel: String) = ICfg(rh.gs(R.string.ultra_fast_acting_insulin_comment), peak, dia) override fun configuration(): JSONObject = JSONObject() override fun applyConfiguration(configuration: JSONObject) {} @@ -38,7 +41,7 @@ class InsulinOrefUltraRapidActingPlugin @Inject constructor( init { pluginDescription - .pluginName(R.string.ultra_rapid_oref) + .pluginName(app.aaps.core.interfaces.R.string.ultra_rapid_oref) .description(R.string.description_insulin_ultra_rapid) } } \ No newline at end of file diff --git a/plugins/insulin/src/main/res/values/strings.xml b/plugins/insulin/src/main/res/values/strings.xml index 2cc6a61c9d7..2df3a352efd 100644 --- a/plugins/insulin/src/main/res/values/strings.xml +++ b/plugins/insulin/src/main/res/values/strings.xml @@ -1,7 +1,6 @@ - Lyumjev Insulin preset for Humalog and NovoRapid / NovoLog Insulin preset for Fiasp Insulin preset for Lyumjev @@ -9,9 +8,6 @@ INS IOB Curve Peak Time Peak Time [min] - Free-Peak Oref - Rapid-Acting Oref - Ultra-Rapid Oref DIA of %1$f too short - using %2$f instead! Novorapid, Novolog, Humalog Fiasp From 6412eb7c01b40c9a088fc2d39b86b334cbaf7e50 Mon Sep 17 00:00:00 2001 From: Philoul Date: Wed, 12 Feb 2025 08:55:20 +0100 Subject: [PATCH 03/41] Include ICfg in PureProfile --- .../kotlin/app/aaps/core/interfaces/profile/ProfileSource.kt | 1 + .../kotlin/app/aaps/core/interfaces/profile/PureProfile.kt | 2 ++ .../aaps/core/objects/extensions/ProfileSwitchExtension.kt | 5 ++++- .../kotlin/app/aaps/core/objects/profile/ProfileSealed.kt | 3 +++ .../kotlin/app/aaps/plugins/aps/autotune/data/ATProfile.kt | 3 +++ .../kotlin/app/aaps/plugins/aps/autotune/AutotuneCoreTest.kt | 2 ++ .../kotlin/app/aaps/plugins/aps/autotune/AutotunePrepTest.kt | 2 ++ .../kotlin/app/aaps/plugins/main/profile/ProfilePlugin.kt | 3 +++ 8 files changed, 20 insertions(+), 1 deletion(-) diff --git a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/ProfileSource.kt b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/ProfileSource.kt index 33434f3873b..b8fd4845985 100644 --- a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/ProfileSource.kt +++ b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/ProfileSource.kt @@ -1,6 +1,7 @@ package app.aaps.core.interfaces.profile import androidx.fragment.app.FragmentActivity +import app.aaps.core.data.model.ICfg import org.json.JSONArray interface ProfileSource { diff --git a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/PureProfile.kt b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/PureProfile.kt index c33e3123c81..f3eed66c0b9 100644 --- a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/PureProfile.kt +++ b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/PureProfile.kt @@ -1,6 +1,7 @@ package app.aaps.core.interfaces.profile import app.aaps.core.data.model.GlucoseUnit +import app.aaps.core.data.model.ICfg import app.aaps.core.data.model.data.Block import app.aaps.core.data.model.data.TargetBlock import org.json.JSONObject @@ -12,6 +13,7 @@ class PureProfile( var isfBlocks: List, var icBlocks: List, var targetBlocks: List, + var iCfg: ICfg, var dia: Double, var glucoseUnit: GlucoseUnit, var timeZone: TimeZone diff --git a/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/ProfileSwitchExtension.kt b/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/ProfileSwitchExtension.kt index 3660b2677e5..9ecd6710dd9 100644 --- a/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/ProfileSwitchExtension.kt +++ b/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/ProfileSwitchExtension.kt @@ -2,6 +2,7 @@ package app.aaps.core.objects.extensions import app.aaps.core.data.configuration.Constants import app.aaps.core.data.model.GlucoseUnit +import app.aaps.core.data.model.ICfg import app.aaps.core.data.model.PS import app.aaps.core.data.time.T import app.aaps.core.interfaces.profile.PureProfile @@ -34,6 +35,7 @@ fun pureProfileFromJson(jsonObject: JSONObject, dateUtil: DateUtil, defaultUnits val units = GlucoseUnit.fromText(txtUnits) val dia = JsonHelper.safeGetDoubleAllowNull(jsonObject, "dia") ?: return null val timezone = TimeZone.getTimeZone(JsonHelper.safeGetString(jsonObject, "timezone", "UTC")) + val iCfg = JsonHelper.safeGetJSONObject(jsonObject, "icfg", null)?.let { ICfg.fromJson(it) } ?: return null val isfBlocks = blockFromJsonArray(jsonObject.getJSONArray("sens"), dateUtil) ?: return null val icBlocks = blockFromJsonArray(jsonObject.getJSONArray("carbratio"), dateUtil) @@ -51,7 +53,8 @@ fun pureProfileFromJson(jsonObject: JSONObject, dateUtil: DateUtil, defaultUnits targetBlocks = targetBlocks, glucoseUnit = units, timeZone = timezone, - dia = dia + dia = dia, + iCfg = iCfg ) } catch (ignored: Exception) { return null diff --git a/core/objects/src/main/kotlin/app/aaps/core/objects/profile/ProfileSealed.kt b/core/objects/src/main/kotlin/app/aaps/core/objects/profile/ProfileSealed.kt index 5d1b6a0dd6a..6a0f00e7e4b 100644 --- a/core/objects/src/main/kotlin/app/aaps/core/objects/profile/ProfileSealed.kt +++ b/core/objects/src/main/kotlin/app/aaps/core/objects/profile/ProfileSealed.kt @@ -26,6 +26,7 @@ import app.aaps.core.objects.extensions.lowTargetBlockValueBySeconds import app.aaps.core.objects.extensions.shiftBlock import app.aaps.core.objects.extensions.shiftTargetBlock import app.aaps.core.objects.extensions.targetBlockValueBySeconds +import app.aaps.core.objects.extensions.toJson import app.aaps.core.ui.R import app.aaps.core.utils.MidnightUtils import org.json.JSONArray @@ -318,6 +319,7 @@ sealed class ProfileSealed( icBlocks = icBlocks.shiftBlock(100.0 / percentage, timeshift), targetBlocks = targetBlocks.shiftTargetBlock(timeshift), glucoseUnit = units, + iCfg = iCfg, dia = when (this) { is PS -> this.value.iCfg.insulinEndTime / 3600.0 / 1000.0 is EPS -> this.value.iCfg.insulinEndTime / 3600.0 / 1000.0 @@ -330,6 +332,7 @@ sealed class ProfileSealed( val o = JSONObject() o.put("units", units.asText) o.put("dia", dia) + o.put("icfg", iCfg.toJson()) o.put("timezone", dateUtil.timeZoneByOffset(utcOffset).id ?: "UTC") // SENS val sens = JSONArray() diff --git a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/data/ATProfile.kt b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/data/ATProfile.kt index 7313825f560..4dc934bab69 100644 --- a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/data/ATProfile.kt +++ b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/data/ATProfile.kt @@ -1,6 +1,7 @@ package app.aaps.plugins.aps.autotune.data import app.aaps.core.data.model.GlucoseUnit +import app.aaps.core.data.model.ICfg import app.aaps.core.data.model.data.Block import app.aaps.core.data.time.T import app.aaps.core.interfaces.configuration.Config @@ -110,6 +111,7 @@ class ATProfile(profile: Profile, var localInsulin: LocalInsulin, val injector: json.put("name", profileName) json.put("min_5m_carbimpact", sp.getDouble("openapsama_min_5m_carbimpact", 3.0)) json.put("dia", dia) + json.put("icfg", ICfg("", peak, dia)) if (insulinInterface.id === Insulin.InsulinType.OREF_ULTRA_RAPID_ACTING) json.put( "curve", "ultra-rapid" @@ -161,6 +163,7 @@ class ATProfile(profile: Profile, var localInsulin: LocalInsulin, val injector: fun data(circadian: Boolean = false): PureProfile? { val json: JSONObject = profile.toPureNsJson(dateUtil) try { + json.put("icfg", ICfg("", peak, dia)) json.put("dia", dia) if (circadian) { json.put("sens", jsonArray(pumpProfile.isfBlocks, avgISF / pumpProfileAvgISF)) diff --git a/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/autotune/AutotuneCoreTest.kt b/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/autotune/AutotuneCoreTest.kt index 28db294a5ef..6fa497bb6dc 100644 --- a/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/autotune/AutotuneCoreTest.kt +++ b/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/autotune/AutotuneCoreTest.kt @@ -1,6 +1,7 @@ package app.aaps.plugins.aps.autotune import app.aaps.core.data.model.GlucoseUnit +import app.aaps.core.data.model.ICfg import app.aaps.core.data.model.data.Block import app.aaps.core.data.model.data.TargetBlock import app.aaps.core.data.time.T @@ -119,6 +120,7 @@ class AutotuneCoreTest : TestBaseWithProfile() { targetBlocks = targetBlocks, glucoseUnit = units, timeZone = timezone, + iCfg = ICfg("", peak, dia), dia = dia ) return ATProfile(ProfileSealed.Pure(pure, activePlugin), localInsulin, injector).also { it.dateUtil = dateUtil; it.profileUtil = profileUtil } diff --git a/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/autotune/AutotunePrepTest.kt b/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/autotune/AutotunePrepTest.kt index 04240500294..08ba1b8909c 100644 --- a/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/autotune/AutotunePrepTest.kt +++ b/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/autotune/AutotunePrepTest.kt @@ -4,6 +4,7 @@ import app.aaps.core.data.model.BS import app.aaps.core.data.model.CA import app.aaps.core.data.model.GV import app.aaps.core.data.model.GlucoseUnit +import app.aaps.core.data.model.ICfg import app.aaps.core.data.model.SourceSensor import app.aaps.core.data.model.TrendArrow import app.aaps.core.data.model.data.Block @@ -190,6 +191,7 @@ class AutotunePrepTest : TestBaseWithProfile() { targetBlocks = targetBlocks, glucoseUnit = units, timeZone = timezone, + iCfg = ICfg("", peak, dia), dia = dia ) return ATProfile(ProfileSealed.Pure(pure, activePlugin), localInsulin, injector).also { it.dateUtil = dateUtil } diff --git a/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfilePlugin.kt b/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfilePlugin.kt index 1d1ed9745b2..41d8b600bb0 100644 --- a/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfilePlugin.kt +++ b/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfilePlugin.kt @@ -3,6 +3,7 @@ package app.aaps.plugins.main.profile import androidx.fragment.app.FragmentActivity import app.aaps.core.data.configuration.Constants import app.aaps.core.data.model.GlucoseUnit +import app.aaps.core.data.model.ICfg import app.aaps.core.data.plugin.PluginType import app.aaps.core.interfaces.configuration.Config import app.aaps.core.interfaces.logging.AAPSLogger @@ -29,6 +30,7 @@ import app.aaps.core.interfaces.utils.DecimalFormatter import app.aaps.core.interfaces.utils.HardLimits import app.aaps.core.objects.extensions.blockFromJsonArray import app.aaps.core.objects.extensions.pureProfileFromJson +import app.aaps.core.objects.extensions.toJson import app.aaps.core.objects.profile.ProfileSealed import app.aaps.core.ui.dialogs.OKDialog import app.aaps.core.ui.toast.ToastUtils @@ -176,6 +178,7 @@ class ProfilePlugin @Inject constructor( val localProfileNumbered = Constants.LOCAL_PROFILE + "_" + i + "_" sp.putString(localProfileNumbered + "name", name) sp.putBoolean(localProfileNumbered + "mgdl", mgdl) + //sp.putString(localProfileNumbered + "icfg", iCfg.toJson().toString()) sp.putDouble(localProfileNumbered + "dia", dia) sp.putString(localProfileNumbered + "ic", ic.toString()) sp.putString(localProfileNumbered + "isf", isf.toString()) From 876118aea11c48fef28602e98b969ef2f6765441 Mon Sep 17 00:00:00 2001 From: Philoul Date: Wed, 12 Feb 2025 13:39:49 +0100 Subject: [PATCH 04/41] Include ICfg in SingleProfile --- .../app/aaps/core/interfaces/profile/ProfileSource.kt | 2 ++ .../app/aaps/core/objects/extensions/InsulinExtension.kt | 7 ++++--- .../kotlin/app/aaps/plugins/main/profile/ProfilePlugin.kt | 8 +++++++- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/ProfileSource.kt b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/ProfileSource.kt index b8fd4845985..c489e8895a5 100644 --- a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/ProfileSource.kt +++ b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/ProfileSource.kt @@ -12,6 +12,7 @@ interface ProfileSource { class SingleProfile( var name: String, var mgdl: Boolean, + var iCfg: ICfg, var dia: Double, var ic: JSONArray, var isf: JSONArray, @@ -24,6 +25,7 @@ interface ProfileSource { SingleProfile( name = name, mgdl = mgdl, + iCfg = iCfg.deepClone(), dia = dia, ic = JSONArray(ic.toString()), isf = JSONArray(isf.toString()), diff --git a/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/InsulinExtension.kt b/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/InsulinExtension.kt index 9860aa26aef..749cbce412c 100644 --- a/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/InsulinExtension.kt +++ b/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/InsulinExtension.kt @@ -1,15 +1,16 @@ package app.aaps.core.objects.extensions import app.aaps.core.data.model.ICfg +import app.aaps.core.interfaces.insulin.Insulin import org.json.JSONObject fun ICfg.toJson(): JSONObject = JSONObject() .put("insulinLabel", insulinLabel) .put("insulinEndTime", insulinEndTime) - .put("peak", insulinPeakTime) + .put("insulinPeakTime", insulinPeakTime) fun ICfg.Companion.fromJson(json: JSONObject): ICfg = ICfg( insulinLabel = json.optString("insulinLabel", ""), - insulinEndTime = json.optLong("insulinEndTime", 6 * 3600 * 1000), - insulinPeakTime = json.optLong("peak") + insulinEndTime = json.optLong("insulinEndTime", (Insulin.InsulinType.OREF_RAPID_ACTING.dia * 3600 * 1000).toLong()), + insulinPeakTime = json.optLong("insulinPeakTime", Insulin.InsulinType.OREF_RAPID_ACTING.peak * 60000L) ) \ No newline at end of file diff --git a/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfilePlugin.kt b/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfilePlugin.kt index 41d8b600bb0..2b29d3bca28 100644 --- a/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfilePlugin.kt +++ b/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfilePlugin.kt @@ -29,6 +29,7 @@ import app.aaps.core.interfaces.utils.DateUtil import app.aaps.core.interfaces.utils.DecimalFormatter import app.aaps.core.interfaces.utils.HardLimits import app.aaps.core.objects.extensions.blockFromJsonArray +import app.aaps.core.objects.extensions.fromJson import app.aaps.core.objects.extensions.pureProfileFromJson import app.aaps.core.objects.extensions.toJson import app.aaps.core.objects.profile.ProfileSealed @@ -158,6 +159,7 @@ class ProfilePlugin @Inject constructor( fun getEditedProfile(): PureProfile? { val profile = JSONObject() with(profiles[currentProfileIndex]) { + profile.put("icfg", iCfg.toJson()) profile.put("dia", dia) profile.put("carbratio", ic) profile.put("sens", isf) @@ -178,7 +180,7 @@ class ProfilePlugin @Inject constructor( val localProfileNumbered = Constants.LOCAL_PROFILE + "_" + i + "_" sp.putString(localProfileNumbered + "name", name) sp.putBoolean(localProfileNumbered + "mgdl", mgdl) - //sp.putString(localProfileNumbered + "icfg", iCfg.toJson().toString()) + sp.putString(localProfileNumbered + "icfg", iCfg.toJson().toString()) sp.putDouble(localProfileNumbered + "dia", dia) sp.putString(localProfileNumbered + "ic", ic.toString()) sp.putString(localProfileNumbered + "isf", isf.toString()) @@ -216,6 +218,7 @@ class ProfilePlugin @Inject constructor( ProfileSource.SingleProfile( name = name, mgdl = sp.getBoolean(localProfileNumbered + "mgdl", false), + iCfg = ICfg.fromJson(JSONObject(sp.getString(localProfileNumbered + "icfg", ""))), dia = sp.getDouble(localProfileNumbered + "dia", Constants.defaultDIA), ic = JSONArray(sp.getString(localProfileNumbered + "ic", defaultArray)), isf = JSONArray(sp.getString(localProfileNumbered + "isf", defaultArray)), @@ -279,6 +282,7 @@ class ProfilePlugin @Inject constructor( return ProfileSource.SingleProfile( name = verifiedName, mgdl = profile.units == GlucoseUnit.MGDL, + iCfg = pureProfile.iCfg.deepClone(), dia = pureJson.getDouble("dia"), ic = pureJson.getJSONArray("carbratio"), isf = pureJson.getJSONArray("sens"), @@ -349,6 +353,7 @@ class ProfilePlugin @Inject constructor( ProfileSource.SingleProfile( name = Constants.LOCAL_PROFILE + free, mgdl = profileFunction.getUnits() == GlucoseUnit.MGDL, + iCfg = activePlugin.activeInsulin.iCfg, dia = Constants.defaultDIA, ic = JSONArray(defaultArray), isf = JSONArray(defaultArray), @@ -397,6 +402,7 @@ class ProfilePlugin @Inject constructor( for (i in 0 until numOfProfiles) { profiles[i].run { val profile = JSONObject() + profile.put("icfg", iCfg.toJson()) profile.put("dia", dia) profile.put("carbratio", ic) profile.put("sens", isf) From b95a9f45d0072a0d781888e60b757cdbb773003f Mon Sep 17 00:00:00 2001 From: Philoul Date: Mon, 17 Feb 2025 09:25:40 +0100 Subject: [PATCH 05/41] Fix tests --- .../kotlin/app/aaps/CompatDbHelperTest.kt | 2 +- .../androidTest/kotlin/app/aaps/LoopTest.kt | 2 +- .../core/objects/profile/ProfileSealedTest.kt | 14 +++++++------- .../plugins/aps/autotune/AutotuneCoreTest.kt | 5 +++-- .../plugins/aps/autotune/AutotunePrepTest.kt | 3 ++- .../app/aaps/pump/medtrum/MedtrumPumpTest.kt | 6 +++--- .../aaps/shared/tests/TestBaseWithProfile.kt | 6 +++--- .../aaps/ui/defaultProfile/DefaultProfile.kt | 6 +++++- .../ui/defaultProfile/DefaultProfileDPV.kt | 6 +++++- .../ui/defaultProfile/DefaultProfileTest.kt | 19 ++++++++++++++++--- 10 files changed, 46 insertions(+), 23 deletions(-) diff --git a/app/src/androidTest/kotlin/app/aaps/CompatDbHelperTest.kt b/app/src/androidTest/kotlin/app/aaps/CompatDbHelperTest.kt index 0e819d087e9..9e84ef02a31 100644 --- a/app/src/androidTest/kotlin/app/aaps/CompatDbHelperTest.kt +++ b/app/src/androidTest/kotlin/app/aaps/CompatDbHelperTest.kt @@ -68,7 +68,7 @@ class CompatDbHelperTest @Inject constructor() { private val context = ApplicationProvider.getApplicationContext() private val profileData = "{\"_id\":\"653f90bc89f99714b4635b33\",\"defaultProfile\":\"U200_32\",\"date\":1695655201449,\"created_at\":\"2023-09-25T15:20:01.449Z\"," + - "\"startDate\":\"2023-09-25T15:20:01.4490000Z\",\"store\":{\"U200_32\":{\"dia\":8,\"carbratio\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":14.618357917185001},{\"time\":\"06:00\",\"timeAsSeconds\":21600,\"value\":8.99591256442154},{\"time\":\"09:00\",\"timeAsSeconds\":32400,\"value\":10.12040163497423},{\"time\":\"11:00\",\"timeAsSeconds\":39600,\"value\":11.244890705526924},{\"time\":\"14:00\",\"timeAsSeconds\":50400,\"value\":13.493868846632308},{\"time\":\"17:00\",\"timeAsSeconds\":61200,\"value\":13.493868846632308},{\"time\":\"19:00\",\"timeAsSeconds\":68400,\"value\":13.493868846632308}],\"sens\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":8.55361111111111}],\"basal\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":0.306},{\"time\":\"01:00\",\"timeAsSeconds\":3600,\"value\":0.306},{\"time\":\"02:00\",\"timeAsSeconds\":7200,\"value\":0.334},{\"time\":\"03:00\",\"timeAsSeconds\":10800,\"value\":0.337},{\"time\":\"04:00\",\"timeAsSeconds\":14400,\"value\":0.35},{\"time\":\"05:00\",\"timeAsSeconds\":18000,\"value\":0.388},{\"time\":\"06:00\",\"timeAsSeconds\":21600,\"value\":0.388},{\"time\":\"07:00\",\"timeAsSeconds\":25200,\"value\":0.391},{\"time\":\"08:00\",\"timeAsSeconds\":28800,\"value\":0.365},{\"time\":\"09:00\",\"timeAsSeconds\":32400,\"value\":0.34},{\"time\":\"10:00\",\"timeAsSeconds\":36000,\"value\":0.337},{\"time\":\"11:00\",\"timeAsSeconds\":39600,\"value\":0.35},{\"time\":\"12:00\",\"timeAsSeconds\":43200,\"value\":0.36},{\"time\":\"13:00\",\"timeAsSeconds\":46800,\"value\":0.351},{\"time\":\"14:00\",\"timeAsSeconds\":50400,\"value\":0.349},{\"time\":\"15:00\",\"timeAsSeconds\":54000,\"value\":0.359},{\"time\":\"16:00\",\"timeAsSeconds\":57600,\"value\":0.354},{\"time\":\"17:00\",\"timeAsSeconds\":61200,\"value\":0.336},{\"time\":\"18:00\",\"timeAsSeconds\":64800,\"value\":0.339},{\"time\":\"19:00\",\"timeAsSeconds\":68400,\"value\":0.357},{\"time\":\"20:00\",\"timeAsSeconds\":72000,\"value\":0.368},{\"time\":\"21:00\",\"timeAsSeconds\":75600,\"value\":0.327},{\"time\":\"22:00\",\"timeAsSeconds\":79200,\"value\":0.318},{\"time\":\"23:00\",\"timeAsSeconds\":82800,\"value\":0.318}],\"target_low\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":5.5}],\"target_high\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":5.5}],\"units\":\"mmol\",\"timezone\":\"GMT\"}},\"app\":\"AAPS\",\"utcOffset\":120,\"identifier\":\"6b503f6c-b676-5746-b331-658b03d50843\",\"srvModified\":1698763282534,\"srvCreated\":1698664636986,\"subject\":\"Phone\"},{\"_id\":\"6511a54e3c60c21734f1988b\",\"defaultProfile\":\"U200_32\",\"date\":1695655201449,\"created_at\":\"2023-09-25T15:20:01.4490000Z\",\"startDate\":\"2023-09-25T15:20:01.4490000Z\",\"store\":{\"U200_32\":{\"dia\":8,\"carbratio\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":14.618357917185001},{\"time\":\"06:00\",\"timeAsSeconds\":21600,\"value\":8.99591256442154},{\"time\":\"09:00\",\"timeAsSeconds\":32400,\"value\":10.12040163497423},{\"time\":\"11:00\",\"timeAsSeconds\":39600,\"value\":11.244890705526924},{\"time\":\"14:00\",\"timeAsSeconds\":50400,\"value\":13.493868846632308},{\"time\":\"17:00\",\"timeAsSeconds\":61200,\"value\":13.493868846632308},{\"time\":\"19:00\",\"timeAsSeconds\":68400,\"value\":13.493868846632308}],\"sens\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":8.55361111111111}],\"basal\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":0.306},{\"time\":\"01:00\",\"timeAsSeconds\":3600,\"value\":0.306},{\"time\":\"02:00\",\"timeAsSeconds\":7200,\"value\":0.334},{\"time\":\"03:00\",\"timeAsSeconds\":10800,\"value\":0.337},{\"time\":\"04:00\",\"timeAsSeconds\":14400,\"value\":0.35},{\"time\":\"05:00\",\"timeAsSeconds\":18000,\"value\":0.388},{\"time\":\"06:00\",\"timeAsSeconds\":21600,\"value\":0.388},{\"time\":\"07:00\",\"timeAsSeconds\":25200,\"value\":0.391},{\"time\":\"08:00\",\"timeAsSeconds\":28800,\"value\":0.365},{\"time\":\"09:00\",\"timeAsSeconds\":32400,\"value\":0.34},{\"time\":\"10:00\",\"timeAsSeconds\":36000,\"value\":0.337},{\"time\":\"11:00\",\"timeAsSeconds\":39600,\"value\":0.35},{\"time\":\"12:00\",\"timeAsSeconds\":43200,\"value\":0.36},{\"time\":\"13:00\",\"timeAsSeconds\":46800,\"value\":0.351},{\"time\":\"14:00\",\"timeAsSeconds\":50400,\"value\":0.349},{\"time\":\"15:00\",\"timeAsSeconds\":54000,\"value\":0.359},{\"time\":\"16:00\",\"timeAsSeconds\":57600,\"value\":0.354},{\"time\":\"17:00\",\"timeAsSeconds\":61200,\"value\":0.336},{\"time\":\"18:00\",\"timeAsSeconds\":64800,\"value\":0.339},{\"time\":\"19:00\",\"timeAsSeconds\":68400,\"value\":0.357},{\"time\":\"20:00\",\"timeAsSeconds\":72000,\"value\":0.368},{\"time\":\"21:00\",\"timeAsSeconds\":75600,\"value\":0.327},{\"time\":\"22:00\",\"timeAsSeconds\":79200,\"value\":0.318},{\"time\":\"23:00\",\"timeAsSeconds\":82800,\"value\":0.318}],\"target_low\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":5.5}],\"target_high\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":5.5}],\"units\":\"mmol\",\"timezone\":\"Europe/Prague\"}}}" + "\"startDate\":\"2023-09-25T15:20:01.4490000Z\",\"store\":{\"U200_32\":{\"icfg\":{\"insulinLabel\":\"\",\"insulinEndTime\":18000000,\"insulinPeakTime\":4500000},\"dia\":8,\"carbratio\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":14.618357917185001},{\"time\":\"06:00\",\"timeAsSeconds\":21600,\"value\":8.99591256442154},{\"time\":\"09:00\",\"timeAsSeconds\":32400,\"value\":10.12040163497423},{\"time\":\"11:00\",\"timeAsSeconds\":39600,\"value\":11.244890705526924},{\"time\":\"14:00\",\"timeAsSeconds\":50400,\"value\":13.493868846632308},{\"time\":\"17:00\",\"timeAsSeconds\":61200,\"value\":13.493868846632308},{\"time\":\"19:00\",\"timeAsSeconds\":68400,\"value\":13.493868846632308}],\"sens\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":8.55361111111111}],\"basal\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":0.306},{\"time\":\"01:00\",\"timeAsSeconds\":3600,\"value\":0.306},{\"time\":\"02:00\",\"timeAsSeconds\":7200,\"value\":0.334},{\"time\":\"03:00\",\"timeAsSeconds\":10800,\"value\":0.337},{\"time\":\"04:00\",\"timeAsSeconds\":14400,\"value\":0.35},{\"time\":\"05:00\",\"timeAsSeconds\":18000,\"value\":0.388},{\"time\":\"06:00\",\"timeAsSeconds\":21600,\"value\":0.388},{\"time\":\"07:00\",\"timeAsSeconds\":25200,\"value\":0.391},{\"time\":\"08:00\",\"timeAsSeconds\":28800,\"value\":0.365},{\"time\":\"09:00\",\"timeAsSeconds\":32400,\"value\":0.34},{\"time\":\"10:00\",\"timeAsSeconds\":36000,\"value\":0.337},{\"time\":\"11:00\",\"timeAsSeconds\":39600,\"value\":0.35},{\"time\":\"12:00\",\"timeAsSeconds\":43200,\"value\":0.36},{\"time\":\"13:00\",\"timeAsSeconds\":46800,\"value\":0.351},{\"time\":\"14:00\",\"timeAsSeconds\":50400,\"value\":0.349},{\"time\":\"15:00\",\"timeAsSeconds\":54000,\"value\":0.359},{\"time\":\"16:00\",\"timeAsSeconds\":57600,\"value\":0.354},{\"time\":\"17:00\",\"timeAsSeconds\":61200,\"value\":0.336},{\"time\":\"18:00\",\"timeAsSeconds\":64800,\"value\":0.339},{\"time\":\"19:00\",\"timeAsSeconds\":68400,\"value\":0.357},{\"time\":\"20:00\",\"timeAsSeconds\":72000,\"value\":0.368},{\"time\":\"21:00\",\"timeAsSeconds\":75600,\"value\":0.327},{\"time\":\"22:00\",\"timeAsSeconds\":79200,\"value\":0.318},{\"time\":\"23:00\",\"timeAsSeconds\":82800,\"value\":0.318}],\"target_low\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":5.5}],\"target_high\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":5.5}],\"units\":\"mmol\",\"timezone\":\"GMT\"}},\"app\":\"AAPS\",\"utcOffset\":120,\"identifier\":\"6b503f6c-b676-5746-b331-658b03d50843\",\"srvModified\":1698763282534,\"srvCreated\":1698664636986,\"subject\":\"Phone\"},{\"_id\":\"6511a54e3c60c21734f1988b\",\"defaultProfile\":\"U200_32\",\"date\":1695655201449,\"created_at\":\"2023-09-25T15:20:01.4490000Z\",\"startDate\":\"2023-09-25T15:20:01.4490000Z\",\"store\":{\"U200_32\":{\"dia\":8,\"carbratio\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":14.618357917185001},{\"time\":\"06:00\",\"timeAsSeconds\":21600,\"value\":8.99591256442154},{\"time\":\"09:00\",\"timeAsSeconds\":32400,\"value\":10.12040163497423},{\"time\":\"11:00\",\"timeAsSeconds\":39600,\"value\":11.244890705526924},{\"time\":\"14:00\",\"timeAsSeconds\":50400,\"value\":13.493868846632308},{\"time\":\"17:00\",\"timeAsSeconds\":61200,\"value\":13.493868846632308},{\"time\":\"19:00\",\"timeAsSeconds\":68400,\"value\":13.493868846632308}],\"sens\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":8.55361111111111}],\"basal\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":0.306},{\"time\":\"01:00\",\"timeAsSeconds\":3600,\"value\":0.306},{\"time\":\"02:00\",\"timeAsSeconds\":7200,\"value\":0.334},{\"time\":\"03:00\",\"timeAsSeconds\":10800,\"value\":0.337},{\"time\":\"04:00\",\"timeAsSeconds\":14400,\"value\":0.35},{\"time\":\"05:00\",\"timeAsSeconds\":18000,\"value\":0.388},{\"time\":\"06:00\",\"timeAsSeconds\":21600,\"value\":0.388},{\"time\":\"07:00\",\"timeAsSeconds\":25200,\"value\":0.391},{\"time\":\"08:00\",\"timeAsSeconds\":28800,\"value\":0.365},{\"time\":\"09:00\",\"timeAsSeconds\":32400,\"value\":0.34},{\"time\":\"10:00\",\"timeAsSeconds\":36000,\"value\":0.337},{\"time\":\"11:00\",\"timeAsSeconds\":39600,\"value\":0.35},{\"time\":\"12:00\",\"timeAsSeconds\":43200,\"value\":0.36},{\"time\":\"13:00\",\"timeAsSeconds\":46800,\"value\":0.351},{\"time\":\"14:00\",\"timeAsSeconds\":50400,\"value\":0.349},{\"time\":\"15:00\",\"timeAsSeconds\":54000,\"value\":0.359},{\"time\":\"16:00\",\"timeAsSeconds\":57600,\"value\":0.354},{\"time\":\"17:00\",\"timeAsSeconds\":61200,\"value\":0.336},{\"time\":\"18:00\",\"timeAsSeconds\":64800,\"value\":0.339},{\"time\":\"19:00\",\"timeAsSeconds\":68400,\"value\":0.357},{\"time\":\"20:00\",\"timeAsSeconds\":72000,\"value\":0.368},{\"time\":\"21:00\",\"timeAsSeconds\":75600,\"value\":0.327},{\"time\":\"22:00\",\"timeAsSeconds\":79200,\"value\":0.318},{\"time\":\"23:00\",\"timeAsSeconds\":82800,\"value\":0.318}],\"target_low\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":5.5}],\"target_high\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":5.5}],\"units\":\"mmol\",\"timezone\":\"Europe/Prague\"}}}" @Before fun inject() { diff --git a/app/src/androidTest/kotlin/app/aaps/LoopTest.kt b/app/src/androidTest/kotlin/app/aaps/LoopTest.kt index 5730d13965b..b3963091528 100644 --- a/app/src/androidTest/kotlin/app/aaps/LoopTest.kt +++ b/app/src/androidTest/kotlin/app/aaps/LoopTest.kt @@ -59,7 +59,7 @@ class LoopTest @Inject constructor() { private val context = ApplicationProvider.getApplicationContext() private val profileData = "{\"_id\":\"653f90bc89f99714b4635b33\",\"defaultProfile\":\"U200_32\",\"date\":1695655201449,\"created_at\":\"2023-09-25T15:20:01.449Z\"," + - "\"startDate\":\"2023-09-25T15:20:01.4490000Z\",\"store\":{\"U200_32\":{\"dia\":8,\"carbratio\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":14.618357917185001},{\"time\":\"06:00\",\"timeAsSeconds\":21600,\"value\":8.99591256442154},{\"time\":\"09:00\",\"timeAsSeconds\":32400,\"value\":10.12040163497423},{\"time\":\"11:00\",\"timeAsSeconds\":39600,\"value\":11.244890705526924},{\"time\":\"14:00\",\"timeAsSeconds\":50400,\"value\":13.493868846632308},{\"time\":\"17:00\",\"timeAsSeconds\":61200,\"value\":13.493868846632308},{\"time\":\"19:00\",\"timeAsSeconds\":68400,\"value\":13.493868846632308}],\"sens\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":8.55361111111111}],\"basal\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":0.306},{\"time\":\"01:00\",\"timeAsSeconds\":3600,\"value\":0.306},{\"time\":\"02:00\",\"timeAsSeconds\":7200,\"value\":0.334},{\"time\":\"03:00\",\"timeAsSeconds\":10800,\"value\":0.337},{\"time\":\"04:00\",\"timeAsSeconds\":14400,\"value\":0.35},{\"time\":\"05:00\",\"timeAsSeconds\":18000,\"value\":0.388},{\"time\":\"06:00\",\"timeAsSeconds\":21600,\"value\":0.388},{\"time\":\"07:00\",\"timeAsSeconds\":25200,\"value\":0.391},{\"time\":\"08:00\",\"timeAsSeconds\":28800,\"value\":0.365},{\"time\":\"09:00\",\"timeAsSeconds\":32400,\"value\":0.34},{\"time\":\"10:00\",\"timeAsSeconds\":36000,\"value\":0.337},{\"time\":\"11:00\",\"timeAsSeconds\":39600,\"value\":0.35},{\"time\":\"12:00\",\"timeAsSeconds\":43200,\"value\":0.36},{\"time\":\"13:00\",\"timeAsSeconds\":46800,\"value\":0.351},{\"time\":\"14:00\",\"timeAsSeconds\":50400,\"value\":0.349},{\"time\":\"15:00\",\"timeAsSeconds\":54000,\"value\":0.359},{\"time\":\"16:00\",\"timeAsSeconds\":57600,\"value\":0.354},{\"time\":\"17:00\",\"timeAsSeconds\":61200,\"value\":0.336},{\"time\":\"18:00\",\"timeAsSeconds\":64800,\"value\":0.339},{\"time\":\"19:00\",\"timeAsSeconds\":68400,\"value\":0.357},{\"time\":\"20:00\",\"timeAsSeconds\":72000,\"value\":0.368},{\"time\":\"21:00\",\"timeAsSeconds\":75600,\"value\":0.327},{\"time\":\"22:00\",\"timeAsSeconds\":79200,\"value\":0.318},{\"time\":\"23:00\",\"timeAsSeconds\":82800,\"value\":0.318}],\"target_low\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":5.5}],\"target_high\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":5.5}],\"units\":\"mmol\",\"timezone\":\"GMT\"}},\"app\":\"AAPS\",\"utcOffset\":120,\"identifier\":\"6b503f6c-b676-5746-b331-658b03d50843\",\"srvModified\":1698763282534,\"srvCreated\":1698664636986,\"subject\":\"Phone\"},{\"_id\":\"6511a54e3c60c21734f1988b\",\"defaultProfile\":\"U200_32\",\"date\":1695655201449,\"created_at\":\"2023-09-25T15:20:01.4490000Z\",\"startDate\":\"2023-09-25T15:20:01.4490000Z\",\"store\":{\"U200_32\":{\"dia\":8,\"carbratio\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":14.618357917185001},{\"time\":\"06:00\",\"timeAsSeconds\":21600,\"value\":8.99591256442154},{\"time\":\"09:00\",\"timeAsSeconds\":32400,\"value\":10.12040163497423},{\"time\":\"11:00\",\"timeAsSeconds\":39600,\"value\":11.244890705526924},{\"time\":\"14:00\",\"timeAsSeconds\":50400,\"value\":13.493868846632308},{\"time\":\"17:00\",\"timeAsSeconds\":61200,\"value\":13.493868846632308},{\"time\":\"19:00\",\"timeAsSeconds\":68400,\"value\":13.493868846632308}],\"sens\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":8.55361111111111}],\"basal\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":0.306},{\"time\":\"01:00\",\"timeAsSeconds\":3600,\"value\":0.306},{\"time\":\"02:00\",\"timeAsSeconds\":7200,\"value\":0.334},{\"time\":\"03:00\",\"timeAsSeconds\":10800,\"value\":0.337},{\"time\":\"04:00\",\"timeAsSeconds\":14400,\"value\":0.35},{\"time\":\"05:00\",\"timeAsSeconds\":18000,\"value\":0.388},{\"time\":\"06:00\",\"timeAsSeconds\":21600,\"value\":0.388},{\"time\":\"07:00\",\"timeAsSeconds\":25200,\"value\":0.391},{\"time\":\"08:00\",\"timeAsSeconds\":28800,\"value\":0.365},{\"time\":\"09:00\",\"timeAsSeconds\":32400,\"value\":0.34},{\"time\":\"10:00\",\"timeAsSeconds\":36000,\"value\":0.337},{\"time\":\"11:00\",\"timeAsSeconds\":39600,\"value\":0.35},{\"time\":\"12:00\",\"timeAsSeconds\":43200,\"value\":0.36},{\"time\":\"13:00\",\"timeAsSeconds\":46800,\"value\":0.351},{\"time\":\"14:00\",\"timeAsSeconds\":50400,\"value\":0.349},{\"time\":\"15:00\",\"timeAsSeconds\":54000,\"value\":0.359},{\"time\":\"16:00\",\"timeAsSeconds\":57600,\"value\":0.354},{\"time\":\"17:00\",\"timeAsSeconds\":61200,\"value\":0.336},{\"time\":\"18:00\",\"timeAsSeconds\":64800,\"value\":0.339},{\"time\":\"19:00\",\"timeAsSeconds\":68400,\"value\":0.357},{\"time\":\"20:00\",\"timeAsSeconds\":72000,\"value\":0.368},{\"time\":\"21:00\",\"timeAsSeconds\":75600,\"value\":0.327},{\"time\":\"22:00\",\"timeAsSeconds\":79200,\"value\":0.318},{\"time\":\"23:00\",\"timeAsSeconds\":82800,\"value\":0.318}],\"target_low\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":5.5}],\"target_high\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":5.5}],\"units\":\"mmol\",\"timezone\":\"Europe/Prague\"}}}" + "\"startDate\":\"2023-09-25T15:20:01.4490000Z\",\"store\":{\"U200_32\":{\"icfg\":{\"insulinLabel\":\"\",\"insulinEndTime\":18000000,\"insulinPeakTime\":4500000},\"dia\":8,\"carbratio\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":14.618357917185001},{\"time\":\"06:00\",\"timeAsSeconds\":21600,\"value\":8.99591256442154},{\"time\":\"09:00\",\"timeAsSeconds\":32400,\"value\":10.12040163497423},{\"time\":\"11:00\",\"timeAsSeconds\":39600,\"value\":11.244890705526924},{\"time\":\"14:00\",\"timeAsSeconds\":50400,\"value\":13.493868846632308},{\"time\":\"17:00\",\"timeAsSeconds\":61200,\"value\":13.493868846632308},{\"time\":\"19:00\",\"timeAsSeconds\":68400,\"value\":13.493868846632308}],\"sens\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":8.55361111111111}],\"basal\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":0.306},{\"time\":\"01:00\",\"timeAsSeconds\":3600,\"value\":0.306},{\"time\":\"02:00\",\"timeAsSeconds\":7200,\"value\":0.334},{\"time\":\"03:00\",\"timeAsSeconds\":10800,\"value\":0.337},{\"time\":\"04:00\",\"timeAsSeconds\":14400,\"value\":0.35},{\"time\":\"05:00\",\"timeAsSeconds\":18000,\"value\":0.388},{\"time\":\"06:00\",\"timeAsSeconds\":21600,\"value\":0.388},{\"time\":\"07:00\",\"timeAsSeconds\":25200,\"value\":0.391},{\"time\":\"08:00\",\"timeAsSeconds\":28800,\"value\":0.365},{\"time\":\"09:00\",\"timeAsSeconds\":32400,\"value\":0.34},{\"time\":\"10:00\",\"timeAsSeconds\":36000,\"value\":0.337},{\"time\":\"11:00\",\"timeAsSeconds\":39600,\"value\":0.35},{\"time\":\"12:00\",\"timeAsSeconds\":43200,\"value\":0.36},{\"time\":\"13:00\",\"timeAsSeconds\":46800,\"value\":0.351},{\"time\":\"14:00\",\"timeAsSeconds\":50400,\"value\":0.349},{\"time\":\"15:00\",\"timeAsSeconds\":54000,\"value\":0.359},{\"time\":\"16:00\",\"timeAsSeconds\":57600,\"value\":0.354},{\"time\":\"17:00\",\"timeAsSeconds\":61200,\"value\":0.336},{\"time\":\"18:00\",\"timeAsSeconds\":64800,\"value\":0.339},{\"time\":\"19:00\",\"timeAsSeconds\":68400,\"value\":0.357},{\"time\":\"20:00\",\"timeAsSeconds\":72000,\"value\":0.368},{\"time\":\"21:00\",\"timeAsSeconds\":75600,\"value\":0.327},{\"time\":\"22:00\",\"timeAsSeconds\":79200,\"value\":0.318},{\"time\":\"23:00\",\"timeAsSeconds\":82800,\"value\":0.318}],\"target_low\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":5.5}],\"target_high\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":5.5}],\"units\":\"mmol\",\"timezone\":\"GMT\"}},\"app\":\"AAPS\",\"utcOffset\":120,\"identifier\":\"6b503f6c-b676-5746-b331-658b03d50843\",\"srvModified\":1698763282534,\"srvCreated\":1698664636986,\"subject\":\"Phone\"},{\"_id\":\"6511a54e3c60c21734f1988b\",\"defaultProfile\":\"U200_32\",\"date\":1695655201449,\"created_at\":\"2023-09-25T15:20:01.4490000Z\",\"startDate\":\"2023-09-25T15:20:01.4490000Z\",\"store\":{\"U200_32\":{\"dia\":8,\"carbratio\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":14.618357917185001},{\"time\":\"06:00\",\"timeAsSeconds\":21600,\"value\":8.99591256442154},{\"time\":\"09:00\",\"timeAsSeconds\":32400,\"value\":10.12040163497423},{\"time\":\"11:00\",\"timeAsSeconds\":39600,\"value\":11.244890705526924},{\"time\":\"14:00\",\"timeAsSeconds\":50400,\"value\":13.493868846632308},{\"time\":\"17:00\",\"timeAsSeconds\":61200,\"value\":13.493868846632308},{\"time\":\"19:00\",\"timeAsSeconds\":68400,\"value\":13.493868846632308}],\"sens\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":8.55361111111111}],\"basal\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":0.306},{\"time\":\"01:00\",\"timeAsSeconds\":3600,\"value\":0.306},{\"time\":\"02:00\",\"timeAsSeconds\":7200,\"value\":0.334},{\"time\":\"03:00\",\"timeAsSeconds\":10800,\"value\":0.337},{\"time\":\"04:00\",\"timeAsSeconds\":14400,\"value\":0.35},{\"time\":\"05:00\",\"timeAsSeconds\":18000,\"value\":0.388},{\"time\":\"06:00\",\"timeAsSeconds\":21600,\"value\":0.388},{\"time\":\"07:00\",\"timeAsSeconds\":25200,\"value\":0.391},{\"time\":\"08:00\",\"timeAsSeconds\":28800,\"value\":0.365},{\"time\":\"09:00\",\"timeAsSeconds\":32400,\"value\":0.34},{\"time\":\"10:00\",\"timeAsSeconds\":36000,\"value\":0.337},{\"time\":\"11:00\",\"timeAsSeconds\":39600,\"value\":0.35},{\"time\":\"12:00\",\"timeAsSeconds\":43200,\"value\":0.36},{\"time\":\"13:00\",\"timeAsSeconds\":46800,\"value\":0.351},{\"time\":\"14:00\",\"timeAsSeconds\":50400,\"value\":0.349},{\"time\":\"15:00\",\"timeAsSeconds\":54000,\"value\":0.359},{\"time\":\"16:00\",\"timeAsSeconds\":57600,\"value\":0.354},{\"time\":\"17:00\",\"timeAsSeconds\":61200,\"value\":0.336},{\"time\":\"18:00\",\"timeAsSeconds\":64800,\"value\":0.339},{\"time\":\"19:00\",\"timeAsSeconds\":68400,\"value\":0.357},{\"time\":\"20:00\",\"timeAsSeconds\":72000,\"value\":0.368},{\"time\":\"21:00\",\"timeAsSeconds\":75600,\"value\":0.327},{\"time\":\"22:00\",\"timeAsSeconds\":79200,\"value\":0.318},{\"time\":\"23:00\",\"timeAsSeconds\":82800,\"value\":0.318}],\"target_low\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":5.5}],\"target_high\":[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":5.5}],\"units\":\"mmol\",\"timezone\":\"Europe/Prague\"}}}" @Before fun inject() { diff --git a/core/objects/src/test/kotlin/app/aaps/core/objects/profile/ProfileSealedTest.kt b/core/objects/src/test/kotlin/app/aaps/core/objects/profile/ProfileSealedTest.kt index 2ababdeaf73..e545e5eb678 100644 --- a/core/objects/src/test/kotlin/app/aaps/core/objects/profile/ProfileSealedTest.kt +++ b/core/objects/src/test/kotlin/app/aaps/core/objects/profile/ProfileSealedTest.kt @@ -42,19 +42,19 @@ class ProfileSealedTest : TestBase() { private lateinit var hardLimits: HardLimits private lateinit var dateUtil: DateUtil private lateinit var testPumpPlugin: TestPumpPlugin - - private var okProfile = "{\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}]," + + //ICfg: dia 18000000 = 5.0h, peak = 4500000 = 75 + private var okProfile = "{\"icfg\":{\"insulinLabel\":\"\",\"insulinEndTime\":18000000,\"insulinPeakTime\":4500000},\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}]," + "\"sens\":[{\"time\":\"00:00\",\"value\":\"6\"},{\"time\":\"2:00\",\"value\":\"6.2\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}" private var belowLimitValidProfile = - "{\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.001\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}" + "{\"icfg\":{\"insulinLabel\":\"\",\"insulinEndTime\":18000000,\"insulinPeakTime\":4500000},\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.001\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}" private var notAlignedBasalValidProfile = - "{\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:30\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}" + "{\"icfg\":{\"insulinLabel\":\"\",\"insulinEndTime\":18000000,\"insulinPeakTime\":4500000},\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:30\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}" private var notStartingAtZeroValidProfile = - "{\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:30\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}" + "{\"icfg\":{\"insulinLabel\":\"\",\"insulinEndTime\":18000000,\"insulinPeakTime\":4500000},\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:30\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}" private var noUnitsValidProfile = - "{\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\"}" + "{\"icfg\":{\"insulinLabel\":\"\",\"insulinEndTime\":18000000,\"insulinPeakTime\":4500000},\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\"}" private var wrongProfile = - "{\"dia\":\"5\",\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}" + "{\"icfg\":{\"insulinLabel\":\"\",\"insulinEndTime\":18000000,\"insulinPeakTime\":4500000},\"dia\":\"5\",\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}" //String profileStore = "{\"defaultProfile\":\"Default\",\"store\":{\"Default\":" + validProfile + "}}"; diff --git a/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/autotune/AutotuneCoreTest.kt b/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/autotune/AutotuneCoreTest.kt index 6fa497bb6dc..d7f7b115767 100644 --- a/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/autotune/AutotuneCoreTest.kt +++ b/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/autotune/AutotuneCoreTest.kt @@ -94,6 +94,7 @@ class AutotuneCoreTest : TestBaseWithProfile() { val units = GlucoseUnit.fromText(txtUnits) val dia = JsonHelper.safeGetDoubleAllowNull(jsonObject, "dia") ?: return null val peak = JsonHelper.safeGetIntAllowNull(jsonObject, "insulinPeakTime") ?: return null + val iCfg = ICfg("", peak, dia) val localInsulin = LocalInsulin("insulin", peak, dia) val timezone = TimeZone.getTimeZone(JsonHelper.safeGetString(jsonObject, "timezone", "UTC")) val isfJson = jsonObject.getJSONObject("isfProfile") @@ -120,8 +121,8 @@ class AutotuneCoreTest : TestBaseWithProfile() { targetBlocks = targetBlocks, glucoseUnit = units, timeZone = timezone, - iCfg = ICfg("", peak, dia), - dia = dia + dia = dia, + iCfg = iCfg ) return ATProfile(ProfileSealed.Pure(pure, activePlugin), localInsulin, injector).also { it.dateUtil = dateUtil; it.profileUtil = profileUtil } } catch (ignored: Exception) { diff --git a/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/autotune/AutotunePrepTest.kt b/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/autotune/AutotunePrepTest.kt index 08ba1b8909c..894d9a59acb 100644 --- a/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/autotune/AutotunePrepTest.kt +++ b/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/autotune/AutotunePrepTest.kt @@ -165,6 +165,7 @@ class AutotunePrepTest : TestBaseWithProfile() { val units = GlucoseUnit.fromText(txtUnits) val dia = JsonHelper.safeGetDoubleAllowNull(jsonObject, "dia") ?: return null val peak = JsonHelper.safeGetIntAllowNull(jsonObject, "insulinPeakTime") ?: return null + val iCfg = ICfg("insulin", peak, dia) val localInsulin = LocalInsulin("insulin", peak, dia) val timezone = TimeZone.getTimeZone(JsonHelper.safeGetString(jsonObject, "timezone", "UTC")) val isfJson = jsonObject.getJSONObject("isfProfile") @@ -191,7 +192,7 @@ class AutotunePrepTest : TestBaseWithProfile() { targetBlocks = targetBlocks, glucoseUnit = units, timeZone = timezone, - iCfg = ICfg("", peak, dia), + iCfg = iCfg, dia = dia ) return ATProfile(ProfileSealed.Pure(pure, activePlugin), localInsulin, injector).also { it.dateUtil = dateUtil } diff --git a/pump/medtrum/src/test/kotlin/app/aaps/pump/medtrum/MedtrumPumpTest.kt b/pump/medtrum/src/test/kotlin/app/aaps/pump/medtrum/MedtrumPumpTest.kt index 1b2dc47a853..8b21cf0b585 100644 --- a/pump/medtrum/src/test/kotlin/app/aaps/pump/medtrum/MedtrumPumpTest.kt +++ b/pump/medtrum/src/test/kotlin/app/aaps/pump/medtrum/MedtrumPumpTest.kt @@ -31,7 +31,7 @@ class MedtrumPumpTest : MedtrumTestBase() { // 16:00 : 1.6 // 21:00 : 1.7 // 23:00 : 2 - val profileJSON = "{\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\"," + + val profileJSON = "{\"icfg\":{\"insulinLabel\":\"\",\"insulinEndTime\":18000000,\"insulinPeakTime\":4500000},\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\"," + "\"sens\":[{\"time\":\"00:00\",\"value\":\"3\"},{\"time\":\"02:00\",\"value\":\"3.4\"}],\"timezone\":\"UTC\"," + "\"basal\":[{\"time\":\"00:00\",\"value\":\"2.1\"},{\"time\":\"04:00\",\"value\":\"1.9\"},{\"time\":\"06:00\",\"value\":\"1.7\"}," + "{\"time\":\"08:00\",\"value\":\"1.5\"},{\"time\":\"16:00\",\"value\":\"1.6\"},{\"time\":\"21:00\",\"value\":\"1.7\"},{\"time\":\"23:00\",\"value\":\"2\"}]," + @@ -50,7 +50,7 @@ class MedtrumPumpTest : MedtrumTestBase() { // Inputs // Basal profile with 1 element: // 00:00 : 600 - val profileJSON = "{\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\"," + + val profileJSON = "{\"icfg\":{\"insulinLabel\":\"\",\"insulinEndTime\":18000000,\"insulinPeakTime\":4500000},\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\"," + "\"sens\":[{\"time\":\"00:00\",\"value\":\"3\"},{\"time\":\"02:00\",\"value\":\"3.4\"}],\"timezone\":\"UTC\"," + "\"basal\":[{\"time\":\"00:00\",\"value\":\"600\"}]," + "\"target_low\":[{\"time\":\"00:00\",\"value\":\"4.5\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"7\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}" @@ -73,7 +73,7 @@ class MedtrumPumpTest : MedtrumTestBase() { // 16:00 : 1.6 // 21:00 : 1.7 // 23:00 : 2 - val profileJSON = "{\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\"," + + val profileJSON = "{\"icfg\":{\"insulinLabel\":\"\",\"insulinEndTime\":18000000,\"insulinPeakTime\":4500000},\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\"," + "\"sens\":[{\"time\":\"00:00\",\"value\":\"3\"},{\"time\":\"02:00\",\"value\":\"3.4\"}],\"timezone\":\"UTC\"," + "\"basal\":[{\"time\":\"00:00\",\"value\":\"2.1\"},{\"time\":\"04:00\",\"value\":\"1.9\"},{\"time\":\"06:00\",\"value\":\"1.7\"}," + "{\"time\":\"08:00\",\"value\":\"1.5\"},{\"time\":\"16:00\",\"value\":\"1.6\"},{\"time\":\"21:00\",\"value\":\"1.7\"},{\"time\":\"23:00\",\"value\":\"2\"}]," + diff --git a/shared/tests/src/main/kotlin/app/aaps/shared/tests/TestBaseWithProfile.kt b/shared/tests/src/main/kotlin/app/aaps/shared/tests/TestBaseWithProfile.kt index 0884cc7b9e5..2fa41b997af 100644 --- a/shared/tests/src/main/kotlin/app/aaps/shared/tests/TestBaseWithProfile.kt +++ b/shared/tests/src/main/kotlin/app/aaps/shared/tests/TestBaseWithProfile.kt @@ -102,10 +102,10 @@ open class TestBaseWithProfile : TestBase() { @BeforeEach fun prepareMock() { - validProfileJSON = "{\"dia\":\"5\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"3\"}," + + validProfileJSON = "{\"icfg\":{\"insulinLabel\":\"\",\"insulinEndTime\":18000000,\"insulinPeakTime\":4500000},\"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\"}" - invalidProfileJSON = "{\"dia\":\"1\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"3\"}," + + invalidProfileJSON = "{\"icfg\":{\"insulinLabel\":\"\",\"insulinEndTime\":18000000,\"insulinPeakTime\":4500000},\"dia\":\"1\",\"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\"}" preferenceManager = PreferenceManager(context) @@ -135,7 +135,7 @@ open class TestBaseWithProfile : TestBase() { originalPercentage = 100, originalDuration = 0, originalEnd = 0, - iCfg = ICfg("", 0, 0) + iCfg = ICfg("", 18000000, 4500000) ) Mockito.`when`(rh.gs(R.string.ok)).thenReturn("OK") diff --git a/ui/src/main/kotlin/app/aaps/ui/defaultProfile/DefaultProfile.kt b/ui/src/main/kotlin/app/aaps/ui/defaultProfile/DefaultProfile.kt index cae9bbf710b..4ae425e76a9 100644 --- a/ui/src/main/kotlin/app/aaps/ui/defaultProfile/DefaultProfile.kt +++ b/ui/src/main/kotlin/app/aaps/ui/defaultProfile/DefaultProfile.kt @@ -1,11 +1,13 @@ package app.aaps.ui.defaultProfile import app.aaps.core.data.model.GlucoseUnit +import app.aaps.core.interfaces.plugin.ActivePlugin import app.aaps.core.interfaces.profile.ProfileUtil import app.aaps.core.interfaces.profile.PureProfile import app.aaps.core.interfaces.utils.DateUtil import app.aaps.core.interfaces.utils.Round import app.aaps.core.objects.extensions.pureProfileFromJson +import app.aaps.core.objects.extensions.toJson import org.json.JSONArray import org.json.JSONObject import java.util.Locale @@ -19,7 +21,8 @@ import kotlin.math.abs @Singleton class DefaultProfile @Inject constructor( private val dateUtil: DateUtil, - private val profileUtil: ProfileUtil + private val profileUtil: ProfileUtil, + private val activePlugin: ActivePlugin ) { private var oneToFive: TreeMap> = TreeMap() @@ -53,6 +56,7 @@ class DefaultProfile @Inject constructor( } else if (age > 18) { return null } + profile.put("icfg", activePlugin.activeInsulin.iCfg.toJson()) profile.put("dia", 5.0) profile.put("carbs_hr", 20) // not used profile.put("delay", 5.0) // not used diff --git a/ui/src/main/kotlin/app/aaps/ui/defaultProfile/DefaultProfileDPV.kt b/ui/src/main/kotlin/app/aaps/ui/defaultProfile/DefaultProfileDPV.kt index f04963670c3..5d223557c94 100644 --- a/ui/src/main/kotlin/app/aaps/ui/defaultProfile/DefaultProfileDPV.kt +++ b/ui/src/main/kotlin/app/aaps/ui/defaultProfile/DefaultProfileDPV.kt @@ -1,10 +1,12 @@ package app.aaps.ui.defaultProfile import app.aaps.core.data.model.GlucoseUnit +import app.aaps.core.interfaces.plugin.ActivePlugin import app.aaps.core.interfaces.profile.ProfileUtil import app.aaps.core.interfaces.profile.PureProfile import app.aaps.core.interfaces.utils.DateUtil import app.aaps.core.objects.extensions.pureProfileFromJson +import app.aaps.core.objects.extensions.toJson import org.json.JSONArray import org.json.JSONObject import java.util.Locale @@ -15,7 +17,8 @@ import javax.inject.Singleton @Singleton class DefaultProfileDPV @Inject constructor( private val dateUtil: DateUtil, - private val profileUtil: ProfileUtil + private val profileUtil: ProfileUtil, + private val activePlugin: ActivePlugin ) { private var oneToFive = arrayOf(3.97, 3.61, 3.46, 3.70, 3.76, 3.87, 4.18, 4.01, 3.76, 3.54, 3.15, 2.80, 2.86, 3.21, 3.61, 3.97, 4.43, 4.96, 5.10, 5.50, 5.81, 6.14, 5.52, 5.10) @@ -40,6 +43,7 @@ class DefaultProfileDPV @Inject constructor( } else if (age > 18) { return null } + profile.put("icfg", activePlugin.activeInsulin.iCfg.toJson()) profile.put("dia", 5.0) profile.put("carbs_hr", 20) // not used profile.put("delay", 5.0) // not used diff --git a/ui/src/test/kotlin/app/aaps/ui/defaultProfile/DefaultProfileTest.kt b/ui/src/test/kotlin/app/aaps/ui/defaultProfile/DefaultProfileTest.kt index 2a711405137..53db95ce21e 100644 --- a/ui/src/test/kotlin/app/aaps/ui/defaultProfile/DefaultProfileTest.kt +++ b/ui/src/test/kotlin/app/aaps/ui/defaultProfile/DefaultProfileTest.kt @@ -1,27 +1,40 @@ package app.aaps.ui.defaultProfile import app.aaps.core.data.model.GlucoseUnit +import app.aaps.core.data.model.ICfg +import app.aaps.core.interfaces.insulin.Insulin +import app.aaps.core.interfaces.plugin.ActivePlugin import app.aaps.core.objects.profile.ProfileSealed import app.aaps.shared.tests.TestBaseWithProfile import com.google.common.truth.Truth.assertThat +import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test +import org.mockito.Mock +import org.mockito.Mockito.`when` class DefaultProfileTest : TestBaseWithProfile() { + @Mock lateinit var activeInsulin: Insulin + + @BeforeEach + fun prepare() { + `when`(activePlugin.activeInsulin).thenReturn(activeInsulin) + `when`(activePlugin.activeInsulin.iCfg).thenReturn(ICfg("", 75, 5.0)) + } @Test fun profile() { - val dp = DefaultProfile(dateUtil, profileUtil).profile(5, 5.1 / 0.3, 0.0, GlucoseUnit.MMOL) + val dp = DefaultProfile(dateUtil, profileUtil, activePlugin).profile(5, 5.1 / 0.3, 0.0, GlucoseUnit.MMOL) var p = ProfileSealed.Pure(dp!!, activePlugin) assertThat(p.getBasalTimeFromMidnight(0)).isWithin(0.001).of(0.150) assertThat(p.getIcTimeFromMidnight(0)).isWithin(0.001).of(15.0) assertThat(p.getIsfTimeFromMidnight(0)).isWithin(0.001).of(11.8) - p = ProfileSealed.Pure(DefaultProfile(dateUtil, profileUtil).profile(7, 10.0 / 0.4, 0.0, GlucoseUnit.MMOL)!!, activePlugin) + p = ProfileSealed.Pure(DefaultProfile(dateUtil, profileUtil, activePlugin).profile(7, 10.0 / 0.4, 0.0, GlucoseUnit.MMOL)!!, activePlugin) assertThat(p.getBasalTimeFromMidnight(0)).isWithin(0.001).of(0.350) assertThat(p.getIcTimeFromMidnight(0)).isWithin(0.001).of(15.0) assertThat(p.getIsfTimeFromMidnight(0)).isWithin(0.001).of(6.8) - p = ProfileSealed.Pure(DefaultProfile(dateUtil, profileUtil).profile(12, 25.0 / 0.5, 0.0, GlucoseUnit.MMOL)!!, activePlugin) + p = ProfileSealed.Pure(DefaultProfile(dateUtil, profileUtil, activePlugin).profile(12, 25.0 / 0.5, 0.0, GlucoseUnit.MMOL)!!, activePlugin) assertThat(p.getBasalTimeFromMidnight(0)).isWithin(0.001).of(0.80) assertThat(p.getIcTimeFromMidnight(0)).isWithin(0.001).of(10.0) assertThat(p.getIsfTimeFromMidnight(0)).isWithin(0.001).of(2.2) From c01b06c8877e89766ac1ed8bade1b0aee948e7e2 Mon Sep 17 00:00:00 2001 From: Philoul Date: Sat, 22 Feb 2025 14:15:30 +0100 Subject: [PATCH 06/41] Align code --- .../test/kotlin/app/aaps/ui/defaultProfile/DefaultProfileTest.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/ui/src/test/kotlin/app/aaps/ui/defaultProfile/DefaultProfileTest.kt b/ui/src/test/kotlin/app/aaps/ui/defaultProfile/DefaultProfileTest.kt index 53db95ce21e..5c34596c273 100644 --- a/ui/src/test/kotlin/app/aaps/ui/defaultProfile/DefaultProfileTest.kt +++ b/ui/src/test/kotlin/app/aaps/ui/defaultProfile/DefaultProfileTest.kt @@ -3,7 +3,6 @@ package app.aaps.ui.defaultProfile import app.aaps.core.data.model.GlucoseUnit import app.aaps.core.data.model.ICfg import app.aaps.core.interfaces.insulin.Insulin -import app.aaps.core.interfaces.plugin.ActivePlugin import app.aaps.core.objects.profile.ProfileSealed import app.aaps.shared.tests.TestBaseWithProfile import com.google.common.truth.Truth.assertThat From ca5f85efb7ebb5af51fbba7c2dceaafd69ce3099 Mon Sep 17 00:00:00 2001 From: Philoul Date: Sat, 22 Feb 2025 15:07:28 +0100 Subject: [PATCH 07/41] HardLimits add Min and MaxPeak --- .../main/kotlin/app/aaps/core/interfaces/utils/HardLimits.kt | 2 ++ .../main/kotlin/app/aaps/implementation/utils/HardLimitsImpl.kt | 2 ++ .../src/main/kotlin/app/aaps/shared/tests/HardLimitsMock.kt | 2 ++ 3 files changed, 6 insertions(+) diff --git a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/utils/HardLimits.kt b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/utils/HardLimits.kt index 5c4d3706ac8..56ece59da85 100644 --- a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/utils/HardLimits.kt +++ b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/utils/HardLimits.kt @@ -38,6 +38,8 @@ interface HardLimits { fun maxDia(): Double fun minIC(): Double fun maxIC(): Double + fun minPeak(): Double + fun maxPeak(): Double // safety checks fun checkHardLimits(value: Double, valueName: Int, lowLimit: Double, highLimit: Double): Boolean diff --git a/implementation/src/main/kotlin/app/aaps/implementation/utils/HardLimitsImpl.kt b/implementation/src/main/kotlin/app/aaps/implementation/utils/HardLimitsImpl.kt index 5dd01bc36ca..224d22cfa40 100644 --- a/implementation/src/main/kotlin/app/aaps/implementation/utils/HardLimitsImpl.kt +++ b/implementation/src/main/kotlin/app/aaps/implementation/utils/HardLimitsImpl.kt @@ -51,6 +51,8 @@ class HardLimitsImpl @Inject constructor( override fun maxDia(): Double = HardLimits.MAX_DIA[loadAge()] override fun minIC(): Double = HardLimits.MIN_IC[loadAge()] override fun maxIC(): Double = HardLimits.MAX_IC[loadAge()] + override fun minPeak(): Double = 35.0 + override fun maxPeak(): Double = 120.0 // safety checks override fun checkHardLimits(value: Double, valueName: Int, lowLimit: Double, highLimit: Double): Boolean = diff --git a/shared/tests/src/main/kotlin/app/aaps/shared/tests/HardLimitsMock.kt b/shared/tests/src/main/kotlin/app/aaps/shared/tests/HardLimitsMock.kt index 7304ee110a6..20913ed601f 100644 --- a/shared/tests/src/main/kotlin/app/aaps/shared/tests/HardLimitsMock.kt +++ b/shared/tests/src/main/kotlin/app/aaps/shared/tests/HardLimitsMock.kt @@ -67,6 +67,8 @@ import kotlin.math.min override fun maxDia(): Double = MAX_DIA[loadAge()] override fun minIC(): Double = MIN_IC[loadAge()] override fun maxIC(): Double = MAX_IC[loadAge()] + override fun minPeak(): Double = 35.0 + override fun maxPeak(): Double = 120.0 // safety checks override fun checkHardLimits(value: Double, valueName: Int, lowLimit: Double, highLimit: Double): Boolean = From 8d96d14fc79d1e5d814ebee6408b75d223e559ac Mon Sep 17 00:00:00 2001 From: Philoul Date: Sat, 22 Feb 2025 18:50:33 +0100 Subject: [PATCH 08/41] Tempo Update Autotune --- .../app/aaps/core/graph/ActivityGraph.kt | 47 +++++++++++ core/ui/src/main/res/values/strings.xml | 6 ++ .../aaps/plugins/aps/autotune/AutotuneCore.kt | 4 +- .../plugins/aps/autotune/AutotuneFragment.kt | 2 +- .../plugins/aps/autotune/AutotunePlugin.kt | 2 + .../plugins/aps/autotune/data/ATProfile.kt | 12 +-- .../aaps/ui/dialogs/ProfileViewerDialog.kt | 8 +- .../main/res/layout/dialog_profileviewer.xml | 80 ++++++++++++++++++- 8 files changed, 149 insertions(+), 12 deletions(-) diff --git a/core/graph/src/main/kotlin/app/aaps/core/graph/ActivityGraph.kt b/core/graph/src/main/kotlin/app/aaps/core/graph/ActivityGraph.kt index dbc2019e403..8c1a87a31e4 100644 --- a/core/graph/src/main/kotlin/app/aaps/core/graph/ActivityGraph.kt +++ b/core/graph/src/main/kotlin/app/aaps/core/graph/ActivityGraph.kt @@ -4,6 +4,7 @@ import android.content.Context import android.graphics.Color import android.util.AttributeSet import app.aaps.core.data.model.BS +import app.aaps.core.data.model.ICfg import app.aaps.core.data.time.T import app.aaps.core.interfaces.insulin.Insulin import com.jjoe64.graphview.GraphView @@ -57,4 +58,50 @@ class ActivityGraph : GraphView { secondScale.maxY = 1.0 gridLabelRenderer.verticalLabelsSecondScaleColor = Color.MAGENTA } + + + fun show(insulin: Insulin, iCfg: ICfg?) { + if (iCfg == null) { + show(insulin) + return + } + removeAllSeries() + val dia = iCfg.getDia() + mSecondScale = null + val hours = floor(dia + 1).toLong() + val bolus = BS( + timestamp = 0, + amount = 1.0, + type = BS.Type.NORMAL + ) + val activityArray: MutableList = ArrayList() + val iobArray: MutableList = ArrayList() + var time: Long = 0 + while (time <= T.hours(hours).msecs()) { + val iob = insulin.iobCalcForTreatment(bolus, time, iCfg) + activityArray.add(DataPoint(T.msecs(time).mins().toDouble(), iob.activityContrib)) + iobArray.add(DataPoint(T.msecs(time).mins().toDouble(), iob.iobContrib)) + time += T.mins(5).msecs() + } + addSeries(LineGraphSeries(Array(activityArray.size) { i -> activityArray[i] }).also { + it.thickness = 8 + gridLabelRenderer.verticalLabelsColor = it.color + }) + viewport.isXAxisBoundsManual = true + viewport.setMinX(0.0) + viewport.setMaxX((hours * 60).toDouble()) + viewport.isYAxisBoundsManual = true + viewport.setMinY(0.0) + viewport.setMaxY(0.01) + //gridLabelRenderer.numHorizontalLabels = (hours + 1).toInt() + gridLabelRenderer.horizontalAxisTitle = "[min]" + secondScale.addSeries(LineGraphSeries(Array(iobArray.size) { i -> iobArray[i] }).also { + it.isDrawBackground = true + it.color = Color.MAGENTA + it.backgroundColor = Color.argb(70, 255, 0, 255) + }) + secondScale.minY = 0.0 + secondScale.maxY = 1.0 + gridLabelRenderer.verticalLabelsSecondScaleColor = Color.MAGENTA + } } \ No newline at end of file diff --git a/core/ui/src/main/res/values/strings.xml b/core/ui/src/main/res/values/strings.xml index 8ca726110d2..d7376335041 100644 --- a/core/ui/src/main/res/values/strings.xml +++ b/core/ui/src/main/res/values/strings.xml @@ -162,7 +162,13 @@ Closed Loop Open Loop Low Glucose Suspend + INS + Select Insulin to Edit + Select Pump Insulin + Select Insulin + Insulin Template DIA + Peak IC ISF Canceling of temporary basal failed diff --git a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneCore.kt b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneCore.kt index 10d50bb9a28..e4952d7b549 100644 --- a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneCore.kt +++ b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneCore.kt @@ -486,8 +486,8 @@ class AutotuneCore @Inject constructor( previousAutotune.isf = isf previousAutotune.ic = Round.roundTo(carbRatio, 0.001) previousAutotune.basalUnTuned = basalUnTuned - previousAutotune.dia = newDia - previousAutotune.peak = newPeak + previousAutotune.profile.iCfg.setDia(newDia) + previousAutotune.profile.iCfg.setPeak(newPeak) val localInsulin = LocalInsulin("Ins_$newPeak-$newDia", newPeak, newDia) previousAutotune.localInsulin = localInsulin previousAutotune.updateProfile() diff --git a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneFragment.kt b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneFragment.kt index 18b64caf415..41cb6f42d3f 100644 --- a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneFragment.kt +++ b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneFragment.kt @@ -217,7 +217,7 @@ class AutotuneFragment : DaggerFragment() { binding.autotuneCheckInputProfile.setOnClickListener { val pumpProfile = profileFunction.getProfile()?.let { currentProfile -> profileStore.getSpecificProfile(profileName)?.let { specificProfile -> - ATProfile(ProfileSealed.Pure(specificProfile, null), LocalInsulin(""), injector).also { + ATProfile(ProfileSealed.Pure(specificProfile, null), LocalInsulin("", specificProfile.iCfg.getPeak(), specificProfile.iCfg.getDia()), injector).also { it.profileName = profileName } } diff --git a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotunePlugin.kt b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotunePlugin.kt index 6bf969dbfb4..a7e2121dc66 100644 --- a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotunePlugin.kt +++ b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotunePlugin.kt @@ -378,6 +378,8 @@ class AutotunePlugin @Inject constructor( } profilePlugin.currentProfileIndex = indexLocalProfile profilePlugin.currentProfile()?.dia = newProfile.dia + profilePlugin.currentProfile()?.iCfg?.setDia(newProfile.dia) + profilePlugin.currentProfile()?.iCfg?.setPeak(newProfile.peak) profilePlugin.currentProfile()?.basal = newProfile.basal() profilePlugin.currentProfile()?.ic = newProfile.ic(circadian) profilePlugin.currentProfile()?.isf = newProfile.isf(circadian) diff --git a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/data/ATProfile.kt b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/data/ATProfile.kt index 4dc934bab69..8ca33a261fb 100644 --- a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/data/ATProfile.kt +++ b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/data/ATProfile.kt @@ -24,6 +24,7 @@ import app.aaps.core.keys.IntKey import app.aaps.core.keys.Preferences import app.aaps.core.objects.extensions.blockValueBySeconds import app.aaps.core.objects.extensions.pureProfileFromJson +import app.aaps.core.objects.extensions.toJson import app.aaps.core.objects.profile.ProfileSealed import app.aaps.core.utils.MidnightUtils import app.aaps.plugins.aps.R @@ -57,8 +58,10 @@ class ATProfile(profile: Profile, var localInsulin: LocalInsulin, val injector: var basalUnTuned = IntArray(24) var ic = 0.0 var isf = 0.0 - var dia = 0.0 - var peak = 0 + val dia: Double + get() = profile.iCfg.getDia() + val peak: Int + get() = profile.iCfg.getPeak() var isValid: Boolean = false var from: Long = 0 private var pumpProfileAvgISF = 0.0 @@ -111,7 +114,6 @@ class ATProfile(profile: Profile, var localInsulin: LocalInsulin, val injector: json.put("name", profileName) json.put("min_5m_carbimpact", sp.getDouble("openapsama_min_5m_carbimpact", 3.0)) json.put("dia", dia) - json.put("icfg", ICfg("", peak, dia)) if (insulinInterface.id === Insulin.InsulinType.OREF_ULTRA_RAPID_ACTING) json.put( "curve", "ultra-rapid" @@ -163,7 +165,7 @@ class ATProfile(profile: Profile, var localInsulin: LocalInsulin, val injector: fun data(circadian: Boolean = false): PureProfile? { val json: JSONObject = profile.toPureNsJson(dateUtil) try { - json.put("icfg", ICfg("", peak, dia)) + json.put("icfg", ICfg("Tuned", peak, dia).toJson()) json.put("dia", dia) if (circadian) { json.put("sens", jsonArray(pumpProfile.isfBlocks, avgISF / pumpProfileAvgISF)) @@ -272,7 +274,5 @@ class ATProfile(profile: Profile, var localInsulin: LocalInsulin, val injector: pumpProfileAvgIC = avgIC pumpProfileAvgISF = avgISF } - dia = localInsulin.dia - peak = localInsulin.peak } } \ No newline at end of file diff --git a/ui/src/main/kotlin/app/aaps/ui/dialogs/ProfileViewerDialog.kt b/ui/src/main/kotlin/app/aaps/ui/dialogs/ProfileViewerDialog.kt index 0a7391ee49e..31539b9a0c2 100644 --- a/ui/src/main/kotlin/app/aaps/ui/dialogs/ProfileViewerDialog.kt +++ b/ui/src/main/kotlin/app/aaps/ui/dialogs/ProfileViewerDialog.kt @@ -137,8 +137,10 @@ class ProfileViewerDialog : DaggerDialogFragment() { profile?.let { profile1 -> profile2?.let { profile2 -> binding.units.text = profileFunction.getUnits().asText - binding.dia.text = HtmlHelper.fromHtml(formatColors("", profile1.dia, profile2.dia, DecimalFormat("0.00"), rh.gs(app.aaps.core.interfaces.R.string.shorthour))) + binding.dia.text = HtmlHelper.fromHtml(formatColors("", profile1.iCfg.getDia(), profile2.iCfg.getDia(), DecimalFormat("0.00"), rh.gs(app.aaps.core.interfaces.R.string.shorthour))) + binding.peak.text = HtmlHelper.fromHtml(formatColors("", profile1.iCfg.getPeak().toDouble(), profile2.iCfg.getPeak().toDouble(), DecimalFormat("0"), rh.gs(app.aaps.core.interfaces.R.string.shortminute))) val profileNames = profileName!!.split("\n").toTypedArray() + binding.insulin.text = HtmlHelper.fromHtml(formatColors(profile1.iCfg.insulinLabel, profile2.iCfg.insulinLabel)) binding.activeProfile.text = HtmlHelper.fromHtml(formatColors(profileNames[0], profileNames[1])) binding.date.text = date binding.ic.text = ics(profile1, profile2) @@ -159,7 +161,9 @@ class ProfileViewerDialog : DaggerDialogFragment() { else profile?.let { binding.units.text = it.units.asText - binding.dia.text = rh.gs(app.aaps.core.ui.R.string.format_hours, it.dia) + binding.insulin.text = it.iCfg.insulinLabel + binding.dia.text = rh.gs(app.aaps.core.ui.R.string.format_hours, it.iCfg.getDia()) + binding.peak.text = rh.gs(app.aaps.core.ui.R.string.format_mins, it.iCfg.getPeak()) binding.activeProfile.text = profileName binding.date.text = date binding.ic.text = it.getIcList(rh, dateUtil) diff --git a/ui/src/main/res/layout/dialog_profileviewer.xml b/ui/src/main/res/layout/dialog_profileviewer.xml index 04bf9a8bb5c..bcac0393097 100644 --- a/ui/src/main/res/layout/dialog_profileviewer.xml +++ b/ui/src/main/res/layout/dialog_profileviewer.xml @@ -164,6 +164,84 @@ android:layout_marginBottom="5dp" android:background="?android:attr/dividerHorizontal" /> + + + + + + + + + + + + + + + + + + + + + + From d2cdf53cc96b363badb33109e9345fc707cbaf92 Mon Sep 17 00:00:00 2001 From: Philoul Date: Sun, 23 Feb 2025 20:11:05 +0100 Subject: [PATCH 09/41] Remove LocalInsulin --- .../aaps/core/interfaces/profile/Profile.kt | 2 ++ .../core/objects/profile/ProfileSealed.kt | 5 +++- .../aaps/plugins/aps/autotune/AutotuneCore.kt | 4 ++-- .../plugins/aps/autotune/AutotuneFragment.kt | 24 ++++++++++--------- .../aaps/plugins/aps/autotune/AutotuneIob.kt | 19 ++++++++------- .../plugins/aps/autotune/AutotunePlugin.kt | 17 +++++++------ .../aaps/plugins/aps/autotune/AutotunePrep.kt | 14 +++++------ .../plugins/aps/autotune/data/ATProfile.kt | 8 ++++--- .../plugins/aps/autotune/AutotunePrepTest.kt | 23 ++++++++++-------- .../plugins/insulin/InsulinOrefBasePlugin.kt | 2 +- .../plugins/main/profile/ProfilePlugin.kt | 2 ++ 11 files changed, 68 insertions(+), 52 deletions(-) diff --git a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/Profile.kt b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/Profile.kt index 1c7ce687218..639ab5f5394 100644 --- a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/Profile.kt +++ b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/Profile.kt @@ -1,6 +1,7 @@ package app.aaps.core.interfaces.profile import app.aaps.core.data.model.GlucoseUnit +import app.aaps.core.data.model.ICfg import app.aaps.core.interfaces.configuration.Config import app.aaps.core.interfaces.nsclient.ProcessedDeviceStatusData import app.aaps.core.interfaces.pump.Pump @@ -32,6 +33,7 @@ interface Profile { //@Deprecated("Replace in favor of accessing InsulinProfile") val dia: Double + val insulin: ICfg val percentage: Int diff --git a/core/objects/src/main/kotlin/app/aaps/core/objects/profile/ProfileSealed.kt b/core/objects/src/main/kotlin/app/aaps/core/objects/profile/ProfileSealed.kt index 6a0f00e7e4b..42cdc2329da 100644 --- a/core/objects/src/main/kotlin/app/aaps/core/objects/profile/ProfileSealed.kt +++ b/core/objects/src/main/kotlin/app/aaps/core/objects/profile/ProfileSealed.kt @@ -116,7 +116,7 @@ sealed class ProfileSealed( null, 0, 100, - ICfg("", (value.dia * 3600 * 1000).toLong(), 0), + value.iCfg, value.timeZone.rawOffset.toLong(), activePlugin?.activeAPS ) @@ -237,6 +237,9 @@ sealed class ProfileSealed( override val dia: Double get() = iCfg.insulinEndTime / 1000.0 / 60.0 / 60.0 + override val insulin: ICfg + get() = iCfg + override val timeshift: Int get() = ts diff --git a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneCore.kt b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneCore.kt index e4952d7b549..3444377059e 100644 --- a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneCore.kt +++ b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneCore.kt @@ -488,8 +488,8 @@ class AutotuneCore @Inject constructor( previousAutotune.basalUnTuned = basalUnTuned previousAutotune.profile.iCfg.setDia(newDia) previousAutotune.profile.iCfg.setPeak(newPeak) - val localInsulin = LocalInsulin("Ins_$newPeak-$newDia", newPeak, newDia) - previousAutotune.localInsulin = localInsulin + //val localInsulin = LocalInsulin("Ins_$newPeak-$newDia", newPeak, newDia) + //previousAutotune.localInsulin = localInsulin previousAutotune.updateProfile() return previousAutotune } diff --git a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneFragment.kt b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneFragment.kt index 41cb6f42d3f..8602681b6c8 100644 --- a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneFragment.kt +++ b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneFragment.kt @@ -23,6 +23,7 @@ import app.aaps.core.data.ue.Action import app.aaps.core.data.ue.Sources import app.aaps.core.data.ue.ValueWithUnit import app.aaps.core.interfaces.aps.Loop +import app.aaps.core.interfaces.logging.AAPSLogger import app.aaps.core.interfaces.logging.UserEntryLogger import app.aaps.core.interfaces.objects.Instantiator import app.aaps.core.interfaces.plugin.ActivePlugin @@ -42,6 +43,7 @@ import app.aaps.core.interfaces.utils.fabric.FabricPrivacy import app.aaps.core.keys.BooleanKey import app.aaps.core.keys.IntKey import app.aaps.core.keys.Preferences +import app.aaps.core.objects.extensions.toJson import app.aaps.core.objects.profile.ProfileSealed import app.aaps.core.ui.dialogs.OKDialog import app.aaps.core.ui.elements.WeekDay @@ -49,7 +51,6 @@ import app.aaps.core.ui.extensions.runOnUiThread import app.aaps.core.ui.extensions.toVisibility import app.aaps.plugins.aps.R import app.aaps.plugins.aps.autotune.data.ATProfile -import app.aaps.plugins.aps.autotune.data.LocalInsulin import app.aaps.plugins.aps.autotune.events.EventAutotuneUpdateGui import app.aaps.plugins.aps.databinding.AutotuneFragmentBinding import dagger.android.HasAndroidInjector @@ -110,7 +111,7 @@ class AutotuneFragment : DaggerFragment() { profileStore = activePlugin.activeProfileSource.profile ?: instantiator.provideProfileStore(JSONObject()) profileName = if (binding.profileList.text.toString() == rh.gs(app.aaps.core.ui.R.string.active)) "" else binding.profileList.text.toString() profileFunction.getProfile()?.let { currentProfile -> - profile = ATProfile(profileStore.getSpecificProfile(profileName)?.let { ProfileSealed.Pure(value = it, activePlugin = null) } ?: currentProfile, LocalInsulin(""), injector) + profile = ATProfile(profileStore.getSpecificProfile(profileName)?.let { ProfileSealed.Pure(value = it, activePlugin = null) } ?: currentProfile, injector) } days.addToLayout(binding.selectWeekDays) days.view?.setOnWeekdaysChangeListener { i: Int, selected: Boolean -> @@ -144,8 +145,9 @@ class AutotuneFragment : DaggerFragment() { if (!autotunePlugin.calculationRunning) { profileName = if (binding.profileList.text.toString() == rh.gs(app.aaps.core.ui.R.string.active)) "" else binding.profileList.text.toString() profileFunction.getProfile()?.let { currentProfile -> - profile = ATProfile(profileStore.getSpecificProfile(profileName)?.let { ProfileSealed.Pure(value = it, activePlugin = null) } ?: currentProfile, LocalInsulin(""), injector) + profile = ATProfile(profileStore.getSpecificProfile(profileName)?.let { ProfileSealed.Pure(value = it, activePlugin = null) } ?: currentProfile, injector) } + log("XXXXX peak: ${profile?.iCfg?.getPeak()} dia: ${profile?.iCfg?.getDia()}") autotunePlugin.selectedProfile = profileName resetParam(true) binding.tuneDays.value = autotunePlugin.lastNbDays.toDouble() @@ -217,11 +219,11 @@ class AutotuneFragment : DaggerFragment() { binding.autotuneCheckInputProfile.setOnClickListener { val pumpProfile = profileFunction.getProfile()?.let { currentProfile -> profileStore.getSpecificProfile(profileName)?.let { specificProfile -> - ATProfile(ProfileSealed.Pure(specificProfile, null), LocalInsulin("", specificProfile.iCfg.getPeak(), specificProfile.iCfg.getDia()), injector).also { + ATProfile(ProfileSealed.Pure(specificProfile, null), injector).also { it.profileName = profileName } } - ?: ATProfile(currentProfile, LocalInsulin(""), injector).also { + ?: ATProfile(currentProfile, injector).also { it.profileName = profileFunction.getProfileName() } } @@ -325,7 +327,7 @@ class AutotuneFragment : DaggerFragment() { profileStore = activePlugin.activeProfileSource.profile ?: instantiator.provideProfileStore(JSONObject()) profileName = if (binding.profileList.text.toString() == rh.gs(app.aaps.core.ui.R.string.active)) "" else binding.profileList.text.toString() profileFunction.getProfile()?.let { currentProfile -> - profile = ATProfile(profileStore.getSpecificProfile(profileName)?.let { ProfileSealed.Pure(value = it, activePlugin = null) } ?: currentProfile, LocalInsulin(""), injector) + profile = ATProfile(profileStore.getSpecificProfile(profileName)?.let { ProfileSealed.Pure(value = it, activePlugin = null) } ?: currentProfile, injector) } val profileList: ArrayList = profileStore.getProfileList() profileList.add(0, rh.gs(app.aaps.core.ui.R.string.active)) @@ -389,7 +391,7 @@ class AutotuneFragment : DaggerFragment() { } profileFunction.getProfile()?.let { currentProfile -> profile = - ATProfile(profileStore.getSpecificProfile(profileName)?.let { ProfileSealed.Pure(value = it, activePlugin = null) } ?: currentProfile, LocalInsulin(""), injector).also { profile -> + ATProfile(profileStore.getSpecificProfile(profileName)?.let { ProfileSealed.Pure(value = it, activePlugin = null) } ?: currentProfile, injector).also { profile -> if (!profile.isValid) return rh.gs(R.string.autotune_profile_invalid) if (profile.icSize > 1) { warning += nl + rh.gs(R.string.autotune_ic_warning, profile.icSize, profile.ic) @@ -464,8 +466,8 @@ class AutotuneFragment : DaggerFragment() { toTableRowValue( context, rh.gs(R.string.insulin_peak), - autotunePlugin.pumpProfile.localInsulin.peak.toDouble(), - tuned.localInsulin.peak.toDouble(), + autotunePlugin.pumpProfile.peak.toDouble(), + tuned.peak.toDouble(), "%.0f" ) ) @@ -473,8 +475,8 @@ class AutotuneFragment : DaggerFragment() { toTableRowValue( context, rh.gs(app.aaps.core.ui.R.string.dia), - Round.roundTo(autotunePlugin.pumpProfile.localInsulin.dia, 0.1), - Round.roundTo(tuned.localInsulin.dia, 0.1), + Round.roundTo(autotunePlugin.pumpProfile.dia, 0.1), + Round.roundTo(tuned.dia, 0.1), "%.1f" ) ) diff --git a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneIob.kt b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneIob.kt index 06dee1e62a1..bd274b5e4c7 100644 --- a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneIob.kt +++ b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneIob.kt @@ -6,6 +6,7 @@ import app.aaps.core.data.model.BS import app.aaps.core.data.model.CA import app.aaps.core.data.model.EB import app.aaps.core.data.model.GV +import app.aaps.core.data.model.ICfg import app.aaps.core.data.model.IDs import app.aaps.core.data.model.TB import app.aaps.core.data.model.TE @@ -14,6 +15,7 @@ import app.aaps.core.interfaces.aps.IobTotal import app.aaps.core.interfaces.db.PersistenceLayer import app.aaps.core.interfaces.logging.AAPSLogger import app.aaps.core.interfaces.logging.LTag +import app.aaps.core.interfaces.plugin.ActivePlugin import app.aaps.core.interfaces.profile.Profile import app.aaps.core.interfaces.profile.ProfileFunction import app.aaps.core.interfaces.utils.DateUtil @@ -41,7 +43,8 @@ open class AutotuneIob @Inject constructor( private val profileFunction: ProfileFunction, private val preferences: Preferences, private val dateUtil: DateUtil, - private val autotuneFS: AutotuneFS + private val autotuneFS: AutotuneFS, + private val activePlugin: ActivePlugin ) { private var nsTreatments = ArrayList() @@ -245,23 +248,23 @@ open class AutotuneIob @Inject constructor( } } - open fun getIOB(time: Long, localInsulin: LocalInsulin): IobTotal = - getCalculationToTimeTreatments(time, localInsulin).round() + open fun getIOB(time: Long, iCfg: ICfg): IobTotal = + getCalculationToTimeTreatments(time, iCfg).round() // Add specific calculation for Autotune (reference localInsulin for Peak/dia) - private fun BS.iobCalc(time: Long, localInsulin: LocalInsulin): Iob { + private fun BS.iobCalc(time: Long, iCfg: ICfg): Iob { if (!isValid || type == BS.Type.PRIMING) return Iob() - return localInsulin.iobCalcForTreatment(this, time) + return activePlugin.activeInsulin.iobCalcForTreatment(this, time, iCfg) } - private fun getCalculationToTimeTreatments(time: Long, localInsulin: LocalInsulin): IobTotal { + private fun getCalculationToTimeTreatments(time: Long, iCfg: ICfg): IobTotal { val total = IobTotal(time) val detailedLog = preferences.get(BooleanKey.AutotuneAdditionalLog) for (pos in boluses.indices) { val t = boluses[pos] if (!t.isValid) continue - if (t.timestamp > time || t.timestamp < time - localInsulin.duration) continue - val tIOB = t.iobCalc(time, localInsulin) + if (t.timestamp > time || t.timestamp < time - iCfg.insulinEndTime) continue + val tIOB = t.iobCalc(time, iCfg) if (detailedLog) log( "iobCalc;${t.ids.nightscoutId};$time;${t.timestamp};${tIOB.iobContrib};${tIOB.activityContrib};${dateUtil.dateAndTimeAndSecondsString(time)};${ diff --git a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotunePlugin.kt b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotunePlugin.kt index a7e2121dc66..22083a890f7 100644 --- a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotunePlugin.kt +++ b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotunePlugin.kt @@ -145,9 +145,8 @@ class AutotunePlugin @Inject constructor( } selectedProfile = profileToTune.ifEmpty { profileFunction.getProfileName() } profileFunction.getProfile()?.let { currentProfile -> - profile = profileStore.getSpecificProfile(profileToTune)?.let { ProfileSealed.Pure(value = it, activePlugin = null) } ?: currentProfile + profile = profileStore.getSpecificProfile(profileToTune)?.let { ProfileSealed.Pure(value = it, activePlugin = activePlugin) } ?: currentProfile } - val localInsulin = LocalInsulin("PumpInsulin", activePlugin.activeInsulin.peak, profile.dia) // var because localInsulin could be updated later with Tune Insulin peak/dia log("Start Autotune with $daysBack days back") autotuneFS.createAutotuneFolder() //create autotune subfolder for autotune files if not exists @@ -157,10 +156,10 @@ class AutotunePlugin @Inject constructor( if (endTime > lastRun) endTime -= 24 * 60 * 60 * 1000L // Check if 4 AM is before now val startTime = endTime - daysBack * 24 * 60 * 60 * 1000L autotuneFS.exportSettings(settings(lastRun, daysBack, startTime, endTime)) - tunedProfile = ATProfile(profile, localInsulin, injector).also { + tunedProfile = ATProfile(profile, injector).also { it.profileName = rh.gs(R.string.autotune_tunedprofile_name) } - pumpProfile = ATProfile(profile, localInsulin, injector).also { + pumpProfile = ATProfile(profile, injector).also { it.profileName = selectedProfile } autotuneFS.exportPumpProfile(pumpProfile) @@ -286,9 +285,9 @@ class AutotunePlugin @Inject constructor( strResult += rh.gs(R.string.autotune_log_title) strResult += line val tuneInsulin = preferences.get(BooleanKey.AutotuneTuneInsulinCurve) - if (tuneInsulin) { - strResult += rh.gs(R.string.autotune_log_peak, rh.gs(R.string.insulin_peak), pumpProfile.localInsulin.peak, tunedProfile.localInsulin.peak) - strResult += rh.gs(R.string.autotune_log_dia, rh.gs(app.aaps.core.ui.R.string.ic_short), pumpProfile.localInsulin.dia, tunedProfile.localInsulin.dia) + if (tuneInsulin || true) { + strResult += rh.gs(R.string.autotune_log_peak, rh.gs(R.string.insulin_peak), pumpProfile.peak, tunedProfile.peak) + strResult += rh.gs(R.string.autotune_log_dia, rh.gs(app.aaps.core.ui.R.string.ic_short), pumpProfile.dia, tunedProfile.dia) } // show ISF and CR strResult += rh.gs(R.string.autotune_log_ic_isf, rh.gs(app.aaps.core.ui.R.string.isf_short), pumpProfile.isf, tunedProfile.isf) @@ -425,7 +424,7 @@ class AutotunePlugin @Inject constructor( selectedProfile = JsonHelper.safeGetString(json, "pumpProfileName", "") val profile = JsonHelper.safeGetJSONObject(json, "pumpProfile", null)?.let { pureProfileFromJson(it, dateUtil) } ?: return - pumpProfile = ATProfile(ProfileSealed.Pure(value = profile, activePlugin = null), localInsulin, injector).also { it.profileName = selectedProfile } + pumpProfile = ATProfile(ProfileSealed.Pure(value = profile, activePlugin = null), injector).also { it.profileName = selectedProfile } val tunedPeak = JsonHelper.safeGetInt(json, "tunedPeak") val tunedDia = JsonHelper.safeGetDouble(json, "tunedDia") localInsulin = LocalInsulin("PumpInsulin", tunedPeak, tunedDia) @@ -434,7 +433,7 @@ class AutotunePlugin @Inject constructor( ?: return val circadianTuned = JsonHelper.safeGetJSONObject(json, "tunedCircadianProfile", null)?.let { pureProfileFromJson(it, dateUtil) } ?: return - tunedProfile = ATProfile(ProfileSealed.Pure(value = tuned, activePlugin = null), localInsulin, injector).also { atProfile -> + tunedProfile = ATProfile(ProfileSealed.Pure(value = tuned, activePlugin = null), injector).also { atProfile -> atProfile.profileName = tunedProfileName atProfile.circadianProfile = ProfileSealed.Pure(value = circadianTuned, activePlugin = null) for (i in 0..23) { diff --git a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotunePrep.kt b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotunePrep.kt index b5269250694..b710bc7e507 100644 --- a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotunePrep.kt +++ b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotunePrep.kt @@ -33,14 +33,14 @@ class AutotunePrep @Inject constructor( ) { fun categorize(tunedProfile: ATProfile): PreppedGlucose? { - val preppedGlucose = categorizeBGDatums(tunedProfile, tunedProfile.localInsulin) + val preppedGlucose = categorizeBGDatums(tunedProfile) val tuneInsulin = preferences.get(BooleanKey.AutotuneTuneInsulinCurve) if (tuneInsulin) { var minDeviations = 1000000.0 val diaDeviations: MutableList = ArrayList() val peakDeviations: MutableList = ArrayList() - val currentDIA = tunedProfile.localInsulin.dia - val currentPeak = tunedProfile.localInsulin.peak + val currentDIA = tunedProfile.dia + val currentPeak = tunedProfile.peak var dia = currentDIA - 2 val endDIA = currentDIA + 2 @@ -49,7 +49,7 @@ class AutotunePrep @Inject constructor( var deviations = 0.0 var deviationsSq = 0.0 val localInsulin = LocalInsulin("Ins_$currentPeak-$dia", currentPeak, dia) - val curveOutput = categorizeBGDatums(tunedProfile, localInsulin, false) + val curveOutput = categorizeBGDatums(tunedProfile, false) val basalGlucose = curveOutput?.basalGlucoseData basalGlucose?.let { @@ -96,7 +96,7 @@ class AutotunePrep @Inject constructor( var deviations = 0.0 var deviationsSq = 0.0 val localInsulin = LocalInsulin("Ins_$peak-$currentDIA", peak, currentDIA) - val curveOutput = categorizeBGDatums(tunedProfile, localInsulin, false) + val curveOutput = categorizeBGDatums(tunedProfile, false) val basalGlucose = curveOutput?.basalGlucoseData basalGlucose?.let { @@ -141,7 +141,7 @@ class AutotunePrep @Inject constructor( } // private static Logger log = LoggerFactory.getLogger(AutotunePlugin.class); - fun categorizeBGDatums(tunedProfile: ATProfile, localInsulin: LocalInsulin, verbose: Boolean = true): PreppedGlucose? { + fun categorizeBGDatums(tunedProfile: ATProfile, verbose: Boolean = true): PreppedGlucose? { //lib/meals is called before to get only meals data (in AAPS it's done in AutotuneIob) val treatments: MutableList = autotuneIob.meals val boluses: MutableList = autotuneIob.boluses @@ -294,7 +294,7 @@ class AutotunePrep @Inject constructor( //var iob = getIOB(IOBInputs)[0]; // in autotune iob is calculated with 6 hours of history data, tunedProfile and average pumpProfile basal rate... //log("currentBasal: " + currentBasal + " BGTime: " + BGTime + " / " + dateUtil!!.timeStringWithSeconds(BGTime) + "******************************************************************************************") - val iob = autotuneIob.getIOB(bgTime, localInsulin) // add localInsulin to be independent to InsulinPlugin + val iob = autotuneIob.getIOB(bgTime, tunedProfile.iCfg) // add localInsulin to be independent to InsulinPlugin // activity times ISF times 5 minutes is BGI val bgi = Round.roundTo(-iob.activity * sens * 5, 0.01) diff --git a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/data/ATProfile.kt b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/data/ATProfile.kt index 8ca33a261fb..1020e31bc74 100644 --- a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/data/ATProfile.kt +++ b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/data/ATProfile.kt @@ -37,7 +37,7 @@ import java.util.TimeZone import javax.inject.Inject import kotlin.math.min -class ATProfile(profile: Profile, var localInsulin: LocalInsulin, val injector: HasAndroidInjector) { +class ATProfile(profile: Profile, val injector: HasAndroidInjector) { @Inject lateinit var activePlugin: ActivePlugin @Inject lateinit var sp: SP @@ -58,6 +58,8 @@ class ATProfile(profile: Profile, var localInsulin: LocalInsulin, val injector: var basalUnTuned = IntArray(24) var ic = 0.0 var isf = 0.0 + val iCfg: ICfg + get() = profile.iCfg val dia: Double get() = profile.iCfg.getDia() val peak: Int @@ -100,8 +102,8 @@ class ATProfile(profile: Profile, var localInsulin: LocalInsulin, val injector: } fun updateProfile() { - data()?.let { profile = ProfileSealed.Pure(value = it, activePlugin = null) } - data(true)?.let { circadianProfile = ProfileSealed.Pure(value = it, activePlugin = null) } + data()?.let { profile = ProfileSealed.Pure(value = it, activePlugin) } + data(true)?.let { circadianProfile = ProfileSealed.Pure(value = it, activePlugin) } } //Export json string with oref0 format used for autotune diff --git a/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/autotune/AutotunePrepTest.kt b/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/autotune/AutotunePrepTest.kt index 894d9a59acb..8b18d5d0ccc 100644 --- a/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/autotune/AutotunePrepTest.kt +++ b/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/autotune/AutotunePrepTest.kt @@ -13,6 +13,7 @@ import app.aaps.core.data.time.T import app.aaps.core.interfaces.aps.IobTotal import app.aaps.core.interfaces.db.PersistenceLayer import app.aaps.core.interfaces.logging.AAPSLogger +import app.aaps.core.interfaces.plugin.ActivePlugin import app.aaps.core.interfaces.profile.ProfileFunction import app.aaps.core.interfaces.profile.PureProfile import app.aaps.core.interfaces.utils.DateUtil @@ -57,7 +58,7 @@ class AutotunePrepTest : TestBaseWithProfile() { fun autotunePrepTest1() { // Test if categorisation with standard treatments with carbs is Ok val inputIobJson = File("src/test/res/autotune/test1/oaps-iobCalc.2022-05-21.json").readText() //json files build with iob/activity calculated by OAPS val iobOapsCalculation = buildIobOaps(JSONArray(inputIobJson)) - autotuneIob = TestAutotuneIob(aapsLogger, persistenceLayer, profileFunction, preferences, dateUtil, autotuneFS, iobOapsCalculation) + autotuneIob = TestAutotuneIob(aapsLogger, persistenceLayer, profileFunction, preferences, dateUtil, autotuneFS, iobOapsCalculation, activePlugin) autotunePrep = AutotunePrep(preferences, dateUtil, autotuneFS, autotuneIob) val inputProfileJson = File("src/test/res/autotune/test1/profile.pump.json").readText() val inputProfile = atProfileFromOapsJson(JSONObject(inputProfileJson), dateUtil)!! @@ -70,7 +71,7 @@ class AutotunePrepTest : TestBaseWithProfile() { autotuneIob.boluses = buildBoluses(oapsPreppedGlucose) //Values from oapsPrepData because linked to iob calculation method for TBR `when`(preferences.get(DoubleKey.ApsSmbMin5MinCarbsImpact)).thenReturn(min5mCarbImpact) `when`(preferences.get(BooleanKey.AutotuneCategorizeUamAsBasal)).thenReturn(false) - val aapsPreppedGlucose = autotunePrep.categorizeBGDatums(inputProfile, inputProfile.localInsulin, false)!! + val aapsPreppedGlucose = autotunePrep.categorizeBGDatums(inputProfile, false)!! // compare all categorization calculated by aaps plugin (aapsPreppedGlucose) with categorization calculated by OpenAPS (oapsPreppedGlucose) for (i in aapsPreppedGlucose.crData.indices) assertThat(oapsPreppedGlucose.crData[i].equals(aapsPreppedGlucose.crData[i])).isTrue() @@ -90,7 +91,7 @@ class AutotunePrepTest : TestBaseWithProfile() { fun autotunePrepTest2() { // Test if categorisation without carbs (full UAM) and categorize UAM as basal false is Ok val inputIobJson = File("src/test/res/autotune/test2/oaps-iobCalc.2022-05-21.json").readText() //json files build with iob/activity calculated by OAPS val iobOapsCalculation = buildIobOaps(JSONArray(inputIobJson)) - autotuneIob = TestAutotuneIob(aapsLogger, persistenceLayer, profileFunction, preferences, dateUtil, autotuneFS, iobOapsCalculation) + autotuneIob = TestAutotuneIob(aapsLogger, persistenceLayer, profileFunction, preferences, dateUtil, autotuneFS, iobOapsCalculation, activePlugin) autotunePrep = AutotunePrep(preferences, dateUtil, autotuneFS, autotuneIob) val inputProfileJson = File("src/test/res/autotune/test2/profile.pump.json").readText() val inputProfile = atProfileFromOapsJson(JSONObject(inputProfileJson), dateUtil)!! @@ -103,7 +104,7 @@ class AutotunePrepTest : TestBaseWithProfile() { autotuneIob.boluses = buildBoluses(oapsPreppedGlucose) //Values from oapsPrepData because linked to iob calculation method for TBR `when`(preferences.get(DoubleKey.ApsSmbMin5MinCarbsImpact)).thenReturn(min5mCarbImpact) `when`(preferences.get(BooleanKey.AutotuneCategorizeUamAsBasal)).thenReturn(false) // CategorizeUAM as Basal = False - val aapsPreppedGlucose = autotunePrep.categorizeBGDatums(inputProfile, inputProfile.localInsulin, false)!! + val aapsPreppedGlucose = autotunePrep.categorizeBGDatums(inputProfile, false)!! // compare all categorization calculated by aaps plugin (aapsPreppedGlucose) with categorization calculated by OpenAPS (oapsPreppedGlucose) for (i in aapsPreppedGlucose.crData.indices) assertThat(oapsPreppedGlucose.crData[i].equals(aapsPreppedGlucose.crData[i])).isTrue() @@ -123,7 +124,7 @@ class AutotunePrepTest : TestBaseWithProfile() { fun autotunePrepTest3() { // Test if categorisation without carbs (full UAM) and categorize UAM as basal true is Ok val inputIobJson = File("src/test/res/autotune/test3/oaps-iobCalc.2022-05-21.json").readText() //json files build with iob/activity calculated by OAPS val iobOapsCalculation = buildIobOaps(JSONArray(inputIobJson)) - autotuneIob = TestAutotuneIob(aapsLogger, persistenceLayer, profileFunction, preferences, dateUtil, autotuneFS, iobOapsCalculation) + autotuneIob = TestAutotuneIob(aapsLogger, persistenceLayer, profileFunction, preferences, dateUtil, autotuneFS, iobOapsCalculation, activePlugin) autotunePrep = AutotunePrep(preferences, dateUtil, autotuneFS, autotuneIob) val inputProfileJson = File("src/test/res/autotune/test3/profile.pump.json").readText() val inputProfile = atProfileFromOapsJson(JSONObject(inputProfileJson), dateUtil)!! @@ -136,7 +137,7 @@ class AutotunePrepTest : TestBaseWithProfile() { autotuneIob.boluses = buildBoluses(oapsPreppedGlucose) //Values from oapsPrepData because linked to iob calculation method for TBR `when`(preferences.get(DoubleKey.ApsSmbMin5MinCarbsImpact)).thenReturn(min5mCarbImpact) `when`(preferences.get(BooleanKey.AutotuneCategorizeUamAsBasal)).thenReturn(true) // CategorizeUAM as Basal = True - val aapsPreppedGlucose = autotunePrep.categorizeBGDatums(inputProfile, inputProfile.localInsulin, false)!! + val aapsPreppedGlucose = autotunePrep.categorizeBGDatums(inputProfile, false)!! // compare all categorization calculated by aaps plugin (aapsPreppedGlucose) with categorization calculated by OpenAPS (oapsPreppedGlucose) for (i in aapsPreppedGlucose.crData.indices) assertThat(oapsPreppedGlucose.crData[i].equals(aapsPreppedGlucose.crData[i])).isTrue() @@ -195,7 +196,7 @@ class AutotunePrepTest : TestBaseWithProfile() { iCfg = iCfg, dia = dia ) - return ATProfile(ProfileSealed.Pure(pure, activePlugin), localInsulin, injector).also { it.dateUtil = dateUtil } + return ATProfile(ProfileSealed.Pure(pure, activePlugin), injector).also { it.dateUtil = dateUtil } } catch (ignored: Exception) { return null } @@ -295,17 +296,19 @@ class AutotunePrepTest : TestBaseWithProfile() { preferences: Preferences, dateUtil: DateUtil, autotuneFS: AutotuneFS, - private val iobOapsCalculation: ArrayList + private val iobOapsCalculation: ArrayList, + activePlugin: ActivePlugin ) : AutotuneIob( aapsLogger, persistenceLayer, profileFunction, preferences, dateUtil, - autotuneFS + autotuneFS, + activePlugin ) { - override fun getIOB(time: Long, localInsulin: LocalInsulin): IobTotal { + override fun getIOB(time: Long, iCfg: ICfg): IobTotal { val bolusIob = IobTotal(time) iobOapsCalculation.forEach { if (it.time == time) diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt index 02676556831..8e78598223b 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt @@ -103,7 +103,7 @@ abstract class InsulinOrefBasePlugin( } override val iCfg: ICfg - get() = ICfg(friendlyName, (dia * 1000.0 * 3600.0).toLong(), T.mins(peak.toLong()).msecs()) + get() = ICfg(friendlyName, peak, dia) override val comment get(): String { diff --git a/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfilePlugin.kt b/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfilePlugin.kt index 2b29d3bca28..bf22012f9a9 100644 --- a/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfilePlugin.kt +++ b/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfilePlugin.kt @@ -177,6 +177,8 @@ class ProfilePlugin @Inject constructor( override fun storeSettings(activity: FragmentActivity?, timestamp: Long) { for (i in 0 until numOfProfiles) { profiles[i].run { + //if (iCfg.getPeak()==0) + // iCfg.setPeak(activePlugin.activeInsulin.peak) val localProfileNumbered = Constants.LOCAL_PROFILE + "_" + i + "_" sp.putString(localProfileNumbered + "name", name) sp.putBoolean(localProfileNumbered + "mgdl", mgdl) From 4b0da8604121044ab3114d4790f9210ffb8f0dc4 Mon Sep 17 00:00:00 2001 From: Philoul Date: Sun, 23 Feb 2025 20:50:02 +0100 Subject: [PATCH 10/41] Fix ICfg update --- app/src/main/kotlin/app/aaps/MainApp.kt | 69 +++++++++++++++++++ .../aaps/core/interfaces/insulin/Insulin.kt | 3 + .../core/interfaces/profile/ProfileSource.kt | 2 + .../objects/extensions/InsulinExtension.kt | 6 +- .../plugins/aps/autotune/AutotuneFragment.kt | 2 +- .../plugins/insulin/InsulinOrefBasePlugin.kt | 3 +- .../plugins/main/profile/ProfileFragment.kt | 11 ++- .../plugins/main/profile/ProfilePlugin.kt | 5 +- 8 files changed, 91 insertions(+), 10 deletions(-) diff --git a/app/src/main/kotlin/app/aaps/MainApp.kt b/app/src/main/kotlin/app/aaps/MainApp.kt index e73def11a03..0b111a66061 100644 --- a/app/src/main/kotlin/app/aaps/MainApp.kt +++ b/app/src/main/kotlin/app/aaps/MainApp.kt @@ -9,7 +9,9 @@ import android.os.Build import android.os.Handler import android.os.HandlerThread import androidx.lifecycle.ProcessLifecycleOwner +import app.aaps.core.data.configuration.Constants import app.aaps.core.data.model.GlucoseUnit +import app.aaps.core.data.model.ICfg import app.aaps.core.data.model.TE import app.aaps.core.data.ue.Action import app.aaps.core.data.ue.Sources @@ -17,9 +19,12 @@ import app.aaps.core.interfaces.alerts.LocalAlertUtils import app.aaps.core.interfaces.configuration.Config import app.aaps.core.interfaces.configuration.ConfigBuilder import app.aaps.core.interfaces.db.PersistenceLayer +import app.aaps.core.interfaces.insulin.Insulin import app.aaps.core.interfaces.logging.AAPSLogger import app.aaps.core.interfaces.logging.LTag +import app.aaps.core.interfaces.plugin.ActivePlugin import app.aaps.core.interfaces.plugin.PluginBase +import app.aaps.core.interfaces.profile.ProfileSource import app.aaps.core.interfaces.resources.ResourceHelper import app.aaps.core.interfaces.sharedPreferences.SP import app.aaps.core.interfaces.ui.UiInteraction @@ -30,6 +35,8 @@ import app.aaps.core.keys.IntKey import app.aaps.core.keys.Preferences import app.aaps.core.keys.StringKey import app.aaps.core.keys.UnitDoubleKey +import app.aaps.core.objects.extensions.fromJson +import app.aaps.core.objects.extensions.toJson import app.aaps.core.ui.extensions.runOnUiThread import app.aaps.core.ui.locale.LocaleHelper import app.aaps.database.persistence.CompatDBHelper @@ -59,6 +66,9 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.launch +import org.json.JSONArray +import org.json.JSONException +import org.json.JSONObject import rxdogtag2.RxDogTag import java.io.IOException import javax.inject.Inject @@ -85,6 +95,7 @@ class MainApp : DaggerApplication() { @Inject lateinit var processLifecycleListener: Provider @Inject lateinit var themeSwitcherPlugin: ThemeSwitcherPlugin @Inject lateinit var localAlertUtils: LocalAlertUtils + @Inject lateinit var activePlugin: ActivePlugin @Inject lateinit var rh: Provider private var handler = Handler(HandlerThread(this::class.simpleName + "Handler").also { it.start() }.looper) @@ -186,6 +197,25 @@ class MainApp : DaggerApplication() { private fun doMigrations() { // set values for different builds + + // replace dia by ICfg within profile + if (sp.getBoolean("ConfigBuilder_INSULIN_InsulinOrefRapidActingPlugin_Enabled", false) || + sp.getBoolean("ConfigBuilder_INSULIN_InsulinOrefUltraRapidActingPlugin_Enabled", false) || + sp.getBoolean("ConfigBuilder_INSULIN_InsulinLyumjevPlugin_Enabled", false) || + sp.getBoolean("ConfigBuilder_INSULIN_InsulinOrefFreePeakPlugin_Enabled", false)) { + aapsLogger.debug("XXXXX Start Migration") + val defaultInsulin = when { + sp.getBoolean("ConfigBuilder_INSULIN_InsulinOrefUltraRapidActingPlugin_Enabled", false) -> Insulin.InsulinType.OREF_ULTRA_RAPID_ACTING.getICfg() + sp.getBoolean("ConfigBuilder_INSULIN_InsulinLyumjevPlugin_Enabled", false) -> Insulin.InsulinType.OREF_LYUMJEV.getICfg() + sp.getBoolean("ConfigBuilder_INSULIN_InsulinOrefFreePeakPlugin_Enabled", false) -> Insulin.InsulinType.OREF_FREE_PEAK.getICfg().also { + it.setPeak(preferences.get(IntKey.InsulinOrefPeak)) + } + else -> Insulin.InsulinType.OREF_RAPID_ACTING.getICfg() + } + migrateProfiles(defaultInsulin) + // todo include remove key and put key to activate InsulinPlugin + } + // 3.1.0 if (preferences.getIfExists(StringKey.MaintenanceEmail) == "logs@androidaps.org") preferences.put(StringKey.MaintenanceEmail, "logs@aaps.app") @@ -222,6 +252,45 @@ class MainApp : DaggerApplication() { if (preferences.get(StringKey.SmsOtpPassword).length > 10) preferences.put(StringKey.SmsOtpPassword, "") } + private fun migrateProfiles(defaultInsulin: ICfg) { + val numOfProfiles = sp.getInt(Constants.LOCAL_PROFILE + "_profiles", 0) + val defaultArray = "[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":0}]" +// numOfProfiles = max(numOfProfiles, 1) // create at least one default profile if none exists + + for (i in 0 until numOfProfiles) { + val localProfileNumbered = Constants.LOCAL_PROFILE + "_" + i + "_" + val name = sp.getString(localProfileNumbered + "name", Constants.LOCAL_PROFILE + i) + try { + ProfileSource.SingleProfile( + name = name, + mgdl = sp.getBoolean(localProfileNumbered + "mgdl", false), + iCfg = ICfg.fromJson(JSONObject(sp.getString(localProfileNumbered + "icfg", defaultInsulin.toJson().toString()))), + dia = sp.getDouble(localProfileNumbered + "dia", Constants.defaultDIA), + ic = JSONArray(sp.getString(localProfileNumbered + "ic", defaultArray)), + isf = JSONArray(sp.getString(localProfileNumbered + "isf", defaultArray)), + basal = JSONArray(sp.getString(localProfileNumbered + "basal", defaultArray)), + targetLow = JSONArray(sp.getString(localProfileNumbered + "targetlow", defaultArray)), + targetHigh = JSONArray(sp.getString(localProfileNumbered + "targethigh", defaultArray)) + ).also { + it.iCfg.setDia(it.dia) + sp.putString(localProfileNumbered + "name", it.name) + sp.putBoolean(localProfileNumbered + "mgdl", it.mgdl) + sp.putString(localProfileNumbered + "icfg", it.iCfg.toJson().toString()) + sp.putDouble(localProfileNumbered + "dia", it.dia) + sp.putString(localProfileNumbered + "ic", it.ic.toString()) + sp.putString(localProfileNumbered + "isf", it.isf.toString()) + sp.putString(localProfileNumbered + "basal", it.basal.toString()) + sp.putString(localProfileNumbered + "targetlow", it.targetLow.toString()) + sp.putString(localProfileNumbered + "targethigh", it.targetHigh.toString()) + } + } catch (e: JSONException) { + aapsLogger.error("Exception", e) + } + } + // reload profile settings after update + activePlugin.activeProfileSource.loadSettings() + } + override fun applicationInjector(): AndroidInjector { return DaggerAppComponent .builder() diff --git a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/insulin/Insulin.kt b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/insulin/Insulin.kt index b07be4d194a..b6be548c4a1 100644 --- a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/insulin/Insulin.kt +++ b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/insulin/Insulin.kt @@ -6,6 +6,7 @@ import app.aaps.core.data.model.BS import app.aaps.core.data.model.ICfg import app.aaps.core.interfaces.R import app.aaps.core.interfaces.configuration.ConfigExportImport +import app.aaps.core.interfaces.resources.ResourceHelper interface Insulin : ConfigExportImport { enum class InsulinType(val value: Int, val peak: Int, val dia: Double, @StringRes val label: Int) { @@ -18,6 +19,8 @@ interface Insulin : ConfigExportImport { OREF_FREE_PEAK(4, 50, 6.0, R.string.free_peak_oref), OREF_LYUMJEV(5, 45, 6.0, R.string.lyumjev); + fun getICfg() = ICfg(this.name, peak, dia) + companion object { private val map = entries.associateBy(InsulinType::value) diff --git a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/ProfileSource.kt b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/ProfileSource.kt index c489e8895a5..4e2d75dcfcf 100644 --- a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/ProfileSource.kt +++ b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/ProfileSource.kt @@ -75,4 +75,6 @@ interface ProfileSource { */ fun loadFromStore(store: ProfileStore) + fun loadSettings() + } \ No newline at end of file diff --git a/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/InsulinExtension.kt b/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/InsulinExtension.kt index 749cbce412c..cd4f898b57e 100644 --- a/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/InsulinExtension.kt +++ b/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/InsulinExtension.kt @@ -5,12 +5,12 @@ import app.aaps.core.interfaces.insulin.Insulin import org.json.JSONObject fun ICfg.toJson(): JSONObject = JSONObject() - .put("insulinLabel", insulinLabel) + .put("c", insulinLabel) .put("insulinEndTime", insulinEndTime) .put("insulinPeakTime", insulinPeakTime) fun ICfg.Companion.fromJson(json: JSONObject): ICfg = ICfg( insulinLabel = json.optString("insulinLabel", ""), - insulinEndTime = json.optLong("insulinEndTime", (Insulin.InsulinType.OREF_RAPID_ACTING.dia * 3600 * 1000).toLong()), - insulinPeakTime = json.optLong("insulinPeakTime", Insulin.InsulinType.OREF_RAPID_ACTING.peak * 60000L) + insulinEndTime = json.optLong("insulinEndTime", 0), + insulinPeakTime = json.optLong("insulinPeakTime", 0) ) \ No newline at end of file diff --git a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneFragment.kt b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneFragment.kt index 8602681b6c8..2c2b6ac2d12 100644 --- a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneFragment.kt +++ b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneFragment.kt @@ -147,7 +147,7 @@ class AutotuneFragment : DaggerFragment() { profileFunction.getProfile()?.let { currentProfile -> profile = ATProfile(profileStore.getSpecificProfile(profileName)?.let { ProfileSealed.Pure(value = it, activePlugin = null) } ?: currentProfile, injector) } - log("XXXXX peak: ${profile?.iCfg?.getPeak()} dia: ${profile?.iCfg?.getDia()}") + log("XXXXX AT ${profile?.iCfg?.insulinLabel} peak: ${profile?.iCfg?.getPeak()} dia: ${profile?.iCfg?.getDia()}") autotunePlugin.selectedProfile = profileName resetParam(true) binding.tuneDays.value = autotunePlugin.lastNbDays.toDouble() diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt index 8e78598223b..85c48b7bc9f 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt @@ -55,7 +55,8 @@ abstract class InsulinOrefBasePlugin( hardLimits.minDia() } } - override fun setDefault(iCfg: ICfg?) { } + override fun setDefault(iCfg: ICfg?) { + } open fun sendShortDiaNotification(dia: Double) { if (System.currentTimeMillis() - lastWarned > 60 * 1000) { diff --git a/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfileFragment.kt b/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfileFragment.kt index 04eb896978b..fe732a0c394 100644 --- a/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfileFragment.kt +++ b/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfileFragment.kt @@ -9,6 +9,7 @@ import android.view.ViewGroup import android.widget.AdapterView import android.widget.ArrayAdapter import app.aaps.core.data.model.GlucoseUnit +import app.aaps.core.data.model.ICfg import app.aaps.core.data.ue.Action import app.aaps.core.data.ue.Sources import app.aaps.core.data.ue.ValueWithUnit @@ -76,7 +77,7 @@ class ProfileFragment : DaggerFragment() { binding.icGraph.show(ProfileSealed.Pure(it, null)) binding.isfGraph.show(ProfileSealed.Pure(it, null)) binding.targetGraph.show(ProfileSealed.Pure(it, null)) - binding.insulinGraph.show(activePlugin.activeInsulin, SafeParse.stringToDouble(binding.dia.text)) + binding.insulinGraph.show(activePlugin.activeInsulin, profilePlugin.currentProfile()?.iCfg) } } @@ -84,7 +85,11 @@ class ProfileFragment : DaggerFragment() { override fun afterTextChanged(s: Editable) {} override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {} override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { - profilePlugin.currentProfile()?.dia = SafeParse.stringToDouble(binding.dia.text) + val dia = SafeParse.stringToDouble(binding.dia.text) + val peak = activePlugin.activeInsulin.peak + val name = activePlugin.activeInsulin.friendlyName + profilePlugin.currentProfile()?.dia = dia + profilePlugin.currentProfile()?.iCfg = ICfg(name, peak, dia) profilePlugin.currentProfile()?.name = binding.name.text.toString() doEdit() } @@ -137,7 +142,7 @@ class ProfileFragment : DaggerFragment() { if (profilePlugin.numOfProfiles == 0) profilePlugin.addNewProfile() val currentProfile = profilePlugin.currentProfile() ?: return val units = if (currentProfile.mgdl) GlucoseUnit.MGDL.asText else GlucoseUnit.MMOL.asText - + aapsLogger.debug("XXXXX PR ${currentProfile?.iCfg?.insulinLabel} peak: ${currentProfile.iCfg.getPeak()} dia: ${currentProfile.iCfg.getDia()}") binding.name.removeTextChangedListener(textWatch) binding.name.setText(currentProfile.name) binding.name.addTextChangedListener(textWatch) diff --git a/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfilePlugin.kt b/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfilePlugin.kt index bf22012f9a9..b562f3fe879 100644 --- a/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfilePlugin.kt +++ b/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfilePlugin.kt @@ -76,6 +76,7 @@ class ProfilePlugin @Inject constructor( private var rawProfile: ProfileStore? = null private val defaultArray = "[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":0}]" + private val defaultICfg = "{\"insulinLabel\":\"\",\"insulinEndTime\":0,\"insulinPeakTime\":0}" override fun onStart() { super.onStart() @@ -206,7 +207,7 @@ class ProfilePlugin @Inject constructor( } @Synchronized - fun loadSettings() { + override fun loadSettings() { val numOfProfiles = sp.getInt(Constants.LOCAL_PROFILE + "_profiles", 0) profiles.clear() // numOfProfiles = max(numOfProfiles, 1) // create at least one default profile if none exists @@ -220,7 +221,7 @@ class ProfilePlugin @Inject constructor( ProfileSource.SingleProfile( name = name, mgdl = sp.getBoolean(localProfileNumbered + "mgdl", false), - iCfg = ICfg.fromJson(JSONObject(sp.getString(localProfileNumbered + "icfg", ""))), + iCfg = ICfg.fromJson(JSONObject(sp.getString(localProfileNumbered + "icfg", defaultICfg))), dia = sp.getDouble(localProfileNumbered + "dia", Constants.defaultDIA), ic = JSONArray(sp.getString(localProfileNumbered + "ic", defaultArray)), isf = JSONArray(sp.getString(localProfileNumbered + "isf", defaultArray)), From 4810dcdba2e84d5393f0b8c121eb0cf4ae38a45a Mon Sep 17 00:00:00 2001 From: Philoul Date: Mon, 24 Feb 2025 20:53:23 +0100 Subject: [PATCH 11/41] Fix test --- .../app/aaps/plugins/insulin/InsulinOrefBasePluginTest.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePluginTest.kt b/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePluginTest.kt index 49ec59a748f..842d76b24a3 100644 --- a/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePluginTest.kt +++ b/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePluginTest.kt @@ -2,6 +2,7 @@ package app.aaps.plugins.insulin import app.aaps.core.data.configuration.Constants import app.aaps.core.data.model.BS +import app.aaps.core.data.model.ICfg import app.aaps.core.interfaces.configuration.Config import app.aaps.core.interfaces.insulin.Insulin import app.aaps.core.interfaces.logging.AAPSLogger @@ -48,6 +49,10 @@ class InsulinOrefBasePluginTest { override val peak: Int get() = testPeak + override fun getOrCreateInsulin(iCfg: ICfg): ICfg = ICfg("Test-Insulin", 45, 8.0) + + override fun getInsulin(insulinLabel: String): ICfg = ICfg("Test-Insulin", 45, 8.0) + override fun commentStandardText(): String = "" override val id get(): Insulin.InsulinType = Insulin.InsulinType.UNKNOWN override val friendlyName get(): String = "" From b9535ab16aec588bca12e3e90466d1ef31c1928b Mon Sep 17 00:00:00 2001 From: Philoul Date: Mon, 24 Feb 2025 21:46:57 +0100 Subject: [PATCH 12/41] Code Leaning --- .../main/kotlin/app/aaps/core/interfaces/insulin/Insulin.kt | 1 - .../main/kotlin/app/aaps/core/interfaces/profile/Profile.kt | 4 ++++ .../kotlin/app/aaps/core/interfaces/profile/ProfileSource.kt | 3 +++ .../kotlin/app/aaps/plugins/main/profile/ProfilePlugin.kt | 2 -- ui/src/main/res/layout/dialog_profileviewer.xml | 1 - 5 files changed, 7 insertions(+), 4 deletions(-) diff --git a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/insulin/Insulin.kt b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/insulin/Insulin.kt index b6be548c4a1..43fc93d0fa2 100644 --- a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/insulin/Insulin.kt +++ b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/insulin/Insulin.kt @@ -6,7 +6,6 @@ import app.aaps.core.data.model.BS import app.aaps.core.data.model.ICfg import app.aaps.core.interfaces.R import app.aaps.core.interfaces.configuration.ConfigExportImport -import app.aaps.core.interfaces.resources.ResourceHelper interface Insulin : ConfigExportImport { enum class InsulinType(val value: Int, val peak: Int, val dia: Double, @StringRes val label: Int) { diff --git a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/Profile.kt b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/Profile.kt index 639ab5f5394..77c4994aea5 100644 --- a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/Profile.kt +++ b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/Profile.kt @@ -33,6 +33,10 @@ interface Profile { //@Deprecated("Replace in favor of accessing InsulinProfile") val dia: Double + + /** + * InsulinProfile + */ val insulin: ICfg val percentage: Int diff --git a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/ProfileSource.kt b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/ProfileSource.kt index 4e2d75dcfcf..87066bd5235 100644 --- a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/ProfileSource.kt +++ b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/ProfileSource.kt @@ -75,6 +75,9 @@ interface ProfileSource { */ fun loadFromStore(store: ProfileStore) + /** + * Load [ProfileStore] from SharedPreferences (for ICfg migration) + */ fun loadSettings() } \ No newline at end of file diff --git a/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfilePlugin.kt b/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfilePlugin.kt index b562f3fe879..703108d68f1 100644 --- a/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfilePlugin.kt +++ b/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfilePlugin.kt @@ -178,8 +178,6 @@ class ProfilePlugin @Inject constructor( override fun storeSettings(activity: FragmentActivity?, timestamp: Long) { for (i in 0 until numOfProfiles) { profiles[i].run { - //if (iCfg.getPeak()==0) - // iCfg.setPeak(activePlugin.activeInsulin.peak) val localProfileNumbered = Constants.LOCAL_PROFILE + "_" + i + "_" sp.putString(localProfileNumbered + "name", name) sp.putBoolean(localProfileNumbered + "mgdl", mgdl) diff --git a/ui/src/main/res/layout/dialog_profileviewer.xml b/ui/src/main/res/layout/dialog_profileviewer.xml index bcac0393097..820f20e1426 100644 --- a/ui/src/main/res/layout/dialog_profileviewer.xml +++ b/ui/src/main/res/layout/dialog_profileviewer.xml @@ -164,7 +164,6 @@ android:layout_marginBottom="5dp" android:background="?android:attr/dividerHorizontal" /> - Date: Mon, 24 Feb 2025 22:03:33 +0100 Subject: [PATCH 13/41] Add UEL keys --- core/data/src/main/kotlin/app/aaps/core/data/ue/Action.kt | 4 ++++ .../data/src/main/kotlin/app/aaps/core/data/ue/Sources.kt | 1 + core/ui/src/main/res/values/strings.xml | 6 ++++++ .../main/kotlin/app/aaps/database/entities/UserEntry.kt | 5 +++++ .../database/persistence/converters/ActionExtension.kt | 8 ++++++++ .../database/persistence/converters/SourcesExtension.kt | 2 ++ .../userEntry/UserEntryPresentationHelperImpl.kt | 1 + .../app/aaps/implementation/utils/TranslatorImpl.kt | 5 +++++ 8 files changed, 32 insertions(+) diff --git a/core/data/src/main/kotlin/app/aaps/core/data/ue/Action.kt b/core/data/src/main/kotlin/app/aaps/core/data/ue/Action.kt index 1996554c8cb..909b6e5f18d 100644 --- a/core/data/src/main/kotlin/app/aaps/core/data/ue/Action.kt +++ b/core/data/src/main/kotlin/app/aaps/core/data/ue/Action.kt @@ -12,6 +12,10 @@ enum class Action(val colorGroup: ColorGroup) { EXTENDED_CARBS(ColorGroup.CarbTreatment), TEMP_BASAL(ColorGroup.BasalTreatment), TT(ColorGroup.TT), + NEW_INSULIN(ColorGroup.InsulinTreatment), + CLONE_INSULIN(ColorGroup.InsulinTreatment), + STORE_INSULIN(ColorGroup.InsulinTreatment), + INSULIN_REMOVED(ColorGroup.InsulinTreatment), NEW_PROFILE(ColorGroup.Profile), CLONE_PROFILE(ColorGroup.Profile), STORE_PROFILE(ColorGroup.Profile), diff --git a/core/data/src/main/kotlin/app/aaps/core/data/ue/Sources.kt b/core/data/src/main/kotlin/app/aaps/core/data/ue/Sources.kt index 4c9677b8ba2..667a4b085f7 100644 --- a/core/data/src/main/kotlin/app/aaps/core/data/ue/Sources.kt +++ b/core/data/src/main/kotlin/app/aaps/core/data/ue/Sources.kt @@ -36,6 +36,7 @@ enum class Sources { Glunovo, Intelligo, Xdrip, + Insulin, //From Insulin plugin LocalProfile, //From LocalProfile plugin Loop, //From Loop plugin Maintenance, //From Maintenance plugin diff --git a/core/ui/src/main/res/values/strings.xml b/core/ui/src/main/res/values/strings.xml index d7376335041..2872b10d2a6 100644 --- a/core/ui/src/main/res/values/strings.xml +++ b/core/ui/src/main/res/values/strings.xml @@ -393,6 +393,10 @@ "%1$s;%2$s;%3$s;%4$s;%5$s;%6$s;%7$s;%8$s;%9$s;%10$s;%11$s;%12$s;%13$s;%14$s;%15$s;%16$s;%17$s" LOOP CHANGED LOOP REMOVED + NEW INSULIN + CLONE INSULIN + STORE INSULIN + INSULIN REMOVED OTHER @@ -402,6 +406,8 @@ Temporary target top value Temporary target value Profile DIA value + Insulin DIA value + Insulin Peak value Profile sensitivity value Maximal profile basal value Current basal value diff --git a/database/impl/src/main/kotlin/app/aaps/database/entities/UserEntry.kt b/database/impl/src/main/kotlin/app/aaps/database/entities/UserEntry.kt index 4b0b603791b..5effbfc2360 100644 --- a/database/impl/src/main/kotlin/app/aaps/database/entities/UserEntry.kt +++ b/database/impl/src/main/kotlin/app/aaps/database/entities/UserEntry.kt @@ -37,6 +37,9 @@ data class UserEntry( EXTENDED_CARBS, TEMP_BASAL, TT, + NEW_INSULIN, + CLONE_INSULIN, + STORE_INSULIN, NEW_PROFILE, CLONE_PROFILE, STORE_PROFILE, @@ -75,6 +78,7 @@ data class UserEntry( CAREPORTAL_REMOVED, EXTENDED_BOLUS_REMOVED, FOOD_REMOVED, + INSULIN_REMOVED, PROFILE_REMOVED, PROFILE_SWITCH_REMOVED, RESTART_EVENTS_REMOVED, @@ -153,6 +157,7 @@ data class UserEntry( Glunovo, Intelligo, Xdrip, + Insulin, //From Insulin plugin LocalProfile, //From LocalProfile plugin Loop, //From Loop plugin Maintenance, //From Maintenance plugin diff --git a/database/persistence/src/main/kotlin/app/aaps/database/persistence/converters/ActionExtension.kt b/database/persistence/src/main/kotlin/app/aaps/database/persistence/converters/ActionExtension.kt index 9fcdcf94691..d5a5c639ab5 100644 --- a/database/persistence/src/main/kotlin/app/aaps/database/persistence/converters/ActionExtension.kt +++ b/database/persistence/src/main/kotlin/app/aaps/database/persistence/converters/ActionExtension.kt @@ -93,6 +93,10 @@ fun UserEntry.Action.fromDb(): Action = UserEntry.Action.PLUGIN_ENABLED -> Action.PLUGIN_ENABLED UserEntry.Action.PLUGIN_DISABLED -> Action.PLUGIN_DISABLED UserEntry.Action.UNKNOWN -> Action.UNKNOWN + UserEntry.Action.NEW_INSULIN -> Action.NEW_INSULIN + UserEntry.Action.CLONE_INSULIN -> Action.CLONE_INSULIN + UserEntry.Action.STORE_INSULIN -> Action.STORE_INSULIN + UserEntry.Action.INSULIN_REMOVED -> Action.INSULIN_REMOVED } fun Action.toDb(): UserEntry.Action = @@ -185,5 +189,9 @@ fun Action.toDb(): UserEntry.Action = Action.PLUGIN_ENABLED -> UserEntry.Action.PLUGIN_ENABLED Action.PLUGIN_DISABLED -> UserEntry.Action.PLUGIN_DISABLED Action.UNKNOWN -> UserEntry.Action.UNKNOWN + Action.NEW_INSULIN -> UserEntry.Action.NEW_INSULIN + Action.CLONE_INSULIN -> UserEntry.Action.CLONE_INSULIN + Action.STORE_INSULIN -> UserEntry.Action.STORE_INSULIN + Action.INSULIN_REMOVED -> UserEntry.Action.INSULIN_REMOVED } diff --git a/database/persistence/src/main/kotlin/app/aaps/database/persistence/converters/SourcesExtension.kt b/database/persistence/src/main/kotlin/app/aaps/database/persistence/converters/SourcesExtension.kt index e6f773725ee..ce348f4fc4b 100644 --- a/database/persistence/src/main/kotlin/app/aaps/database/persistence/converters/SourcesExtension.kt +++ b/database/persistence/src/main/kotlin/app/aaps/database/persistence/converters/SourcesExtension.kt @@ -40,6 +40,7 @@ fun UserEntry.Sources.fromDb(): Sources = UserEntry.Sources.Glunovo -> Sources.Glunovo UserEntry.Sources.Intelligo -> Sources.Intelligo UserEntry.Sources.Xdrip -> Sources.Xdrip + UserEntry.Sources.Insulin -> Sources.Insulin UserEntry.Sources.LocalProfile -> Sources.LocalProfile UserEntry.Sources.Loop -> Sources.Loop UserEntry.Sources.Maintenance -> Sources.Maintenance @@ -159,5 +160,6 @@ fun Sources.toDb(): UserEntry.Sources = Sources.Unknown -> UserEntry.Sources.Unknown Sources.Ottai -> UserEntry.Sources.Ottai Sources.SyaiTag -> UserEntry.Sources.SyaiTag + Sources.Insulin -> UserEntry.Sources.Insulin } diff --git a/implementation/src/main/kotlin/app/aaps/implementation/userEntry/UserEntryPresentationHelperImpl.kt b/implementation/src/main/kotlin/app/aaps/implementation/userEntry/UserEntryPresentationHelperImpl.kt index 63ee9171e31..be201e10056 100644 --- a/implementation/src/main/kotlin/app/aaps/implementation/userEntry/UserEntryPresentationHelperImpl.kt +++ b/implementation/src/main/kotlin/app/aaps/implementation/userEntry/UserEntryPresentationHelperImpl.kt @@ -116,6 +116,7 @@ class UserEntryPresentationHelperImpl @Inject constructor( Sources.BgFragment -> R.drawable.ic_aaps Sources.Ottai -> R.drawable.ic_ottai Sources.SyaiTag -> R.drawable.ic_syai_tag + Sources.Insulin -> R.drawable.ic_insulin } override fun actionToColoredString(action: Action): Spanned = when (action) { diff --git a/implementation/src/main/kotlin/app/aaps/implementation/utils/TranslatorImpl.kt b/implementation/src/main/kotlin/app/aaps/implementation/utils/TranslatorImpl.kt index 31a4d2f0ee0..1ef9f169e51 100644 --- a/implementation/src/main/kotlin/app/aaps/implementation/utils/TranslatorImpl.kt +++ b/implementation/src/main/kotlin/app/aaps/implementation/utils/TranslatorImpl.kt @@ -104,6 +104,11 @@ class TranslatorImpl @Inject internal constructor( Action.PLUGIN_DISABLED -> rh.gs(app.aaps.core.ui.R.string.uel_plugin_disabled) Action.LOOP_CHANGE -> rh.gs(app.aaps.core.ui.R.string.uel_loop_change) Action.LOOP_REMOVED -> rh.gs(app.aaps.core.ui.R.string.uel_loop_removed) + Action.NEW_INSULIN -> rh.gs(app.aaps.core.ui.R.string.uel_new_insulin) + Action.CLONE_INSULIN -> rh.gs(app.aaps.core.ui.R.string.uel_clone_insulin) + Action.STORE_INSULIN -> rh.gs(app.aaps.core.ui.R.string.uel_store_insulin) + Action.INSULIN_REMOVED -> rh.gs(app.aaps.core.ui.R.string.uel_insulin_removed) + Action.UNKNOWN -> rh.gs(app.aaps.core.ui.R.string.unknown) } From 277d7e963dea86f9cf08b9722d4008d2dd1ef9f4 Mon Sep 17 00:00:00 2001 From: Philoul Date: Wed, 26 Feb 2025 09:17:08 +0100 Subject: [PATCH 14/41] AT delete Local Insulin class --- .../aaps/plugins/aps/autotune/AutotuneCore.kt | 1 - .../aaps/plugins/aps/autotune/AutotuneIob.kt | 1 - .../plugins/aps/autotune/AutotunePlugin.kt | 11 ----- .../aaps/plugins/aps/autotune/AutotunePrep.kt | 3 -- .../plugins/aps/autotune/data/LocalInsulin.kt | 48 ------------------- .../plugins/aps/autotune/AutotuneCoreTest.kt | 4 +- .../plugins/aps/autotune/AutotunePrepTest.kt | 2 - 7 files changed, 1 insertion(+), 69 deletions(-) delete mode 100644 plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/data/LocalInsulin.kt diff --git a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneCore.kt b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneCore.kt index 3444377059e..b3f5a076c0c 100644 --- a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneCore.kt +++ b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneCore.kt @@ -5,7 +5,6 @@ import app.aaps.core.keys.DoubleKey import app.aaps.core.keys.Preferences import app.aaps.core.utils.Percentile import app.aaps.plugins.aps.autotune.data.ATProfile -import app.aaps.plugins.aps.autotune.data.LocalInsulin import app.aaps.plugins.aps.autotune.data.PreppedGlucose import java.util.Calendar import javax.inject.Inject diff --git a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneIob.kt b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneIob.kt index bd274b5e4c7..2f6807383ff 100644 --- a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneIob.kt +++ b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneIob.kt @@ -29,7 +29,6 @@ import app.aaps.core.objects.extensions.toJson import app.aaps.core.objects.extensions.toTemporaryBasal import app.aaps.core.utils.MidnightUtils import app.aaps.plugins.aps.autotune.data.ATProfile -import app.aaps.plugins.aps.autotune.data.LocalInsulin import org.json.JSONArray import org.json.JSONObject import javax.inject.Inject diff --git a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotunePlugin.kt b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotunePlugin.kt index 22083a890f7..5e00e82beda 100644 --- a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotunePlugin.kt +++ b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotunePlugin.kt @@ -42,7 +42,6 @@ import app.aaps.core.validators.preferences.AdaptiveIntPreference import app.aaps.core.validators.preferences.AdaptiveSwitchPreference import app.aaps.plugins.aps.R import app.aaps.plugins.aps.autotune.data.ATProfile -import app.aaps.plugins.aps.autotune.data.LocalInsulin import app.aaps.plugins.aps.autotune.data.PreppedGlucose import app.aaps.plugins.aps.autotune.events.EventAutotuneUpdateGui import dagger.android.HasAndroidInjector @@ -391,14 +390,10 @@ class AutotunePlugin @Inject constructor( json.put("lastRun", lastRun) json.put("pumpProfile", pumpProfile.profile.toPureNsJson(dateUtil)) json.put("pumpProfileName", pumpProfile.profileName) - json.put("pumpPeak", pumpProfile.peak) - json.put("pumpDia", pumpProfile.dia) tunedProfile?.let { atProfile -> json.put("tunedProfile", atProfile.profile.toPureNsJson(dateUtil)) json.put("tunedCircadianProfile", atProfile.circadianProfile.toPureNsJson(dateUtil)) json.put("tunedProfileName", atProfile.profileName) - json.put("tunedPeak", atProfile.peak) - json.put("tunedDia", atProfile.dia) for (i in 0..23) { json.put("missingDays_$i", atProfile.basalUnTuned[i]) } @@ -418,16 +413,10 @@ class AutotunePlugin @Inject constructor( val json = JSONObject(sp.getString(R.string.key_autotune_last_run, "")) lastNbDays = JsonHelper.safeGetString(json, "lastNbDays", "") lastRun = JsonHelper.safeGetLong(json, "lastRun") - val pumpPeak = JsonHelper.safeGetInt(json, "pumpPeak") - val pumpDia = JsonHelper.safeGetDouble(json, "pumpDia") - var localInsulin = LocalInsulin("PumpInsulin", pumpPeak, pumpDia) selectedProfile = JsonHelper.safeGetString(json, "pumpProfileName", "") val profile = JsonHelper.safeGetJSONObject(json, "pumpProfile", null)?.let { pureProfileFromJson(it, dateUtil) } ?: return pumpProfile = ATProfile(ProfileSealed.Pure(value = profile, activePlugin = null), injector).also { it.profileName = selectedProfile } - val tunedPeak = JsonHelper.safeGetInt(json, "tunedPeak") - val tunedDia = JsonHelper.safeGetDouble(json, "tunedDia") - localInsulin = LocalInsulin("PumpInsulin", tunedPeak, tunedDia) val tunedProfileName = JsonHelper.safeGetString(json, "tunedProfileName", "") val tuned = JsonHelper.safeGetJSONObject(json, "tunedProfile", null)?.let { pureProfileFromJson(it, dateUtil) } ?: return diff --git a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotunePrep.kt b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotunePrep.kt index b710bc7e507..bf4ad384bf2 100644 --- a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotunePrep.kt +++ b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotunePrep.kt @@ -14,7 +14,6 @@ import app.aaps.plugins.aps.autotune.data.ATProfile import app.aaps.plugins.aps.autotune.data.BGDatum import app.aaps.plugins.aps.autotune.data.CRDatum import app.aaps.plugins.aps.autotune.data.DiaDeviation -import app.aaps.plugins.aps.autotune.data.LocalInsulin import app.aaps.plugins.aps.autotune.data.PeakDeviation import app.aaps.plugins.aps.autotune.data.PreppedGlucose import javax.inject.Inject @@ -48,7 +47,6 @@ class AutotunePrep @Inject constructor( var sqrtDeviations = 0.0 var deviations = 0.0 var deviationsSq = 0.0 - val localInsulin = LocalInsulin("Ins_$currentPeak-$dia", currentPeak, dia) val curveOutput = categorizeBGDatums(tunedProfile, false) val basalGlucose = curveOutput?.basalGlucoseData @@ -95,7 +93,6 @@ class AutotunePrep @Inject constructor( var sqrtDeviations = 0.0 var deviations = 0.0 var deviationsSq = 0.0 - val localInsulin = LocalInsulin("Ins_$peak-$currentDIA", peak, currentDIA) val curveOutput = categorizeBGDatums(tunedProfile, false) val basalGlucose = curveOutput?.basalGlucoseData diff --git a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/data/LocalInsulin.kt b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/data/LocalInsulin.kt deleted file mode 100644 index 1d7e7bb9aa5..00000000000 --- a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/data/LocalInsulin.kt +++ /dev/null @@ -1,48 +0,0 @@ -package app.aaps.plugins.aps.autotune.data - -import app.aaps.core.data.iob.Iob -import app.aaps.core.data.model.BS -import kotlin.math.exp -import kotlin.math.pow - -class LocalInsulin(val name: String?, val peak: Int = DEFAULT_PEAK, private val userDefinedDia: Double = DEFAULT_DIA) { - - val dia - get(): Double { - val dia = userDefinedDia - return if (dia >= MIN_DIA) { - dia - } else { - MIN_DIA - } - } - - val duration - get() = (60 * 60 * 1000L * dia).toLong() - - fun iobCalcForTreatment(bolus: BS, time: Long): Iob { - val result = Iob() - if (bolus.amount != 0.0) { - val bolusTime = bolus.timestamp - val t = (time - bolusTime) / 1000.0 / 60.0 - val td = dia * 60 //getDIA() always >= MIN_DIA - val tp = peak.toDouble() - // force the IOB to 0 if over DIA hours have passed - if (t < td) { - val tau = tp * (1 - tp / td) / (1 - 2 * tp / td) - val a = 2 * tau / td - val s = 1 / (1 - a + (1 + a) * exp(-td / tau)) - result.activityContrib = bolus.amount * (s / tau.pow(2.0)) * t * (1 - t / td) * exp(-t / tau) - result.iobContrib = bolus.amount * (1 - s * (1 - a) * ((t.pow(2.0) / (tau * td * (1 - a)) - t / tau - 1) * exp(-t / tau) + 1)) - } - } - return result - } - - companion object { - - private const val MIN_DIA = 5.0 - private const val DEFAULT_DIA = 6.0 - private const val DEFAULT_PEAK = 75 - } -} \ No newline at end of file diff --git a/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/autotune/AutotuneCoreTest.kt b/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/autotune/AutotuneCoreTest.kt index d7f7b115767..9749458eec1 100644 --- a/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/autotune/AutotuneCoreTest.kt +++ b/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/autotune/AutotuneCoreTest.kt @@ -11,7 +11,6 @@ import app.aaps.core.keys.DoubleKey import app.aaps.core.objects.profile.ProfileSealed import app.aaps.core.utils.JsonHelper import app.aaps.plugins.aps.autotune.data.ATProfile -import app.aaps.plugins.aps.autotune.data.LocalInsulin import app.aaps.plugins.aps.autotune.data.PreppedGlucose import app.aaps.shared.tests.TestBaseWithProfile import com.google.common.truth.Truth.assertThat @@ -95,7 +94,6 @@ class AutotuneCoreTest : TestBaseWithProfile() { val dia = JsonHelper.safeGetDoubleAllowNull(jsonObject, "dia") ?: return null val peak = JsonHelper.safeGetIntAllowNull(jsonObject, "insulinPeakTime") ?: return null val iCfg = ICfg("", peak, dia) - val localInsulin = LocalInsulin("insulin", peak, dia) val timezone = TimeZone.getTimeZone(JsonHelper.safeGetString(jsonObject, "timezone", "UTC")) val isfJson = jsonObject.getJSONObject("isfProfile") val isfBlocks = ArrayList(1).also { @@ -124,7 +122,7 @@ class AutotuneCoreTest : TestBaseWithProfile() { dia = dia, iCfg = iCfg ) - return ATProfile(ProfileSealed.Pure(pure, activePlugin), localInsulin, injector).also { it.dateUtil = dateUtil; it.profileUtil = profileUtil } + return ATProfile(ProfileSealed.Pure(pure, activePlugin), injector).also { it.dateUtil = dateUtil; it.profileUtil = profileUtil } } catch (ignored: Exception) { return null } diff --git a/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/autotune/AutotunePrepTest.kt b/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/autotune/AutotunePrepTest.kt index 8b18d5d0ccc..d6d2eaaf62a 100644 --- a/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/autotune/AutotunePrepTest.kt +++ b/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/autotune/AutotunePrepTest.kt @@ -24,7 +24,6 @@ import app.aaps.core.objects.extensions.shiftBlock import app.aaps.core.objects.profile.ProfileSealed import app.aaps.core.utils.JsonHelper import app.aaps.plugins.aps.autotune.data.ATProfile -import app.aaps.plugins.aps.autotune.data.LocalInsulin import app.aaps.plugins.aps.autotune.data.PreppedGlucose import app.aaps.shared.tests.TestBaseWithProfile import com.google.common.truth.Truth.assertThat @@ -167,7 +166,6 @@ class AutotunePrepTest : TestBaseWithProfile() { val dia = JsonHelper.safeGetDoubleAllowNull(jsonObject, "dia") ?: return null val peak = JsonHelper.safeGetIntAllowNull(jsonObject, "insulinPeakTime") ?: return null val iCfg = ICfg("insulin", peak, dia) - val localInsulin = LocalInsulin("insulin", peak, dia) val timezone = TimeZone.getTimeZone(JsonHelper.safeGetString(jsonObject, "timezone", "UTC")) val isfJson = jsonObject.getJSONObject("isfProfile") val isfBlocks = ArrayList(1).also { From ede7360fdeba22486f67de8f4818ecb02d5a722d Mon Sep 17 00:00:00 2001 From: Philoul Date: Wed, 26 Feb 2025 09:29:37 +0100 Subject: [PATCH 15/41] use iCfg within ProfileSwitch function --- .../app/aaps/implementation/profile/ProfileFunctionImpl.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/implementation/src/main/kotlin/app/aaps/implementation/profile/ProfileFunctionImpl.kt b/implementation/src/main/kotlin/app/aaps/implementation/profile/ProfileFunctionImpl.kt index 9f722965f4b..d397c1358ae 100644 --- a/implementation/src/main/kotlin/app/aaps/implementation/profile/ProfileFunctionImpl.kt +++ b/implementation/src/main/kotlin/app/aaps/implementation/profile/ProfileFunctionImpl.kt @@ -158,9 +158,7 @@ class ProfileFunctionImpl @Inject constructor( timeshift = T.hours(timeShiftInHours.toLong()).msecs(), percentage = percentage, duration = T.mins(durationInMinutes.toLong()).msecs(), - iCfg = activePlugin.activeInsulin.iCfg.also { - it.insulinEndTime = (pureProfile.dia * 3600 * 1000).toLong() - } + iCfg = pureProfile.iCfg ) } From 4e18d67da1d407b23bb94d6ced552a321039d089 Mon Sep 17 00:00:00 2001 From: Philoul Date: Wed, 26 Feb 2025 11:44:03 +0100 Subject: [PATCH 16/41] Show Insulin Name --- .../objects/extensions/InsulinExtension.kt | 2 +- .../plugins/main/profile/ProfileFragment.kt | 4 +- .../src/main/res/layout/profile_fragment.xml | 65 +++++++++++++++++-- 3 files changed, 64 insertions(+), 7 deletions(-) diff --git a/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/InsulinExtension.kt b/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/InsulinExtension.kt index cd4f898b57e..b3eb2d2da44 100644 --- a/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/InsulinExtension.kt +++ b/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/InsulinExtension.kt @@ -5,7 +5,7 @@ import app.aaps.core.interfaces.insulin.Insulin import org.json.JSONObject fun ICfg.toJson(): JSONObject = JSONObject() - .put("c", insulinLabel) + .put("insulinLabel", insulinLabel) .put("insulinEndTime", insulinEndTime) .put("insulinPeakTime", insulinPeakTime) diff --git a/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfileFragment.kt b/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfileFragment.kt index fe732a0c394..af206d76f1b 100644 --- a/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfileFragment.kt +++ b/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfileFragment.kt @@ -148,6 +148,8 @@ class ProfileFragment : DaggerFragment() { binding.name.addTextChangedListener(textWatch) binding.profileList.filters = arrayOf() binding.profileList.setText(currentProfile.name) + binding.insulinName.text = currentProfile.iCfg.insulinLabel + binding.peak.text = rh.gs(app.aaps.core.ui.R.string.mins,currentProfile.iCfg.getPeak()) binding.dia.setParams(currentProfile.dia, hardLimits.minDia(), hardLimits.maxDia(), 0.1, DecimalFormat("0.0"), false, null, textWatch) binding.dia.tag = "LP_DIA" TimeListEdit( @@ -421,7 +423,7 @@ class ProfileFragment : DaggerFragment() { } private fun processVisibility(position: Int) { - binding.diaPlaceholder.visibility = (position == 0).toVisibility() + binding.insulinPlaceholder.visibility = (position == 0).toVisibility() binding.ic.visibility = (position == 1).toVisibility() binding.isf.visibility = (position == 2).toVisibility() binding.basal.visibility = (position == 3).toVisibility() diff --git a/plugins/main/src/main/res/layout/profile_fragment.xml b/plugins/main/src/main/res/layout/profile_fragment.xml index 3cba27fda4d..5caeb6db272 100644 --- a/plugins/main/src/main/res/layout/profile_fragment.xml +++ b/plugins/main/src/main/res/layout/profile_fragment.xml @@ -128,7 +128,7 @@ + android:text="@string/insulin_shortname" /> - + android:orientation="horizontal" + android:paddingTop="5dp"> + + + + + + + + + + + + + + + + + + Date: Wed, 26 Feb 2025 12:14:54 +0100 Subject: [PATCH 17/41] Clean ActivityGraph --- .../app/aaps/core/graph/ActivityGraph.kt | 52 ++----------------- .../plugins/main/profile/ProfileFragment.kt | 3 +- 2 files changed, 5 insertions(+), 50 deletions(-) diff --git a/core/graph/src/main/kotlin/app/aaps/core/graph/ActivityGraph.kt b/core/graph/src/main/kotlin/app/aaps/core/graph/ActivityGraph.kt index 8c1a87a31e4..8f285d896d9 100644 --- a/core/graph/src/main/kotlin/app/aaps/core/graph/ActivityGraph.kt +++ b/core/graph/src/main/kotlin/app/aaps/core/graph/ActivityGraph.kt @@ -18,57 +18,11 @@ class ActivityGraph : GraphView { constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) - fun show(insulin: Insulin, diaSample: Double? = null) { + fun show(insulin: Insulin, iCfgSample: ICfg? = null) { + val iCfg = iCfgSample ?:insulin.iCfg removeAllSeries() - val dia = diaSample ?: insulin.dia mSecondScale = null - val hours = floor(dia + 1).toLong() - val bolus = BS( - timestamp = 0, - amount = 1.0, - type = BS.Type.NORMAL - ) - val activityArray: MutableList = ArrayList() - val iobArray: MutableList = ArrayList() - var time: Long = 0 - while (time <= T.hours(hours).msecs()) { - val iob = insulin.iobCalcForTreatment(bolus, time, dia) - activityArray.add(DataPoint(T.msecs(time).mins().toDouble(), iob.activityContrib)) - iobArray.add(DataPoint(T.msecs(time).mins().toDouble(), iob.iobContrib)) - time += T.mins(5).msecs() - } - addSeries(LineGraphSeries(Array(activityArray.size) { i -> activityArray[i] }).also { - it.thickness = 8 - gridLabelRenderer.verticalLabelsColor = it.color - }) - viewport.isXAxisBoundsManual = true - viewport.setMinX(0.0) - viewport.setMaxX((hours * 60).toDouble()) - viewport.isYAxisBoundsManual = true - viewport.setMinY(0.0) - viewport.setMaxY(0.01) - //gridLabelRenderer.numHorizontalLabels = (hours + 1).toInt() - gridLabelRenderer.horizontalAxisTitle = "[min]" - secondScale.addSeries(LineGraphSeries(Array(iobArray.size) { i -> iobArray[i] }).also { - it.isDrawBackground = true - it.color = Color.MAGENTA - it.backgroundColor = Color.argb(70, 255, 0, 255) - }) - secondScale.minY = 0.0 - secondScale.maxY = 1.0 - gridLabelRenderer.verticalLabelsSecondScaleColor = Color.MAGENTA - } - - - fun show(insulin: Insulin, iCfg: ICfg?) { - if (iCfg == null) { - show(insulin) - return - } - removeAllSeries() - val dia = iCfg.getDia() - mSecondScale = null - val hours = floor(dia + 1).toLong() + val hours = floor(iCfg.getDia() + 1).toLong() val bolus = BS( timestamp = 0, amount = 1.0, diff --git a/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfileFragment.kt b/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfileFragment.kt index af206d76f1b..cc593a968f2 100644 --- a/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfileFragment.kt +++ b/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfileFragment.kt @@ -91,6 +91,7 @@ class ProfileFragment : DaggerFragment() { profilePlugin.currentProfile()?.dia = dia profilePlugin.currentProfile()?.iCfg = ICfg(name, peak, dia) profilePlugin.currentProfile()?.name = binding.name.text.toString() + binding.insulinGraph.show(activePlugin.activeInsulin, profilePlugin.currentProfile()?.iCfg) doEdit() } } @@ -283,7 +284,7 @@ class ProfileFragment : DaggerFragment() { binding.icGraph.show(ProfileSealed.Pure(it, null)) binding.isfGraph.show(ProfileSealed.Pure(it, null)) binding.targetGraph.show(ProfileSealed.Pure(it, null)) - binding.insulinGraph.show(activePlugin.activeInsulin, SafeParse.stringToDouble(binding.dia.text)) + binding.insulinGraph.show(activePlugin.activeInsulin, it.iCfg) } binding.profileAdd.setOnClickListener { From bc210b6d7c20711ee5f46291a8965eef660ccbea Mon Sep 17 00:00:00 2001 From: Philoul Date: Wed, 26 Feb 2025 13:46:39 +0100 Subject: [PATCH 18/41] Fix AT Tests --- .../kotlin/app/aaps/plugins/aps/autotune/data/ATProfile.kt | 4 ++-- .../kotlin/app/aaps/plugins/aps/autotune/AutotuneCoreTest.kt | 1 + .../app/aaps/plugins/insulin/InsulinLyumjevPluginTest.kt | 4 ++-- .../app/aaps/plugins/insulin/InsulinOrefFreePeakPluginTest.kt | 2 +- .../aaps/plugins/insulin/InsulinOrefRapidActingPluginTest.kt | 2 +- .../plugins/insulin/InsulinOrefUltraRapidActingPluginTest.kt | 2 +- 6 files changed, 8 insertions(+), 7 deletions(-) diff --git a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/data/ATProfile.kt b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/data/ATProfile.kt index 1020e31bc74..331a8714ec6 100644 --- a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/data/ATProfile.kt +++ b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/data/ATProfile.kt @@ -102,8 +102,8 @@ class ATProfile(profile: Profile, val injector: HasAndroidInjector) { } fun updateProfile() { - data()?.let { profile = ProfileSealed.Pure(value = it, activePlugin) } - data(true)?.let { circadianProfile = ProfileSealed.Pure(value = it, activePlugin) } + data()?.let { profile = ProfileSealed.Pure(value = it, null) } + data(true)?.let { circadianProfile = ProfileSealed.Pure(value = it, null) } } //Export json string with oref0 format used for autotune diff --git a/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/autotune/AutotuneCoreTest.kt b/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/autotune/AutotuneCoreTest.kt index 9749458eec1..9a22c4f2c7d 100644 --- a/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/autotune/AutotuneCoreTest.kt +++ b/plugins/aps/src/test/kotlin/app/aaps/plugins/aps/autotune/AutotuneCoreTest.kt @@ -5,6 +5,7 @@ import app.aaps.core.data.model.ICfg import app.aaps.core.data.model.data.Block import app.aaps.core.data.model.data.TargetBlock import app.aaps.core.data.time.T +import app.aaps.core.interfaces.plugin.ActivePlugin import app.aaps.core.interfaces.profile.PureProfile import app.aaps.core.interfaces.utils.DateUtil import app.aaps.core.keys.DoubleKey diff --git a/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinLyumjevPluginTest.kt b/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinLyumjevPluginTest.kt index 34e0a8c6383..8660c50fffc 100644 --- a/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinLyumjevPluginTest.kt +++ b/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinLyumjevPluginTest.kt @@ -50,13 +50,13 @@ class InsulinLyumjevPluginTest { @Test fun commentStandardTextTest() { - `when`(rh.gs(eq(R.string.lyumjev))).thenReturn("Lyumjev") + `when`(rh.gs(eq(app.aaps.core.interfaces.R.string.lyumjev))).thenReturn("Lyumjev") assertThat(sut.commentStandardText()).isEqualTo("Lyumjev") } @Test fun getFriendlyNameTest() { - `when`(rh.gs(eq(R.string.lyumjev))).thenReturn("Lyumjev") + `when`(rh.gs(eq(app.aaps.core.interfaces.R.string.lyumjev))).thenReturn("Lyumjev") assertThat(sut.friendlyName).isEqualTo("Lyumjev") } diff --git a/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinOrefFreePeakPluginTest.kt b/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinOrefFreePeakPluginTest.kt index e2be91b236c..cbce7805e6d 100644 --- a/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinOrefFreePeakPluginTest.kt +++ b/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinOrefFreePeakPluginTest.kt @@ -60,7 +60,7 @@ class InsulinOrefFreePeakPluginTest : TestBaseWithProfile() { @Test fun getFriendlyNameTest() { - `when`(rh.gs(eq(R.string.free_peak_oref))).thenReturn("Free-Peak Oref") + `when`(rh.gs(eq(app.aaps.core.interfaces.R.string.free_peak_oref))).thenReturn("Free-Peak Oref") assertThat(sut.friendlyName).isEqualTo("Free-Peak Oref") } diff --git a/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinOrefRapidActingPluginTest.kt b/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinOrefRapidActingPluginTest.kt index 43d9d90eabf..f2b47f62ab6 100644 --- a/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinOrefRapidActingPluginTest.kt +++ b/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinOrefRapidActingPluginTest.kt @@ -56,7 +56,7 @@ class InsulinOrefRapidActingPluginTest { @Test fun getFriendlyNameTest() { - `when`(rh.gs(eq(R.string.rapid_acting_oref))).thenReturn("Rapid-Acting Oref") + `when`(rh.gs(eq(app.aaps.core.interfaces.R.string.rapid_acting_oref))).thenReturn("Rapid-Acting Oref") assertThat(sut.friendlyName).isEqualTo("Rapid-Acting Oref") } diff --git a/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinOrefUltraRapidActingPluginTest.kt b/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinOrefUltraRapidActingPluginTest.kt index 8a3353f4ead..4a3fa57bfa0 100644 --- a/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinOrefUltraRapidActingPluginTest.kt +++ b/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinOrefUltraRapidActingPluginTest.kt @@ -56,7 +56,7 @@ class InsulinOrefUltraRapidActingPluginTest { @Test fun getFriendlyNameTest() { - `when`(rh.gs(eq(R.string.ultra_rapid_oref))).thenReturn("Ultra-Rapid Oref") + `when`(rh.gs(eq(app.aaps.core.interfaces.R.string.ultra_rapid_oref))).thenReturn("Ultra-Rapid Oref") assertThat(sut.friendlyName).isEqualTo("Ultra-Rapid Oref") } From 1e0af6bc7a4fa943cfe2ec602ec18abf3c78c345 Mon Sep 17 00:00:00 2001 From: Philoul Date: Wed, 26 Feb 2025 14:45:46 +0100 Subject: [PATCH 19/41] Fix ProfileStore Unit Test (dia replaced by iCfg) --- .../main/kotlin/app/aaps/shared/tests/TestBaseWithProfile.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/tests/src/main/kotlin/app/aaps/shared/tests/TestBaseWithProfile.kt b/shared/tests/src/main/kotlin/app/aaps/shared/tests/TestBaseWithProfile.kt index 2fa41b997af..0ae628d8b28 100644 --- a/shared/tests/src/main/kotlin/app/aaps/shared/tests/TestBaseWithProfile.kt +++ b/shared/tests/src/main/kotlin/app/aaps/shared/tests/TestBaseWithProfile.kt @@ -105,7 +105,7 @@ open class TestBaseWithProfile : TestBase() { validProfileJSON = "{\"icfg\":{\"insulinLabel\":\"\",\"insulinEndTime\":18000000,\"insulinPeakTime\":4500000},\"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\"}" - invalidProfileJSON = "{\"icfg\":{\"insulinLabel\":\"\",\"insulinEndTime\":18000000,\"insulinPeakTime\":4500000},\"dia\":\"1\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"3\"}," + + invalidProfileJSON = "{\"icfg\":{\"insulinLabel\":\"\",\"insulinEndTime\":3600000,\"insulinPeakTime\":4500000},\"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\"}" preferenceManager = PreferenceManager(context) From 27a8c84ae275a4902270e6bc3b33ef7f6f7df2da Mon Sep 17 00:00:00 2001 From: Philoul Date: Thu, 27 Feb 2025 08:48:40 +0100 Subject: [PATCH 20/41] Clean Code --- .../kotlin/app/aaps/core/objects/extensions/InsulinExtension.kt | 1 - .../main/kotlin/app/aaps/plugins/aps/autotune/AutotuneCore.kt | 2 -- .../kotlin/app/aaps/plugins/aps/autotune/AutotuneFragment.kt | 2 -- .../main/kotlin/app/aaps/plugins/aps/autotune/AutotunePlugin.kt | 2 +- .../kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt | 1 + 5 files changed, 2 insertions(+), 6 deletions(-) diff --git a/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/InsulinExtension.kt b/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/InsulinExtension.kt index b3eb2d2da44..5213136c7cd 100644 --- a/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/InsulinExtension.kt +++ b/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/InsulinExtension.kt @@ -1,7 +1,6 @@ package app.aaps.core.objects.extensions import app.aaps.core.data.model.ICfg -import app.aaps.core.interfaces.insulin.Insulin import org.json.JSONObject fun ICfg.toJson(): JSONObject = JSONObject() diff --git a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneCore.kt b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneCore.kt index b3f5a076c0c..204feffdf7a 100644 --- a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneCore.kt +++ b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneCore.kt @@ -487,8 +487,6 @@ class AutotuneCore @Inject constructor( previousAutotune.basalUnTuned = basalUnTuned previousAutotune.profile.iCfg.setDia(newDia) previousAutotune.profile.iCfg.setPeak(newPeak) - //val localInsulin = LocalInsulin("Ins_$newPeak-$newDia", newPeak, newDia) - //previousAutotune.localInsulin = localInsulin previousAutotune.updateProfile() return previousAutotune } diff --git a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneFragment.kt b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneFragment.kt index 2c2b6ac2d12..51545057c32 100644 --- a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneFragment.kt +++ b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneFragment.kt @@ -23,7 +23,6 @@ import app.aaps.core.data.ue.Action import app.aaps.core.data.ue.Sources import app.aaps.core.data.ue.ValueWithUnit import app.aaps.core.interfaces.aps.Loop -import app.aaps.core.interfaces.logging.AAPSLogger import app.aaps.core.interfaces.logging.UserEntryLogger import app.aaps.core.interfaces.objects.Instantiator import app.aaps.core.interfaces.plugin.ActivePlugin @@ -43,7 +42,6 @@ import app.aaps.core.interfaces.utils.fabric.FabricPrivacy import app.aaps.core.keys.BooleanKey import app.aaps.core.keys.IntKey import app.aaps.core.keys.Preferences -import app.aaps.core.objects.extensions.toJson import app.aaps.core.objects.profile.ProfileSealed import app.aaps.core.ui.dialogs.OKDialog import app.aaps.core.ui.elements.WeekDay diff --git a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotunePlugin.kt b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotunePlugin.kt index 5e00e82beda..31ceb78b727 100644 --- a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotunePlugin.kt +++ b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotunePlugin.kt @@ -284,7 +284,7 @@ class AutotunePlugin @Inject constructor( strResult += rh.gs(R.string.autotune_log_title) strResult += line val tuneInsulin = preferences.get(BooleanKey.AutotuneTuneInsulinCurve) - if (tuneInsulin || true) { + if (tuneInsulin) { strResult += rh.gs(R.string.autotune_log_peak, rh.gs(R.string.insulin_peak), pumpProfile.peak, tunedProfile.peak) strResult += rh.gs(R.string.autotune_log_dia, rh.gs(app.aaps.core.ui.R.string.ic_short), pumpProfile.dia, tunedProfile.dia) } diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt index 85c48b7bc9f..166791f6ec4 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt @@ -56,6 +56,7 @@ abstract class InsulinOrefBasePlugin( } } override fun setDefault(iCfg: ICfg?) { + // fun added for future unique Insulin Plugin to replace "selected insulin plugin", by "DefaultInsulin" } open fun sendShortDiaNotification(dia: Double) { From b300e4f2c5aa7393cde4f31d6edf97a31ee00cf3 Mon Sep 17 00:00:00 2001 From: Philoul Date: Thu, 27 Feb 2025 17:51:04 +0100 Subject: [PATCH 21/41] Create InsulinPlugin --- app/src/main/kotlin/app/aaps/MainApp.kt | 11 +- .../kotlin/app/aaps/di/PluginsListModule.kt | 9 +- .../aaps/core/interfaces/utils/HardLimits.kt | 4 +- .../src/main/res/drawable/ic_auto_fix.xml | 10 + core/utils/src/main/res/values/keys.xml | 1 + .../implementation/utils/HardLimitsImpl.kt | 4 +- .../aaps/plugins/insulin/InsulinFragment.kt | 219 ++++++++++- .../plugins/insulin/InsulinOrefBasePlugin.kt | 1 - .../app/aaps/plugins/insulin/InsulinPlugin.kt | 362 ++++++++++++++++++ .../src/main/res/layout/insulin_fragment.xml | 249 +++++++++++- .../insulin/src/main/res/values/strings.xml | 11 +- .../app/aaps/shared/tests/HardLimitsMock.kt | 4 +- 12 files changed, 853 insertions(+), 32 deletions(-) create mode 100644 core/objects/src/main/res/drawable/ic_auto_fix.xml create mode 100644 plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt diff --git a/app/src/main/kotlin/app/aaps/MainApp.kt b/app/src/main/kotlin/app/aaps/MainApp.kt index 0b111a66061..2a7c7710581 100644 --- a/app/src/main/kotlin/app/aaps/MainApp.kt +++ b/app/src/main/kotlin/app/aaps/MainApp.kt @@ -203,7 +203,6 @@ class MainApp : DaggerApplication() { sp.getBoolean("ConfigBuilder_INSULIN_InsulinOrefUltraRapidActingPlugin_Enabled", false) || sp.getBoolean("ConfigBuilder_INSULIN_InsulinLyumjevPlugin_Enabled", false) || sp.getBoolean("ConfigBuilder_INSULIN_InsulinOrefFreePeakPlugin_Enabled", false)) { - aapsLogger.debug("XXXXX Start Migration") val defaultInsulin = when { sp.getBoolean("ConfigBuilder_INSULIN_InsulinOrefUltraRapidActingPlugin_Enabled", false) -> Insulin.InsulinType.OREF_ULTRA_RAPID_ACTING.getICfg() sp.getBoolean("ConfigBuilder_INSULIN_InsulinLyumjevPlugin_Enabled", false) -> Insulin.InsulinType.OREF_LYUMJEV.getICfg() @@ -213,7 +212,15 @@ class MainApp : DaggerApplication() { else -> Insulin.InsulinType.OREF_RAPID_ACTING.getICfg() } migrateProfiles(defaultInsulin) - // todo include remove key and put key to activate InsulinPlugin + sp.remove("ConfigBuilder_INSULIN_InsulinOrefRapidActingPlugin_Enabled") + sp.remove("ConfigBuilder_INSULIN_InsulinOrefRapidActingPlugin_Visible") + sp.remove("ConfigBuilder_INSULIN_InsulinOrefUltraRapidActingPlugin_Enabled") + sp.remove("ConfigBuilder_INSULIN_InsulinOrefUltraRapidActingPlugin_Visible") + sp.remove("ConfigBuilder_INSULIN_InsulinLyumjevPlugin_Enabled") + sp.remove("ConfigBuilder_INSULIN_InsulinLyumjevPlugin_Visible") + sp.remove("ConfigBuilder_INSULIN_InsulinOrefFreePeakPlugin_Enabled") + sp.remove("ConfigBuilder_INSULIN_InsulinOrefFreePeakPlugin_Visible") + sp.putBoolean("ConfigBuilder_INSULIN_InsulinPlugin_Enabled", true) } // 3.1.0 diff --git a/app/src/main/kotlin/app/aaps/di/PluginsListModule.kt b/app/src/main/kotlin/app/aaps/di/PluginsListModule.kt index 30570b41c1d..325970bfda2 100644 --- a/app/src/main/kotlin/app/aaps/di/PluginsListModule.kt +++ b/app/src/main/kotlin/app/aaps/di/PluginsListModule.kt @@ -16,6 +16,7 @@ import app.aaps.plugins.constraints.safety.SafetyPlugin import app.aaps.plugins.constraints.signatureVerifier.SignatureVerifierPlugin import app.aaps.plugins.constraints.storage.StorageConstraintPlugin import app.aaps.plugins.constraints.versionChecker.VersionCheckerPlugin +import app.aaps.plugins.insulin.InsulinPlugin import app.aaps.plugins.insulin.InsulinLyumjevPlugin import app.aaps.plugins.insulin.InsulinOrefFreePeakPlugin import app.aaps.plugins.insulin.InsulinOrefRapidActingPlugin @@ -120,12 +121,18 @@ abstract class PluginsListModule { @IntKey(42) abstract fun bindInsulinLyumjevPlugin(plugin: InsulinLyumjevPlugin): PluginBase - @Binds +@Binds @AllConfigs @IntoMap @IntKey(50) abstract fun bindInsulinOrefFreePeakPlugin(plugin: InsulinOrefFreePeakPlugin): PluginBase + @Binds + @AllConfigs + @IntoMap + @IntKey(55) + abstract fun bindInsulinPlugin(plugin: InsulinPlugin): PluginBase + @Binds @AllConfigs @IntoMap diff --git a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/utils/HardLimits.kt b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/utils/HardLimits.kt index 56ece59da85..965906d6785 100644 --- a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/utils/HardLimits.kt +++ b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/utils/HardLimits.kt @@ -38,8 +38,8 @@ interface HardLimits { fun maxDia(): Double fun minIC(): Double fun maxIC(): Double - fun minPeak(): Double - fun maxPeak(): Double + fun minPeak(): Int + fun maxPeak(): Int // safety checks fun checkHardLimits(value: Double, valueName: Int, lowLimit: Double, highLimit: Double): Boolean diff --git a/core/objects/src/main/res/drawable/ic_auto_fix.xml b/core/objects/src/main/res/drawable/ic_auto_fix.xml new file mode 100644 index 00000000000..caa88df7fb4 --- /dev/null +++ b/core/objects/src/main/res/drawable/ic_auto_fix.xml @@ -0,0 +1,10 @@ + + + + + diff --git a/core/utils/src/main/res/values/keys.xml b/core/utils/src/main/res/values/keys.xml index 31b4be268dd..96ff6529c02 100644 --- a/core/utils/src/main/res/values/keys.xml +++ b/core/utils/src/main/res/values/keys.xml @@ -32,5 +32,6 @@ ObjectivesActionsUsed ObjectivesScaleUsed used_autosens_on_main_phone + insulin_configuration \ No newline at end of file diff --git a/implementation/src/main/kotlin/app/aaps/implementation/utils/HardLimitsImpl.kt b/implementation/src/main/kotlin/app/aaps/implementation/utils/HardLimitsImpl.kt index 224d22cfa40..47f6afbfdc4 100644 --- a/implementation/src/main/kotlin/app/aaps/implementation/utils/HardLimitsImpl.kt +++ b/implementation/src/main/kotlin/app/aaps/implementation/utils/HardLimitsImpl.kt @@ -51,8 +51,8 @@ class HardLimitsImpl @Inject constructor( override fun maxDia(): Double = HardLimits.MAX_DIA[loadAge()] override fun minIC(): Double = HardLimits.MIN_IC[loadAge()] override fun maxIC(): Double = HardLimits.MAX_IC[loadAge()] - override fun minPeak(): Double = 35.0 - override fun maxPeak(): Double = 120.0 + override fun minPeak(): Int = 35 + override fun maxPeak(): Int = 120 // safety checks override fun checkHardLimits(value: Double, valueName: Int, lowLimit: Double, highLimit: Double): Boolean = diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt index 5579bc447a1..9e94021d9b3 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt @@ -1,25 +1,62 @@ package app.aaps.plugins.insulin import android.os.Bundle +import android.text.Editable +import android.text.TextWatcher import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.AdapterView +import android.widget.ArrayAdapter +import app.aaps.core.data.model.ICfg +import app.aaps.core.data.ue.Action +import app.aaps.core.data.ue.Sources +import app.aaps.core.data.ue.ValueWithUnit +import app.aaps.core.interfaces.insulin.Insulin +import app.aaps.core.interfaces.logging.AAPSLogger +import app.aaps.core.interfaces.logging.UserEntryLogger import app.aaps.core.interfaces.plugin.ActivePlugin import app.aaps.core.interfaces.resources.ResourceHelper +import app.aaps.core.interfaces.utils.HardLimits +import app.aaps.core.interfaces.utils.SafeParse +import app.aaps.core.ui.dialogs.OKDialog +import app.aaps.core.ui.extensions.toVisibility import app.aaps.plugins.insulin.databinding.InsulinFragmentBinding +import com.google.android.material.tabs.TabLayout import dagger.android.support.DaggerFragment +import java.text.DecimalFormat import javax.inject.Inject class InsulinFragment : DaggerFragment() { @Inject lateinit var activePlugin: ActivePlugin + @Inject lateinit var hardLimits: HardLimits @Inject lateinit var rh: ResourceHelper + @Inject lateinit var insulinPlugin: InsulinPlugin + @Inject lateinit var uel: UserEntryLogger + @Inject lateinit var aapsLogger: AAPSLogger private var _binding: InsulinFragmentBinding? = null // This property is only valid between onCreateView and // onDestroyView. private val binding get() = _binding!! + private val currentInsulin: ICfg + get() = insulinPlugin.currentInsulin + private var selectedTemplate = Insulin.InsulinType.OREF_RAPID_ACTING // Default Insulin (should only be used on new install + private var minPeak = Insulin.InsulinType.OREF_RAPID_ACTING.peak.toDouble() + private var maxPeak = Insulin.InsulinType.OREF_RAPID_ACTING.peak.toDouble() + + private val textWatch = object : TextWatcher { + override fun afterTextChanged(s: Editable) {} + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {} + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + currentInsulin.insulinLabel = binding.name.text.toString() + currentInsulin.setPeak(SafeParse.stringToInt(binding.peak.text)) + currentInsulin.setDia(SafeParse.stringToDouble(binding.dia.text)) + doEdit() + } + } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -29,16 +66,190 @@ class InsulinFragment : DaggerFragment() { return binding.root } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + binding.insulinList.onItemClickListener = AdapterView.OnItemClickListener { _, _, position, _ -> + if (insulinPlugin.isEdited) { + activity?.let { activity -> + OKDialog.showConfirmation( + activity, rh.gs(R.string.do_you_want_switch_insulin), + { + insulinPlugin.currentInsulinIndex = position + insulinPlugin.currentInsulin = insulinPlugin.currentInsulin().deepClone() + insulinPlugin.isEdited = false + build() + }, null + ) + } + } else { + insulinPlugin.currentInsulinIndex = position + insulinPlugin.currentInsulin = insulinPlugin.currentInsulin().deepClone() + build() + } + } + if (insulinPlugin.numOfInsulins == 0) + insulinPlugin.addNewInsulin( + ICfg("", selectedTemplate.peak, selectedTemplate.dia), + autoName = true + ) + insulinPlugin.currentInsulin = insulinPlugin.currentInsulin().deepClone() + + processVisibility(0) + binding.tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener { + override fun onTabSelected(tab: TabLayout.Tab) { + processVisibility(tab.position) + } + + override fun onTabUnselected(tab: TabLayout.Tab) {} + override fun onTabReselected(tab: TabLayout.Tab) {} + }) + + binding.insulinTemplate.onItemClickListener = AdapterView.OnItemClickListener { _, _, position, _ -> + selectedTemplate = insulinFromTemplate(insulinPlugin.insulinTemplateList()[position].toString()) + currentInsulin.setPeak(selectedTemplate.peak) + currentInsulin.setDia(selectedTemplate.dia) + insulinPlugin.isEdited = false + build() + } + binding.insulinAdd.setOnClickListener { + if (insulinPlugin.isEdited) { + activity?.let { OKDialog.show(it, "", rh.gs(R.string.save_or_reset_changes_first)) } + } else { + insulinPlugin.addNewInsulin( + ICfg( + insulinLabel = "", // Let plugin propose a new unique name from template + peak = selectedTemplate.peak, + dia = selectedTemplate.dia + ) + ) + insulinPlugin.isEdited = true + build() + } + } + binding.insulinRemove.setOnClickListener { + if (insulinPlugin.isEdited) { + activity?.let { OKDialog.show(it, "", rh.gs(R.string.save_or_reset_changes_first)) } + } else { + if (insulinPlugin.currentInsulinIndex != insulinPlugin.defaultInsulinIndex) { + insulinPlugin.removeCurrentInsulin(activity) + insulinPlugin.isEdited = false + } + build() + } + } + binding.reset.setOnClickListener { + insulinPlugin.currentInsulin = insulinPlugin.currentInsulin().deepClone() + insulinPlugin.isEdited = false + build() + } + binding.save.setOnClickListener { + if (!insulinPlugin.isValidEditState(activity)) { + return@setOnClickListener //Should not happen as saveButton should not be visible if not valid + } + uel.log( + action = Action.STORE_INSULIN, source = Sources.Insulin, + value = ValueWithUnit.SimpleString(insulinPlugin.currentInsulin().insulinLabel) + ) + insulinPlugin.insulins[insulinPlugin.currentInsulinIndex] = currentInsulin + insulinPlugin.storeSettings() + insulinPlugin.isEdited = false + build() + } + binding.autoName.setOnClickListener { + binding.name.setText(insulinPlugin.createNewInsulinLabel(currentInsulin, includingCurrent = false)) + insulinPlugin.isEdited = true + build() + } + + val insulinTemplateList: ArrayList = insulinPlugin.insulinTemplateList() + context?.let { context -> + binding.insulinTemplate.setAdapter(ArrayAdapter(context, app.aaps.core.ui.R.layout.spinner_centered, insulinTemplateList)) + } ?: return + insulinPlugin.currentInsulin = insulinPlugin.currentInsulin().deepClone() + binding.insulinTemplate.setText(currentInsulin.let { rh.gs(Insulin.InsulinType.fromPeak(it.insulinPeakTime).label) }, false) + } + override fun onResume() { super.onResume() - binding.name.text = activePlugin.activeInsulin.friendlyName - binding.comment.text = activePlugin.activeInsulin.comment - binding.dia.text = rh.gs(app.aaps.core.ui.R.string.dia) + ": " + rh.gs(app.aaps.core.ui.R.string.format_hours, activePlugin.activeInsulin.dia) - binding.graph.show(activePlugin.activeInsulin) + build() } override fun onDestroyView() { super.onDestroyView() _binding = null } + + private fun updateGUI() { + if (_binding == null) return + val isValid = insulinPlugin.isValidEditState(activity) + val isEdited = insulinPlugin.isEdited + + val insulinList: ArrayList = insulinPlugin.insulinList() + context?.let { context -> + binding.insulinList.setAdapter(ArrayAdapter(context, app.aaps.core.ui.R.layout.spinner_centered, insulinList)) + } ?: return + binding.insulinList.setText(insulinPlugin.currentInsulin().insulinLabel, false) + if (isValid) { + this.view?.setBackgroundColor(rh.gac(context, app.aaps.core.ui.R.attr.okBackgroundColor)) + binding.insulinList.isEnabled = true + + if (isEdited) { + //edited insulin -> save first + //binding.updateProfiles.visibility = View.GONE + binding.save.visibility = View.VISIBLE + } else { + //binding.updateProfiles.visibility = View.VISIBLE + binding.save.visibility = View.GONE + } + } else { + this.view?.setBackgroundColor(rh.gac(context, app.aaps.core.ui.R.attr.errorBackgroundColor)) + binding.insulinList.isEnabled = false + //binding.updateProfiles.visibility = View.GONE + binding.save.visibility = View.GONE //don't save an invalid profile + } + + //Show reset button if data was edited + if (isEdited) { + binding.reset.visibility = View.VISIBLE + } else { + binding.reset.visibility = View.GONE + } + binding.graph.show(activePlugin.activeInsulin, currentInsulin) + } + + fun build() { + binding.insulinTemplate.setText(rh.gs(Insulin.InsulinType.fromPeak(currentInsulin.insulinPeakTime).label), false) + binding.name.removeTextChangedListener(textWatch) + binding.name.setText(currentInsulin.insulinLabel) + binding.name.addTextChangedListener(textWatch) + binding.insulinList.filters = arrayOf() + binding.insulinList.setText(insulinPlugin.currentInsulin()?.insulinLabel ?:"") + + when (selectedTemplate) { + Insulin.InsulinType.OREF_FREE_PEAK -> { + minPeak = hardLimits.minPeak().toDouble() + maxPeak = hardLimits.maxPeak().toDouble() + } + else -> { + minPeak = currentInsulin.getPeak().toDouble() + maxPeak = minPeak + } + } + binding.peak.setParams(currentInsulin.getPeak().toDouble(), minPeak, maxPeak, 1.0, DecimalFormat("0"), false, null, textWatch) + binding.dia.setParams(currentInsulin.getDia(), hardLimits.minDia(), hardLimits.maxDia(), 0.1, DecimalFormat("0.0"), false, null, textWatch) + + updateGUI() + } + + fun insulinFromTemplate(label: String): Insulin.InsulinType = Insulin.InsulinType.values().firstOrNull { rh.gs(it.label) == label } ?:Insulin.InsulinType.OREF_FREE_PEAK + + fun doEdit() { + insulinPlugin.isEdited = true + updateGUI() + } + + private fun processVisibility(position: Int) { + binding.insulinPlaceholder.visibility = (position == 0).toVisibility() + binding.profilePlaceholder.visibility = (position == 1).toVisibility() + } } \ No newline at end of file diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt index 166791f6ec4..933247122eb 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt @@ -4,7 +4,6 @@ import app.aaps.core.data.iob.Iob import app.aaps.core.data.model.BS import app.aaps.core.data.model.ICfg import app.aaps.core.data.plugin.PluginType -import app.aaps.core.data.time.T import app.aaps.core.interfaces.configuration.Config import app.aaps.core.interfaces.insulin.Insulin import app.aaps.core.interfaces.logging.AAPSLogger diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt new file mode 100644 index 00000000000..7e9a5b42ad2 --- /dev/null +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt @@ -0,0 +1,362 @@ +package app.aaps.plugins.insulin + +import androidx.fragment.app.FragmentActivity +import app.aaps.core.data.iob.Iob +import app.aaps.core.data.model.BS +import app.aaps.core.data.model.ICfg +import app.aaps.core.data.plugin.PluginType +import app.aaps.core.data.ue.Action +import app.aaps.core.data.ue.Sources +import app.aaps.core.data.ue.ValueWithUnit +import app.aaps.core.interfaces.configuration.Config +import app.aaps.core.interfaces.insulin.Insulin +import app.aaps.core.interfaces.logging.AAPSLogger +import app.aaps.core.interfaces.logging.LTag +import app.aaps.core.interfaces.logging.UserEntryLogger +import app.aaps.core.interfaces.notifications.Notification +import app.aaps.core.interfaces.plugin.PluginBase +import app.aaps.core.interfaces.plugin.PluginDescription +import app.aaps.core.interfaces.profile.ProfileFunction +import app.aaps.core.interfaces.resources.ResourceHelper +import app.aaps.core.interfaces.rx.bus.RxBus +import app.aaps.core.interfaces.sharedPreferences.SP +import app.aaps.core.interfaces.ui.UiInteraction +import app.aaps.core.interfaces.utils.HardLimits +import app.aaps.core.keys.Preferences +import app.aaps.core.objects.extensions.fromJson +import app.aaps.core.objects.extensions.toJson +import app.aaps.core.ui.toast.ToastUtils +import org.json.JSONArray +import org.json.JSONObject +import javax.inject.Inject +import javax.inject.Singleton +import kotlin.math.exp +import kotlin.math.pow + +/** + * Created by Philoul on 29.12.2024. + * + * + */ + +@Singleton +class InsulinPlugin @Inject constructor( + val preferences: Preferences, + rh: ResourceHelper, + val profileFunction: ProfileFunction, + val rxBus: RxBus, + private val sp: SP, + aapsLogger: AAPSLogger, + val config: Config, + val hardLimits: HardLimits, + val uiInteraction: UiInteraction, + val uel: UserEntryLogger +) : PluginBase( + PluginDescription() + .mainType(PluginType.INSULIN) + .fragmentClass(InsulinFragment::class.java.name) + .pluginIcon(app.aaps.core.objects.R.drawable.ic_insulin) + .pluginName(R.string.insulin_plugin) + .shortName(R.string.insulin_shortname) + .visibleByDefault(true) + .neverVisible(config.AAPSCLIENT) + .description(R.string.description_insulin_plugin), + aapsLogger, rh +), Insulin { + + override val id = Insulin.InsulinType.UNKNOWN + override var friendlyName: String = "Insulin" + + override val dia + get(): Double { + val dia = userDefinedDia + return if (dia >= hardLimits.minDia() && dia <= hardLimits.maxDia()) { + dia + } else { + if (dia < hardLimits.minDia()) + hardLimits.minDia() + else + hardLimits.maxDia() + } + } + override val peak: Int + get(): Int { + val peak = userDefinedPeak + return if (peak >= hardLimits.minPeak() && dia <= hardLimits.maxPeak()) { + peak.toInt() + } else { + if (peak < hardLimits.minPeak()) + hardLimits.minPeak().toInt() + else + hardLimits.maxDia().toInt() + } + } + + override fun setDefault(insulin: ICfg?) { + insulins.forEachIndexed { index, iCfg -> + if(iCfg.isEqual(insulin)) + defaultInsulinIndex = index + } + currentInsulinIndex = defaultInsulinIndex + } + + override val iCfg: ICfg + get() = insulins[defaultInsulinIndex] + + lateinit var currentInsulin: ICfg + private var lastWarned: Long = 0 + var insulins: ArrayList = ArrayList() + var defaultInsulinIndex = 0 + var currentInsulinIndex = 0 + val numOfInsulins get() = insulins.size + var isEdited: Boolean = false + val userDefinedDia: Double + get() { + val profile = profileFunction.getProfile() + return profile?.dia ?: hardLimits.minDia() + } + val userDefinedPeak: Int + get() { + val profile = profileFunction.getProfile() + return profile?.insulin?.getPeak() ?: hardLimits.minPeak() + } + + override fun onStart() { + super.onStart() + loadSettings() + } + + override fun insulinList(): ArrayList { + val ret = ArrayList() + insulins.forEach { ret.add(it.insulinLabel) } + return ret + } + + override fun getOrCreateInsulin(iCfg: ICfg): ICfg { + // First Check insulin with hardlimits, and set default value if not consistent + if (iCfg.getPeak() < hardLimits.minPeak() || iCfg.getPeak() > hardLimits.maxPeak()) + iCfg.insulinPeakTime = insulins[defaultInsulinIndex].insulinPeakTime + if (iCfg.getDia() < hardLimits.minDia() || iCfg.getDia() > hardLimits.maxDia()) + iCfg.insulinEndTime = insulins[defaultInsulinIndex].insulinEndTime + insulins.forEach { + if (iCfg.isEqual(it)) + return it + } + return addNewInsulin(iCfg, true) + } + + override fun getInsulin(insulinLabel: String): ICfg { + insulins.forEach { + if (it.insulinLabel == insulinLabel) + return it + } + aapsLogger.debug(LTag.APS, "Insulin $insulinLabel not found, return default insulin ${insulins[defaultInsulinIndex].insulinLabel}") + return insulins[defaultInsulinIndex] + } + + fun insulinTemplateList(): ArrayList { + val ret = ArrayList() + ret.add(rh.gs(Insulin.InsulinType.OREF_RAPID_ACTING.label)) + ret.add(rh.gs(Insulin.InsulinType.OREF_ULTRA_RAPID_ACTING.label)) + ret.add(rh.gs(Insulin.InsulinType.OREF_LYUMJEV.label)) + ret.add(rh.gs(Insulin.InsulinType.OREF_FREE_PEAK.label)) + return ret + } + + fun sendShortDiaNotification(dia: Double) { + // Todo Check if we need this kind of function to send notification + if (System.currentTimeMillis() - lastWarned > 60 * 1000) { + lastWarned = System.currentTimeMillis() + uiInteraction.addNotification(Notification.SHORT_DIA, String.format(notificationPattern, dia, hardLimits.minDia()), Notification.URGENT) + } + } + private val notificationPattern: String + get() = rh.gs(R.string.dia_too_short) + + + fun addNewInsulin(template: ICfg, autoName: Boolean = false): ICfg { + if (autoName) + template.insulinLabel = createNewInsulinLabel(template) + val newInsulin = template.deepClone() + insulins.add(newInsulin) + uel.log(Action.NEW_INSULIN, Sources.Insulin, value = ValueWithUnit.SimpleString(newInsulin.insulinLabel)) + currentInsulinIndex = insulins.size - 1 + currentInsulin = newInsulin.deepClone() + storeSettings() + return newInsulin + } + + fun removeCurrentInsulin(activity: FragmentActivity?) { + // activity included to include PopUp or Toast when Remove can't be done (default insulin or insulin used within profile + // Todo include Remove authorization and message + val insulinRemoved = currentInsulin().insulinLabel + insulins.removeAt(currentInsulinIndex) + uel.log(Action.INSULIN_REMOVED, Sources.Insulin, value = ValueWithUnit.SimpleString(insulinRemoved)) + currentInsulinIndex = defaultInsulinIndex + currentInsulin = currentInsulin().deepClone() + storeSettings() + } + + fun createNewInsulinLabel(iCfg: ICfg, includingCurrent: Boolean = true): String { + val template = Insulin.InsulinType.fromPeak(iCfg.insulinPeakTime) + var insulinLabel = when (template) { + Insulin.InsulinType.OREF_FREE_PEAK -> "${rh.gs(template.label)}_${iCfg.getPeak()}_${iCfg.getDia()}" + else -> "${rh.gs(template.label)}_${iCfg.getDia()}" + } + if (insulinLabelAlreadyExists(insulinLabel, if (includingCurrent) 10000 else currentInsulinIndex)) { + for (i in 1..10000) { + if (!insulinLabelAlreadyExists("${insulinLabel}_$i", if (includingCurrent) 10000 else currentInsulinIndex)) { + insulinLabel = "${insulinLabel}_$i" + break + } + } + } + return insulinLabel + } + + + @Synchronized + fun loadSettings() { + val jsonString = sp.getString(app.aaps.core.utils.R.string.key_insulin_configuration, "") + try { + JSONObject(jsonString).let { + applyConfiguration(it) + } + } catch (_: Exception) { + // + } + } + + @Synchronized + fun storeSettings() { + sp.putString(app.aaps.core.utils.R.string.key_insulin_configuration, configuration().toString()) + } + + override fun iobCalcForTreatment(bolus: BS, time: Long, iCfg: ICfg): Iob { + return iobCalc(bolus, time, iCfg.getPeak().toDouble(), iCfg.getDia()) + } + + override fun iobCalcForTreatment(bolus: BS, time: Long, dia: Double): Iob { + assert(dia != 0.0) + assert(peak != 0) + return iobCalc(bolus, time, peak.toDouble(), dia) + } + + private fun iobCalc(bolus: BS, time: Long, peak: Double, dia: Double): Iob { + val result = Iob() + if (bolus.amount != 0.0) { + val bolusTime = bolus.timestamp + val t = (time - bolusTime) / 1000.0 / 60.0 + val td = dia * 60 //getDIA() always >= MIN_DIA + val tp = peak + // force the IOB to 0 if over DIA hours have passed + if (t < td) { + val tau = tp * (1 - tp / td) / (1 - 2 * tp / td) + val a = 2 * tau / td + val s = 1 / (1 - a + (1 + a) * exp(-td / tau)) + result.activityContrib = bolus.amount * (s / tau.pow(2.0)) * t * (1 - t / td) * exp(-t / tau) + result.iobContrib = bolus.amount * (1 - s * (1 - a) * ((t.pow(2.0) / (tau * td * (1 - a)) - t / tau - 1) * exp(-t / tau) + 1)) + } + } + return result + } + + @Synchronized + override fun configuration(): JSONObject { + val json = JSONObject() + val jsonArray = JSONArray() + insulins.forEach { + try { + jsonArray.put(it.toJson()) + } catch (e: Exception) { + // + } + } + json.put("insulins", jsonArray) + json.put("default_insulin", defaultInsulinIndex) + json.put("current_insulin", currentInsulinIndex) + return json + } + + override fun applyConfiguration(configuration: JSONObject) { + insulins.clear() + configuration.optJSONArray("insulins")?.let { + for (index in 0 until (it.length())) { + try { + val o = it.getJSONObject(index) + insulins.add(ICfg.fromJson(o)) + + } catch (e: Exception) { + // + } + } + } + defaultInsulinIndex = configuration.optInt("default_insulin") + currentInsulinIndex = configuration.optInt("current_insulin") + } + + override val comment + get(): String { + var comment = commentStandardText() + val userDia = userDefinedDia + if (userDia < hardLimits.minDia()) { + comment += "\n" + rh.gs(R.string.dia_too_short, userDia, hardLimits.minDia()) + } + return comment + } + + fun commentStandardText(): String { + return rh.gs(R.string.insulin_peak_time) + ": " + peak + } + + @Synchronized + fun isValidEditState(activity: FragmentActivity?, verbose: Boolean = true): Boolean { + with(currentInsulin) { + if (insulinEndTime < hardLimits.minDia() || dia > hardLimits.maxDia()) { + if (verbose) + ToastUtils.errorToast(activity, rh.gs(app.aaps.core.ui.R.string.value_out_of_hard_limits, rh.gs(app.aaps.core.ui.R.string.insulin_dia), dia)) + return false + } + if (peak < hardLimits.minPeak() || dia > hardLimits.maxPeak()) { + if (verbose) + ToastUtils.errorToast(activity, rh.gs(app.aaps.core.ui.R.string.value_out_of_hard_limits, rh.gs(app.aaps.core.ui.R.string.insulin_peak), peak)) + return false + } + if (insulinLabel.isEmpty()) { + if (verbose) + ToastUtils.errorToast(activity, rh.gs(R.string.missing_insulin_name)) + return false + } + // Check Inulin name is unique and insulin parameters is unique + if (insulinLabelAlreadyExists(this.insulinLabel, currentInsulinIndex)) { + if (verbose) + ToastUtils.errorToast(activity, rh.gs(R.string.insulin_name_exists, insulinLabel)) + return false + } + + insulins.forEachIndexed { index, iCfg -> + if (index != currentInsulinIndex) { + if (isEqual(iCfg)) { + if (verbose) + ToastUtils.errorToast(activity, rh.gs(R.string.insulin_duplicated, iCfg.insulinLabel)) + return false + } + } + } + } + return true + } + + private fun insulinLabelAlreadyExists(insulinLabel: String, currentIndex: Int): Boolean { + insulins.forEachIndexed { index, iCfg -> + if (index != currentIndex) { + if (iCfg.insulinLabel == insulinLabel) { + return true + } + } + } + return false + } + + fun currentInsulin(): ICfg = insulins[currentInsulinIndex] +} \ No newline at end of file diff --git a/plugins/insulin/src/main/res/layout/insulin_fragment.xml b/plugins/insulin/src/main/res/layout/insulin_fragment.xml index 99e57da9d47..167969485fa 100644 --- a/plugins/insulin/src/main/res/layout/insulin_fragment.xml +++ b/plugins/insulin/src/main/res/layout/insulin_fragment.xml @@ -1,5 +1,6 @@ @@ -9,32 +10,246 @@ android:layout_height="wrap_content" android:orientation="vertical"> - + android:layout_marginStart="5dp" + android:layout_marginEnd="5dp" + android:hint="@string/select_insulin"> - + + + + + android:layout_height="wrap_content"> + + + + - + + + android:orientation="vertical"> + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + android:layout_height="wrap_content" + android:orientation="vertical"> + + diff --git a/plugins/insulin/src/main/res/values/strings.xml b/plugins/insulin/src/main/res/values/strings.xml index 2df3a352efd..0e79826079e 100644 --- a/plugins/insulin/src/main/res/values/strings.xml +++ b/plugins/insulin/src/main/res/values/strings.xml @@ -5,12 +5,21 @@ Insulin preset for Fiasp Insulin preset for Lyumjev Allows you to define the peak of the insulin activity and should only be used by advanced users + Allows you to manage the different insulin you will use within AAPS + Insulin INS IOB Curve Peak Time Peak Time [min] + Update Profiles DIA of %1$f too short - using %2$f instead! Novorapid, Novolog, Humalog Fiasp - + Missing Insulin Name + Insulin Name %1$s already exists, select a new name + Insulin already exists with name: %1$s + Do you want to switch insulin and discard changes made to current insulin? + Add new insulin + Delete current insulin + Save or reset current changes first \ No newline at end of file diff --git a/shared/tests/src/main/kotlin/app/aaps/shared/tests/HardLimitsMock.kt b/shared/tests/src/main/kotlin/app/aaps/shared/tests/HardLimitsMock.kt index 20913ed601f..c7114c0ba91 100644 --- a/shared/tests/src/main/kotlin/app/aaps/shared/tests/HardLimitsMock.kt +++ b/shared/tests/src/main/kotlin/app/aaps/shared/tests/HardLimitsMock.kt @@ -67,8 +67,8 @@ import kotlin.math.min override fun maxDia(): Double = MAX_DIA[loadAge()] override fun minIC(): Double = MIN_IC[loadAge()] override fun maxIC(): Double = MAX_IC[loadAge()] - override fun minPeak(): Double = 35.0 - override fun maxPeak(): Double = 120.0 + override fun minPeak(): Int = 35 + override fun maxPeak(): Int = 120 // safety checks override fun checkHardLimits(value: Double, valueName: Int, lowLimit: Double, highLimit: Double): Boolean = From 5c4615ce8a01f684c7be365a9016fe3cb669de4b Mon Sep 17 00:00:00 2001 From: Philoul Date: Thu, 27 Feb 2025 19:03:09 +0100 Subject: [PATCH 22/41] Update ProfileFragment for insulin selection --- .../aaps/core/interfaces/insulin/Insulin.kt | 2 +- .../plugins/insulin/InsulinOrefBasePlugin.kt | 2 +- .../app/aaps/plugins/insulin/InsulinPlugin.kt | 12 +++-- .../plugins/main/profile/ProfileFragment.kt | 40 ++++++++++----- .../src/main/res/layout/profile_fragment.xml | 51 +++++++------------ 5 files changed, 55 insertions(+), 52 deletions(-) diff --git a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/insulin/Insulin.kt b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/insulin/Insulin.kt index 43fc93d0fa2..cc60e0575df 100644 --- a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/insulin/Insulin.kt +++ b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/insulin/Insulin.kt @@ -33,7 +33,7 @@ interface Insulin : ConfigExportImport { val comment: String val dia: Double val peak: Int - fun setDefault(iCfg: ICfg?) + fun setDefault(iCfg: ICfg) fun insulinList() = ArrayList() fun getOrCreateInsulin(iCfg: ICfg): ICfg fun getInsulin(insulinLabel: String): ICfg diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt index 933247122eb..8f054d31e9a 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt @@ -54,7 +54,7 @@ abstract class InsulinOrefBasePlugin( hardLimits.minDia() } } - override fun setDefault(iCfg: ICfg?) { + override fun setDefault(iCfg: ICfg) { // fun added for future unique Insulin Plugin to replace "selected insulin plugin", by "DefaultInsulin" } diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt index 7e9a5b42ad2..1eb53fa5b70 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt @@ -92,12 +92,14 @@ class InsulinPlugin @Inject constructor( } } - override fun setDefault(insulin: ICfg?) { - insulins.forEachIndexed { index, iCfg -> - if(iCfg.isEqual(insulin)) - defaultInsulinIndex = index + override fun setDefault(insulin: ICfg) { + getOrCreateInsulin(insulin).let { + insulins.forEachIndexed { index, iCfg -> + if(iCfg.isEqual(it)) + defaultInsulinIndex = index + } + currentInsulinIndex = defaultInsulinIndex } - currentInsulinIndex = defaultInsulinIndex } override val iCfg: ICfg diff --git a/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfileFragment.kt b/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfileFragment.kt index cc593a968f2..6cf7ec1125e 100644 --- a/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfileFragment.kt +++ b/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfileFragment.kt @@ -68,6 +68,8 @@ class ProfileFragment : DaggerFragment() { private var inMenu = false private var queryingProtection = false private var basalView: TimeListEdit? = null + private val insulinPlugin + get() = activePlugin.activeInsulin private val save = Runnable { doEdit() @@ -77,7 +79,7 @@ class ProfileFragment : DaggerFragment() { binding.icGraph.show(ProfileSealed.Pure(it, null)) binding.isfGraph.show(ProfileSealed.Pure(it, null)) binding.targetGraph.show(ProfileSealed.Pure(it, null)) - binding.insulinGraph.show(activePlugin.activeInsulin, profilePlugin.currentProfile()?.iCfg) + binding.insulinGraph.show(activePlugin.activeInsulin, it.iCfg) } } @@ -85,13 +87,11 @@ class ProfileFragment : DaggerFragment() { override fun afterTextChanged(s: Editable) {} override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {} override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { - val dia = SafeParse.stringToDouble(binding.dia.text) - val peak = activePlugin.activeInsulin.peak - val name = activePlugin.activeInsulin.friendlyName - profilePlugin.currentProfile()?.dia = dia - profilePlugin.currentProfile()?.iCfg = ICfg(name, peak, dia) + //profilePlugin.currentProfile()?.dia = SafeParse.stringToDouble(binding.dia.text) profilePlugin.currentProfile()?.name = binding.name.text.toString() - binding.insulinGraph.show(activePlugin.activeInsulin, profilePlugin.currentProfile()?.iCfg) + val insulin = insulinPlugin.getInsulin(binding.insulinList.text.toString()) + profilePlugin.currentProfile()?.iCfg = insulin + profilePlugin.currentProfile()?.dia = insulin.getDia() doEdit() } } @@ -126,7 +126,7 @@ class ProfileFragment : DaggerFragment() { override fun onTabUnselected(tab: TabLayout.Tab) {} override fun onTabReselected(tab: TabLayout.Tab) {} }) - binding.diaLabel.labelFor = binding.dia.editTextId + //binding.diaLabel.labelFor = binding.dia.editTextId binding.unlock.setOnClickListener { queryProtection() } val profiles = profilePlugin.profile?.getProfileList() ?: ArrayList() @@ -136,6 +136,14 @@ class ProfileFragment : DaggerFragment() { val aps = activePlugin.activeAPS binding.isfDynamicLabel.visibility = aps.supportsDynamicIsf().toVisibility() binding.icDynamicLabel.visibility = aps.supportsDynamicIc().toVisibility() + binding.insulinList.onItemClickListener = AdapterView.OnItemClickListener { _, _, _, _ -> + val insulin = insulinPlugin.getInsulin(binding.insulinList.text.toString()) + profilePlugin.currentProfile()?.iCfg = insulin + binding.dia.text = rh.gs(app.aaps.core.ui.R.string.format_hours,insulin.getDia()) + binding.peak.text = rh.gs(app.aaps.core.ui.R.string.mins,insulin.getPeak()) + binding.insulinGraph.show(activePlugin.activeInsulin, insulin) + doEdit() + } } fun build() { @@ -149,10 +157,18 @@ class ProfileFragment : DaggerFragment() { binding.name.addTextChangedListener(textWatch) binding.profileList.filters = arrayOf() binding.profileList.setText(currentProfile.name) - binding.insulinName.text = currentProfile.iCfg.insulinLabel - binding.peak.text = rh.gs(app.aaps.core.ui.R.string.mins,currentProfile.iCfg.getPeak()) - binding.dia.setParams(currentProfile.dia, hardLimits.minDia(), hardLimits.maxDia(), 0.1, DecimalFormat("0.0"), false, null, textWatch) - binding.dia.tag = "LP_DIA" + val insulin = insulinPlugin.getOrCreateInsulin(currentProfile.iCfg) + currentProfile.iCfg = insulin + binding.dia.text = rh.gs(app.aaps.core.ui.R.string.format_hours,insulin.getDia()) + binding.peak.text = rh.gs(app.aaps.core.ui.R.string.mins,insulin.getPeak()) + //binding.dia.setParams(currentProfile.dia, hardLimits.minDia(), hardLimits.maxDia(), 0.1, DecimalFormat("0.0"), false, null, textWatch) + //binding.dia.tag = "LP_DIA" + val insulinList: ArrayList = insulinPlugin.insulinList() + context?.let { context -> + binding.insulinList.setAdapter(ArrayAdapter(context, app.aaps.core.ui.R.layout.spinner_centered, insulinList)) + } ?: return + binding.insulinList.setText(currentProfile.iCfg.insulinLabel, false) + TimeListEdit( requireContext(), aapsLogger, diff --git a/plugins/main/src/main/res/layout/profile_fragment.xml b/plugins/main/src/main/res/layout/profile_fragment.xml index 5caeb6db272..34a17a86f37 100644 --- a/plugins/main/src/main/res/layout/profile_fragment.xml +++ b/plugins/main/src/main/res/layout/profile_fragment.xml @@ -158,36 +158,22 @@ android:layout_height="wrap_content" android:orientation="vertical"> - - - + android:layout_marginStart="5dp" + android:layout_marginEnd="5dp" + android:hint="@string/select_pump_insulin"> - + android:inputType="none" /> - + - - + + android:textAppearance="?android:attr/textAppearanceMedium" /> From 254ea0b728b2c3eea62b4e52817ed08b8fb8ef97 Mon Sep 17 00:00:00 2001 From: Philoul Date: Sun, 2 Mar 2025 12:25:15 +0100 Subject: [PATCH 23/41] List and Save profiles using current insulin --- .../aaps/core/interfaces/insulin/Insulin.kt | 1 - .../core/interfaces/profile/ProfileStore.kt | 3 + core/ui/src/main/res/values/strings.xml | 1 + .../profile/ProfileStoreObject.kt | 15 +++ .../plugins/aps/autotune/AutotuneFragment.kt | 1 - .../aaps/plugins/insulin/InsulinFragment.kt | 98 +++++++++++++++++-- .../plugins/insulin/InsulinOrefBasePlugin.kt | 10 -- .../app/aaps/plugins/insulin/InsulinPlugin.kt | 44 ++++++--- .../src/main/res/layout/insulin_fragment.xml | 6 ++ .../main/res/layout/insulin_profile_item.xml | 33 +++++++ .../insulin/src/main/res/values/strings.xml | 2 + 11 files changed, 177 insertions(+), 37 deletions(-) create mode 100644 plugins/insulin/src/main/res/layout/insulin_profile_item.xml diff --git a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/insulin/Insulin.kt b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/insulin/Insulin.kt index cc60e0575df..0a1db9f7cbf 100644 --- a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/insulin/Insulin.kt +++ b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/insulin/Insulin.kt @@ -30,7 +30,6 @@ interface Insulin : ConfigExportImport { val id: InsulinType val friendlyName: String - val comment: String val dia: Double val peak: Int fun setDefault(iCfg: ICfg) diff --git a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/ProfileStore.kt b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/ProfileStore.kt index d7d82431459..4ae0923e6a9 100644 --- a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/ProfileStore.kt +++ b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/ProfileStore.kt @@ -1,5 +1,7 @@ package app.aaps.core.interfaces.profile +import androidx.collection.ArrayMap +import app.aaps.core.data.model.ICfg import org.json.JSONObject interface ProfileStore { @@ -11,6 +13,7 @@ interface ProfileStore { fun getDefaultProfileJson(): JSONObject? fun getDefaultProfileName(): String? fun getProfileList(): ArrayList + fun getProfileList(iCfg: ICfg): ArrayList fun getSpecificProfile(profileName: String): PureProfile? val allProfilesValid: Boolean } \ No newline at end of file diff --git a/core/ui/src/main/res/values/strings.xml b/core/ui/src/main/res/values/strings.xml index 2872b10d2a6..7c33176208e 100644 --- a/core/ui/src/main/res/values/strings.xml +++ b/core/ui/src/main/res/values/strings.xml @@ -144,6 +144,7 @@ reset ProfileSwitch missing. Please do a profile switch or press \"Activate Profile\" in the LocalProfile. Profile + Profile (%1$d) Select for removal Are you sure you want to remove %1$d items Treatment diff --git a/implementation/src/main/kotlin/app/aaps/implementation/profile/ProfileStoreObject.kt b/implementation/src/main/kotlin/app/aaps/implementation/profile/ProfileStoreObject.kt index 2bf7f1774f3..1494479aa46 100644 --- a/implementation/src/main/kotlin/app/aaps/implementation/profile/ProfileStoreObject.kt +++ b/implementation/src/main/kotlin/app/aaps/implementation/profile/ProfileStoreObject.kt @@ -1,6 +1,7 @@ package app.aaps.implementation.profile import androidx.collection.ArrayMap +import app.aaps.core.data.model.ICfg import app.aaps.core.interfaces.configuration.Config import app.aaps.core.interfaces.logging.AAPSLogger import app.aaps.core.interfaces.plugin.ActivePlugin @@ -69,6 +70,20 @@ class ProfileStoreObject( return ret } + override fun getProfileList(iCfg: ICfg): ArrayList { + val ret = ArrayList() + getStore()?.keys()?.let { keys -> + while (keys.hasNext()) { + val profileName = keys.next() as String + getSpecificProfile(profileName)?.let { + if (it.iCfg.isEqual(iCfg)) + ret.add(profileName) + } + } + } + return ret + } + @Synchronized override fun getSpecificProfile(profileName: String): PureProfile? { var profile: PureProfile? = null diff --git a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneFragment.kt b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneFragment.kt index 51545057c32..bb966eba3dc 100644 --- a/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneFragment.kt +++ b/plugins/aps/src/main/kotlin/app/aaps/plugins/aps/autotune/AutotuneFragment.kt @@ -145,7 +145,6 @@ class AutotuneFragment : DaggerFragment() { profileFunction.getProfile()?.let { currentProfile -> profile = ATProfile(profileStore.getSpecificProfile(profileName)?.let { ProfileSealed.Pure(value = it, activePlugin = null) } ?: currentProfile, injector) } - log("XXXXX AT ${profile?.iCfg?.insulinLabel} peak: ${profile?.iCfg?.getPeak()} dia: ${profile?.iCfg?.getDia()}") autotunePlugin.selectedProfile = profileName resetParam(true) binding.tuneDays.value = autotunePlugin.lastNbDays.toDouble() diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt index 9e94021d9b3..53d50dccf43 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt @@ -8,6 +8,9 @@ import android.view.View import android.view.ViewGroup import android.widget.AdapterView import android.widget.ArrayAdapter +import android.widget.TextView +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView import app.aaps.core.data.model.ICfg import app.aaps.core.data.ue.Action import app.aaps.core.data.ue.Sources @@ -15,15 +18,21 @@ import app.aaps.core.data.ue.ValueWithUnit import app.aaps.core.interfaces.insulin.Insulin import app.aaps.core.interfaces.logging.AAPSLogger import app.aaps.core.interfaces.logging.UserEntryLogger +import app.aaps.core.interfaces.objects.Instantiator import app.aaps.core.interfaces.plugin.ActivePlugin +import app.aaps.core.interfaces.profile.ProfileStore import app.aaps.core.interfaces.resources.ResourceHelper +import app.aaps.core.interfaces.ui.UiInteraction +import app.aaps.core.interfaces.utils.DateUtil import app.aaps.core.interfaces.utils.HardLimits import app.aaps.core.interfaces.utils.SafeParse import app.aaps.core.ui.dialogs.OKDialog import app.aaps.core.ui.extensions.toVisibility import app.aaps.plugins.insulin.databinding.InsulinFragmentBinding +import app.aaps.plugins.insulin.databinding.InsulinProfileItemBinding import com.google.android.material.tabs.TabLayout import dagger.android.support.DaggerFragment +import org.json.JSONObject import java.text.DecimalFormat import javax.inject.Inject @@ -35,6 +44,9 @@ class InsulinFragment : DaggerFragment() { @Inject lateinit var insulinPlugin: InsulinPlugin @Inject lateinit var uel: UserEntryLogger @Inject lateinit var aapsLogger: AAPSLogger + @Inject lateinit var instantiator: Instantiator + @Inject lateinit var uiInteraction: UiInteraction + @Inject lateinit var dateUtil: DateUtil private var _binding: InsulinFragmentBinding? = null @@ -43,9 +55,12 @@ class InsulinFragment : DaggerFragment() { private val binding get() = _binding!! private val currentInsulin: ICfg get() = insulinPlugin.currentInsulin + private var sourceInsulin: ICfg? = null private var selectedTemplate = Insulin.InsulinType.OREF_RAPID_ACTING // Default Insulin (should only be used on new install private var minPeak = Insulin.InsulinType.OREF_RAPID_ACTING.peak.toDouble() private var maxPeak = Insulin.InsulinType.OREF_RAPID_ACTING.peak.toDouble() + private lateinit var profileStore: ProfileStore + private var profileList = ArrayList() private val textWatch = object : TextWatcher { override fun afterTextChanged(s: Editable) {} @@ -68,6 +83,9 @@ class InsulinFragment : DaggerFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + profileStore = activePlugin.activeProfileSource.profile ?: instantiator.provideProfileStore(JSONObject()) + binding.recyclerview.setHasFixedSize(true) + binding.recyclerview.layoutManager = LinearLayoutManager(context) binding.insulinList.onItemClickListener = AdapterView.OnItemClickListener { _, _, position, _ -> if (insulinPlugin.isEdited) { activity?.let { activity -> @@ -86,13 +104,19 @@ class InsulinFragment : DaggerFragment() { insulinPlugin.currentInsulin = insulinPlugin.currentInsulin().deepClone() build() } + sourceInsulin = currentInsulin.deepClone() + profileList = profileStore.getProfileList(currentInsulin) + swapAdapter(profileList) } if (insulinPlugin.numOfInsulins == 0) insulinPlugin.addNewInsulin( ICfg("", selectedTemplate.peak, selectedTemplate.dia), autoName = true ) - insulinPlugin.currentInsulin = insulinPlugin.currentInsulin().deepClone() + insulinPlugin.currentInsulin = insulinPlugin.iCfg.deepClone() + sourceInsulin = currentInsulin.deepClone() + profileList = profileStore.getProfileList(currentInsulin) + swapAdapter(profileList) processVisibility(0) binding.tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener { @@ -108,8 +132,8 @@ class InsulinFragment : DaggerFragment() { selectedTemplate = insulinFromTemplate(insulinPlugin.insulinTemplateList()[position].toString()) currentInsulin.setPeak(selectedTemplate.peak) currentInsulin.setDia(selectedTemplate.dia) - insulinPlugin.isEdited = false - build() + insulinPlugin.isEdited = true + doEdit() } binding.insulinAdd.setOnClickListener { if (insulinPlugin.isEdited) { @@ -150,10 +174,22 @@ class InsulinFragment : DaggerFragment() { action = Action.STORE_INSULIN, source = Sources.Insulin, value = ValueWithUnit.SimpleString(insulinPlugin.currentInsulin().insulinLabel) ) - insulinPlugin.insulins[insulinPlugin.currentInsulinIndex] = currentInsulin - insulinPlugin.storeSettings() - insulinPlugin.isEdited = false - build() + if (profileList.isEmpty()) { + insulinPlugin.insulins[insulinPlugin.currentInsulinIndex] = currentInsulin + insulinPlugin.storeSettings() + build() + } else { + OKDialog.showConfirmation(requireContext(), + rh.gs(R.string.update_profiles_title), + rh.gs(R.string.update_profiles_message, profileList.size), + Runnable { + insulinPlugin.insulins[insulinPlugin.currentInsulinIndex] = currentInsulin + insulinPlugin.storeSettings() + insulinPlugin.updateProfiles(profileList, profileStore, dateUtil.now()) + build() + } + ) + } } binding.autoName.setOnClickListener { binding.name.setText(insulinPlugin.createNewInsulinLabel(currentInsulin, includingCurrent = false)) @@ -171,6 +207,8 @@ class InsulinFragment : DaggerFragment() { override fun onResume() { super.onResume() + sourceInsulin?.let { profileList = profileStore.getProfileList(it) } + swapAdapter(profileList) build() } @@ -223,7 +261,7 @@ class InsulinFragment : DaggerFragment() { binding.name.setText(currentInsulin.insulinLabel) binding.name.addTextChangedListener(textWatch) binding.insulinList.filters = arrayOf() - binding.insulinList.setText(insulinPlugin.currentInsulin()?.insulinLabel ?:"") + binding.insulinList.setText(insulinPlugin.currentInsulin().insulinLabel) when (selectedTemplate) { Insulin.InsulinType.OREF_FREE_PEAK -> { @@ -241,7 +279,7 @@ class InsulinFragment : DaggerFragment() { updateGUI() } - fun insulinFromTemplate(label: String): Insulin.InsulinType = Insulin.InsulinType.values().firstOrNull { rh.gs(it.label) == label } ?:Insulin.InsulinType.OREF_FREE_PEAK + fun insulinFromTemplate(label: String): Insulin.InsulinType = Insulin.InsulinType.entries.firstOrNull { rh.gs(it.label) == label } ?:Insulin.InsulinType.OREF_FREE_PEAK fun doEdit() { insulinPlugin.isEdited = true @@ -252,4 +290,46 @@ class InsulinFragment : DaggerFragment() { binding.insulinPlaceholder.visibility = (position == 0).toVisibility() binding.profilePlaceholder.visibility = (position == 1).toVisibility() } + + private fun swapAdapter(list: List) { + binding.tabLayout.getTabAt(1)?.text = rh.gs(app.aaps.core.ui.R.string.profile_number, list.size) + binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) + } + + inner class RecyclerViewAdapter internal constructor(private var profileList: List) : RecyclerView.Adapter() { + + override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ProfileViewHolder = + ProfileViewHolder(LayoutInflater.from(viewGroup.context).inflate(R.layout.insulin_profile_item, viewGroup, false)) + + override fun onBindViewHolder(holder: ProfileViewHolder, position: Int) { + val record = this@RecyclerViewAdapter.profileList[position] + holder.binding.profileName.text = record + + } + + override fun getItemCount(): Int { + return profileList.size + } + + inner class ProfileViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + + val binding = InsulinProfileItemBinding.bind(itemView) + init { + binding.profileName.setOnClickListener { + activity?.let { activity -> + val profileName = (it as TextView).text.toString() + profileStore.getSpecificProfile((it as TextView).text.toString())?.let { profile -> + uiInteraction.runProfileViewerDialog( + fragmentManager = childFragmentManager, + time = dateUtil.now(), + mode = UiInteraction.Mode.CUSTOM_PROFILE, + customProfile = profile.jsonObject.toString(), + customProfileName = profileName + ) + } + } + } + } + } + } } \ No newline at end of file diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt index 8f054d31e9a..999464d2831 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt @@ -106,16 +106,6 @@ abstract class InsulinOrefBasePlugin( override val iCfg: ICfg get() = ICfg(friendlyName, peak, dia) - override val comment - get(): String { - var comment = commentStandardText() - val userDia = userDefinedDia - if (userDia < hardLimits.minDia()) { - comment += "\n" + rh.gs(R.string.dia_too_short, userDia, hardLimits.minDia()) - } - return comment - } - abstract override val peak: Int abstract fun commentStandardText(): String } \ No newline at end of file diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt index 1eb53fa5b70..5afb472007d 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt @@ -14,11 +14,14 @@ import app.aaps.core.interfaces.logging.AAPSLogger import app.aaps.core.interfaces.logging.LTag import app.aaps.core.interfaces.logging.UserEntryLogger import app.aaps.core.interfaces.notifications.Notification +import app.aaps.core.interfaces.plugin.ActivePlugin import app.aaps.core.interfaces.plugin.PluginBase import app.aaps.core.interfaces.plugin.PluginDescription import app.aaps.core.interfaces.profile.ProfileFunction +import app.aaps.core.interfaces.profile.ProfileStore import app.aaps.core.interfaces.resources.ResourceHelper import app.aaps.core.interfaces.rx.bus.RxBus +import app.aaps.core.interfaces.rx.events.EventLocalProfileChanged import app.aaps.core.interfaces.sharedPreferences.SP import app.aaps.core.interfaces.ui.UiInteraction import app.aaps.core.interfaces.utils.HardLimits @@ -50,7 +53,8 @@ class InsulinPlugin @Inject constructor( val config: Config, val hardLimits: HardLimits, val uiInteraction: UiInteraction, - val uel: UserEntryLogger + val uel: UserEntryLogger, + val activePlugin: ActivePlugin ) : PluginBase( PluginDescription() .mainType(PluginType.INSULIN) @@ -103,7 +107,10 @@ class InsulinPlugin @Inject constructor( } override val iCfg: ICfg - get() = insulins[defaultInsulinIndex] + get() { + val profile = profileFunction.getProfile() + return profile?.insulin ?:insulins[defaultInsulinIndex] + } lateinit var currentInsulin: ICfg private var lastWarned: Long = 0 @@ -216,6 +223,24 @@ class InsulinPlugin @Inject constructor( return insulinLabel } + fun updateProfiles(profileList: ArrayList, profileStore: ProfileStore, now: Long) { + val profilePlugin = activePlugin.activeProfileSource + val fullProfileList = profileStore.getProfileList() + profileList.forEach { profileName -> + for (p in fullProfileList.indices) + if (fullProfileList[p].toString() == profileName) { + profilePlugin.currentProfileIndex = p + profilePlugin.currentProfile()?.iCfg = currentInsulin + uel.log( + action = Action.STORE_PROFILE, + source = Sources.Insulin, + value = ValueWithUnit.SimpleString(profileName) + ) + } + } + profilePlugin.storeSettings(timestamp = now) + rxBus.send(EventLocalProfileChanged()) + } @Synchronized fun loadSettings() { @@ -232,6 +257,7 @@ class InsulinPlugin @Inject constructor( @Synchronized fun storeSettings() { sp.putString(app.aaps.core.utils.R.string.key_insulin_configuration, configuration().toString()) + isEdited = false } override fun iobCalcForTreatment(bolus: BS, time: Long, iCfg: ICfg): Iob { @@ -297,20 +323,6 @@ class InsulinPlugin @Inject constructor( currentInsulinIndex = configuration.optInt("current_insulin") } - override val comment - get(): String { - var comment = commentStandardText() - val userDia = userDefinedDia - if (userDia < hardLimits.minDia()) { - comment += "\n" + rh.gs(R.string.dia_too_short, userDia, hardLimits.minDia()) - } - return comment - } - - fun commentStandardText(): String { - return rh.gs(R.string.insulin_peak_time) + ": " + peak - } - @Synchronized fun isValidEditState(activity: FragmentActivity?, verbose: Boolean = true): Boolean { with(currentInsulin) { diff --git a/plugins/insulin/src/main/res/layout/insulin_fragment.xml b/plugins/insulin/src/main/res/layout/insulin_fragment.xml index 167969485fa..0005eab854c 100644 --- a/plugins/insulin/src/main/res/layout/insulin_fragment.xml +++ b/plugins/insulin/src/main/res/layout/insulin_fragment.xml @@ -249,6 +249,12 @@ android:layout_height="wrap_content" android:orientation="vertical"> + + diff --git a/plugins/insulin/src/main/res/layout/insulin_profile_item.xml b/plugins/insulin/src/main/res/layout/insulin_profile_item.xml new file mode 100644 index 00000000000..bdc1e52a541 --- /dev/null +++ b/plugins/insulin/src/main/res/layout/insulin_profile_item.xml @@ -0,0 +1,33 @@ + + + + + + + + + + diff --git a/plugins/insulin/src/main/res/values/strings.xml b/plugins/insulin/src/main/res/values/strings.xml index 0e79826079e..fc740fd7fc9 100644 --- a/plugins/insulin/src/main/res/values/strings.xml +++ b/plugins/insulin/src/main/res/values/strings.xml @@ -21,5 +21,7 @@ Add new insulin Delete current insulin Save or reset current changes first + Update Profiles + Thihs insulin is used within %1$d profile(s)\nDo you confirm the update of this insulin?\n\nA profile switch will be required to apply the modification within your Loop \ No newline at end of file From 1b195f29dc1c9a440358d6e469cc55982ffef0d4 Mon Sep 17 00:00:00 2001 From: Philoul Date: Sun, 2 Mar 2025 19:31:42 +0100 Subject: [PATCH 24/41] InsulinPlugin Unit tests --- .../src/main/res/values/strings.xml | 2 + .../aaps/plugins/insulin/InsulinFragment.kt | 17 ++-- .../plugins/insulin/InsulinOrefBasePlugin.kt | 2 +- .../insulin/InsulinOrefRapidActingPlugin.kt | 3 +- .../app/aaps/plugins/insulin/InsulinPlugin.kt | 54 +++++++---- .../insulin/src/main/res/values/strings.xml | 4 +- .../aaps/plugins/insulin/InsulinPluginTest.kt | 93 +++++++++++++++++++ 7 files changed, 139 insertions(+), 36 deletions(-) create mode 100644 plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinPluginTest.kt diff --git a/core/interfaces/src/main/res/values/strings.xml b/core/interfaces/src/main/res/values/strings.xml index da518651edd..e45e7be36c7 100644 --- a/core/interfaces/src/main/res/values/strings.xml +++ b/core/interfaces/src/main/res/values/strings.xml @@ -75,6 +75,8 @@ E %1$.2f U/h @%2$s %3$d/%4$d min + Insulin + INS Unknown Rapid-Acting Oref Lyumjev diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt index 53d50dccf43..ce4c62e5d57 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt @@ -55,7 +55,6 @@ class InsulinFragment : DaggerFragment() { private val binding get() = _binding!! private val currentInsulin: ICfg get() = insulinPlugin.currentInsulin - private var sourceInsulin: ICfg? = null private var selectedTemplate = Insulin.InsulinType.OREF_RAPID_ACTING // Default Insulin (should only be used on new install private var minPeak = Insulin.InsulinType.OREF_RAPID_ACTING.peak.toDouble() private var maxPeak = Insulin.InsulinType.OREF_RAPID_ACTING.peak.toDouble() @@ -104,7 +103,6 @@ class InsulinFragment : DaggerFragment() { insulinPlugin.currentInsulin = insulinPlugin.currentInsulin().deepClone() build() } - sourceInsulin = currentInsulin.deepClone() profileList = profileStore.getProfileList(currentInsulin) swapAdapter(profileList) } @@ -113,8 +111,7 @@ class InsulinFragment : DaggerFragment() { ICfg("", selectedTemplate.peak, selectedTemplate.dia), autoName = true ) - insulinPlugin.currentInsulin = insulinPlugin.iCfg.deepClone() - sourceInsulin = currentInsulin.deepClone() + insulinPlugin.setCurrent(insulinPlugin.iCfg) profileList = profileStore.getProfileList(currentInsulin) swapAdapter(profileList) @@ -201,13 +198,14 @@ class InsulinFragment : DaggerFragment() { context?.let { context -> binding.insulinTemplate.setAdapter(ArrayAdapter(context, app.aaps.core.ui.R.layout.spinner_centered, insulinTemplateList)) } ?: return - insulinPlugin.currentInsulin = insulinPlugin.currentInsulin().deepClone() + //insulinPlugin.currentInsulin = insulinPlugin.currentInsulin().deepClone() binding.insulinTemplate.setText(currentInsulin.let { rh.gs(Insulin.InsulinType.fromPeak(it.insulinPeakTime).label) }, false) } override fun onResume() { super.onResume() - sourceInsulin?.let { profileList = profileStore.getProfileList(it) } + insulinPlugin.setCurrent(insulinPlugin.iCfg) + profileList = profileStore.getProfileList(currentInsulin) swapAdapter(profileList) build() } @@ -226,23 +224,20 @@ class InsulinFragment : DaggerFragment() { context?.let { context -> binding.insulinList.setAdapter(ArrayAdapter(context, app.aaps.core.ui.R.layout.spinner_centered, insulinList)) } ?: return - binding.insulinList.setText(insulinPlugin.currentInsulin().insulinLabel, false) + binding.insulinList.setText(insulinPlugin.currentInsulin.insulinLabel, false) if (isValid) { this.view?.setBackgroundColor(rh.gac(context, app.aaps.core.ui.R.attr.okBackgroundColor)) binding.insulinList.isEnabled = true if (isEdited) { //edited insulin -> save first - //binding.updateProfiles.visibility = View.GONE binding.save.visibility = View.VISIBLE } else { - //binding.updateProfiles.visibility = View.VISIBLE binding.save.visibility = View.GONE } } else { this.view?.setBackgroundColor(rh.gac(context, app.aaps.core.ui.R.attr.errorBackgroundColor)) binding.insulinList.isEnabled = false - //binding.updateProfiles.visibility = View.GONE binding.save.visibility = View.GONE //don't save an invalid profile } @@ -261,7 +256,7 @@ class InsulinFragment : DaggerFragment() { binding.name.setText(currentInsulin.insulinLabel) binding.name.addTextChangedListener(textWatch) binding.insulinList.filters = arrayOf() - binding.insulinList.setText(insulinPlugin.currentInsulin().insulinLabel) + binding.insulinList.setText(currentInsulin.insulinLabel) when (selectedTemplate) { Insulin.InsulinType.OREF_FREE_PEAK -> { diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt index 999464d2831..581b9e0bfd6 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt @@ -37,7 +37,7 @@ abstract class InsulinOrefBasePlugin( .mainType(PluginType.INSULIN) .fragmentClass(InsulinFragment::class.java.name) .pluginIcon(app.aaps.core.objects.R.drawable.ic_insulin) - .shortName(R.string.insulin_shortname) + .shortName(app.aaps.core.interfaces.R.string.insulin_shortname) .visibleByDefault(false) .neverVisible(config.AAPSCLIENT), aapsLogger, rh diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefRapidActingPlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefRapidActingPlugin.kt index bec4e545b38..6d8467c0851 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefRapidActingPlugin.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefRapidActingPlugin.kt @@ -43,7 +43,6 @@ class InsulinOrefRapidActingPlugin @Inject constructor( pluginDescription .pluginName(app.aaps.core.interfaces.R.string.rapid_acting_oref) .description(R.string.description_insulin_rapid) - .setDefault() - .enableByDefault(true) + .enableByDefault(false) } } \ No newline at end of file diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt index 5afb472007d..552ef3cd848 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt @@ -60,16 +60,18 @@ class InsulinPlugin @Inject constructor( .mainType(PluginType.INSULIN) .fragmentClass(InsulinFragment::class.java.name) .pluginIcon(app.aaps.core.objects.R.drawable.ic_insulin) - .pluginName(R.string.insulin_plugin) - .shortName(R.string.insulin_shortname) + .pluginName(app.aaps.core.interfaces.R.string.insulin_plugin) + .shortName(app.aaps.core.interfaces.R.string.insulin_shortname) + .setDefault(true) .visibleByDefault(true) + .enableByDefault(true) .neverVisible(config.AAPSCLIENT) .description(R.string.description_insulin_plugin), aapsLogger, rh ), Insulin { override val id = Insulin.InsulinType.UNKNOWN - override var friendlyName: String = "Insulin" + override val friendlyName get(): String = rh.gs(app.aaps.core.interfaces.R.string.insulin_plugin) override val dia get(): Double { @@ -92,7 +94,7 @@ class InsulinPlugin @Inject constructor( if (peak < hardLimits.minPeak()) hardLimits.minPeak().toInt() else - hardLimits.maxDia().toInt() + hardLimits.maxPeak().toInt() } } @@ -109,7 +111,7 @@ class InsulinPlugin @Inject constructor( override val iCfg: ICfg get() { val profile = profileFunction.getProfile() - return profile?.insulin ?:insulins[defaultInsulinIndex] + return getOrCreateInsulin(profile?.insulin ?:insulins[defaultInsulinIndex]) } lateinit var currentInsulin: ICfg @@ -120,15 +122,10 @@ class InsulinPlugin @Inject constructor( val numOfInsulins get() = insulins.size var isEdited: Boolean = false val userDefinedDia: Double - get() { - val profile = profileFunction.getProfile() - return profile?.dia ?: hardLimits.minDia() - } + get() = iCfg.getDia() + val userDefinedPeak: Int - get() { - val profile = profileFunction.getProfile() - return profile?.insulin?.getPeak() ?: hardLimits.minPeak() - } + get() =iCfg.getPeak() override fun onStart() { super.onStart() @@ -147,13 +144,27 @@ class InsulinPlugin @Inject constructor( iCfg.insulinPeakTime = insulins[defaultInsulinIndex].insulinPeakTime if (iCfg.getDia() < hardLimits.minDia() || iCfg.getDia() > hardLimits.maxDia()) iCfg.insulinEndTime = insulins[defaultInsulinIndex].insulinEndTime - insulins.forEach { + insulins.forEachIndexed { index, it -> if (iCfg.isEqual(it)) return it } return addNewInsulin(iCfg, true) } + fun setCurrent(iCfg: ICfg): Int { + // First Check insulin with hardlimits, and set default value if not consistent + insulins.forEachIndexed { index, it -> + if (iCfg.isEqual(it)) { + currentInsulinIndex = index + currentInsulin = currentInsulin().deepClone() + return index + } + } + addNewInsulin(iCfg, true) + currentInsulin = currentInsulin().deepClone() + return insulins.size - 1 + } + override fun getInsulin(insulinLabel: String): ICfg { insulins.forEach { if (it.insulinLabel == insulinLabel) @@ -329,16 +340,19 @@ class InsulinPlugin @Inject constructor( if (insulinEndTime < hardLimits.minDia() || dia > hardLimits.maxDia()) { if (verbose) ToastUtils.errorToast(activity, rh.gs(app.aaps.core.ui.R.string.value_out_of_hard_limits, rh.gs(app.aaps.core.ui.R.string.insulin_dia), dia)) + aapsLogger.debug("XXXXX PeakValue currentIndex: $currentInsulinIndex current: ${insulinLabel} peak: ${getDia()}") return false } if (peak < hardLimits.minPeak() || dia > hardLimits.maxPeak()) { if (verbose) ToastUtils.errorToast(activity, rh.gs(app.aaps.core.ui.R.string.value_out_of_hard_limits, rh.gs(app.aaps.core.ui.R.string.insulin_peak), peak)) + aapsLogger.debug("XXXXX PeakValue currentIndex: $currentInsulinIndex current: ${insulinLabel} peak: ${getPeak()}") return false } if (insulinLabel.isEmpty()) { if (verbose) ToastUtils.errorToast(activity, rh.gs(R.string.missing_insulin_name)) + aapsLogger.debug("XXXXX LabelEmpty currentIndex: $currentInsulinIndex current: ${insulinLabel}") return false } // Check Inulin name is unique and insulin parameters is unique @@ -348,11 +362,12 @@ class InsulinPlugin @Inject constructor( return false } - insulins.forEachIndexed { index, iCfg -> + insulins.forEachIndexed { index, insulin -> if (index != currentInsulinIndex) { - if (isEqual(iCfg)) { + if (isEqual(insulin)) { if (verbose) - ToastUtils.errorToast(activity, rh.gs(R.string.insulin_duplicated, iCfg.insulinLabel)) + ToastUtils.errorToast(activity, rh.gs(R.string.insulin_duplicated, insulin.insulinLabel)) + aapsLogger.debug("XXXXX Duplicate currentIndex: $currentInsulinIndex current: ${insulinLabel} index: $index, label: ${insulin.insulinLabel} peak: ${insulin.getPeak()}, dia: ${insulin.getDia()}") return false } } @@ -362,9 +377,10 @@ class InsulinPlugin @Inject constructor( } private fun insulinLabelAlreadyExists(insulinLabel: String, currentIndex: Int): Boolean { - insulins.forEachIndexed { index, iCfg -> + insulins.forEachIndexed { index, insulin -> if (index != currentIndex) { - if (iCfg.insulinLabel == insulinLabel) { + if (insulin.insulinLabel == insulinLabel) { + aapsLogger.debug("XXXXX Label currentIndex: $currentIndex current: ${insulinLabel} index: $index, label: ${insulin.insulinLabel}") return true } } diff --git a/plugins/insulin/src/main/res/values/strings.xml b/plugins/insulin/src/main/res/values/strings.xml index fc740fd7fc9..8eaf6b676ab 100644 --- a/plugins/insulin/src/main/res/values/strings.xml +++ b/plugins/insulin/src/main/res/values/strings.xml @@ -6,8 +6,6 @@ Insulin preset for Lyumjev Allows you to define the peak of the insulin activity and should only be used by advanced users Allows you to manage the different insulin you will use within AAPS - Insulin - INS IOB Curve Peak Time Peak Time [min] Update Profiles @@ -22,6 +20,6 @@ Delete current insulin Save or reset current changes first Update Profiles - Thihs insulin is used within %1$d profile(s)\nDo you confirm the update of this insulin?\n\nA profile switch will be required to apply the modification within your Loop + This insulin is used within %1$d profile(s)\nDo you confirm the update of this insulin?\n\nA profile switch will be required to apply the modification within your Loop \ No newline at end of file diff --git a/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinPluginTest.kt b/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinPluginTest.kt new file mode 100644 index 00000000000..59a5e2c77a4 --- /dev/null +++ b/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinPluginTest.kt @@ -0,0 +1,93 @@ +package app.aaps.plugins.insulin + +import android.content.SharedPreferences +import app.aaps.core.data.configuration.Constants +import app.aaps.core.data.model.BS +import app.aaps.core.data.model.ICfg +import app.aaps.core.interfaces.insulin.Insulin +import app.aaps.core.interfaces.logging.UserEntryLogger +import app.aaps.core.interfaces.ui.UiInteraction +import app.aaps.core.validators.preferences.AdaptiveIntPreference +import app.aaps.shared.tests.TestBaseWithProfile +import com.google.common.truth.Truth.assertThat +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.mockito.ArgumentMatchers.eq +import org.mockito.Mock +import org.mockito.Mockito.`when` +import org.mockito.junit.jupiter.MockitoExtension +import org.mockito.junit.jupiter.MockitoSettings +import org.mockito.quality.Strictness + +@ExtendWith(MockitoExtension::class) +@MockitoSettings(strictness = Strictness.LENIENT) +class InsulinPluginTest: TestBaseWithProfile() { + + private lateinit var sut: InsulinPlugin + + @Mock lateinit var uiInteraction: UiInteraction + @Mock lateinit var uel: UserEntryLogger + @Mock lateinit var sharedPrefs: SharedPreferences + + init { + addInjector { + if (it is AdaptiveIntPreference) { + it.profileUtil = profileUtil + it.preferences = preferences + it.sharedPrefs = sharedPrefs + it.config = config + } + } + } + + + @BeforeEach + fun setup() { + sut = InsulinPlugin(preferences, rh, profileFunction, rxBus, sp, aapsLogger, config, hardLimits, uiInteraction, uel, activePlugin) + } + + @Test + fun `simple peak test`() { + `when`(profileFunction.getProfile()).thenReturn(validProfile) + assertThat(sut.peak).isEqualTo(75) + } + + @Test + fun getIdTest() { + assertThat(sut.id).isEqualTo(Insulin.InsulinType.UNKNOWN) + } + + @Test + fun getFriendlyNameTest() { + `when`(rh.gs(eq(app.aaps.core.interfaces.R.string.insulin_plugin))).thenReturn("Insulin") + assertThat(sut.friendlyName).isEqualTo("Insulin") + } + + @Test + fun testIobCalcForTreatment() { + val treatment = BS(timestamp = 0, amount = 10.0, type = BS.Type.NORMAL) + val iCfg = ICfg("Test", 30, Constants.defaultDIA) + val time = System.currentTimeMillis() + // check directly after bolus + treatment.timestamp = time + treatment.amount = 10.0 + assertThat(sut.iobCalcForTreatment(treatment, time, iCfg).iobContrib).isWithin(0.01).of(10.0) + // check after 1 hour + treatment.timestamp = time - 1 * 60 * 60 * 1000 // 1 hour + treatment.amount = 10.0 + assertThat(sut.iobCalcForTreatment(treatment, time, iCfg).iobContrib).isWithin(0.01).of(3.92) + // check after 2 hour + treatment.timestamp = time - 2 * 60 * 60 * 1000 // 2 hours + treatment.amount = 10.0 + assertThat(sut.iobCalcForTreatment(treatment, time, iCfg).iobContrib).isWithin(0.01).of(0.77) + // check after 3 hour + treatment.timestamp = time - 3 * 60 * 60 * 1000 // 3 hours + treatment.amount = 10.0 + assertThat(sut.iobCalcForTreatment(treatment, time, iCfg).iobContrib).isWithin(0.01).of(0.10) + // check after dia + treatment.timestamp = time - 4 * 60 * 60 * 1000 // 4 hours + treatment.amount = 10.0 + assertThat(sut.iobCalcForTreatment(treatment, time, iCfg).iobContrib).isWithin(0.01).of(0.0) + } +} From e390ae7f661a4c6d664ee43bdb895c27b62f4fcf Mon Sep 17 00:00:00 2001 From: Philoul Date: Sun, 16 Mar 2025 12:39:02 +0100 Subject: [PATCH 25/41] Remove Previous insulin Plugins --- .../kotlin/app/aaps/di/PluginsListModule.kt | 28 ----- .../plugins/insulin/InsulinLyumjevPlugin.kt | 45 ------- .../plugins/insulin/InsulinOrefBasePlugin.kt | 111 ------------------ .../insulin/InsulinOrefFreePeakPlugin.kt | 81 ------------- .../insulin/InsulinOrefRapidActingPlugin.kt | 48 -------- .../InsulinOrefUltraRapidActingPlugin.kt | 47 -------- .../main/extensions/BolusExtensionKtTest.kt | 1 - .../ExtendedBolusExtensionKtTest.kt | 1 - .../TemporaryBasalExtensionKtTest.kt | 1 - 9 files changed, 363 deletions(-) delete mode 100644 plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinLyumjevPlugin.kt delete mode 100644 plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt delete mode 100644 plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefFreePeakPlugin.kt delete mode 100644 plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefRapidActingPlugin.kt delete mode 100644 plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefUltraRapidActingPlugin.kt diff --git a/app/src/main/kotlin/app/aaps/di/PluginsListModule.kt b/app/src/main/kotlin/app/aaps/di/PluginsListModule.kt index 325970bfda2..7a297cbc099 100644 --- a/app/src/main/kotlin/app/aaps/di/PluginsListModule.kt +++ b/app/src/main/kotlin/app/aaps/di/PluginsListModule.kt @@ -17,10 +17,6 @@ import app.aaps.plugins.constraints.signatureVerifier.SignatureVerifierPlugin import app.aaps.plugins.constraints.storage.StorageConstraintPlugin import app.aaps.plugins.constraints.versionChecker.VersionCheckerPlugin import app.aaps.plugins.insulin.InsulinPlugin -import app.aaps.plugins.insulin.InsulinLyumjevPlugin -import app.aaps.plugins.insulin.InsulinOrefFreePeakPlugin -import app.aaps.plugins.insulin.InsulinOrefRapidActingPlugin -import app.aaps.plugins.insulin.InsulinOrefUltraRapidActingPlugin import app.aaps.plugins.main.general.actions.ActionsPlugin import app.aaps.plugins.main.general.food.FoodPlugin import app.aaps.plugins.main.general.overview.OverviewPlugin @@ -107,30 +103,6 @@ abstract class PluginsListModule { @AllConfigs @IntoMap @IntKey(30) - abstract fun bindInsulinOrefRapidActingPlugin(plugin: InsulinOrefRapidActingPlugin): PluginBase - - @Binds - @AllConfigs - @IntoMap - @IntKey(40) - abstract fun bindInsulinOrefUltraRapidActingPlugin(plugin: InsulinOrefUltraRapidActingPlugin): PluginBase - - @Binds - @AllConfigs - @IntoMap - @IntKey(42) - abstract fun bindInsulinLyumjevPlugin(plugin: InsulinLyumjevPlugin): PluginBase - -@Binds - @AllConfigs - @IntoMap - @IntKey(50) - abstract fun bindInsulinOrefFreePeakPlugin(plugin: InsulinOrefFreePeakPlugin): PluginBase - - @Binds - @AllConfigs - @IntoMap - @IntKey(55) abstract fun bindInsulinPlugin(plugin: InsulinPlugin): PluginBase @Binds diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinLyumjevPlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinLyumjevPlugin.kt deleted file mode 100644 index e95715bd6e5..00000000000 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinLyumjevPlugin.kt +++ /dev/null @@ -1,45 +0,0 @@ -package app.aaps.plugins.insulin - -import app.aaps.core.data.model.ICfg -import app.aaps.core.interfaces.configuration.Config -import app.aaps.core.interfaces.insulin.Insulin -import app.aaps.core.interfaces.logging.AAPSLogger -import app.aaps.core.interfaces.profile.ProfileFunction -import app.aaps.core.interfaces.resources.ResourceHelper -import app.aaps.core.interfaces.rx.bus.RxBus -import app.aaps.core.interfaces.ui.UiInteraction -import app.aaps.core.interfaces.utils.HardLimits -import org.json.JSONObject -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class InsulinLyumjevPlugin @Inject constructor( - rh: ResourceHelper, - profileFunction: ProfileFunction, - rxBus: RxBus, - aapsLogger: AAPSLogger, - config: Config, - hardLimits: HardLimits, - uiInteraction: UiInteraction -) : InsulinOrefBasePlugin(rh, profileFunction, rxBus, aapsLogger, config, hardLimits, uiInteraction) { - - override val id get(): Insulin.InsulinType = Insulin.InsulinType.OREF_LYUMJEV - override val friendlyName get(): String = rh.gs(app.aaps.core.interfaces.R.string.lyumjev) - override fun getOrCreateInsulin(iCfg: ICfg) = ICfg(rh.gs(app.aaps.core.interfaces.R.string.lyumjev), peak, dia) - override fun getInsulin(insulinLabel: String)= ICfg(rh.gs(app.aaps.core.interfaces.R.string.lyumjev), peak, dia) - - override fun configuration(): JSONObject = JSONObject() - override fun applyConfiguration(configuration: JSONObject) { } - - override fun commentStandardText(): String = rh.gs(app.aaps.core.interfaces.R.string.lyumjev) - - override val peak = 45 - - init { - pluginDescription - .pluginIcon(app.aaps.core.objects.R.drawable.ic_insulin) - .pluginName(app.aaps.core.interfaces.R.string.lyumjev) - .description(R.string.description_insulin_lyumjev) - } -} \ No newline at end of file diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt deleted file mode 100644 index 581b9e0bfd6..00000000000 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePlugin.kt +++ /dev/null @@ -1,111 +0,0 @@ -package app.aaps.plugins.insulin - -import app.aaps.core.data.iob.Iob -import app.aaps.core.data.model.BS -import app.aaps.core.data.model.ICfg -import app.aaps.core.data.plugin.PluginType -import app.aaps.core.interfaces.configuration.Config -import app.aaps.core.interfaces.insulin.Insulin -import app.aaps.core.interfaces.logging.AAPSLogger -import app.aaps.core.interfaces.notifications.Notification -import app.aaps.core.interfaces.plugin.PluginBase -import app.aaps.core.interfaces.plugin.PluginDescription -import app.aaps.core.interfaces.profile.ProfileFunction -import app.aaps.core.interfaces.resources.ResourceHelper -import app.aaps.core.interfaces.rx.bus.RxBus -import app.aaps.core.interfaces.ui.UiInteraction -import app.aaps.core.interfaces.utils.HardLimits -import kotlin.math.exp -import kotlin.math.pow - -/** - * Created by adrian on 13.08.2017. - * - * parameters are injected from child class - * - */ -abstract class InsulinOrefBasePlugin( - rh: ResourceHelper, - val profileFunction: ProfileFunction, - val rxBus: RxBus, - aapsLogger: AAPSLogger, - config: Config, - val hardLimits: HardLimits, - val uiInteraction: UiInteraction -) : PluginBase( - PluginDescription() - .mainType(PluginType.INSULIN) - .fragmentClass(InsulinFragment::class.java.name) - .pluginIcon(app.aaps.core.objects.R.drawable.ic_insulin) - .shortName(app.aaps.core.interfaces.R.string.insulin_shortname) - .visibleByDefault(false) - .neverVisible(config.AAPSCLIENT), - aapsLogger, rh -), Insulin { - - private var lastWarned: Long = 0 - override val dia - get(): Double { - val dia = userDefinedDia - return if (dia >= hardLimits.minDia()) { - dia - } else { - sendShortDiaNotification(dia) - hardLimits.minDia() - } - } - override fun setDefault(iCfg: ICfg) { - // fun added for future unique Insulin Plugin to replace "selected insulin plugin", by "DefaultInsulin" - } - - open fun sendShortDiaNotification(dia: Double) { - if (System.currentTimeMillis() - lastWarned > 60 * 1000) { - lastWarned = System.currentTimeMillis() - uiInteraction.addNotification(Notification.SHORT_DIA, String.format(notificationPattern, dia, hardLimits.minDia()), Notification.URGENT) - } - } - - private val notificationPattern: String - get() = rh.gs(R.string.dia_too_short) - - open val userDefinedDia: Double - get() { - val profile = profileFunction.getProfile() - return profile?.dia ?: hardLimits.minDia() - } - - override fun iobCalcForTreatment(bolus: BS, time: Long, iCfg: ICfg): Iob { - return iobCalcForTreatment(bolus, time, iCfg.getPeak(), iCfg.getDia()) - } - - override fun iobCalcForTreatment(bolus: BS, time: Long, dia: Double): Iob { - return iobCalcForTreatment(bolus, time, peak, dia) - } - - private fun iobCalcForTreatment(bolus: BS, time: Long, peak: Int, dia: Double): Iob { - assert(dia != 0.0) - assert(peak != 0) - val result = Iob() - if (bolus.amount != 0.0) { - val bolusTime = bolus.timestamp - val t = (time - bolusTime) / 1000.0 / 60.0 - val td = dia * 60 //getDIA() always >= MIN_DIA - val tp = peak.toDouble() - // force the IOB to 0 if over DIA hours have passed - if (t < td) { - val tau = tp * (1 - tp / td) / (1 - 2 * tp / td) - val a = 2 * tau / td - val s = 1 / (1 - a + (1 + a) * exp(-td / tau)) - result.activityContrib = bolus.amount * (s / tau.pow(2.0)) * t * (1 - t / td) * exp(-t / tau) - result.iobContrib = bolus.amount * (1 - s * (1 - a) * ((t.pow(2.0) / (tau * td * (1 - a)) - t / tau - 1) * exp(-t / tau) + 1)) - } - } - return result - } - - override val iCfg: ICfg - get() = ICfg(friendlyName, peak, dia) - - abstract override val peak: Int - abstract fun commentStandardText(): String -} \ No newline at end of file diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefFreePeakPlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefFreePeakPlugin.kt deleted file mode 100644 index 5648fb625ec..00000000000 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefFreePeakPlugin.kt +++ /dev/null @@ -1,81 +0,0 @@ -package app.aaps.plugins.insulin - -import android.content.Context -import androidx.preference.PreferenceCategory -import androidx.preference.PreferenceManager -import androidx.preference.PreferenceScreen -import app.aaps.core.data.model.ICfg -import app.aaps.core.interfaces.configuration.Config -import app.aaps.core.interfaces.insulin.Insulin -import app.aaps.core.interfaces.logging.AAPSLogger -import app.aaps.core.interfaces.plugin.PluginDescription -import app.aaps.core.interfaces.profile.ProfileFunction -import app.aaps.core.interfaces.resources.ResourceHelper -import app.aaps.core.interfaces.rx.bus.RxBus -import app.aaps.core.interfaces.ui.UiInteraction -import app.aaps.core.interfaces.utils.HardLimits -import app.aaps.core.keys.IntKey -import app.aaps.core.keys.Preferences -import app.aaps.core.objects.extensions.put -import app.aaps.core.objects.extensions.store -import app.aaps.core.validators.preferences.AdaptiveIntPreference -import org.json.JSONObject -import javax.inject.Inject -import javax.inject.Singleton - -/** - * Created by adrian on 14/08/17. - */ -@Singleton -class InsulinOrefFreePeakPlugin @Inject constructor( - private val preferences: Preferences, - rh: ResourceHelper, - profileFunction: ProfileFunction, - rxBus: RxBus, - aapsLogger: AAPSLogger, - config: Config, - hardLimits: HardLimits, - uiInteraction: UiInteraction -) : InsulinOrefBasePlugin(rh, profileFunction, rxBus, aapsLogger, config, hardLimits, uiInteraction) { - - override val id get(): Insulin.InsulinType = Insulin.InsulinType.OREF_FREE_PEAK - override val friendlyName get(): String = rh.gs(app.aaps.core.interfaces.R.string.free_peak_oref) - override fun getOrCreateInsulin(iCfg: ICfg) = ICfg(rh.gs(app.aaps.core.interfaces.R.string.free_peak_oref), peak, dia) - override fun getInsulin(insulinLabel: String)= ICfg(rh.gs(app.aaps.core.interfaces.R.string.free_peak_oref), peak, dia) - - override fun configuration(): JSONObject = - JSONObject() - .put(IntKey.InsulinOrefPeak, preferences) - - override fun applyConfiguration(configuration: JSONObject) { - configuration - .store(IntKey.InsulinOrefPeak, preferences) - } - - override fun commentStandardText(): String { - return rh.gs(R.string.insulin_peak_time) + ": " + peak - } - - override val peak: Int - get() = preferences.get(IntKey.InsulinOrefPeak) - - init { - pluginDescription - .pluginIcon(app.aaps.core.objects.R.drawable.ic_insulin) - .pluginName(app.aaps.core.interfaces.R.string.free_peak_oref) - .preferencesId(PluginDescription.PREFERENCE_SCREEN) - .description(R.string.description_insulin_free_peak) - } - - override fun addPreferenceScreen(preferenceManager: PreferenceManager, parent: PreferenceScreen, context: Context, requiredKey: String?) { - if (requiredKey != null) return - val category = PreferenceCategory(context) - parent.addPreference(category) - category.apply { - key = "insulin_free_peak_settings" - title = rh.gs(R.string.insulin_oref_peak) - initialExpandedChildrenCount = 0 - addPreference(AdaptiveIntPreference(ctx = context, intKey = IntKey.InsulinOrefPeak, title = R.string.insulin_peak_time)) - } - } -} \ No newline at end of file diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefRapidActingPlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefRapidActingPlugin.kt deleted file mode 100644 index 6d8467c0851..00000000000 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefRapidActingPlugin.kt +++ /dev/null @@ -1,48 +0,0 @@ -package app.aaps.plugins.insulin - -import app.aaps.core.data.model.ICfg -import app.aaps.core.interfaces.configuration.Config -import app.aaps.core.interfaces.insulin.Insulin -import app.aaps.core.interfaces.logging.AAPSLogger -import app.aaps.core.interfaces.profile.ProfileFunction -import app.aaps.core.interfaces.resources.ResourceHelper -import app.aaps.core.interfaces.rx.bus.RxBus -import app.aaps.core.interfaces.ui.UiInteraction -import app.aaps.core.interfaces.utils.HardLimits -import org.json.JSONObject -import javax.inject.Inject -import javax.inject.Singleton - -/** - * Created by adrian on 14/08/17. - */ -@Singleton -class InsulinOrefRapidActingPlugin @Inject constructor( - rh: ResourceHelper, - profileFunction: ProfileFunction, - rxBus: RxBus, - aapsLogger: AAPSLogger, - config: Config, - hardLimits: HardLimits, - uiInteraction: UiInteraction -) : InsulinOrefBasePlugin(rh, profileFunction, rxBus, aapsLogger, config, hardLimits, uiInteraction) { - - override val id get(): Insulin.InsulinType = Insulin.InsulinType.OREF_RAPID_ACTING - override val friendlyName get(): String = rh.gs(app.aaps.core.interfaces.R.string.rapid_acting_oref) - override fun getOrCreateInsulin(iCfg: ICfg) = ICfg(rh.gs(app.aaps.core.interfaces.R.string.rapid_acting_oref), peak, dia) - override fun getInsulin(insulinLabel: String)= ICfg(rh.gs(app.aaps.core.interfaces.R.string.rapid_acting_oref), peak, dia) - - override fun configuration(): JSONObject = JSONObject() - override fun applyConfiguration(configuration: JSONObject) {} - - override fun commentStandardText(): String = rh.gs(R.string.fast_acting_insulin_comment) - - override val peak = 75 - - init { - pluginDescription - .pluginName(app.aaps.core.interfaces.R.string.rapid_acting_oref) - .description(R.string.description_insulin_rapid) - .enableByDefault(false) - } -} \ No newline at end of file diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefUltraRapidActingPlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefUltraRapidActingPlugin.kt deleted file mode 100644 index 63fac17caa0..00000000000 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinOrefUltraRapidActingPlugin.kt +++ /dev/null @@ -1,47 +0,0 @@ -package app.aaps.plugins.insulin - -import app.aaps.core.data.model.ICfg -import app.aaps.core.interfaces.configuration.Config -import app.aaps.core.interfaces.insulin.Insulin -import app.aaps.core.interfaces.logging.AAPSLogger -import app.aaps.core.interfaces.profile.ProfileFunction -import app.aaps.core.interfaces.resources.ResourceHelper -import app.aaps.core.interfaces.rx.bus.RxBus -import app.aaps.core.interfaces.ui.UiInteraction -import app.aaps.core.interfaces.utils.HardLimits -import org.json.JSONObject -import javax.inject.Inject -import javax.inject.Singleton - -/** - * Created by adrian on 14/08/17. - */ -@Singleton -class InsulinOrefUltraRapidActingPlugin @Inject constructor( - rh: ResourceHelper, - profileFunction: ProfileFunction, - rxBus: RxBus, - aapsLogger: AAPSLogger, - config: Config, - hardLimits: HardLimits, - uiInteraction: UiInteraction -) : InsulinOrefBasePlugin(rh, profileFunction, rxBus, aapsLogger, config, hardLimits, uiInteraction) { - - override val id get(): Insulin.InsulinType = Insulin.InsulinType.OREF_ULTRA_RAPID_ACTING - override val friendlyName get(): String = rh.gs(app.aaps.core.interfaces.R.string.ultra_rapid_oref) - override fun getOrCreateInsulin(iCfg: ICfg) = ICfg(rh.gs(R.string.ultra_fast_acting_insulin_comment), peak, dia) - override fun getInsulin(insulinLabel: String) = ICfg(rh.gs(R.string.ultra_fast_acting_insulin_comment), peak, dia) - - override fun configuration(): JSONObject = JSONObject() - override fun applyConfiguration(configuration: JSONObject) {} - - override fun commentStandardText(): String = rh.gs(R.string.ultra_fast_acting_insulin_comment) - - override val peak = 55 - - init { - pluginDescription - .pluginName(app.aaps.core.interfaces.R.string.ultra_rapid_oref) - .description(R.string.description_insulin_ultra_rapid) - } -} \ No newline at end of file diff --git a/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/BolusExtensionKtTest.kt b/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/BolusExtensionKtTest.kt index 416af5b30f1..d66ab0c1513 100644 --- a/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/BolusExtensionKtTest.kt +++ b/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/BolusExtensionKtTest.kt @@ -6,7 +6,6 @@ import app.aaps.core.interfaces.insulin.Insulin import app.aaps.core.interfaces.profile.ProfileFunction import app.aaps.core.interfaces.ui.UiInteraction import app.aaps.core.objects.extensions.iobCalc -import app.aaps.plugins.insulin.InsulinLyumjevPlugin import app.aaps.shared.tests.TestBaseWithProfile import com.google.common.truth.Truth.assertThat import org.junit.jupiter.api.BeforeEach diff --git a/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/ExtendedBolusExtensionKtTest.kt b/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/ExtendedBolusExtensionKtTest.kt index 7dd11cc282d..85dd8b5e476 100644 --- a/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/ExtendedBolusExtensionKtTest.kt +++ b/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/ExtendedBolusExtensionKtTest.kt @@ -11,7 +11,6 @@ import app.aaps.core.interfaces.ui.UiInteraction import app.aaps.core.objects.extensions.iobCalc import app.aaps.core.objects.extensions.isInProgress import app.aaps.core.objects.extensions.toTemporaryBasal -import app.aaps.plugins.insulin.InsulinLyumjevPlugin import app.aaps.shared.tests.TestBaseWithProfile import com.google.common.truth.Truth.assertThat import org.junit.jupiter.api.BeforeEach diff --git a/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/TemporaryBasalExtensionKtTest.kt b/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/TemporaryBasalExtensionKtTest.kt index 3e64a823360..f1e6f989ff5 100644 --- a/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/TemporaryBasalExtensionKtTest.kt +++ b/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/TemporaryBasalExtensionKtTest.kt @@ -8,7 +8,6 @@ import app.aaps.core.interfaces.insulin.Insulin import app.aaps.core.interfaces.profile.ProfileFunction import app.aaps.core.interfaces.ui.UiInteraction import app.aaps.core.objects.extensions.iobCalc -import app.aaps.plugins.insulin.InsulinLyumjevPlugin import app.aaps.shared.tests.TestBaseWithProfile import com.google.common.truth.Truth.assertThat import org.junit.jupiter.api.BeforeEach From 8557ea807be365b2f2592a28984a840535a14eaa Mon Sep 17 00:00:00 2001 From: Philoul Date: Sun, 16 Mar 2025 12:41:40 +0100 Subject: [PATCH 26/41] Remove Previous insulin Plugins tests --- .../insulin/InsulinLyumjevPluginTest.kt | 63 ---------- .../insulin/InsulinOrefBasePluginTest.kt | 116 ------------------ .../insulin/InsulinOrefFreePeakPluginTest.kt | 73 ----------- .../InsulinOrefRapidActingPluginTest.kt | 63 ---------- .../InsulinOrefUltraRapidActingPluginTest.kt | 63 ---------- 5 files changed, 378 deletions(-) delete mode 100644 plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinLyumjevPluginTest.kt delete mode 100644 plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePluginTest.kt delete mode 100644 plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinOrefFreePeakPluginTest.kt delete mode 100644 plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinOrefRapidActingPluginTest.kt delete mode 100644 plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinOrefUltraRapidActingPluginTest.kt diff --git a/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinLyumjevPluginTest.kt b/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinLyumjevPluginTest.kt deleted file mode 100644 index 8660c50fffc..00000000000 --- a/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinLyumjevPluginTest.kt +++ /dev/null @@ -1,63 +0,0 @@ -package app.aaps.plugins.insulin - -import app.aaps.core.interfaces.configuration.Config -import app.aaps.core.interfaces.insulin.Insulin -import app.aaps.core.interfaces.logging.AAPSLogger -import app.aaps.core.interfaces.profile.ProfileFunction -import app.aaps.core.interfaces.resources.ResourceHelper -import app.aaps.core.interfaces.rx.bus.RxBus -import app.aaps.core.interfaces.ui.UiInteraction -import app.aaps.core.interfaces.utils.HardLimits -import com.google.common.truth.Truth.assertThat -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.ExtendWith -import org.mockito.ArgumentMatchers.eq -import org.mockito.Mock -import org.mockito.Mockito.`when` -import org.mockito.junit.jupiter.MockitoExtension -import org.mockito.junit.jupiter.MockitoSettings -import org.mockito.quality.Strictness - -@ExtendWith(MockitoExtension::class) -@MockitoSettings(strictness = Strictness.LENIENT) -class InsulinLyumjevPluginTest { - - private lateinit var sut: InsulinLyumjevPlugin - - @Mock lateinit var rh: ResourceHelper - @Mock lateinit var rxBus: RxBus - @Mock lateinit var profileFunction: ProfileFunction - @Mock lateinit var aapsLogger: AAPSLogger - @Mock lateinit var config: Config - @Mock lateinit var hardLimits: HardLimits - @Mock lateinit var uiInteraction: UiInteraction - - @BeforeEach - fun setup() { - sut = InsulinLyumjevPlugin(rh, profileFunction, rxBus, aapsLogger, config, hardLimits, uiInteraction) - } - - @Test - fun `simple peak test`() { - assertThat(sut.peak).isEqualTo(45) - } - - @Test - fun getIdTest() { - assertThat(sut.id).isEqualTo(Insulin.InsulinType.OREF_LYUMJEV) - } - - @Test - fun commentStandardTextTest() { - `when`(rh.gs(eq(app.aaps.core.interfaces.R.string.lyumjev))).thenReturn("Lyumjev") - assertThat(sut.commentStandardText()).isEqualTo("Lyumjev") - } - - @Test - fun getFriendlyNameTest() { - `when`(rh.gs(eq(app.aaps.core.interfaces.R.string.lyumjev))).thenReturn("Lyumjev") - assertThat(sut.friendlyName).isEqualTo("Lyumjev") - } - -} diff --git a/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePluginTest.kt b/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePluginTest.kt deleted file mode 100644 index 842d76b24a3..00000000000 --- a/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinOrefBasePluginTest.kt +++ /dev/null @@ -1,116 +0,0 @@ -package app.aaps.plugins.insulin - -import app.aaps.core.data.configuration.Constants -import app.aaps.core.data.model.BS -import app.aaps.core.data.model.ICfg -import app.aaps.core.interfaces.configuration.Config -import app.aaps.core.interfaces.insulin.Insulin -import app.aaps.core.interfaces.logging.AAPSLogger -import app.aaps.core.interfaces.profile.ProfileFunction -import app.aaps.core.interfaces.resources.ResourceHelper -import app.aaps.core.interfaces.rx.bus.RxBus -import app.aaps.core.interfaces.ui.UiInteraction -import app.aaps.core.interfaces.utils.HardLimits -import com.google.common.truth.Truth.assertThat -import org.json.JSONObject -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.ExtendWith -import org.mockito.Mock -import org.mockito.Mockito.`when` -import org.mockito.junit.jupiter.MockitoExtension -import org.mockito.junit.jupiter.MockitoSettings -import org.mockito.quality.Strictness - -@ExtendWith(MockitoExtension::class) -@MockitoSettings(strictness = Strictness.LENIENT) -class InsulinOrefBasePluginTest { - - var testPeak = 0 - var testUserDefinedDia = 0.0 - var shortDiaNotificationSend = false - - inner class InsulinBaseTest( - rh: ResourceHelper, - profileFunction: ProfileFunction, - rxBus: RxBus, - aapsLogger: AAPSLogger, - config: Config, - hardLimits: HardLimits - ) : InsulinOrefBasePlugin(rh, profileFunction, rxBus, aapsLogger, config, hardLimits, uiInteraction) { - - override fun sendShortDiaNotification(dia: Double) { - shortDiaNotificationSend = true - } - - override val userDefinedDia: Double - get() = testUserDefinedDia - - override val peak: Int - get() = testPeak - - override fun getOrCreateInsulin(iCfg: ICfg): ICfg = ICfg("Test-Insulin", 45, 8.0) - - override fun getInsulin(insulinLabel: String): ICfg = ICfg("Test-Insulin", 45, 8.0) - - override fun commentStandardText(): String = "" - override val id get(): Insulin.InsulinType = Insulin.InsulinType.UNKNOWN - override val friendlyName get(): String = "" - override fun configuration(): JSONObject = JSONObject() - override fun applyConfiguration(configuration: JSONObject) {} - } - - private lateinit var sut: InsulinBaseTest - - @Mock lateinit var rh: ResourceHelper - @Mock lateinit var profileFunction: ProfileFunction - @Mock lateinit var rxBus: RxBus - @Mock lateinit var aapsLogger: AAPSLogger - @Mock lateinit var config: Config - @Mock lateinit var hardLimits: HardLimits - @Mock lateinit var uiInteraction: UiInteraction - - @BeforeEach - fun setUp() { - sut = InsulinBaseTest(rh, profileFunction, rxBus, aapsLogger, config, hardLimits) - `when`(hardLimits.minDia()).thenReturn(5.0) - } - - @Test - fun testGetDia() { - assertThat(sut.dia).isEqualTo(5.0) - testUserDefinedDia = 5.0 + 1 - assertThat(sut.dia).isEqualTo(5.0 + 1) - testUserDefinedDia = 5.0 - 1 - assertThat(sut.dia).isEqualTo(5.0) - assertThat(shortDiaNotificationSend).isTrue() - } - - @Test - fun testIobCalcForTreatment() { - val treatment = BS(timestamp = 0, amount = 10.0, type = BS.Type.NORMAL) - testPeak = 30 - testUserDefinedDia = 4.0 - val time = System.currentTimeMillis() - // check directly after bolus - treatment.timestamp = time - treatment.amount = 10.0 - assertThat(sut.iobCalcForTreatment(treatment, time, Constants.defaultDIA).iobContrib).isWithin(0.01).of(10.0) - // check after 1 hour - treatment.timestamp = time - 1 * 60 * 60 * 1000 // 1 hour - treatment.amount = 10.0 - assertThat(sut.iobCalcForTreatment(treatment, time, Constants.defaultDIA).iobContrib).isWithin(0.01).of(3.92) - // check after 2 hour - treatment.timestamp = time - 2 * 60 * 60 * 1000 // 2 hours - treatment.amount = 10.0 - assertThat(sut.iobCalcForTreatment(treatment, time, Constants.defaultDIA).iobContrib).isWithin(0.01).of(0.77) - // check after 3 hour - treatment.timestamp = time - 3 * 60 * 60 * 1000 // 3 hours - treatment.amount = 10.0 - assertThat(sut.iobCalcForTreatment(treatment, time, Constants.defaultDIA).iobContrib).isWithin(0.01).of(0.10) - // check after dia - treatment.timestamp = time - 4 * 60 * 60 * 1000 // 4 hours - treatment.amount = 10.0 - assertThat(sut.iobCalcForTreatment(treatment, time, Constants.defaultDIA).iobContrib).isWithin(0.01).of(0.0) - } -} diff --git a/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinOrefFreePeakPluginTest.kt b/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinOrefFreePeakPluginTest.kt deleted file mode 100644 index cbce7805e6d..00000000000 --- a/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinOrefFreePeakPluginTest.kt +++ /dev/null @@ -1,73 +0,0 @@ -package app.aaps.plugins.insulin - -import android.content.SharedPreferences -import app.aaps.core.interfaces.insulin.Insulin -import app.aaps.core.interfaces.ui.UiInteraction -import app.aaps.core.keys.IntKey -import app.aaps.core.validators.preferences.AdaptiveIntPreference -import app.aaps.shared.tests.TestBaseWithProfile -import com.google.common.truth.Truth.assertThat -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -import org.mockito.ArgumentMatchers.eq -import org.mockito.Mock -import org.mockito.Mockito.`when` - -/** - * Created by adrian on 2019-12-25. - */ - -class InsulinOrefFreePeakPluginTest : TestBaseWithProfile() { - - private lateinit var sut: InsulinOrefFreePeakPlugin - - @Mock lateinit var uiInteraction: UiInteraction - @Mock lateinit var sharedPrefs: SharedPreferences - - init { - addInjector { - if (it is AdaptiveIntPreference) { - it.profileUtil = profileUtil - it.preferences = preferences - it.sharedPrefs = sharedPrefs - it.config = config - } - } - } - - @BeforeEach - fun setup() { - sut = InsulinOrefFreePeakPlugin(preferences, rh, profileFunction, rxBus, aapsLogger, config, hardLimits, uiInteraction) - } - - @Test - fun `simple peak test`() { - `when`(preferences.get(IntKey.InsulinOrefPeak)).thenReturn(90) - assertThat(sut.peak).isEqualTo(90) - } - - @Test - fun getIdTest() { - assertThat(sut.id).isEqualTo(Insulin.InsulinType.OREF_FREE_PEAK) - } - - @Test - fun commentStandardTextTest() { - `when`(preferences.get(IntKey.InsulinOrefPeak)).thenReturn(90) - `when`(rh.gs(eq(R.string.insulin_peak_time))).thenReturn("Peak Time [min]") - assertThat(sut.commentStandardText()).isEqualTo("Peak Time [min]: 90") - } - - @Test - fun getFriendlyNameTest() { - `when`(rh.gs(eq(app.aaps.core.interfaces.R.string.free_peak_oref))).thenReturn("Free-Peak Oref") - assertThat(sut.friendlyName).isEqualTo("Free-Peak Oref") - } - - @Test - fun preferenceScreenTest() { - val screen = preferenceManager.createPreferenceScreen(context) - sut.addPreferenceScreen(preferenceManager, screen, context, null) - assertThat(screen.preferenceCount).isGreaterThan(0) - } -} diff --git a/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinOrefRapidActingPluginTest.kt b/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinOrefRapidActingPluginTest.kt deleted file mode 100644 index f2b47f62ab6..00000000000 --- a/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinOrefRapidActingPluginTest.kt +++ /dev/null @@ -1,63 +0,0 @@ -package app.aaps.plugins.insulin - -import app.aaps.core.interfaces.configuration.Config -import app.aaps.core.interfaces.insulin.Insulin -import app.aaps.core.interfaces.logging.AAPSLogger -import app.aaps.core.interfaces.profile.ProfileFunction -import app.aaps.core.interfaces.resources.ResourceHelper -import app.aaps.core.interfaces.rx.bus.RxBus -import app.aaps.core.interfaces.ui.UiInteraction -import app.aaps.core.interfaces.utils.HardLimits -import com.google.common.truth.Truth.assertThat -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.ExtendWith -import org.mockito.ArgumentMatchers.eq -import org.mockito.Mock -import org.mockito.Mockito.`when` -import org.mockito.junit.jupiter.MockitoExtension -import org.mockito.junit.jupiter.MockitoSettings -import org.mockito.quality.Strictness - -@ExtendWith(MockitoExtension::class) -@MockitoSettings(strictness = Strictness.LENIENT) -class InsulinOrefRapidActingPluginTest { - - private lateinit var sut: InsulinOrefRapidActingPlugin - - @Mock lateinit var rh: ResourceHelper - @Mock lateinit var rxBus: RxBus - @Mock lateinit var profileFunction: ProfileFunction - @Mock lateinit var aapsLogger: AAPSLogger - @Mock lateinit var config: Config - @Mock lateinit var hardLimits: HardLimits - @Mock lateinit var uiInteraction: UiInteraction - - @BeforeEach - fun setup() { - sut = InsulinOrefRapidActingPlugin(rh, profileFunction, rxBus, aapsLogger, config, hardLimits, uiInteraction) - } - - @Test - fun `simple peak test`() { - assertThat(sut.peak).isEqualTo(75) - } - - @Test - fun getIdTest() { - assertThat(sut.id).isEqualTo(Insulin.InsulinType.OREF_RAPID_ACTING) - } - - @Test - fun commentStandardTextTest() { - `when`(rh.gs(eq(R.string.fast_acting_insulin_comment))).thenReturn("Novorapid, Novolog, Humalog") - assertThat(sut.commentStandardText()).isEqualTo("Novorapid, Novolog, Humalog") - } - - @Test - fun getFriendlyNameTest() { - `when`(rh.gs(eq(app.aaps.core.interfaces.R.string.rapid_acting_oref))).thenReturn("Rapid-Acting Oref") - assertThat(sut.friendlyName).isEqualTo("Rapid-Acting Oref") - } - -} diff --git a/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinOrefUltraRapidActingPluginTest.kt b/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinOrefUltraRapidActingPluginTest.kt deleted file mode 100644 index 4a3fa57bfa0..00000000000 --- a/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinOrefUltraRapidActingPluginTest.kt +++ /dev/null @@ -1,63 +0,0 @@ -package app.aaps.plugins.insulin - -import app.aaps.core.interfaces.configuration.Config -import app.aaps.core.interfaces.insulin.Insulin -import app.aaps.core.interfaces.logging.AAPSLogger -import app.aaps.core.interfaces.profile.ProfileFunction -import app.aaps.core.interfaces.resources.ResourceHelper -import app.aaps.core.interfaces.rx.bus.RxBus -import app.aaps.core.interfaces.ui.UiInteraction -import app.aaps.core.interfaces.utils.HardLimits -import com.google.common.truth.Truth.assertThat -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.ExtendWith -import org.mockito.ArgumentMatchers.eq -import org.mockito.Mock -import org.mockito.Mockito.`when` -import org.mockito.junit.jupiter.MockitoExtension -import org.mockito.junit.jupiter.MockitoSettings -import org.mockito.quality.Strictness - -@ExtendWith(MockitoExtension::class) -@MockitoSettings(strictness = Strictness.LENIENT) -class InsulinOrefUltraRapidActingPluginTest { - - private lateinit var sut: InsulinOrefUltraRapidActingPlugin - - @Mock lateinit var rh: ResourceHelper - @Mock lateinit var rxBus: RxBus - @Mock lateinit var profileFunction: ProfileFunction - @Mock lateinit var aapsLogger: AAPSLogger - @Mock lateinit var config: Config - @Mock lateinit var hardLimits: HardLimits - @Mock lateinit var uiInteraction: UiInteraction - - @BeforeEach - fun setup() { - sut = InsulinOrefUltraRapidActingPlugin(rh, profileFunction, rxBus, aapsLogger, config, hardLimits, uiInteraction) - } - - @Test - fun `simple peak test`() { - assertThat(sut.peak).isEqualTo(55) - } - - @Test - fun getIdTest() { - assertThat(sut.id).isEqualTo(Insulin.InsulinType.OREF_ULTRA_RAPID_ACTING) - } - - @Test - fun commentStandardTextTest() { - `when`(rh.gs(eq(R.string.ultra_fast_acting_insulin_comment))).thenReturn("Fiasp") - assertThat(sut.commentStandardText()).isEqualTo("Fiasp") - } - - @Test - fun getFriendlyNameTest() { - `when`(rh.gs(eq(app.aaps.core.interfaces.R.string.ultra_rapid_oref))).thenReturn("Ultra-Rapid Oref") - assertThat(sut.friendlyName).isEqualTo("Ultra-Rapid Oref") - } - -} From 34d98d1e822ae5c0164eb9dc0491c0f4794088cc Mon Sep 17 00:00:00 2001 From: Philoul Date: Sun, 16 Mar 2025 16:17:53 +0100 Subject: [PATCH 27/41] Fix Tests --- .../main/extensions/BolusExtensionKtTest.kt | 17 ++++++++++------- .../extensions/ExtendedBolusExtensionKtTest.kt | 5 ++++- .../extensions/TemporaryBasalExtensionKtTest.kt | 5 ++++- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/BolusExtensionKtTest.kt b/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/BolusExtensionKtTest.kt index d66ab0c1513..58096cadd2a 100644 --- a/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/BolusExtensionKtTest.kt +++ b/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/BolusExtensionKtTest.kt @@ -3,9 +3,11 @@ package app.aaps.plugins.main.extensions import app.aaps.core.data.model.BS import app.aaps.core.data.time.T import app.aaps.core.interfaces.insulin.Insulin +import app.aaps.core.interfaces.logging.UserEntryLogger import app.aaps.core.interfaces.profile.ProfileFunction import app.aaps.core.interfaces.ui.UiInteraction import app.aaps.core.objects.extensions.iobCalc +import app.aaps.plugins.insulin.InsulinPlugin import app.aaps.shared.tests.TestBaseWithProfile import com.google.common.truth.Truth.assertThat import org.junit.jupiter.api.BeforeEach @@ -17,31 +19,32 @@ class BolusExtensionKtTest : TestBaseWithProfile() { @Mock lateinit var profileFunctions: ProfileFunction @Mock lateinit var uiInteraction: UiInteraction + @Mock lateinit var uel: UserEntryLogger private lateinit var insulin: Insulin - private val dia = 7.0 + private val iCfg = Insulin.InsulinType.OREF_LYUMJEV.getICfg().also {it.setDia(7.0) } @BeforeEach fun setup() { - insulin = InsulinLyumjevPlugin(rh, profileFunctions, rxBus, aapsLogger, config, hardLimits, uiInteraction) + insulin = InsulinPlugin(preferences, rh, profileFunctions, rxBus, sp, aapsLogger, config, hardLimits, uiInteraction, uel, activePlugin) Mockito.`when`(activePlugin.activeInsulin).thenReturn(insulin) } @Test fun iobCalc() { val bolus = BS(timestamp = now - 1, amount = 1.0, type = BS.Type.NORMAL) // there should be almost full IOB after now - assertThat(bolus.iobCalc(activePlugin, now, dia).iobContrib).isWithin(0.01).of(1.0) + assertThat(bolus.iobCalc(activePlugin, now, iCfg).iobContrib).isWithin(0.01).of(1.0) // there should be less than 5% after DIA -1 assertThat( - bolus.iobCalc(activePlugin, now + T.hours(dia.toLong() - 1).msecs(), dia).iobContrib + bolus.iobCalc(activePlugin, now + T.hours(iCfg.getDia().toLong() - 1).msecs(), iCfg).iobContrib ).isLessThan(0.05) // there should be zero after DIA - assertThat(bolus.iobCalc(activePlugin, now + T.hours(dia.toLong() + 1).msecs(), dia).iobContrib).isEqualTo(0.0) + assertThat(bolus.iobCalc(activePlugin, now + T.hours(iCfg.getDia().toLong() + 1).msecs(), iCfg).iobContrib).isEqualTo(0.0) // no IOB for invalid record bolus.isValid = false - assertThat(bolus.iobCalc(activePlugin, now + T.hours(1).msecs(), dia).iobContrib).isEqualTo(0.0) + assertThat(bolus.iobCalc(activePlugin, now + T.hours(1).msecs(), iCfg).iobContrib).isEqualTo(0.0) bolus.isValid = true bolus.type = BS.Type.PRIMING - assertThat(bolus.iobCalc(activePlugin, now + T.hours(1).msecs(), dia).iobContrib).isEqualTo(0.0) + assertThat(bolus.iobCalc(activePlugin, now + T.hours(1).msecs(), iCfg).iobContrib).isEqualTo(0.0) } } diff --git a/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/ExtendedBolusExtensionKtTest.kt b/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/ExtendedBolusExtensionKtTest.kt index 85dd8b5e476..ee5e21801ca 100644 --- a/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/ExtendedBolusExtensionKtTest.kt +++ b/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/ExtendedBolusExtensionKtTest.kt @@ -6,11 +6,13 @@ import app.aaps.core.data.model.TB import app.aaps.core.data.time.T import app.aaps.core.interfaces.aps.AutosensResult import app.aaps.core.interfaces.insulin.Insulin +import app.aaps.core.interfaces.logging.UserEntryLogger import app.aaps.core.interfaces.profile.ProfileFunction import app.aaps.core.interfaces.ui.UiInteraction import app.aaps.core.objects.extensions.iobCalc import app.aaps.core.objects.extensions.isInProgress import app.aaps.core.objects.extensions.toTemporaryBasal +import app.aaps.plugins.insulin.InsulinPlugin import app.aaps.shared.tests.TestBaseWithProfile import com.google.common.truth.Truth.assertThat import org.junit.jupiter.api.BeforeEach @@ -22,13 +24,14 @@ class ExtendedBolusExtensionKtTest : TestBaseWithProfile() { @Mock lateinit var profileFunctions: ProfileFunction @Mock lateinit var uiInteraction: UiInteraction + @Mock lateinit var uel: UserEntryLogger private lateinit var insulin: Insulin private val dia = 7.0 @BeforeEach fun setup() { - insulin = InsulinLyumjevPlugin(rh, profileFunctions, rxBus, aapsLogger, config, hardLimits, uiInteraction) + insulin = InsulinPlugin(preferences, rh, profileFunctions, rxBus, sp, aapsLogger, config, hardLimits, uiInteraction, uel, activePlugin) Mockito.`when`(activePlugin.activeInsulin).thenReturn(insulin) Mockito.`when`(dateUtil.now()).thenReturn(now) } diff --git a/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/TemporaryBasalExtensionKtTest.kt b/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/TemporaryBasalExtensionKtTest.kt index f1e6f989ff5..422fb59b9c1 100644 --- a/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/TemporaryBasalExtensionKtTest.kt +++ b/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/TemporaryBasalExtensionKtTest.kt @@ -5,9 +5,11 @@ import app.aaps.core.data.model.TB import app.aaps.core.data.time.T import app.aaps.core.interfaces.aps.AutosensResult import app.aaps.core.interfaces.insulin.Insulin +import app.aaps.core.interfaces.logging.UserEntryLogger import app.aaps.core.interfaces.profile.ProfileFunction import app.aaps.core.interfaces.ui.UiInteraction import app.aaps.core.objects.extensions.iobCalc +import app.aaps.plugins.insulin.InsulinPlugin import app.aaps.shared.tests.TestBaseWithProfile import com.google.common.truth.Truth.assertThat import org.junit.jupiter.api.BeforeEach @@ -19,6 +21,7 @@ class TemporaryBasalExtensionKtTest : TestBaseWithProfile() { @Mock lateinit var profileFunctions: ProfileFunction @Mock lateinit var uiInteraction: UiInteraction + @Mock lateinit var uel: UserEntryLogger private lateinit var insulin: Insulin @@ -26,7 +29,7 @@ class TemporaryBasalExtensionKtTest : TestBaseWithProfile() { @BeforeEach fun setup() { - insulin = InsulinLyumjevPlugin(rh, profileFunctions, rxBus, aapsLogger, config, hardLimits, uiInteraction) + insulin = InsulinPlugin(preferences, rh, profileFunctions, rxBus, sp, aapsLogger, config, hardLimits, uiInteraction, uel, activePlugin) Mockito.`when`(activePlugin.activeInsulin).thenReturn(insulin) Mockito.`when`(dateUtil.now()).thenReturn(now) } From a9900f80799629ab41bae0c4d34992547c7e3224 Mon Sep 17 00:00:00 2001 From: Philoul Date: Sun, 16 Mar 2025 17:32:43 +0100 Subject: [PATCH 28/41] Delete iobCalcForTreatment with dia --- .../app/aaps/core/interfaces/insulin/Insulin.kt | 1 - .../aaps/core/objects/extensions/BolusExtension.kt | 5 +++-- .../objects/extensions/ExtendedBolusExtension.kt | 12 ++++++------ .../objects/extensions/TemporaryBasalExtension.kt | 12 ++++++------ .../kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt | 6 ------ .../iob/iobCobCalculator/IobCobCalculatorPlugin.kt | 8 ++++---- .../fragments/TreatmentsBolusCarbsFragment.kt | 2 +- 7 files changed, 20 insertions(+), 26 deletions(-) diff --git a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/insulin/Insulin.kt b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/insulin/Insulin.kt index 0a1db9f7cbf..06a79a3e7bd 100644 --- a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/insulin/Insulin.kt +++ b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/insulin/Insulin.kt @@ -36,7 +36,6 @@ interface Insulin : ConfigExportImport { fun insulinList() = ArrayList() fun getOrCreateInsulin(iCfg: ICfg): ICfg fun getInsulin(insulinLabel: String): ICfg - fun iobCalcForTreatment(bolus: BS, time: Long, dia: Double): Iob fun iobCalcForTreatment(bolus: BS, time: Long, iCfg: ICfg): Iob val iCfg: ICfg diff --git a/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/BolusExtension.kt b/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/BolusExtension.kt index f9b3647a9e8..4469406b5f6 100644 --- a/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/BolusExtension.kt +++ b/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/BolusExtension.kt @@ -2,11 +2,12 @@ package app.aaps.core.objects.extensions import app.aaps.core.data.iob.Iob import app.aaps.core.data.model.BS +import app.aaps.core.data.model.ICfg import app.aaps.core.interfaces.insulin.Insulin import app.aaps.core.interfaces.plugin.ActivePlugin -fun BS.iobCalc(activePlugin: ActivePlugin, time: Long, dia: Double): Iob { +fun BS.iobCalc(activePlugin: ActivePlugin, time: Long, iCfg: ICfg): Iob { if (!isValid || type == BS.Type.PRIMING) return Iob() val insulinInterface: Insulin = activePlugin.activeInsulin - return insulinInterface.iobCalcForTreatment(this, time, dia) + return insulinInterface.iobCalcForTreatment(this, time, iCfg) } \ No newline at end of file diff --git a/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/ExtendedBolusExtension.kt b/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/ExtendedBolusExtension.kt index 2a7460f56a1..0646ef9a946 100644 --- a/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/ExtendedBolusExtension.kt +++ b/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/ExtendedBolusExtension.kt @@ -47,8 +47,8 @@ fun EB.iobCalc(time: Long, profile: Profile, insulinInterface: Insulin): IobTota val result = IobTotal(time) val realDuration = getPassedDurationToTimeInMinutes(time) if (realDuration > 0) { - val dia = profile.dia - val diaAgo = time - dia * 60 * 60 * 1000 + val iCfg = profile.insulin + val diaAgo = time - iCfg.insulinEndTime val aboutFiveMinIntervals = ceil(realDuration / 5.0).toInt() val spacing = realDuration / aboutFiveMinIntervals.toDouble() for (j in 0L until aboutFiveMinIntervals) { @@ -61,7 +61,7 @@ fun EB.iobCalc(time: Long, profile: Profile, insulinInterface: Insulin): IobTota amount = tempBolusSize, type = BS.Type.NORMAL ) - val aIOB = insulinInterface.iobCalcForTreatment(tempBolusPart, time, dia) + val aIOB = insulinInterface.iobCalcForTreatment(tempBolusPart, time, iCfg) result.iob += aIOB.iobContrib result.activity += aIOB.activityContrib result.extendedBolusInsulin += tempBolusPart.amount @@ -93,8 +93,8 @@ fun EB.iobCalc( } if (realDuration > 0) { var netBasalRate: Double - val dia = profile.dia - val diaAgo = time - dia * 60 * 60 * 1000 + val iCfg = profile.insulin + val diaAgo = time - iCfg.insulinEndTime val aboutFiveMinIntervals = ceil(realDuration / 5.0).toInt() val spacing = realDuration / aboutFiveMinIntervals for (j in 0L until aboutFiveMinIntervals) { @@ -110,7 +110,7 @@ fun EB.iobCalc( amount = tempBolusSize, type = BS.Type.NORMAL ) - val aIOB = insulinInterface.iobCalcForTreatment(tempBolusPart, time, dia) + val aIOB = insulinInterface.iobCalcForTreatment(tempBolusPart, time, iCfg) result.iob += aIOB.iobContrib result.activity += aIOB.activityContrib result.extendedBolusInsulin += tempBolusPart.amount diff --git a/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/TemporaryBasalExtension.kt b/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/TemporaryBasalExtension.kt index a96be727b04..be5efd0975b 100644 --- a/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/TemporaryBasalExtension.kt +++ b/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/TemporaryBasalExtension.kt @@ -62,8 +62,8 @@ fun TB.iobCalc(time: Long, profile: Profile, insulinInterface: Insulin): IobTota var netBasalAmount = 0.0 if (realDuration > 0) { var netBasalRate: Double - val dia = profile.dia - val diaAgo = time - dia * 60 * 60 * 1000 + val iCfg = profile.insulin + val diaAgo = time - iCfg.insulinEndTime val aboutFiveMinIntervals = ceil(realDuration / 5.0).toInt() val tempBolusSpacing = realDuration / aboutFiveMinIntervals.toDouble() for (j in 0L until aboutFiveMinIntervals) { @@ -83,7 +83,7 @@ fun TB.iobCalc(time: Long, profile: Profile, insulinInterface: Insulin): IobTota amount = tempBolusSize, type = BS.Type.NORMAL ) - val aIOB = insulinInterface.iobCalcForTreatment(tempBolusPart, time, dia) + val aIOB = insulinInterface.iobCalcForTreatment(tempBolusPart, time, iCfg) result.basaliob += aIOB.iobContrib result.activity += aIOB.activityContrib result.netbasalinsulin += tempBolusPart.amount @@ -120,8 +120,8 @@ fun TB.iobCalc( } if (realDuration > 0) { var netBasalRate: Double - val dia = profile.dia - val diaAgo = time - dia * 60 * 60 * 1000 + val iCfg = profile.insulin + val diaAgo = time - iCfg.insulinEndTime val aboutFiveMinIntervals = ceil(realDuration / 5.0).toInt() val tempBolusSpacing = realDuration / aboutFiveMinIntervals.toDouble() for (j in 0L until aboutFiveMinIntervals) { @@ -143,7 +143,7 @@ fun TB.iobCalc( amount = tempBolusSize, type = BS.Type.NORMAL ) - val aIOB = insulinInterface.iobCalcForTreatment(tempBolusPart, time, dia) + val aIOB = insulinInterface.iobCalcForTreatment(tempBolusPart, time, iCfg) result.basaliob += aIOB.iobContrib result.activity += aIOB.activityContrib result.netbasalinsulin += tempBolusPart.amount diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt index 552ef3cd848..02fb5bbef1e 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt @@ -275,12 +275,6 @@ class InsulinPlugin @Inject constructor( return iobCalc(bolus, time, iCfg.getPeak().toDouble(), iCfg.getDia()) } - override fun iobCalcForTreatment(bolus: BS, time: Long, dia: Double): Iob { - assert(dia != 0.0) - assert(peak != 0) - return iobCalc(bolus, time, peak.toDouble(), dia) - } - private fun iobCalc(bolus: BS, time: Long, peak: Double, dia: Double): Iob { val result = Iob() if (bolus.amount != 0.0) { diff --git a/plugins/main/src/main/kotlin/app/aaps/plugins/main/iob/iobCobCalculator/IobCobCalculatorPlugin.kt b/plugins/main/src/main/kotlin/app/aaps/plugins/main/iob/iobCobCalculator/IobCobCalculatorPlugin.kt index 9f68ad23781..2150c5547bb 100644 --- a/plugins/main/src/main/kotlin/app/aaps/plugins/main/iob/iobCobCalculator/IobCobCalculatorPlugin.kt +++ b/plugins/main/src/main/kotlin/app/aaps/plugins/main/iob/iobCobCalculator/IobCobCalculatorPlugin.kt @@ -514,7 +514,7 @@ class IobCobCalculatorPlugin @Inject constructor( private fun calculateIobFromBolusToTime(toTime: Long): IobTotal { val total = IobTotal(toTime) val profile = profileFunction.getProfile() ?: return total - val dia = profile.dia + val iCfg = profile.insulin val divisor = preferences.get(DoubleKey.ApsAmaBolusSnoozeDivisor) assert(divisor > 0) @@ -522,7 +522,7 @@ class IobCobCalculatorPlugin @Inject constructor( boluses.forEach { t -> if (t.isValid && t.timestamp < toTime) { - val tIOB = t.iobCalc(activePlugin, toTime, dia) + val tIOB = t.iobCalc(activePlugin, toTime, iCfg) total.iob += tIOB.iobContrib total.activity += tIOB.activityContrib if (t.amount > 0 && t.timestamp > total.lastBolusTime) total.lastBolusTime = t.timestamp @@ -531,7 +531,7 @@ class IobCobCalculatorPlugin @Inject constructor( // multiply the time the treatment is seen active. val timeSinceTreatment = toTime - t.timestamp val snoozeTime = t.timestamp + (timeSinceTreatment * divisor).toLong() - val bIOB = t.iobCalc(activePlugin, snoozeTime, dia) + val bIOB = t.iobCalc(activePlugin, snoozeTime, iCfg) total.bolussnooze += bIOB.iobContrib } } @@ -579,7 +579,7 @@ class IobCobCalculatorPlugin @Inject constructor( type = BS.Type.NORMAL, isBasalInsulin = true ) - val iob = bolus.iobCalc(activePlugin, toTime, profile.dia) + val iob = bolus.iobCalc(activePlugin, toTime, profile.insulin) total.basaliob += iob.iobContrib total.activity += iob.activityContrib i += T.mins(5).msecs() diff --git a/ui/src/main/kotlin/app/aaps/ui/activities/fragments/TreatmentsBolusCarbsFragment.kt b/ui/src/main/kotlin/app/aaps/ui/activities/fragments/TreatmentsBolusCarbsFragment.kt index 5e20a3b5c1c..e94db9c3cea 100644 --- a/ui/src/main/kotlin/app/aaps/ui/activities/fragments/TreatmentsBolusCarbsFragment.kt +++ b/ui/src/main/kotlin/app/aaps/ui/activities/fragments/TreatmentsBolusCarbsFragment.kt @@ -224,7 +224,7 @@ class TreatmentsBolusCarbsFragment : DaggerFragment(), MenuProvider { holder.binding.bolusNs.visibility = (bolus.ids.nightscoutId != null).toVisibility() holder.binding.bolusPump.visibility = bolus.ids.isPumpHistory().toVisibility() holder.binding.bolusInvalid.visibility = bolus.isValid.not().toVisibility() - val iob = bolus.iobCalc(activePlugin, System.currentTimeMillis(), profile.dia) + val iob = bolus.iobCalc(activePlugin, System.currentTimeMillis(), profile.insulin) if (iob.iobContrib > 0.01) { holder.binding.iob.setTextColor(rh.gac(context, app.aaps.core.ui.R.attr.activeColor)) holder.binding.iob.text = rh.gs(app.aaps.core.ui.R.string.format_insulin_units, iob.iobContrib) From 508f5862d1e15dac5542050e6626f1e0ea1534e4 Mon Sep 17 00:00:00 2001 From: Philoul Date: Sun, 16 Mar 2025 20:01:43 +0100 Subject: [PATCH 29/41] Insulin ReadOnly within Profile --- .../plugins/main/profile/ProfileFragment.kt | 8 +- .../src/main/res/layout/profile_fragment.xml | 148 +++++++++++------- 2 files changed, 100 insertions(+), 56 deletions(-) diff --git a/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfileFragment.kt b/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfileFragment.kt index 6cf7ec1125e..30cd9743c69 100644 --- a/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfileFragment.kt +++ b/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfileFragment.kt @@ -14,6 +14,7 @@ import app.aaps.core.data.ue.Action import app.aaps.core.data.ue.Sources import app.aaps.core.data.ue.ValueWithUnit import app.aaps.core.interfaces.aps.Loop +import app.aaps.core.interfaces.configuration.Config import app.aaps.core.interfaces.logging.AAPSLogger import app.aaps.core.interfaces.logging.LTag import app.aaps.core.interfaces.logging.UserEntryLogger @@ -63,6 +64,7 @@ class ProfileFragment : DaggerFragment() { @Inject lateinit var uiInteraction: UiInteraction @Inject lateinit var decimalFormatter: DecimalFormatter @Inject lateinit var loop: Loop + @Inject lateinit var config: Config private var disposable: CompositeDisposable = CompositeDisposable() private var inMenu = false @@ -122,7 +124,6 @@ class ProfileFragment : DaggerFragment() { override fun onTabSelected(tab: TabLayout.Tab) { processVisibility(tab.position) } - override fun onTabUnselected(tab: TabLayout.Tab) {} override fun onTabReselected(tab: TabLayout.Tab) {} }) @@ -161,13 +162,12 @@ class ProfileFragment : DaggerFragment() { currentProfile.iCfg = insulin binding.dia.text = rh.gs(app.aaps.core.ui.R.string.format_hours,insulin.getDia()) binding.peak.text = rh.gs(app.aaps.core.ui.R.string.mins,insulin.getPeak()) - //binding.dia.setParams(currentProfile.dia, hardLimits.minDia(), hardLimits.maxDia(), 0.1, DecimalFormat("0.0"), false, null, textWatch) - //binding.dia.tag = "LP_DIA" val insulinList: ArrayList = insulinPlugin.insulinList() context?.let { context -> binding.insulinList.setAdapter(ArrayAdapter(context, app.aaps.core.ui.R.layout.spinner_centered, insulinList)) } ?: return binding.insulinList.setText(currentProfile.iCfg.insulinLabel, false) + binding.insulinName.text = currentProfile.iCfg.insulinLabel TimeListEdit( requireContext(), @@ -380,6 +380,8 @@ class ProfileFragment : DaggerFragment() { .toObservable(EventLocalProfileChanged::class.java) .observeOn(aapsSchedulers.main) .subscribe({ build() }, fabricPrivacy::logException) + binding.insulinRow.visibility = config.AAPSCLIENT.toVisibility() + binding.insulinMenu.visibility = (!config.AAPSCLIENT).toVisibility() build() } diff --git a/plugins/main/src/main/res/layout/profile_fragment.xml b/plugins/main/src/main/res/layout/profile_fragment.xml index 34a17a86f37..c338e05c8dc 100644 --- a/plugins/main/src/main/res/layout/profile_fragment.xml +++ b/plugins/main/src/main/res/layout/profile_fragment.xml @@ -160,6 +160,7 @@ - - - - - - - - - - - - - - - + + + + + + + + + + - - + + + + + + + + + + + android:gravity="center_horizontal" + android:orientation="horizontal" + android:paddingTop="5dp"> + + + + + + + + + + - Date: Mon, 24 Mar 2025 09:08:16 +0100 Subject: [PATCH 30/41] Fix Insulin Plugin UI --- .../kotlin/app/aaps/core/data/model/ICfg.kt | 2 +- .../aaps/plugins/insulin/InsulinFragment.kt | 68 ++++++++++++------- .../app/aaps/plugins/insulin/InsulinPlugin.kt | 27 +++++--- .../plugins/main/profile/ProfileFragment.kt | 2 - 4 files changed, 60 insertions(+), 39 deletions(-) diff --git a/core/data/src/main/kotlin/app/aaps/core/data/model/ICfg.kt b/core/data/src/main/kotlin/app/aaps/core/data/model/ICfg.kt index bbe490b294b..2f17a7c7bbd 100644 --- a/core/data/src/main/kotlin/app/aaps/core/data/model/ICfg.kt +++ b/core/data/src/main/kotlin/app/aaps/core/data/model/ICfg.kt @@ -19,7 +19,7 @@ data class ICfg( return false } - fun getDia(): Double = insulinEndTime / 3600.0 / 1000.0 + fun getDia(): Double = Math.round(insulinEndTime / 3600.0 / 100.0) / 10.0 fun getPeak(): Int = (insulinPeakTime / 60000).toInt() fun setDia(dia: Double) { insulinEndTime = (dia * 3600 * 1000).toLong() diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt index ce4c62e5d57..125881b1c30 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt @@ -20,6 +20,7 @@ import app.aaps.core.interfaces.logging.AAPSLogger import app.aaps.core.interfaces.logging.UserEntryLogger import app.aaps.core.interfaces.objects.Instantiator import app.aaps.core.interfaces.plugin.ActivePlugin +import app.aaps.core.interfaces.profile.ProfileFunction import app.aaps.core.interfaces.profile.ProfileStore import app.aaps.core.interfaces.resources.ResourceHelper import app.aaps.core.interfaces.ui.UiInteraction @@ -42,6 +43,7 @@ class InsulinFragment : DaggerFragment() { @Inject lateinit var hardLimits: HardLimits @Inject lateinit var rh: ResourceHelper @Inject lateinit var insulinPlugin: InsulinPlugin + @Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var uel: UserEntryLogger @Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var instantiator: Instantiator @@ -94,6 +96,7 @@ class InsulinFragment : DaggerFragment() { insulinPlugin.currentInsulinIndex = position insulinPlugin.currentInsulin = insulinPlugin.currentInsulin().deepClone() insulinPlugin.isEdited = false + swapAdapter() build() }, null ) @@ -101,19 +104,18 @@ class InsulinFragment : DaggerFragment() { } else { insulinPlugin.currentInsulinIndex = position insulinPlugin.currentInsulin = insulinPlugin.currentInsulin().deepClone() + swapAdapter() build() } - profileList = profileStore.getProfileList(currentInsulin) - swapAdapter(profileList) } - if (insulinPlugin.numOfInsulins == 0) + if (insulinPlugin.numOfInsulins == 0) { insulinPlugin.addNewInsulin( ICfg("", selectedTemplate.peak, selectedTemplate.dia), autoName = true ) + } insulinPlugin.setCurrent(insulinPlugin.iCfg) - profileList = profileStore.getProfileList(currentInsulin) - swapAdapter(profileList) + swapAdapter() processVisibility(0) binding.tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener { @@ -144,6 +146,7 @@ class InsulinFragment : DaggerFragment() { ) ) insulinPlugin.isEdited = true + swapAdapter() build() } } @@ -155,6 +158,7 @@ class InsulinFragment : DaggerFragment() { insulinPlugin.removeCurrentInsulin(activity) insulinPlugin.isEdited = false } + swapAdapter() build() } } @@ -176,15 +180,18 @@ class InsulinFragment : DaggerFragment() { insulinPlugin.storeSettings() build() } else { - OKDialog.showConfirmation(requireContext(), - rh.gs(R.string.update_profiles_title), - rh.gs(R.string.update_profiles_message, profileList.size), - Runnable { - insulinPlugin.insulins[insulinPlugin.currentInsulinIndex] = currentInsulin - insulinPlugin.storeSettings() - insulinPlugin.updateProfiles(profileList, profileStore, dateUtil.now()) - build() - } + OKDialog.showConfirmation( + requireContext(), + rh.gs(R.string.update_profiles_title), + rh.gs(R.string.update_profiles_message, profileList.size), + Runnable { + insulinPlugin.insulins[insulinPlugin.currentInsulinIndex] = currentInsulin + insulinPlugin.storeSettings() + insulinPlugin.updateProfiles(profileList, profileStore, dateUtil.now()) + profileStore = activePlugin.activeProfileSource.profile ?: instantiator.provideProfileStore(JSONObject()) + swapAdapter() + build() + } ) } } @@ -198,15 +205,13 @@ class InsulinFragment : DaggerFragment() { context?.let { context -> binding.insulinTemplate.setAdapter(ArrayAdapter(context, app.aaps.core.ui.R.layout.spinner_centered, insulinTemplateList)) } ?: return - //insulinPlugin.currentInsulin = insulinPlugin.currentInsulin().deepClone() binding.insulinTemplate.setText(currentInsulin.let { rh.gs(Insulin.InsulinType.fromPeak(it.insulinPeakTime).label) }, false) } + @Synchronized override fun onResume() { super.onResume() - insulinPlugin.setCurrent(insulinPlugin.iCfg) - profileList = profileStore.getProfileList(currentInsulin) - swapAdapter(profileList) + swapAdapter() build() } @@ -219,7 +224,6 @@ class InsulinFragment : DaggerFragment() { if (_binding == null) return val isValid = insulinPlugin.isValidEditState(activity) val isEdited = insulinPlugin.isEdited - val insulinList: ArrayList = insulinPlugin.insulinList() context?.let { context -> binding.insulinList.setAdapter(ArrayAdapter(context, app.aaps.core.ui.R.layout.spinner_centered, insulinList)) @@ -247,6 +251,11 @@ class InsulinFragment : DaggerFragment() { } else { binding.reset.visibility = View.GONE } + //Show Remove button if profileList is empty + if (profileList.isEmpty) + binding.insulinRemove.visibility = View.VISIBLE + else + binding.insulinRemove.visibility = View.GONE binding.graph.show(activePlugin.activeInsulin, currentInsulin) } @@ -263,7 +272,8 @@ class InsulinFragment : DaggerFragment() { minPeak = hardLimits.minPeak().toDouble() maxPeak = hardLimits.maxPeak().toDouble() } - else -> { + + else -> { minPeak = currentInsulin.getPeak().toDouble() maxPeak = minPeak } @@ -274,7 +284,7 @@ class InsulinFragment : DaggerFragment() { updateGUI() } - fun insulinFromTemplate(label: String): Insulin.InsulinType = Insulin.InsulinType.entries.firstOrNull { rh.gs(it.label) == label } ?:Insulin.InsulinType.OREF_FREE_PEAK + fun insulinFromTemplate(label: String): Insulin.InsulinType = Insulin.InsulinType.entries.firstOrNull { rh.gs(it.label) == label } ?: Insulin.InsulinType.OREF_FREE_PEAK fun doEdit() { insulinPlugin.isEdited = true @@ -286,9 +296,12 @@ class InsulinFragment : DaggerFragment() { binding.profilePlaceholder.visibility = (position == 1).toVisibility() } - private fun swapAdapter(list: List) { - binding.tabLayout.getTabAt(1)?.text = rh.gs(app.aaps.core.ui.R.string.profile_number, list.size) - binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) + private fun swapAdapter() { + profileList = profileStore.getProfileList(insulinPlugin.currentInsulin()) + if (insulinPlugin.currentInsulin().isEqual(insulinPlugin.iCfg)) + profileList.add(0, rh.gs(app.aaps.core.ui.R.string.active)) + binding.tabLayout.getTabAt(1)?.text = rh.gs(app.aaps.core.ui.R.string.profile_number, profileList.size) + binding.recyclerview.swapAdapter(RecyclerViewAdapter(profileList), true) } inner class RecyclerViewAdapter internal constructor(private var profileList: List) : RecyclerView.Adapter() { @@ -309,11 +322,16 @@ class InsulinFragment : DaggerFragment() { inner class ProfileViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val binding = InsulinProfileItemBinding.bind(itemView) + init { binding.profileName.setOnClickListener { activity?.let { activity -> val profileName = (it as TextView).text.toString() - profileStore.getSpecificProfile((it as TextView).text.toString())?.let { profile -> + val selectedProfile = if ((it as TextView).text.toString()==rh.gs(app.aaps.core.ui.R.string.active)) + profileFunction.getProfile()?.convertToNonCustomizedProfile(dateUtil) + else + profileStore.getSpecificProfile((it as TextView).text.toString()) + selectedProfile?.let { profile -> uiInteraction.runProfileViewerDialog( fragmentManager = childFragmentManager, time = dateUtil.now(), diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt index 02fb5bbef1e..19901c0412f 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt @@ -99,19 +99,18 @@ class InsulinPlugin @Inject constructor( } override fun setDefault(insulin: ICfg) { - getOrCreateInsulin(insulin).let { - insulins.forEachIndexed { index, iCfg -> - if(iCfg.isEqual(it)) - defaultInsulinIndex = index + insulins.forEachIndexed { index, iCfg -> + if (iCfg.isEqual(insulin)) { + defaultInsulinIndex = index + currentInsulinIndex = defaultInsulinIndex } - currentInsulinIndex = defaultInsulinIndex } } override val iCfg: ICfg get() { val profile = profileFunction.getProfile() - return getOrCreateInsulin(profile?.insulin ?:insulins[defaultInsulinIndex]) + return profile?.insulin ?:insulins[defaultInsulinIndex] } lateinit var currentInsulin: ICfg @@ -145,9 +144,12 @@ class InsulinPlugin @Inject constructor( if (iCfg.getDia() < hardLimits.minDia() || iCfg.getDia() > hardLimits.maxDia()) iCfg.insulinEndTime = insulins[defaultInsulinIndex].insulinEndTime insulins.forEachIndexed { index, it -> - if (iCfg.isEqual(it)) + if (iCfg.isEqual(it)) { + aapsLogger.debug("XXXXX getOrCreate index: $index name : ${it.insulinLabel}") return it + } } + aapsLogger.debug("XXXXX getOrCreate iCfg: ${iCfg.insulinLabel}") return addNewInsulin(iCfg, true) } @@ -160,6 +162,7 @@ class InsulinPlugin @Inject constructor( return index } } + aapsLogger.debug("XXXXX setCurrent iCfg: ${iCfg.insulinLabel} ${iCfg.getPeak()} ${iCfg.getDia()}") addNewInsulin(iCfg, true) currentInsulin = currentInsulin().deepClone() return insulins.size - 1 @@ -194,6 +197,7 @@ class InsulinPlugin @Inject constructor( get() = rh.gs(R.string.dia_too_short) + @Synchronized fun addNewInsulin(template: ICfg, autoName: Boolean = false): ICfg { if (autoName) template.insulinLabel = createNewInsulinLabel(template) @@ -206,6 +210,7 @@ class InsulinPlugin @Inject constructor( return newInsulin } + @Synchronized fun removeCurrentInsulin(activity: FragmentActivity?) { // activity included to include PopUp or Toast when Remove can't be done (default insulin or insulin used within profile // Todo include Remove authorization and message @@ -234,6 +239,7 @@ class InsulinPlugin @Inject constructor( return insulinLabel } + @Synchronized fun updateProfiles(profileList: ArrayList, profileStore: ProfileStore, now: Long) { val profilePlugin = activePlugin.activeProfileSource val fullProfileList = profileStore.getProfileList() @@ -311,14 +317,15 @@ class InsulinPlugin @Inject constructor( return json } + @Synchronized override fun applyConfiguration(configuration: JSONObject) { insulins.clear() configuration.optJSONArray("insulins")?.let { + aapsLogger.debug("XXXXX applyConfig insert ${it.length()} insulins") for (index in 0 until (it.length())) { try { val o = it.getJSONObject(index) - insulins.add(ICfg.fromJson(o)) - + getOrCreateInsulin(ICfg.fromJson(o)) } catch (e: Exception) { // } @@ -361,7 +368,6 @@ class InsulinPlugin @Inject constructor( if (isEqual(insulin)) { if (verbose) ToastUtils.errorToast(activity, rh.gs(R.string.insulin_duplicated, insulin.insulinLabel)) - aapsLogger.debug("XXXXX Duplicate currentIndex: $currentInsulinIndex current: ${insulinLabel} index: $index, label: ${insulin.insulinLabel} peak: ${insulin.getPeak()}, dia: ${insulin.getDia()}") return false } } @@ -374,7 +380,6 @@ class InsulinPlugin @Inject constructor( insulins.forEachIndexed { index, insulin -> if (index != currentIndex) { if (insulin.insulinLabel == insulinLabel) { - aapsLogger.debug("XXXXX Label currentIndex: $currentIndex current: ${insulinLabel} index: $index, label: ${insulin.insulinLabel}") return true } } diff --git a/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfileFragment.kt b/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfileFragment.kt index 30cd9743c69..9c024bc28a2 100644 --- a/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfileFragment.kt +++ b/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfileFragment.kt @@ -9,7 +9,6 @@ import android.view.ViewGroup import android.widget.AdapterView import android.widget.ArrayAdapter import app.aaps.core.data.model.GlucoseUnit -import app.aaps.core.data.model.ICfg import app.aaps.core.data.ue.Action import app.aaps.core.data.ue.Sources import app.aaps.core.data.ue.ValueWithUnit @@ -30,7 +29,6 @@ import app.aaps.core.interfaces.ui.UiInteraction import app.aaps.core.interfaces.utils.DateUtil import app.aaps.core.interfaces.utils.DecimalFormatter import app.aaps.core.interfaces.utils.HardLimits -import app.aaps.core.interfaces.utils.SafeParse import app.aaps.core.interfaces.utils.fabric.FabricPrivacy import app.aaps.core.objects.profile.ProfileSealed import app.aaps.core.ui.dialogs.OKDialog From fff4c60c53d85cf90075002c447fd7e608d3eff8 Mon Sep 17 00:00:00 2001 From: Philoul Date: Fri, 28 Mar 2025 09:01:14 +0100 Subject: [PATCH 31/41] Fix 3.3.3.0 pref --- app/src/main/kotlin/app/aaps/MainApp.kt | 7 ++++--- .../src/main/kotlin/app/aaps/core/keys/StringKey.kt | 1 + core/utils/src/main/res/values/keys.xml | 2 +- .../kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt | 10 ++++++---- .../app/aaps/plugins/insulin/InsulinPluginTest.kt | 3 +-- .../app/aaps/plugins/main/profile/ProfilePlugin.kt | 8 ++------ .../main/profile/keys/ProfileComposedStringKey.kt | 2 ++ 7 files changed, 17 insertions(+), 16 deletions(-) diff --git a/app/src/main/kotlin/app/aaps/MainApp.kt b/app/src/main/kotlin/app/aaps/MainApp.kt index f7a0ed070d4..978afd79c0b 100644 --- a/app/src/main/kotlin/app/aaps/MainApp.kt +++ b/app/src/main/kotlin/app/aaps/MainApp.kt @@ -231,7 +231,8 @@ class MainApp : DaggerApplication() { sp.remove("ConfigBuilder_INSULIN_InsulinLyumjevPlugin_Visible") sp.remove("ConfigBuilder_INSULIN_InsulinOrefFreePeakPlugin_Enabled") sp.remove("ConfigBuilder_INSULIN_InsulinOrefFreePeakPlugin_Visible") - sp.putBoolean("ConfigBuilder_INSULIN_InsulinPlugin_Enabled", true) + preferences.put(ConfigurationBooleanComposedKey.ConfigBuilderVisible, "INSULIN_InsulinPlugin", value = true) + preferences.put(ConfigurationBooleanComposedKey.ConfigBuilderVisible, "INSULIN_InsulinPlugin", value = true) } // 3.3 @@ -339,9 +340,9 @@ class MainApp : DaggerApplication() { preferences.put(ProfileComposedStringKey.LocalProfileNumberedIc, SafeParse.stringToInt(number), value = value as String) sp.remove(key) } - if (key.startsWith(Constants.LOCAL_PROFILE + "_") && key.endsWith("_ic")) { + if (key.startsWith(Constants.LOCAL_PROFILE + "_") && key.endsWith("_icfg")) { val number = key.split("_")[1] - preferences.put(ProfileComposedStringKey.LocalProfileNumberedIc, SafeParse.stringToInt(number), value = value as String) + preferences.put(ProfileComposedStringKey.LocalProfileNumberedIcfg, SafeParse.stringToInt(number), value = value as String) sp.remove(key) } if (key.startsWith(Constants.LOCAL_PROFILE + "_") && key.endsWith("_basal")) { diff --git a/core/keys/src/main/kotlin/app/aaps/core/keys/StringKey.kt b/core/keys/src/main/kotlin/app/aaps/core/keys/StringKey.kt index b7a483d28f9..93680ec9c78 100644 --- a/core/keys/src/main/kotlin/app/aaps/core/keys/StringKey.kt +++ b/core/keys/src/main/kotlin/app/aaps/core/keys/StringKey.kt @@ -41,6 +41,7 @@ enum class StringKey( MaintenanceEmail("maintenance_logs_email", "logs@aaps.app", defaultedBySM = true), MaintenanceIdentification("email_for_crash_report", ""), AutomationLocation("location", "PASSIVE", hideParentScreenIfHidden = true), + InsulinConfiguration("insulin_configuration",""), SmsAllowedNumbers("smscommunicator_allowednumbers", ""), SmsOtpPassword("smscommunicator_otp_password", "", dependency = BooleanKey.SmsAllowRemoteCommands, isPassword = true), diff --git a/core/utils/src/main/res/values/keys.xml b/core/utils/src/main/res/values/keys.xml index f4ad293f92e..0dfca3ffc0a 100644 --- a/core/utils/src/main/res/values/keys.xml +++ b/core/utils/src/main/res/values/keys.xml @@ -2,5 +2,5 @@ units_mgdl - insulin_configuration + \ No newline at end of file diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt index 19901c0412f..6c75bc3215a 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt @@ -25,8 +25,11 @@ import app.aaps.core.interfaces.rx.events.EventLocalProfileChanged import app.aaps.core.interfaces.sharedPreferences.SP import app.aaps.core.interfaces.ui.UiInteraction import app.aaps.core.interfaces.utils.HardLimits -import app.aaps.core.keys.Preferences +import app.aaps.core.keys.IntKey +import app.aaps.core.keys.StringKey +import app.aaps.core.keys.interfaces.Preferences import app.aaps.core.objects.extensions.fromJson +import app.aaps.core.objects.extensions.store import app.aaps.core.objects.extensions.toJson import app.aaps.core.ui.toast.ToastUtils import org.json.JSONArray @@ -48,7 +51,6 @@ class InsulinPlugin @Inject constructor( rh: ResourceHelper, val profileFunction: ProfileFunction, val rxBus: RxBus, - private val sp: SP, aapsLogger: AAPSLogger, val config: Config, val hardLimits: HardLimits, @@ -261,7 +263,7 @@ class InsulinPlugin @Inject constructor( @Synchronized fun loadSettings() { - val jsonString = sp.getString(app.aaps.core.utils.R.string.key_insulin_configuration, "") + val jsonString = preferences.get(StringKey.InsulinConfiguration) try { JSONObject(jsonString).let { applyConfiguration(it) @@ -273,7 +275,7 @@ class InsulinPlugin @Inject constructor( @Synchronized fun storeSettings() { - sp.putString(app.aaps.core.utils.R.string.key_insulin_configuration, configuration().toString()) + preferences.put(StringKey.InsulinConfiguration, configuration().toString()) isEdited = false } diff --git a/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinPluginTest.kt b/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinPluginTest.kt index 59a5e2c77a4..4583b38e56e 100644 --- a/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinPluginTest.kt +++ b/plugins/insulin/src/test/kotlin/app/aaps/plugins/insulin/InsulinPluginTest.kt @@ -35,7 +35,6 @@ class InsulinPluginTest: TestBaseWithProfile() { if (it is AdaptiveIntPreference) { it.profileUtil = profileUtil it.preferences = preferences - it.sharedPrefs = sharedPrefs it.config = config } } @@ -44,7 +43,7 @@ class InsulinPluginTest: TestBaseWithProfile() { @BeforeEach fun setup() { - sut = InsulinPlugin(preferences, rh, profileFunction, rxBus, sp, aapsLogger, config, hardLimits, uiInteraction, uel, activePlugin) + sut = InsulinPlugin(preferences, rh, profileFunction, rxBus, aapsLogger, config, hardLimits, uiInteraction, uel, activePlugin) } @Test diff --git a/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfilePlugin.kt b/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfilePlugin.kt index ddfdf3d0c1b..7e2028ed772 100644 --- a/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfilePlugin.kt +++ b/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfilePlugin.kt @@ -28,11 +28,7 @@ import app.aaps.core.interfaces.utils.DateUtil import app.aaps.core.interfaces.utils.DecimalFormatter import app.aaps.core.interfaces.utils.HardLimits import app.aaps.core.keys.LongNonKey -import app.aaps.core.keys.interfaces.BooleanComposedNonPreferenceKey -import app.aaps.core.keys.interfaces.DoubleComposedNonPreferenceKey -import app.aaps.core.keys.interfaces.IntNonPreferenceKey import app.aaps.core.keys.interfaces.Preferences -import app.aaps.core.keys.interfaces.StringComposedNonPreferenceKey import app.aaps.core.objects.extensions.blockFromJsonArray import app.aaps.core.objects.extensions.fromJson import app.aaps.core.objects.extensions.pureProfileFromJson @@ -195,8 +191,8 @@ class ProfilePlugin @Inject constructor( profiles[i].run { preferences.put(ProfileComposedStringKey.LocalProfileNumberedName, i, value = name) preferences.put(ProfileComposedBooleanKey.LocalProfileNumberedMgdl, i, value = mgdl) - sp.putString(localProfileNumbered + "icfg", iCfg.toJson().toString()) preferences.put(ProfileComposedDoubleKey.LocalProfileNumberedDia, i, value = dia) + preferences.put(ProfileComposedStringKey.LocalProfileNumberedIcfg, i, value = iCfg.toJson().toString()) preferences.put(ProfileComposedStringKey.LocalProfileNumberedIc, i, value = ic.toString()) preferences.put(ProfileComposedStringKey.LocalProfileNumberedIsf, i, value = isf.toString()) preferences.put(ProfileComposedStringKey.LocalProfileNumberedBasal, i, value = basal.toString()) @@ -232,7 +228,7 @@ class ProfilePlugin @Inject constructor( ProfileSource.SingleProfile( name = name, mgdl = preferences.get(ProfileComposedBooleanKey.LocalProfileNumberedMgdl, i), - iCfg = ICfg.fromJson(JSONObject(sp.getString(localProfileNumbered + "icfg", DEFAULT_ICFG))), + iCfg = ICfg.fromJson(JSONObject(preferences.get(ProfileComposedStringKey.LocalProfileNumberedIcfg, i))), dia = preferences.get(ProfileComposedDoubleKey.LocalProfileNumberedDia, i), ic = JSONArray(preferences.get(ProfileComposedStringKey.LocalProfileNumberedIc, i)), isf = JSONArray(preferences.get(ProfileComposedStringKey.LocalProfileNumberedIsf, i)), diff --git a/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/keys/ProfileComposedStringKey.kt b/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/keys/ProfileComposedStringKey.kt index 83db71c1736..64fa8028189 100644 --- a/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/keys/ProfileComposedStringKey.kt +++ b/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/keys/ProfileComposedStringKey.kt @@ -3,6 +3,7 @@ package app.aaps.plugins.main.profile.keys import app.aaps.core.data.configuration.Constants import app.aaps.core.keys.interfaces.StringComposedNonPreferenceKey import app.aaps.plugins.main.profile.ProfilePlugin.Companion.DEFAULT_ARRAY +import app.aaps.plugins.main.profile.ProfilePlugin.Companion.DEFAULT_ICFG enum class ProfileComposedStringKey( override val key: String, @@ -12,6 +13,7 @@ enum class ProfileComposedStringKey( ) : StringComposedNonPreferenceKey { LocalProfileNumberedIsf(Constants.LOCAL_PROFILE + "_isf_", "%d", DEFAULT_ARRAY), + LocalProfileNumberedIcfg(Constants.LOCAL_PROFILE + "_icfg_", "%d", DEFAULT_ICFG), LocalProfileNumberedIc(Constants.LOCAL_PROFILE + "_ic_", "%d", DEFAULT_ARRAY), LocalProfileNumberedBasal(Constants.LOCAL_PROFILE + "_basal_", "%d", DEFAULT_ARRAY), LocalProfileNumberedTargetLow(Constants.LOCAL_PROFILE + "_targetlow_", "%d", DEFAULT_ARRAY), From cae5a537ebf1cc08224697803067db784539abc9 Mon Sep 17 00:00:00 2001 From: Philoul Date: Fri, 28 Mar 2025 10:40:57 +0100 Subject: [PATCH 32/41] Fix tests --- .../app/aaps/plugins/main/extensions/BolusExtensionKtTest.kt | 2 +- .../plugins/main/extensions/ExtendedBolusExtensionKtTest.kt | 2 +- .../plugins/main/extensions/TemporaryBasalExtensionKtTest.kt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/BolusExtensionKtTest.kt b/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/BolusExtensionKtTest.kt index 58096cadd2a..7b95409a085 100644 --- a/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/BolusExtensionKtTest.kt +++ b/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/BolusExtensionKtTest.kt @@ -26,7 +26,7 @@ class BolusExtensionKtTest : TestBaseWithProfile() { private val iCfg = Insulin.InsulinType.OREF_LYUMJEV.getICfg().also {it.setDia(7.0) } @BeforeEach fun setup() { - insulin = InsulinPlugin(preferences, rh, profileFunctions, rxBus, sp, aapsLogger, config, hardLimits, uiInteraction, uel, activePlugin) + insulin = InsulinPlugin(preferences, rh, profileFunctions, rxBus, aapsLogger, config, hardLimits, uiInteraction, uel, activePlugin) Mockito.`when`(activePlugin.activeInsulin).thenReturn(insulin) } diff --git a/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/ExtendedBolusExtensionKtTest.kt b/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/ExtendedBolusExtensionKtTest.kt index ee5e21801ca..7049115a07b 100644 --- a/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/ExtendedBolusExtensionKtTest.kt +++ b/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/ExtendedBolusExtensionKtTest.kt @@ -31,7 +31,7 @@ class ExtendedBolusExtensionKtTest : TestBaseWithProfile() { private val dia = 7.0 @BeforeEach fun setup() { - insulin = InsulinPlugin(preferences, rh, profileFunctions, rxBus, sp, aapsLogger, config, hardLimits, uiInteraction, uel, activePlugin) + insulin = InsulinPlugin(preferences, rh, profileFunctions, rxBus, aapsLogger, config, hardLimits, uiInteraction, uel, activePlugin) Mockito.`when`(activePlugin.activeInsulin).thenReturn(insulin) Mockito.`when`(dateUtil.now()).thenReturn(now) } diff --git a/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/TemporaryBasalExtensionKtTest.kt b/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/TemporaryBasalExtensionKtTest.kt index 422fb59b9c1..15a430e0e9a 100644 --- a/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/TemporaryBasalExtensionKtTest.kt +++ b/plugins/main/src/test/kotlin/app/aaps/plugins/main/extensions/TemporaryBasalExtensionKtTest.kt @@ -29,7 +29,7 @@ class TemporaryBasalExtensionKtTest : TestBaseWithProfile() { @BeforeEach fun setup() { - insulin = InsulinPlugin(preferences, rh, profileFunctions, rxBus, sp, aapsLogger, config, hardLimits, uiInteraction, uel, activePlugin) + insulin = InsulinPlugin(preferences, rh, profileFunctions, rxBus, aapsLogger, config, hardLimits, uiInteraction, uel, activePlugin) Mockito.`when`(activePlugin.activeInsulin).thenReturn(insulin) Mockito.`when`(dateUtil.now()).thenReturn(now) } From f8c3cdc88b6c5f24e370de6a02309df1086526fc Mon Sep 17 00:00:00 2001 From: Philoul Date: Mon, 31 Mar 2025 12:53:46 +0200 Subject: [PATCH 33/41] Fix Crash when wrong profile migration --- .../src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt index 6c75bc3215a..ca6230e90d1 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt @@ -285,7 +285,7 @@ class InsulinPlugin @Inject constructor( private fun iobCalc(bolus: BS, time: Long, peak: Double, dia: Double): Iob { val result = Iob() - if (bolus.amount != 0.0) { + if (bolus.amount != 0.0 && peak != 0.0) { val bolusTime = bolus.timestamp val t = (time - bolusTime) / 1000.0 / 60.0 val td = dia * 60 //getDIA() always >= MIN_DIA From 1a355b9c125c0aa20544018764d7c028cbec01de Mon Sep 17 00:00:00 2001 From: Philoul Date: Tue, 1 Apr 2025 11:52:03 +0200 Subject: [PATCH 34/41] Fix Insulin and Profile migration --- app/src/main/kotlin/app/aaps/MainApp.kt | 90 ++++++++----------- .../aaps/core/keys/interfaces/Preferences.kt | 8 ++ .../sharedPreferences/PreferencesImpl.kt | 4 + .../aaps/plugins/insulin/InsulinFragment.kt | 2 +- .../app/aaps/plugins/insulin/InsulinPlugin.kt | 4 +- .../wear/sharedPreferences/PreferencesImpl.kt | 4 + 6 files changed, 54 insertions(+), 58 deletions(-) diff --git a/app/src/main/kotlin/app/aaps/MainApp.kt b/app/src/main/kotlin/app/aaps/MainApp.kt index 978afd79c0b..f80a3cdde25 100644 --- a/app/src/main/kotlin/app/aaps/MainApp.kt +++ b/app/src/main/kotlin/app/aaps/MainApp.kt @@ -24,7 +24,6 @@ import app.aaps.core.interfaces.logging.AAPSLogger import app.aaps.core.interfaces.logging.LTag import app.aaps.core.interfaces.plugin.ActivePlugin import app.aaps.core.interfaces.plugin.PluginBase -import app.aaps.core.interfaces.profile.ProfileSource import app.aaps.core.interfaces.resources.ResourceHelper import app.aaps.core.interfaces.sharedPreferences.SP import app.aaps.core.interfaces.ui.UiInteraction @@ -74,8 +73,6 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.launch -import org.json.JSONArray -import org.json.JSONException import org.json.JSONObject import rxdogtag2.RxDogTag import java.io.IOException @@ -208,21 +205,27 @@ class MainApp : DaggerApplication() { private fun doMigrations() { // set values for different builds + var defaultInsulin = Insulin.InsulinType.OREF_RAPID_ACTING.getICfg() + // replace dia by ICfg within profile either if we are from 3.3.2.0 or 3.3.3.0 + if (sp.getBoolean("ConfigBuilder_INSULIN_InsulinOrefRapidActingPlugin_Enabled", false) || preferences.get(ConfigurationBooleanComposedKey.ConfigBuilderEnabled, "INSULIN_InsulinOrefRapidActingPlugin") || + sp.getBoolean("ConfigBuilder_INSULIN_InsulinOrefUltraRapidActingPlugin_Enabled", false) || preferences.get(ConfigurationBooleanComposedKey.ConfigBuilderEnabled, "INSULIN_InsulinOrefUltraRapidActingPlugin") || + sp.getBoolean("ConfigBuilder_INSULIN_InsulinLyumjevPlugin_Enabled", false) || preferences.get(ConfigurationBooleanComposedKey.ConfigBuilderEnabled, "INSULIN_InsulinLyumjevPlugin") || + sp.getBoolean("ConfigBuilder_INSULIN_InsulinOrefFreePeakPlugin_Enabled", false) || preferences.get(ConfigurationBooleanComposedKey.ConfigBuilderEnabled, "INSULIN_InsulinOrefFreePeakPlugin") + ) { + aapsLogger.debug("XXXXX Migration InsulinPlugin") + defaultInsulin = when { + sp.getBoolean("ConfigBuilder_INSULIN_InsulinOrefUltraRapidActingPlugin_Enabled", false) || + preferences.get(ConfigurationBooleanComposedKey.ConfigBuilderEnabled, "INSULIN_InsulinOrefRapidActingPlugin") -> Insulin.InsulinType.OREF_ULTRA_RAPID_ACTING.getICfg() - // replace dia by ICfg within profile - if (sp.getBoolean("ConfigBuilder_INSULIN_InsulinOrefRapidActingPlugin_Enabled", false) || - sp.getBoolean("ConfigBuilder_INSULIN_InsulinOrefUltraRapidActingPlugin_Enabled", false) || - sp.getBoolean("ConfigBuilder_INSULIN_InsulinLyumjevPlugin_Enabled", false) || - sp.getBoolean("ConfigBuilder_INSULIN_InsulinOrefFreePeakPlugin_Enabled", false)) { - val defaultInsulin = when { - sp.getBoolean("ConfigBuilder_INSULIN_InsulinOrefUltraRapidActingPlugin_Enabled", false) -> Insulin.InsulinType.OREF_ULTRA_RAPID_ACTING.getICfg() - sp.getBoolean("ConfigBuilder_INSULIN_InsulinLyumjevPlugin_Enabled", false) -> Insulin.InsulinType.OREF_LYUMJEV.getICfg() - sp.getBoolean("ConfigBuilder_INSULIN_InsulinOrefFreePeakPlugin_Enabled", false) -> Insulin.InsulinType.OREF_FREE_PEAK.getICfg().also { + sp.getBoolean("ConfigBuilder_INSULIN_InsulinLyumjevPlugin_Enabled", false) || + preferences.get(ConfigurationBooleanComposedKey.ConfigBuilderEnabled, "INSULIN_InsulinLyumjevPlugin") -> Insulin.InsulinType.OREF_LYUMJEV.getICfg() + + sp.getBoolean("ConfigBuilder_INSULIN_InsulinOrefFreePeakPlugin_Enabled", false) || + preferences.get(ConfigurationBooleanComposedKey.ConfigBuilderEnabled, "INSULIN_InsulinOrefFreePeakPlugin") -> Insulin.InsulinType.OREF_FREE_PEAK.getICfg().also { it.setPeak(preferences.get(IntKey.InsulinOrefPeak)) } - else -> Insulin.InsulinType.OREF_RAPID_ACTING.getICfg() + else -> Insulin.InsulinType.OREF_RAPID_ACTING.getICfg() } - migrateProfiles(defaultInsulin) sp.remove("ConfigBuilder_INSULIN_InsulinOrefRapidActingPlugin_Enabled") sp.remove("ConfigBuilder_INSULIN_InsulinOrefRapidActingPlugin_Visible") sp.remove("ConfigBuilder_INSULIN_InsulinOrefUltraRapidActingPlugin_Enabled") @@ -231,8 +234,16 @@ class MainApp : DaggerApplication() { sp.remove("ConfigBuilder_INSULIN_InsulinLyumjevPlugin_Visible") sp.remove("ConfigBuilder_INSULIN_InsulinOrefFreePeakPlugin_Enabled") sp.remove("ConfigBuilder_INSULIN_InsulinOrefFreePeakPlugin_Visible") + preferences.remove(ConfigurationBooleanComposedKey.ConfigBuilderEnabled, "INSULIN_InsulinOrefRapidActingPlugin") + preferences.remove(ConfigurationBooleanComposedKey.ConfigBuilderEnabled, "INSULIN_InsulinOrefUltraRapidActingPlugin") + preferences.remove(ConfigurationBooleanComposedKey.ConfigBuilderEnabled, "INSULIN_InsulinLyumjevPlugin") + preferences.remove(ConfigurationBooleanComposedKey.ConfigBuilderEnabled, "INSULIN_InsulinOrefFreePeakPlugin") + preferences.remove(ConfigurationBooleanComposedKey.ConfigBuilderVisible, "INSULIN_InsulinOrefRapidActingPlugin") + preferences.remove(ConfigurationBooleanComposedKey.ConfigBuilderVisible, "INSULIN_InsulinOrefUltraRapidActingPlugin") + preferences.remove(ConfigurationBooleanComposedKey.ConfigBuilderVisible, "INSULIN_InsulinLyumjevPlugin") + preferences.remove(ConfigurationBooleanComposedKey.ConfigBuilderVisible, "INSULIN_InsulinOrefFreePeakPlugin") preferences.put(ConfigurationBooleanComposedKey.ConfigBuilderVisible, "INSULIN_InsulinPlugin", value = true) - preferences.put(ConfigurationBooleanComposedKey.ConfigBuilderVisible, "INSULIN_InsulinPlugin", value = true) + preferences.put(ConfigurationBooleanComposedKey.ConfigBuilderEnabled, "INSULIN_InsulinPlugin", value = true) } // 3.3 @@ -342,7 +353,9 @@ class MainApp : DaggerApplication() { } if (key.startsWith(Constants.LOCAL_PROFILE + "_") && key.endsWith("_icfg")) { val number = key.split("_")[1] - preferences.put(ProfileComposedStringKey.LocalProfileNumberedIcfg, SafeParse.stringToInt(number), value = value as String) + val iCfg = ICfg.fromJson(JSONObject(value as String)) + if (iCfg.getPeak() > 0) + preferences.put(ProfileComposedStringKey.LocalProfileNumberedIcfg, SafeParse.stringToInt(number), value = value as String) sp.remove(key) } if (key.startsWith(Constants.LOCAL_PROFILE + "_") && key.endsWith("_basal")) { @@ -373,48 +386,15 @@ class MainApp : DaggerApplication() { preferences.put(ProfileComposedDoubleKey.LocalProfileNumberedDia, SafeParse.stringToInt(number), value = value.toDouble()) else preferences.put(ProfileComposedDoubleKey.LocalProfileNumberedDia, SafeParse.stringToInt(number), value = value as Double) - sp.remove(key) - } - } - } - - private fun migrateProfiles(defaultInsulin: ICfg) { - val numOfProfiles = sp.getInt(Constants.LOCAL_PROFILE + "_profiles", 0) - val defaultArray = "[{\"time\":\"00:00\",\"timeAsSeconds\":0,\"value\":0}]" -// numOfProfiles = max(numOfProfiles, 1) // create at least one default profile if none exists - - for (i in 0 until numOfProfiles) { - val localProfileNumbered = Constants.LOCAL_PROFILE + "_" + i + "_" - val name = sp.getString(localProfileNumbered + "name", Constants.LOCAL_PROFILE + i) - try { - ProfileSource.SingleProfile( - name = name, - mgdl = sp.getBoolean(localProfileNumbered + "mgdl", false), - iCfg = ICfg.fromJson(JSONObject(sp.getString(localProfileNumbered + "icfg", defaultInsulin.toJson().toString()))), - dia = sp.getDouble(localProfileNumbered + "dia", Constants.defaultDIA), - ic = JSONArray(sp.getString(localProfileNumbered + "ic", defaultArray)), - isf = JSONArray(sp.getString(localProfileNumbered + "isf", defaultArray)), - basal = JSONArray(sp.getString(localProfileNumbered + "basal", defaultArray)), - targetLow = JSONArray(sp.getString(localProfileNumbered + "targetlow", defaultArray)), - targetHigh = JSONArray(sp.getString(localProfileNumbered + "targethigh", defaultArray)) - ).also { - it.iCfg.setDia(it.dia) - sp.putString(localProfileNumbered + "name", it.name) - sp.putBoolean(localProfileNumbered + "mgdl", it.mgdl) - sp.putString(localProfileNumbered + "icfg", it.iCfg.toJson().toString()) - sp.putDouble(localProfileNumbered + "dia", it.dia) - sp.putString(localProfileNumbered + "ic", it.ic.toString()) - sp.putString(localProfileNumbered + "isf", it.isf.toString()) - sp.putString(localProfileNumbered + "basal", it.basal.toString()) - sp.putString(localProfileNumbered + "targetlow", it.targetLow.toString()) - sp.putString(localProfileNumbered + "targethigh", it.targetHigh.toString()) + defaultInsulin.also { + it.setDia(preferences.get(ProfileComposedDoubleKey.LocalProfileNumberedDia, SafeParse.stringToInt(number))) } - } catch (e: JSONException) { - aapsLogger.error("Exception", e) + val iCfg = ICfg.fromJson(JSONObject(preferences.get(ProfileComposedStringKey.LocalProfileNumberedIcfg, SafeParse.stringToInt(number)))) + if (iCfg.getPeak() == 0) + preferences.put(ProfileComposedStringKey.LocalProfileNumberedIcfg, SafeParse.stringToInt(number), value = defaultInsulin.toJson().toString()) + sp.remove(key) } } - // reload profile settings after update - activePlugin.activeProfileSource.loadSettings() } override fun applicationInjector(): AndroidInjector { diff --git a/core/keys/src/main/kotlin/app/aaps/core/keys/interfaces/Preferences.kt b/core/keys/src/main/kotlin/app/aaps/core/keys/interfaces/Preferences.kt index ef6913f603d..5c03cd3b239 100644 --- a/core/keys/src/main/kotlin/app/aaps/core/keys/interfaces/Preferences.kt +++ b/core/keys/src/main/kotlin/app/aaps/core/keys/interfaces/Preferences.kt @@ -95,6 +95,14 @@ interface Preferences { */ fun put(key: BooleanComposedNonPreferenceKey, vararg arguments: Any, value: Boolean) + /** + * Remove value from [android.content.SharedPreferences] + * + * @param key [app.aaps.core.keys.interfaces.PreferenceKey] enum + * @param arguments arguments to compose final key using String::format + */ + fun remove(key: BooleanComposedNonPreferenceKey, vararg arguments: Any) + /* STRING */ /** diff --git a/implementation/src/main/kotlin/app/aaps/implementation/sharedPreferences/PreferencesImpl.kt b/implementation/src/main/kotlin/app/aaps/implementation/sharedPreferences/PreferencesImpl.kt index d8d7cf95e20..ac311813792 100644 --- a/implementation/src/main/kotlin/app/aaps/implementation/sharedPreferences/PreferencesImpl.kt +++ b/implementation/src/main/kotlin/app/aaps/implementation/sharedPreferences/PreferencesImpl.kt @@ -261,6 +261,10 @@ class PreferencesImpl @Inject constructor( sp.putBoolean(key.composeKey(*arguments), value) } + override fun remove(key: BooleanComposedNonPreferenceKey, vararg arguments: Any) { + sp.remove(String.format(Locale.ENGLISH, key.key, arguments)) + } + override fun get(key: StringComposedNonPreferenceKey, vararg arguments: Any): String = sp.getString(key.composeKey(*arguments), key.defaultValue) diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt index 125881b1c30..187bba69dab 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt @@ -252,7 +252,7 @@ class InsulinFragment : DaggerFragment() { binding.reset.visibility = View.GONE } //Show Remove button if profileList is empty - if (profileList.isEmpty) + if (profileList.isEmpty()) binding.insulinRemove.visibility = View.VISIBLE else binding.insulinRemove.visibility = View.GONE diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt index ca6230e90d1..34bea22d1c9 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt @@ -100,9 +100,9 @@ class InsulinPlugin @Inject constructor( } } - override fun setDefault(insulin: ICfg) { + override fun setDefault(iCfg: ICfg) { insulins.forEachIndexed { index, iCfg -> - if (iCfg.isEqual(insulin)) { + if (iCfg.isEqual(iCfg)) { defaultInsulinIndex = index currentInsulinIndex = defaultInsulinIndex } diff --git a/wear/src/main/kotlin/app/aaps/wear/sharedPreferences/PreferencesImpl.kt b/wear/src/main/kotlin/app/aaps/wear/sharedPreferences/PreferencesImpl.kt index 736f4ee0491..2d23bd67010 100644 --- a/wear/src/main/kotlin/app/aaps/wear/sharedPreferences/PreferencesImpl.kt +++ b/wear/src/main/kotlin/app/aaps/wear/sharedPreferences/PreferencesImpl.kt @@ -202,6 +202,10 @@ class PreferencesImpl @Inject constructor( sp.putBoolean(key.composeKey(*arguments), value) } + override fun remove(key: BooleanComposedNonPreferenceKey, vararg arguments: Any) { + sp.remove(String.format(Locale.ENGLISH, key.key, arguments)) + } + override fun get(key: StringComposedNonPreferenceKey, vararg arguments: Any): String = sp.getString(key.composeKey(*arguments), key.defaultValue) From b08532ef6d7b94f30c12c801b2aa401a4f57daf7 Mon Sep 17 00:00:00 2001 From: Philoul Date: Tue, 1 Apr 2025 18:43:32 +0200 Subject: [PATCH 35/41] Fix Insulin UI --- .../kotlin/app/aaps/plugins/insulin/InsulinFragment.kt | 3 +++ .../main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt | 7 ++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt index 187bba69dab..237fb01c2ee 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt @@ -114,6 +114,7 @@ class InsulinFragment : DaggerFragment() { autoName = true ) } + insulinPlugin.setDefault(insulinPlugin.iCfg) insulinPlugin.setCurrent(insulinPlugin.iCfg) swapAdapter() @@ -133,6 +134,7 @@ class InsulinFragment : DaggerFragment() { currentInsulin.setDia(selectedTemplate.dia) insulinPlugin.isEdited = true doEdit() + build() } binding.insulinAdd.setOnClickListener { if (insulinPlugin.isEdited) { @@ -154,6 +156,7 @@ class InsulinFragment : DaggerFragment() { if (insulinPlugin.isEdited) { activity?.let { OKDialog.show(it, "", rh.gs(R.string.save_or_reset_changes_first)) } } else { + aapsLogger.debug("XXXXX defaultIndex: ${insulinPlugin.defaultInsulinIndex} currentIndex: ${insulinPlugin.currentInsulinIndex}") if (insulinPlugin.currentInsulinIndex != insulinPlugin.defaultInsulinIndex) { insulinPlugin.removeCurrentInsulin(activity) insulinPlugin.isEdited = false diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt index 34bea22d1c9..a994f3acabf 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt @@ -147,11 +147,9 @@ class InsulinPlugin @Inject constructor( iCfg.insulinEndTime = insulins[defaultInsulinIndex].insulinEndTime insulins.forEachIndexed { index, it -> if (iCfg.isEqual(it)) { - aapsLogger.debug("XXXXX getOrCreate index: $index name : ${it.insulinLabel}") return it } } - aapsLogger.debug("XXXXX getOrCreate iCfg: ${iCfg.insulinLabel}") return addNewInsulin(iCfg, true) } @@ -216,9 +214,13 @@ class InsulinPlugin @Inject constructor( fun removeCurrentInsulin(activity: FragmentActivity?) { // activity included to include PopUp or Toast when Remove can't be done (default insulin or insulin used within profile // Todo include Remove authorization and message + if (currentInsulinIndex == defaultInsulinIndex) + return val insulinRemoved = currentInsulin().insulinLabel insulins.removeAt(currentInsulinIndex) uel.log(Action.INSULIN_REMOVED, Sources.Insulin, value = ValueWithUnit.SimpleString(insulinRemoved)) + if (currentInsulinIndex < defaultInsulinIndex) + defaultInsulinIndex-- currentInsulinIndex = defaultInsulinIndex currentInsulin = currentInsulin().deepClone() storeSettings() @@ -323,7 +325,6 @@ class InsulinPlugin @Inject constructor( override fun applyConfiguration(configuration: JSONObject) { insulins.clear() configuration.optJSONArray("insulins")?.let { - aapsLogger.debug("XXXXX applyConfig insert ${it.length()} insulins") for (index in 0 until (it.length())) { try { val o = it.getJSONObject(index) From 7a9b5597588cf2e34dd559fcfb94937025a4f315 Mon Sep 17 00:00:00 2001 From: Philoul Date: Tue, 1 Apr 2025 18:47:50 +0200 Subject: [PATCH 36/41] Clean Code --- .../kotlin/app/aaps/plugins/insulin/InsulinFragment.kt | 1 - .../main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt | 7 ------- .../app/aaps/plugins/main/profile/ProfileFragment.kt | 1 - 3 files changed, 9 deletions(-) diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt index 237fb01c2ee..9389fa9abfa 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt @@ -156,7 +156,6 @@ class InsulinFragment : DaggerFragment() { if (insulinPlugin.isEdited) { activity?.let { OKDialog.show(it, "", rh.gs(R.string.save_or_reset_changes_first)) } } else { - aapsLogger.debug("XXXXX defaultIndex: ${insulinPlugin.defaultInsulinIndex} currentIndex: ${insulinPlugin.currentInsulinIndex}") if (insulinPlugin.currentInsulinIndex != insulinPlugin.defaultInsulinIndex) { insulinPlugin.removeCurrentInsulin(activity) insulinPlugin.isEdited = false diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt index a994f3acabf..0fff64af350 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt @@ -22,14 +22,11 @@ import app.aaps.core.interfaces.profile.ProfileStore import app.aaps.core.interfaces.resources.ResourceHelper import app.aaps.core.interfaces.rx.bus.RxBus import app.aaps.core.interfaces.rx.events.EventLocalProfileChanged -import app.aaps.core.interfaces.sharedPreferences.SP import app.aaps.core.interfaces.ui.UiInteraction import app.aaps.core.interfaces.utils.HardLimits -import app.aaps.core.keys.IntKey import app.aaps.core.keys.StringKey import app.aaps.core.keys.interfaces.Preferences import app.aaps.core.objects.extensions.fromJson -import app.aaps.core.objects.extensions.store import app.aaps.core.objects.extensions.toJson import app.aaps.core.ui.toast.ToastUtils import org.json.JSONArray @@ -162,7 +159,6 @@ class InsulinPlugin @Inject constructor( return index } } - aapsLogger.debug("XXXXX setCurrent iCfg: ${iCfg.insulinLabel} ${iCfg.getPeak()} ${iCfg.getDia()}") addNewInsulin(iCfg, true) currentInsulin = currentInsulin().deepClone() return insulins.size - 1 @@ -344,19 +340,16 @@ class InsulinPlugin @Inject constructor( if (insulinEndTime < hardLimits.minDia() || dia > hardLimits.maxDia()) { if (verbose) ToastUtils.errorToast(activity, rh.gs(app.aaps.core.ui.R.string.value_out_of_hard_limits, rh.gs(app.aaps.core.ui.R.string.insulin_dia), dia)) - aapsLogger.debug("XXXXX PeakValue currentIndex: $currentInsulinIndex current: ${insulinLabel} peak: ${getDia()}") return false } if (peak < hardLimits.minPeak() || dia > hardLimits.maxPeak()) { if (verbose) ToastUtils.errorToast(activity, rh.gs(app.aaps.core.ui.R.string.value_out_of_hard_limits, rh.gs(app.aaps.core.ui.R.string.insulin_peak), peak)) - aapsLogger.debug("XXXXX PeakValue currentIndex: $currentInsulinIndex current: ${insulinLabel} peak: ${getPeak()}") return false } if (insulinLabel.isEmpty()) { if (verbose) ToastUtils.errorToast(activity, rh.gs(R.string.missing_insulin_name)) - aapsLogger.debug("XXXXX LabelEmpty currentIndex: $currentInsulinIndex current: ${insulinLabel}") return false } // Check Inulin name is unique and insulin parameters is unique diff --git a/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfileFragment.kt b/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfileFragment.kt index 9c024bc28a2..cca4e661a7f 100644 --- a/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfileFragment.kt +++ b/plugins/main/src/main/kotlin/app/aaps/plugins/main/profile/ProfileFragment.kt @@ -150,7 +150,6 @@ class ProfileFragment : DaggerFragment() { if (profilePlugin.numOfProfiles == 0) profilePlugin.addNewProfile() val currentProfile = profilePlugin.currentProfile() ?: return val units = if (currentProfile.mgdl) GlucoseUnit.MGDL.asText else GlucoseUnit.MMOL.asText - aapsLogger.debug("XXXXX PR ${currentProfile?.iCfg?.insulinLabel} peak: ${currentProfile.iCfg.getPeak()} dia: ${currentProfile.iCfg.getDia()}") binding.name.removeTextChangedListener(textWatch) binding.name.setText(currentProfile.name) binding.name.addTextChangedListener(textWatch) From 0b2f4476fe5b823fa7657b9a773a38f66dee0e83 Mon Sep 17 00:00:00 2001 From: Philoul Date: Thu, 3 Apr 2025 23:59:42 +0200 Subject: [PATCH 37/41] Rename Profile.insulin --- .../main/kotlin/app/aaps/core/interfaces/profile/Profile.kt | 2 +- .../aaps/core/objects/extensions/ExtendedBolusExtension.kt | 4 ++-- .../aaps/core/objects/extensions/TemporaryBasalExtension.kt | 4 ++-- .../kotlin/app/aaps/core/objects/profile/ProfileSealed.kt | 3 +-- .../src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt | 2 +- .../main/iob/iobCobCalculator/IobCobCalculatorPlugin.kt | 4 ++-- .../ui/activities/fragments/TreatmentsBolusCarbsFragment.kt | 2 +- 7 files changed, 10 insertions(+), 11 deletions(-) diff --git a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/Profile.kt b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/Profile.kt index 77c4994aea5..e81c281193c 100644 --- a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/Profile.kt +++ b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/profile/Profile.kt @@ -37,7 +37,7 @@ interface Profile { /** * InsulinProfile */ - val insulin: ICfg + fun iCfg(): ICfg val percentage: Int diff --git a/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/ExtendedBolusExtension.kt b/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/ExtendedBolusExtension.kt index 0646ef9a946..09a9866e87f 100644 --- a/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/ExtendedBolusExtension.kt +++ b/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/ExtendedBolusExtension.kt @@ -47,7 +47,7 @@ fun EB.iobCalc(time: Long, profile: Profile, insulinInterface: Insulin): IobTota val result = IobTotal(time) val realDuration = getPassedDurationToTimeInMinutes(time) if (realDuration > 0) { - val iCfg = profile.insulin + val iCfg = profile.iCfg() val diaAgo = time - iCfg.insulinEndTime val aboutFiveMinIntervals = ceil(realDuration / 5.0).toInt() val spacing = realDuration / aboutFiveMinIntervals.toDouble() @@ -93,7 +93,7 @@ fun EB.iobCalc( } if (realDuration > 0) { var netBasalRate: Double - val iCfg = profile.insulin + val iCfg = profile.iCfg() val diaAgo = time - iCfg.insulinEndTime val aboutFiveMinIntervals = ceil(realDuration / 5.0).toInt() val spacing = realDuration / aboutFiveMinIntervals diff --git a/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/TemporaryBasalExtension.kt b/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/TemporaryBasalExtension.kt index be5efd0975b..cea7bd82775 100644 --- a/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/TemporaryBasalExtension.kt +++ b/core/objects/src/main/kotlin/app/aaps/core/objects/extensions/TemporaryBasalExtension.kt @@ -62,7 +62,7 @@ fun TB.iobCalc(time: Long, profile: Profile, insulinInterface: Insulin): IobTota var netBasalAmount = 0.0 if (realDuration > 0) { var netBasalRate: Double - val iCfg = profile.insulin + val iCfg = profile.iCfg() val diaAgo = time - iCfg.insulinEndTime val aboutFiveMinIntervals = ceil(realDuration / 5.0).toInt() val tempBolusSpacing = realDuration / aboutFiveMinIntervals.toDouble() @@ -120,7 +120,7 @@ fun TB.iobCalc( } if (realDuration > 0) { var netBasalRate: Double - val iCfg = profile.insulin + val iCfg = profile.iCfg() val diaAgo = time - iCfg.insulinEndTime val aboutFiveMinIntervals = ceil(realDuration / 5.0).toInt() val tempBolusSpacing = realDuration / aboutFiveMinIntervals.toDouble() diff --git a/core/objects/src/main/kotlin/app/aaps/core/objects/profile/ProfileSealed.kt b/core/objects/src/main/kotlin/app/aaps/core/objects/profile/ProfileSealed.kt index 42cdc2329da..46ed9945e34 100644 --- a/core/objects/src/main/kotlin/app/aaps/core/objects/profile/ProfileSealed.kt +++ b/core/objects/src/main/kotlin/app/aaps/core/objects/profile/ProfileSealed.kt @@ -237,8 +237,7 @@ sealed class ProfileSealed( override val dia: Double get() = iCfg.insulinEndTime / 1000.0 / 60.0 / 60.0 - override val insulin: ICfg - get() = iCfg + override fun iCfg() = iCfg override val timeshift: Int get() = ts diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt index 0fff64af350..14cf954aed5 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt @@ -109,7 +109,7 @@ class InsulinPlugin @Inject constructor( override val iCfg: ICfg get() { val profile = profileFunction.getProfile() - return profile?.insulin ?:insulins[defaultInsulinIndex] + return profile?.iCfg() ?:insulins[defaultInsulinIndex] } lateinit var currentInsulin: ICfg diff --git a/plugins/main/src/main/kotlin/app/aaps/plugins/main/iob/iobCobCalculator/IobCobCalculatorPlugin.kt b/plugins/main/src/main/kotlin/app/aaps/plugins/main/iob/iobCobCalculator/IobCobCalculatorPlugin.kt index b3b5d774b98..1bcbab760c9 100644 --- a/plugins/main/src/main/kotlin/app/aaps/plugins/main/iob/iobCobCalculator/IobCobCalculatorPlugin.kt +++ b/plugins/main/src/main/kotlin/app/aaps/plugins/main/iob/iobCobCalculator/IobCobCalculatorPlugin.kt @@ -515,7 +515,7 @@ class IobCobCalculatorPlugin @Inject constructor( private fun calculateIobFromBolusToTime(toTime: Long): IobTotal { val total = IobTotal(toTime) val profile = profileFunction.getProfile() ?: return total - val iCfg = profile.insulin + val iCfg = profile.iCfg() val divisor = preferences.get(DoubleKey.ApsAmaBolusSnoozeDivisor) assert(divisor > 0) @@ -580,7 +580,7 @@ class IobCobCalculatorPlugin @Inject constructor( type = BS.Type.NORMAL, isBasalInsulin = true ) - val iob = bolus.iobCalc(activePlugin, toTime, profile.insulin) + val iob = bolus.iobCalc(activePlugin, toTime, profile.iCfg()) total.basaliob += iob.iobContrib total.activity += iob.activityContrib i += T.mins(5).msecs() diff --git a/ui/src/main/kotlin/app/aaps/ui/activities/fragments/TreatmentsBolusCarbsFragment.kt b/ui/src/main/kotlin/app/aaps/ui/activities/fragments/TreatmentsBolusCarbsFragment.kt index 258d7cc2b66..9eb827924c8 100644 --- a/ui/src/main/kotlin/app/aaps/ui/activities/fragments/TreatmentsBolusCarbsFragment.kt +++ b/ui/src/main/kotlin/app/aaps/ui/activities/fragments/TreatmentsBolusCarbsFragment.kt @@ -222,7 +222,7 @@ class TreatmentsBolusCarbsFragment : DaggerFragment(), MenuProvider { holder.binding.bolusNs.visibility = (bolus.ids.nightscoutId != null).toVisibility() holder.binding.bolusPump.visibility = bolus.ids.isPumpHistory().toVisibility() holder.binding.bolusInvalid.visibility = bolus.isValid.not().toVisibility() - val iob = bolus.iobCalc(activePlugin, System.currentTimeMillis(), profile.insulin) + val iob = bolus.iobCalc(activePlugin, System.currentTimeMillis(), profile.iCfg()) if (iob.iobContrib > 0.01) { holder.binding.iob.setTextColor(rh.gac(context, app.aaps.core.ui.R.attr.activeColor)) holder.binding.iob.text = rh.gs(app.aaps.core.ui.R.string.format_insulin_units, iob.iobContrib) From 27e32172ba28e3f4bd0c904835398b2f4fc65aa3 Mon Sep 17 00:00:00 2001 From: Philoul Date: Tue, 8 Apr 2025 13:48:30 +0200 Subject: [PATCH 38/41] Fix Insulin Name --- .../aaps/plugins/insulin/InsulinFragment.kt | 7 ++-- .../app/aaps/plugins/insulin/InsulinPlugin.kt | 40 +++++++++---------- 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt index 9389fa9abfa..364809bab25 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt @@ -110,8 +110,7 @@ class InsulinFragment : DaggerFragment() { } if (insulinPlugin.numOfInsulins == 0) { insulinPlugin.addNewInsulin( - ICfg("", selectedTemplate.peak, selectedTemplate.dia), - autoName = true + ICfg("", selectedTemplate.peak, selectedTemplate.dia) ) } insulinPlugin.setDefault(insulinPlugin.iCfg) @@ -175,7 +174,7 @@ class InsulinFragment : DaggerFragment() { } uel.log( action = Action.STORE_INSULIN, source = Sources.Insulin, - value = ValueWithUnit.SimpleString(insulinPlugin.currentInsulin().insulinLabel) + value = ValueWithUnit.SimpleString(insulinPlugin.currentInsulin.insulinLabel) ) if (profileList.isEmpty()) { insulinPlugin.insulins[insulinPlugin.currentInsulinIndex] = currentInsulin @@ -198,7 +197,7 @@ class InsulinFragment : DaggerFragment() { } } binding.autoName.setOnClickListener { - binding.name.setText(insulinPlugin.createNewInsulinLabel(currentInsulin, includingCurrent = false)) + binding.name.setText(insulinPlugin.createNewInsulinLabel(currentInsulin, insulinPlugin.currentInsulinIndex)) insulinPlugin.isEdited = true build() } diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt index 14cf954aed5..1079eb9558d 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt @@ -97,9 +97,9 @@ class InsulinPlugin @Inject constructor( } } - override fun setDefault(iCfg: ICfg) { + override fun setDefault(defaultICfg: ICfg) { insulins.forEachIndexed { index, iCfg -> - if (iCfg.isEqual(iCfg)) { + if (iCfg.isEqual(defaultICfg)) { defaultInsulinIndex = index currentInsulinIndex = defaultInsulinIndex } @@ -147,7 +147,7 @@ class InsulinPlugin @Inject constructor( return it } } - return addNewInsulin(iCfg, true) + return addNewInsulin(iCfg) } fun setCurrent(iCfg: ICfg): Int { @@ -159,7 +159,7 @@ class InsulinPlugin @Inject constructor( return index } } - addNewInsulin(iCfg, true) + addNewInsulin(iCfg) currentInsulin = currentInsulin().deepClone() return insulins.size - 1 } @@ -194,8 +194,8 @@ class InsulinPlugin @Inject constructor( @Synchronized - fun addNewInsulin(template: ICfg, autoName: Boolean = false): ICfg { - if (autoName) + fun addNewInsulin(template: ICfg): ICfg { + if (template.insulinLabel == "" || insulinLabelAlreadyExists(template.insulinLabel)) template.insulinLabel = createNewInsulinLabel(template) val newInsulin = template.deepClone() insulins.add(newInsulin) @@ -222,15 +222,15 @@ class InsulinPlugin @Inject constructor( storeSettings() } - fun createNewInsulinLabel(iCfg: ICfg, includingCurrent: Boolean = true): String { + fun createNewInsulinLabel(iCfg: ICfg, currentIndex: Int = -1): String { val template = Insulin.InsulinType.fromPeak(iCfg.insulinPeakTime) var insulinLabel = when (template) { Insulin.InsulinType.OREF_FREE_PEAK -> "${rh.gs(template.label)}_${iCfg.getPeak()}_${iCfg.getDia()}" else -> "${rh.gs(template.label)}_${iCfg.getDia()}" } - if (insulinLabelAlreadyExists(insulinLabel, if (includingCurrent) 10000 else currentInsulinIndex)) { + if (insulinLabelAlreadyExists(insulinLabel, currentIndex)) { for (i in 1..10000) { - if (!insulinLabelAlreadyExists("${insulinLabel}_$i", if (includingCurrent) 10000 else currentInsulinIndex)) { + if (!insulinLabelAlreadyExists("${insulinLabel}_$i", currentIndex)) { insulinLabel = "${insulinLabel}_$i" break } @@ -239,6 +239,17 @@ class InsulinPlugin @Inject constructor( return insulinLabel } + private fun insulinLabelAlreadyExists(insulinLabel: String, currentIndex: Int = -1): Boolean { + insulins.forEachIndexed { index, insulin -> + if (index != currentIndex) { + if (insulin.insulinLabel == insulinLabel) { + return true + } + } + } + return false + } + @Synchronized fun updateProfiles(profileList: ArrayList, profileStore: ProfileStore, now: Long) { val profilePlugin = activePlugin.activeProfileSource @@ -372,16 +383,5 @@ class InsulinPlugin @Inject constructor( return true } - private fun insulinLabelAlreadyExists(insulinLabel: String, currentIndex: Int): Boolean { - insulins.forEachIndexed { index, insulin -> - if (index != currentIndex) { - if (insulin.insulinLabel == insulinLabel) { - return true - } - } - } - return false - } - fun currentInsulin(): ICfg = insulins[currentInsulinIndex] } \ No newline at end of file From 16dad4e5fb31594041c04cf526d1f5489b9af241 Mon Sep 17 00:00:00 2001 From: Philoul Date: Tue, 8 Apr 2025 18:32:11 +0200 Subject: [PATCH 39/41] Init all profiles insulins --- .../aaps/core/interfaces/insulin/Insulin.kt | 1 - .../aaps/plugins/insulin/InsulinFragment.kt | 15 ++++++++--- .../app/aaps/plugins/insulin/InsulinPlugin.kt | 27 +++++++++---------- 3 files changed, 24 insertions(+), 19 deletions(-) diff --git a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/insulin/Insulin.kt b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/insulin/Insulin.kt index 06a79a3e7bd..dee69a11041 100644 --- a/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/insulin/Insulin.kt +++ b/core/interfaces/src/main/kotlin/app/aaps/core/interfaces/insulin/Insulin.kt @@ -32,7 +32,6 @@ interface Insulin : ConfigExportImport { val friendlyName: String val dia: Double val peak: Int - fun setDefault(iCfg: ICfg) fun insulinList() = ArrayList() fun getOrCreateInsulin(iCfg: ICfg): ICfg fun getInsulin(insulinLabel: String): ICfg diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt index 364809bab25..c4a77ea335c 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt @@ -85,6 +85,7 @@ class InsulinFragment : DaggerFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) profileStore = activePlugin.activeProfileSource.profile ?: instantiator.provideProfileStore(JSONObject()) + checkInsulinList() binding.recyclerview.setHasFixedSize(true) binding.recyclerview.layoutManager = LinearLayoutManager(context) binding.insulinList.onItemClickListener = AdapterView.OnItemClickListener { _, _, position, _ -> @@ -113,7 +114,6 @@ class InsulinFragment : DaggerFragment() { ICfg("", selectedTemplate.peak, selectedTemplate.dia) ) } - insulinPlugin.setDefault(insulinPlugin.iCfg) insulinPlugin.setCurrent(insulinPlugin.iCfg) swapAdapter() @@ -139,10 +139,11 @@ class InsulinFragment : DaggerFragment() { if (insulinPlugin.isEdited) { activity?.let { OKDialog.show(it, "", rh.gs(R.string.save_or_reset_changes_first)) } } else { + selectedTemplate = Insulin.InsulinType.fromPeak(insulinPlugin.iCfg.insulinPeakTime) insulinPlugin.addNewInsulin( ICfg( - insulinLabel = "", // Let plugin propose a new unique name from template - peak = selectedTemplate.peak, + insulinLabel = "", // Let plugin propose a new unique name from template + peak = insulinPlugin.iCfg.getPeak(), // Current default insulin is default peak for new insulins dia = selectedTemplate.dia ) ) @@ -305,6 +306,14 @@ class InsulinFragment : DaggerFragment() { binding.recyclerview.swapAdapter(RecyclerViewAdapter(profileList), true) } + private fun checkInsulinList() { + profileStore.getProfileList().forEach { profileName -> + profileStore.getSpecificProfile(profileName.toString())?.let { + insulinPlugin.getOrCreateInsulin(it.iCfg) + } + } + } + inner class RecyclerViewAdapter internal constructor(private var profileList: List) : RecyclerView.Adapter() { override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ProfileViewHolder = diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt index 1079eb9558d..d872245db68 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt @@ -97,25 +97,26 @@ class InsulinPlugin @Inject constructor( } } - override fun setDefault(defaultICfg: ICfg) { - insulins.forEachIndexed { index, iCfg -> - if (iCfg.isEqual(defaultICfg)) { - defaultInsulinIndex = index - currentInsulinIndex = defaultInsulinIndex - } - } - } - override val iCfg: ICfg get() { val profile = profileFunction.getProfile() - return profile?.iCfg() ?:insulins[defaultInsulinIndex] + return profile?.iCfg() ?:insulins[0] } lateinit var currentInsulin: ICfg private var lastWarned: Long = 0 var insulins: ArrayList = ArrayList() - var defaultInsulinIndex = 0 + val defaultInsulinIndex: Int + get() { + iCfg.let { + insulins.forEachIndexed { index, iCfg -> + if (iCfg.isEqual(it)) { + return index + } + } + } + return 0 + } var currentInsulinIndex = 0 val numOfInsulins get() = insulins.size var isEdited: Boolean = false @@ -215,8 +216,6 @@ class InsulinPlugin @Inject constructor( val insulinRemoved = currentInsulin().insulinLabel insulins.removeAt(currentInsulinIndex) uel.log(Action.INSULIN_REMOVED, Sources.Insulin, value = ValueWithUnit.SimpleString(insulinRemoved)) - if (currentInsulinIndex < defaultInsulinIndex) - defaultInsulinIndex-- currentInsulinIndex = defaultInsulinIndex currentInsulin = currentInsulin().deepClone() storeSettings() @@ -323,7 +322,6 @@ class InsulinPlugin @Inject constructor( } } json.put("insulins", jsonArray) - json.put("default_insulin", defaultInsulinIndex) json.put("current_insulin", currentInsulinIndex) return json } @@ -341,7 +339,6 @@ class InsulinPlugin @Inject constructor( } } } - defaultInsulinIndex = configuration.optInt("default_insulin") currentInsulinIndex = configuration.optInt("current_insulin") } From 256c17ed2997039e5a1e1eed4f51679dfe38cf8d Mon Sep 17 00:00:00 2001 From: Philoul Date: Wed, 9 Apr 2025 12:31:51 +0200 Subject: [PATCH 40/41] Fix Peak Constraints --- .../src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt index c4a77ea335c..2f07cad9d71 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinFragment.kt @@ -262,6 +262,7 @@ class InsulinFragment : DaggerFragment() { } fun build() { + selectedTemplate = Insulin.InsulinType.fromPeak(insulinPlugin.currentInsulin().insulinPeakTime) binding.insulinTemplate.setText(rh.gs(Insulin.InsulinType.fromPeak(currentInsulin.insulinPeakTime).label), false) binding.name.removeTextChangedListener(textWatch) binding.name.setText(currentInsulin.insulinLabel) From 9ea5431c36ac9a3153ea61de3f380814f681cb39 Mon Sep 17 00:00:00 2001 From: Philoul Date: Wed, 9 Apr 2025 12:55:00 +0200 Subject: [PATCH 41/41] InsulinPlugin Fix Crash --- .../app/aaps/plugins/insulin/InsulinPlugin.kt | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt index d872245db68..e182e07e94d 100644 --- a/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt +++ b/plugins/insulin/src/main/kotlin/app/aaps/plugins/insulin/InsulinPlugin.kt @@ -100,7 +100,7 @@ class InsulinPlugin @Inject constructor( override val iCfg: ICfg get() { val profile = profileFunction.getProfile() - return profile?.iCfg() ?:insulins[0] + return profile?.iCfg() ?: insulins[0] } lateinit var currentInsulin: ICfg @@ -124,7 +124,7 @@ class InsulinPlugin @Inject constructor( get() = iCfg.getDia() val userDefinedPeak: Int - get() =iCfg.getPeak() + get() = iCfg.getPeak() override fun onStart() { super.onStart() @@ -140,13 +140,13 @@ class InsulinPlugin @Inject constructor( override fun getOrCreateInsulin(iCfg: ICfg): ICfg { // First Check insulin with hardlimits, and set default value if not consistent if (iCfg.getPeak() < hardLimits.minPeak() || iCfg.getPeak() > hardLimits.maxPeak()) - iCfg.insulinPeakTime = insulins[defaultInsulinIndex].insulinPeakTime + iCfg.setPeak(if (numOfInsulins == 0) Insulin.InsulinType.OREF_RAPID_ACTING.peak else insulins[defaultInsulinIndex].getPeak()) if (iCfg.getDia() < hardLimits.minDia() || iCfg.getDia() > hardLimits.maxDia()) - iCfg.insulinEndTime = insulins[defaultInsulinIndex].insulinEndTime + iCfg.setDia(if (numOfInsulins == 0) Insulin.InsulinType.OREF_RAPID_ACTING.dia else insulins[defaultInsulinIndex].getDia()) insulins.forEachIndexed { index, it -> if (iCfg.isEqual(it)) { return it - } + } } return addNewInsulin(iCfg) } @@ -190,10 +190,10 @@ class InsulinPlugin @Inject constructor( uiInteraction.addNotification(Notification.SHORT_DIA, String.format(notificationPattern, dia, hardLimits.minDia()), Notification.URGENT) } } + private val notificationPattern: String get() = rh.gs(R.string.dia_too_short) - @Synchronized fun addNewInsulin(template: ICfg): ICfg { if (template.insulinLabel == "" || insulinLabelAlreadyExists(template.insulinLabel)) @@ -339,7 +339,8 @@ class InsulinPlugin @Inject constructor( } } } - currentInsulinIndex = configuration.optInt("current_insulin") + if (insulins.isEmpty()) + currentInsulinIndex = configuration.optInt("current_insulin") } @Synchronized