Show Absolute insulin
This commit is contained in:
parent
228bd76e78
commit
2517a10a5c
6 changed files with 120 additions and 2 deletions
|
@ -19,6 +19,7 @@ import android.view.View
|
|||
import android.view.View.OnLongClickListener
|
||||
import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.jjoe64.graphview.GraphView
|
||||
import dagger.android.HasAndroidInjector
|
||||
|
@ -149,6 +150,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
|||
private var scheduledUpdate: ScheduledFuture<*>? = null
|
||||
|
||||
private val secondaryGraphs = ArrayList<GraphView>()
|
||||
private val secondaryGraphsLabel = ArrayList<TextView>()
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
|
@ -485,8 +487,13 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
|||
//aapsLogger.debug("New secondary graph count ${numOfGraphs-1}")
|
||||
// rebuild needed
|
||||
secondaryGraphs.clear()
|
||||
secondaryGraphsLabel.clear()
|
||||
overview_iobgraph.removeAllViews()
|
||||
for (i in 1 until numOfGraphs) {
|
||||
val label = TextView(context)
|
||||
label.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT).also { it.setMargins(100, 0, 0, -50) }
|
||||
overview_iobgraph.addView(label)
|
||||
secondaryGraphsLabel.add(label)
|
||||
val graph = GraphView(context)
|
||||
graph.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, resourceHelper.dpToPx(100)).also { it.setMargins(0, 0, 0, resourceHelper.dpToPx(10)) }
|
||||
graph.gridLabelRenderer?.gridColor = resourceHelper.gc(R.color.graphgrid)
|
||||
|
@ -818,12 +825,14 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
|||
var useRatioForScale = false
|
||||
var useDSForScale = false
|
||||
var useIAForScale = false
|
||||
var useABSForScale = false
|
||||
when {
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.IOB.ordinal] -> useIobForScale = true
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.COB.ordinal] -> useCobForScale = true
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.DEV.ordinal] -> useDevForScale = true
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.SEN.ordinal] -> useRatioForScale = true
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.ACT.ordinal] -> useIAForScale = true
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.ABS.ordinal] -> useABSForScale = true
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] -> useDSForScale = true
|
||||
}
|
||||
|
||||
|
@ -832,6 +841,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
|||
if (overviewMenus.setting[g + 1][OverviewMenus.CharType.DEV.ordinal]) secondGraphData.addDeviations(fromTime, now, useDevForScale, 1.0)
|
||||
if (overviewMenus.setting[g + 1][OverviewMenus.CharType.SEN.ordinal]) secondGraphData.addRatio(fromTime, now, useRatioForScale, 1.0)
|
||||
if (overviewMenus.setting[g + 1][OverviewMenus.CharType.ACT.ordinal]) secondGraphData.addActivity(fromTime, endTime, useIAForScale, 0.8)
|
||||
if (overviewMenus.setting[g + 1][OverviewMenus.CharType.ABS.ordinal]) secondGraphData.addAbsIob(fromTime, now, useABSForScale, 1.0)
|
||||
if (overviewMenus.setting[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] && buildHelper.isDev()) secondGraphData.addDeviationSlope(fromTime, now, useDSForScale, 1.0)
|
||||
|
||||
// set manual x bounds to have nice steps
|
||||
|
@ -843,12 +853,14 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
|||
// finally enforce drawing of graphs in UI thread
|
||||
graphData.performUpdate()
|
||||
for (g in 0 until secondaryGraphs.size) {
|
||||
secondaryGraphsLabel[g].text = overviewMenus.enabledTypes(g + 1)
|
||||
secondaryGraphs[g].visibility = (
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.IOB.ordinal] ||
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.COB.ordinal] ||
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.DEV.ordinal] ||
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.SEN.ordinal] ||
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.ACT.ordinal] ||
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.ABS.ordinal] ||
|
||||
overviewMenus.setting[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal]
|
||||
).toVisibility()
|
||||
secondaryGraphsData[g].performUpdate()
|
||||
|
|
|
@ -70,12 +70,23 @@ class OverviewMenus @Inject constructor(
|
|||
DEV(R.string.overview_show_deviations, R.color.deviations, primary = false, secondary = true),
|
||||
SEN(R.string.overview_show_sensitivity, R.color.ratio, primary = false, secondary = true),
|
||||
ACT(R.string.overview_show_activity, R.color.activity, primary = true, secondary = true),
|
||||
ABS(R.string.overview_show_absinsulin, R.color.iob, primary = false, secondary = true),
|
||||
DEVSLOPE(R.string.overview_show_deviationslope, R.color.devslopepos, primary = false, secondary = true)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val MAX_GRAPHS = 5 // including main
|
||||
}
|
||||
|
||||
fun enabledTypes(graph: Int): String {
|
||||
val r = StringBuilder()
|
||||
for (type in CharType.values()) if (setting[graph][type.ordinal]) {
|
||||
r.append(type.name)
|
||||
r.append(" ")
|
||||
}
|
||||
return r.toString()
|
||||
}
|
||||
|
||||
var setting: MutableList<Array<Boolean>> = ArrayList()
|
||||
|
||||
private fun storeGraphConfig() {
|
||||
|
@ -86,9 +97,15 @@ class OverviewMenus @Inject constructor(
|
|||
|
||||
private fun loadGraphConfig() {
|
||||
val sts = sp.getString(R.string.key_graphconfig, "")
|
||||
if (sts.isNotEmpty())
|
||||
if (sts.isNotEmpty()) {
|
||||
setting = Gson().fromJson(sts, Array<Array<Boolean>>::class.java).toMutableList()
|
||||
else {
|
||||
// reset when new CharType added
|
||||
for (s in setting)
|
||||
if (s.size != CharType.values().size) {
|
||||
setting = ArrayList()
|
||||
setting.add(Array(CharType.values().size) { true })
|
||||
}
|
||||
} else {
|
||||
setting = ArrayList()
|
||||
setting.add(Array(CharType.values().size) { true })
|
||||
}
|
||||
|
|
|
@ -376,6 +376,40 @@ class GraphData(injector: HasAndroidInjector, private val graph: GraphView, priv
|
|||
addSeries(iobSeries)
|
||||
}
|
||||
|
||||
// scale in % of vertical size (like 0.3)
|
||||
fun addAbsIob(fromTime: Long, toTime: Long, useForScale: Boolean, scale: Double) {
|
||||
val iobSeries: FixedLineGraphSeries<ScaledDataPoint?>
|
||||
val iobArray: MutableList<ScaledDataPoint> = ArrayList()
|
||||
var maxIobValueFound = Double.MIN_VALUE
|
||||
var lastIob = 0.0
|
||||
val iobScale = Scale()
|
||||
var time = fromTime
|
||||
while (time <= toTime) {
|
||||
val profile = profileFunction.getProfile(time)
|
||||
var iob = 0.0
|
||||
if (profile != null) iob = iobCobCalculatorPlugin.calculateAbsInsulinFromTreatmentsAndTempsSynchronized(time, profile).iob
|
||||
if (abs(lastIob - iob) > 0.02) {
|
||||
if (abs(lastIob - iob) > 0.2) iobArray.add(ScaledDataPoint(time, lastIob, iobScale))
|
||||
iobArray.add(ScaledDataPoint(time, iob, iobScale))
|
||||
maxIobValueFound = max(maxIobValueFound, abs(iob))
|
||||
lastIob = iob
|
||||
}
|
||||
time += 5 * 60 * 1000L
|
||||
}
|
||||
iobSeries = FixedLineGraphSeries(Array(iobArray.size) { i -> iobArray[i] }).also {
|
||||
it.isDrawBackground = true
|
||||
it.backgroundColor = -0x7f000001 and resourceHelper.gc(R.color.iob) //50%
|
||||
it.color = resourceHelper.gc(R.color.iob)
|
||||
it.thickness = 3
|
||||
}
|
||||
if (useForScale) {
|
||||
maxY = maxIobValueFound
|
||||
minY = -maxIobValueFound
|
||||
}
|
||||
iobScale.setMultiplier(maxY * scale / maxIobValueFound)
|
||||
addSeries(iobSeries)
|
||||
}
|
||||
|
||||
// scale in % of vertical size (like 0.3)
|
||||
fun addCob(fromTime: Long, toTime: Long, useForScale: Boolean, scale: Double) {
|
||||
val minFailOverActiveList: MutableList<DataPointWithLabelInterface> = ArrayList()
|
||||
|
|
|
@ -71,6 +71,7 @@ public class IobCobCalculatorPlugin extends PluginBase {
|
|||
private CompositeDisposable disposable = new CompositeDisposable();
|
||||
|
||||
private LongSparseArray<IobTotal> iobTable = new LongSparseArray<>(); // oldest at index 0
|
||||
private LongSparseArray<IobTotal> absIobTable = new LongSparseArray<>(); // oldest at index 0, absolute insulin in the body
|
||||
private LongSparseArray<AutosensData> autosensDataTable = new LongSparseArray<>(); // oldest at index 0
|
||||
private LongSparseArray<BasalData> basalDataTable = new LongSparseArray<>(); // oldest at index 0
|
||||
|
||||
|
@ -487,6 +488,27 @@ public class IobCobCalculatorPlugin extends PluginBase {
|
|||
return iobTotal;
|
||||
}
|
||||
|
||||
public IobTotal calculateAbsInsulinFromTreatmentsAndTempsSynchronized(long time, Profile profile) {
|
||||
synchronized (dataLock) {
|
||||
long now = System.currentTimeMillis();
|
||||
time = roundUpTime(time);
|
||||
if (time < now && absIobTable.get(time) != null) {
|
||||
//og.debug(">>> calculateFromTreatmentsAndTemps Cache hit " + new Date(time).toLocaleString());
|
||||
return absIobTable.get(time);
|
||||
} else {
|
||||
//log.debug(">>> calculateFromTreatmentsAndTemps Cache miss " + new Date(time).toLocaleString());
|
||||
}
|
||||
IobTotal bolusIob = treatmentsPlugin.getCalculationToTimeTreatments(time).round();
|
||||
IobTotal basalIob = treatmentsPlugin.getAbsoluteIOBTempBasals(time).round();
|
||||
|
||||
IobTotal iobTotal = IobTotal.combine(bolusIob, basalIob).round();
|
||||
if (time < System.currentTimeMillis()) {
|
||||
absIobTable.put(time, iobTotal);
|
||||
}
|
||||
return iobTotal;
|
||||
}
|
||||
}
|
||||
|
||||
private IobTotal calculateFromTreatmentsAndTemps(long time, AutosensResult lastAutosensResult, boolean exercise_mode, int half_basal_exercise_target, boolean isTempTarget) {
|
||||
long now = DateUtil.now();
|
||||
|
||||
|
@ -809,6 +831,14 @@ public class IobCobCalculatorPlugin extends PluginBase {
|
|||
break;
|
||||
}
|
||||
}
|
||||
for (int index = absIobTable.size() - 1; index >= 0; index--) {
|
||||
if (absIobTable.keyAt(index) > time) {
|
||||
getAapsLogger().debug(LTag.AUTOSENS, "Removing from absIobTable: " + DateUtil.dateAndTimeString(absIobTable.keyAt(index)));
|
||||
absIobTable.removeAt(index);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (int index = autosensDataTable.size() - 1; index >= 0; index--) {
|
||||
if (autosensDataTable.keyAt(index) > time) {
|
||||
getAapsLogger().debug(LTag.AUTOSENS, "Removing from autosensDataTable: " + DateUtil.dateAndTimeString(autosensDataTable.keyAt(index)));
|
||||
|
|
|
@ -59,6 +59,7 @@ import info.nightscout.androidaps.plugins.pump.medtronic.data.MedtronicHistoryDa
|
|||
import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil;
|
||||
import info.nightscout.androidaps.utils.DateUtil;
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy;
|
||||
import info.nightscout.androidaps.utils.T;
|
||||
import info.nightscout.androidaps.utils.resources.ResourceHelper;
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
|
@ -442,6 +443,29 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface
|
|||
return total;
|
||||
}
|
||||
|
||||
public IobTotal getAbsoluteIOBTempBasals(long time) {
|
||||
IobTotal total = new IobTotal(time);
|
||||
|
||||
PumpInterface pumpInterface = activePlugin.getActivePump();
|
||||
|
||||
for (long i = time - range(); i < time; i += T.mins(5).msecs()) {
|
||||
Profile profile = profileFunction.getProfile(i);
|
||||
double basal = profile.getBasal(i);
|
||||
TemporaryBasal runningTBR = getTempBasalFromHistory(i);
|
||||
double running = basal;
|
||||
if (runningTBR != null) {
|
||||
running = runningTBR.tempBasalConvertedToAbsolute(i, profile);
|
||||
}
|
||||
Treatment treatment = new Treatment();
|
||||
treatment.date = i;
|
||||
treatment.insulin = running * 5.0 / 60.0; // 5 min chunk
|
||||
Iob iob = treatment.iobCalc(i, profile.getDia());
|
||||
total.iob += iob.iobContrib;
|
||||
total.activity += iob.activityContrib;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
public IobTotal getCalculationToTimeTempBasals(long time, long truncateTime, AutosensResult lastAutosensResult, boolean exercise_mode, int half_basal_exercise_target, boolean isTempTarget) {
|
||||
IobTotal total = new IobTotal(time);
|
||||
|
||||
|
|
|
@ -1804,4 +1804,5 @@
|
|||
<string name="overview_show_deviationslope">Deviation slope</string>
|
||||
<string name="key_graphconfig" translatable="false">graphconfig</string>
|
||||
<string name="authorizationfailed">Authorization failed</string>
|
||||
<string name="overview_show_absinsulin">Absolute insulin</string>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in a new issue