AndroidAPS/implementation/src/main/kotlin/app/aaps/implementation/overview/OverviewDataImpl.kt
2023-09-25 23:14:05 +02:00

345 lines
16 KiB
Kotlin

package app.aaps.implementation.overview
import android.content.Context
import androidx.annotation.AttrRes
import androidx.annotation.ColorInt
import androidx.annotation.DrawableRes
import app.aaps.core.interfaces.aps.AutosensData
import app.aaps.core.interfaces.aps.AutosensDataStore
import app.aaps.core.interfaces.iob.CobInfo
import app.aaps.core.interfaces.iob.InMemoryGlucoseValue
import app.aaps.core.interfaces.iob.IobCobCalculator
import app.aaps.core.interfaces.iob.IobTotal
import app.aaps.core.interfaces.logging.AAPSLogger
import app.aaps.core.interfaces.plugin.ActivePlugin
import app.aaps.core.interfaces.profile.DefaultValueHelper
import app.aaps.core.interfaces.profile.ProfileFunction
import app.aaps.core.interfaces.resources.ResourceHelper
import app.aaps.core.interfaces.sharedPreferences.SP
import app.aaps.core.interfaces.utils.DateUtil
import app.aaps.core.interfaces.utils.DecimalFormatter
import app.aaps.core.interfaces.utils.T
import app.aaps.core.main.R
import app.aaps.core.main.extensions.convertedToPercent
import app.aaps.core.main.extensions.isInProgress
import app.aaps.core.main.extensions.toStringFull
import app.aaps.core.main.extensions.toStringShort
import app.aaps.core.main.extensions.valueToUnits
import app.aaps.core.main.graph.OverviewData
import app.aaps.core.main.graph.data.DataPointWithLabelInterface
import app.aaps.core.main.graph.data.DeviationDataPoint
import app.aaps.core.main.graph.data.FixedLineGraphSeries
import app.aaps.core.main.graph.data.PointsWithLabelGraphSeries
import app.aaps.core.main.graph.data.Scale
import app.aaps.core.main.graph.data.ScaledDataPoint
import app.aaps.core.main.iob.round
import app.aaps.database.ValueWrapper
import app.aaps.database.entities.GlucoseValue
import app.aaps.database.entities.TemporaryTarget
import com.jjoe64.graphview.series.BarGraphSeries
import com.jjoe64.graphview.series.DataPoint
import com.jjoe64.graphview.series.LineGraphSeries
import info.nightscout.database.impl.AppRepository
import java.util.Calendar
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class OverviewDataImpl @Inject constructor(
private val aapsLogger: AAPSLogger,
private val rh: ResourceHelper,
private val dateUtil: DateUtil,
private val sp: SP,
private val activePlugin: ActivePlugin,
private val defaultValueHelper: DefaultValueHelper,
private val profileFunction: ProfileFunction,
private val repository: AppRepository,
private val decimalFormatter: DecimalFormatter
) : OverviewData {
override var rangeToDisplay = 6 // for graph
override var toTime: Long = 0
override var fromTime: Long = 0
override var endTime: Long = 0
override fun reset() {
pumpStatus = ""
calcProgressPct = 100
bgReadingsArray = ArrayList()
maxBgValue = Double.MIN_VALUE
bucketedGraphSeries = PointsWithLabelGraphSeries()
bgReadingGraphSeries = PointsWithLabelGraphSeries()
predictionsGraphSeries = PointsWithLabelGraphSeries()
baseBasalGraphSeries = LineGraphSeries()
tempBasalGraphSeries = LineGraphSeries()
basalLineGraphSeries = LineGraphSeries()
absoluteBasalGraphSeries = LineGraphSeries()
temporaryTargetSeries = LineGraphSeries()
maxIAValue = 0.0
activitySeries = FixedLineGraphSeries()
activityPredictionSeries = FixedLineGraphSeries()
maxIobValueFound = Double.MIN_VALUE
iobSeries = FixedLineGraphSeries()
absIobSeries = FixedLineGraphSeries()
iobPredictions1Series = PointsWithLabelGraphSeries()
//iobPredictions2Series = PointsWithLabelGraphSeries()
maxBGIValue = Double.MIN_VALUE
minusBgiSeries = FixedLineGraphSeries()
minusBgiHistSeries = FixedLineGraphSeries()
maxCobValueFound = Double.MIN_VALUE
cobSeries = FixedLineGraphSeries()
cobMinFailOverSeries = PointsWithLabelGraphSeries()
maxDevValueFound = Double.MIN_VALUE
deviationsSeries = BarGraphSeries()
maxRatioValueFound = 5.0 //even if sens data equals 0 for all the period, minimum scale is between 95% and 105%
minRatioValueFound = -maxRatioValueFound
ratioSeries = LineGraphSeries()
maxFromMaxValueFound = Double.MIN_VALUE
maxFromMinValueFound = Double.MIN_VALUE
dsMaxSeries = LineGraphSeries()
dsMinSeries = LineGraphSeries()
maxTreatmentsValue = 0.0
treatmentsSeries = PointsWithLabelGraphSeries()
maxEpsValue = 0.0
epsSeries = PointsWithLabelGraphSeries()
maxTherapyEventValue = 0.0
therapyEventSeries = PointsWithLabelGraphSeries()
heartRateGraphSeries = PointsWithLabelGraphSeries()
}
override fun initRange() {
rangeToDisplay = sp.getInt(info.nightscout.core.utils.R.string.key_rangetodisplay, 6)
val calendar = Calendar.getInstance().also {
it.timeInMillis = System.currentTimeMillis()
it[Calendar.MILLISECOND] = 0
it[Calendar.SECOND] = 0
it[Calendar.MINUTE] = 0
it.add(Calendar.HOUR, 1)
}
toTime = calendar.timeInMillis + 100000 // little bit more to avoid wrong rounding - GraphView specific
fromTime = toTime - T.hours(rangeToDisplay.toLong()).msecs()
endTime = toTime
}
/*
* PUMP STATUS
*/
override var pumpStatus: String = ""
/*
* CALC PROGRESS
*/
override var calcProgressPct: Int = 100
/*
* BG
*/
override fun lastBg(autosensDataStore: AutosensDataStore): InMemoryGlucoseValue? =
autosensDataStore.bucketedData?.firstOrNull()
?: repository.getLastGlucoseValueWrapped().blockingGet().let { gvWrapped ->
if (gvWrapped is ValueWrapper.Existing) InMemoryGlucoseValue(gvWrapped.value)
else null
}
override fun isLow(autosensDataStore: AutosensDataStore): Boolean =
lastBg(autosensDataStore)?.let { lastBg ->
lastBg.valueToUnits(profileFunction.getUnits()) < defaultValueHelper.determineLowLine()
} ?: false
override fun isHigh(autosensDataStore: AutosensDataStore): Boolean =
lastBg(autosensDataStore)?.let { lastBg ->
lastBg.valueToUnits(profileFunction.getUnits()) > defaultValueHelper.determineHighLine()
} ?: false
@ColorInt
override fun lastBgColor(context: Context?, autosensDataStore: AutosensDataStore): Int =
when {
isLow(autosensDataStore) -> rh.gac(context, app.aaps.core.ui.R.attr.bgLow)
isHigh(autosensDataStore) -> rh.gac(context, app.aaps.core.ui.R.attr.highColor)
else -> rh.gac(context, app.aaps.core.ui.R.attr.bgInRange)
}
override fun lastBgDescription(autosensDataStore: AutosensDataStore): String =
when {
isLow(autosensDataStore) -> rh.gs(app.aaps.core.ui.R.string.a11y_low)
isHigh(autosensDataStore) -> rh.gs(app.aaps.core.ui.R.string.a11y_high)
else -> rh.gs(app.aaps.core.ui.R.string.a11y_inrange)
}
override fun isActualBg(autosensDataStore: AutosensDataStore): Boolean =
lastBg(autosensDataStore)?.let { lastBg ->
lastBg.timestamp > dateUtil.now() - T.mins(9).msecs()
} ?: false
/*
* TEMPORARY BASAL
*/
override fun temporaryBasalText(iobCobCalculator: IobCobCalculator): String =
profileFunction.getProfile()?.let { profile ->
var temporaryBasal = iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil.now())
if (temporaryBasal?.isInProgress == false) temporaryBasal = null
temporaryBasal?.let { "T:" + it.toStringShort(decimalFormatter) }
?: rh.gs(app.aaps.core.ui.R.string.pump_base_basal_rate, profile.getBasal())
} ?: rh.gs(app.aaps.core.ui.R.string.value_unavailable_short)
override fun temporaryBasalDialogText(iobCobCalculator: IobCobCalculator): String =
profileFunction.getProfile()?.let { profile ->
iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil.now())?.let { temporaryBasal ->
"${rh.gs(app.aaps.core.ui.R.string.base_basal_rate_label)}: ${rh.gs(app.aaps.core.ui.R.string.pump_base_basal_rate, profile.getBasal())}" +
"\n" + rh.gs(app.aaps.core.ui.R.string.tempbasal_label) + ": " + temporaryBasal.toStringFull(profile, dateUtil, decimalFormatter)
}
?: "${rh.gs(app.aaps.core.ui.R.string.base_basal_rate_label)}: ${rh.gs(app.aaps.core.ui.R.string.pump_base_basal_rate, profile.getBasal())}"
} ?: rh.gs(app.aaps.core.ui.R.string.value_unavailable_short)
@DrawableRes override fun temporaryBasalIcon(iobCobCalculator: IobCobCalculator): Int =
profileFunction.getProfile()?.let { profile ->
iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil.now())?.let { temporaryBasal ->
val percentRate = temporaryBasal.convertedToPercent(dateUtil.now(), profile)
when {
percentRate > 100 -> R.drawable.ic_cp_basal_tbr_high
percentRate < 100 -> R.drawable.ic_cp_basal_tbr_low
else -> R.drawable.ic_cp_basal_no_tbr
}
}
} ?: R.drawable.ic_cp_basal_no_tbr
@AttrRes override fun temporaryBasalColor(context: Context?, iobCobCalculator: IobCobCalculator): Int = iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil.now())?.let {
rh.gac(
context, app.aaps.core.ui.R
.attr.basal
)
}
?: rh.gac(context, app.aaps.core.ui.R.attr.defaultTextColor)
/*
* EXTENDED BOLUS
*/
override fun extendedBolusText(iobCobCalculator: IobCobCalculator): String =
iobCobCalculator.getExtendedBolus(dateUtil.now())?.let { extendedBolus ->
if (!extendedBolus.isInProgress(dateUtil)) ""
else if (!activePlugin.activePump.isFakingTempsByExtendedBoluses) rh.gs(app.aaps.core.ui.R.string.pump_base_basal_rate, extendedBolus.rate)
else ""
} ?: ""
override fun extendedBolusDialogText(iobCobCalculator: IobCobCalculator): String =
iobCobCalculator.getExtendedBolus(dateUtil.now())?.toStringFull(dateUtil, decimalFormatter) ?: ""
/*
* IOB, COB
*/
override fun bolusIob(iobCobCalculator: IobCobCalculator): IobTotal = iobCobCalculator.calculateIobFromBolus().round()
override fun basalIob(iobCobCalculator: IobCobCalculator): IobTotal = iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended().round()
override fun cobInfo(iobCobCalculator: IobCobCalculator): CobInfo = iobCobCalculator.getCobInfo("Overview COB")
override val lastCarbsTime: Long
get() = repository.getLastCarbsRecordWrapped().blockingGet().let { lastCarbs ->
if (lastCarbs is ValueWrapper.Existing) lastCarbs.value.timestamp else 0L
}
override fun iobText(iobCobCalculator: IobCobCalculator): String =
rh.gs(app.aaps.core.ui.R.string.format_insulin_units, bolusIob(iobCobCalculator).iob + basalIob(iobCobCalculator).basaliob)
override fun iobDialogText(iobCobCalculator: IobCobCalculator): String =
rh.gs(app.aaps.core.ui.R.string.format_insulin_units, bolusIob(iobCobCalculator).iob + basalIob(iobCobCalculator).basaliob) + "\n" +
rh.gs(app.aaps.core.ui.R.string.bolus) + ": " + rh.gs(app.aaps.core.ui.R.string.format_insulin_units, bolusIob(iobCobCalculator).iob) + "\n" +
rh.gs(app.aaps.core.ui.R.string.basal) + ": " + rh.gs(app.aaps.core.ui.R.string.format_insulin_units, basalIob(iobCobCalculator).basaliob)
/*
* TEMP TARGET
*/
override val temporaryTarget: TemporaryTarget?
get() =
repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet().let { tempTarget ->
if (tempTarget is ValueWrapper.Existing) tempTarget.value
else null
}
/*
* SENSITIVITY
*/
override fun lastAutosensData(iobCobCalculator: IobCobCalculator): AutosensData? = iobCobCalculator.ads.getLastAutosensData("Overview", aapsLogger, dateUtil)
/*
* Graphs
*/
override var bgReadingsArray: List<GlucoseValue> = ArrayList()
override var maxBgValue = Double.MIN_VALUE
override var bucketedGraphSeries: PointsWithLabelGraphSeries<DataPointWithLabelInterface> =
PointsWithLabelGraphSeries()
override var bgReadingGraphSeries: PointsWithLabelGraphSeries<DataPointWithLabelInterface> =
PointsWithLabelGraphSeries()
override var predictionsGraphSeries: PointsWithLabelGraphSeries<DataPointWithLabelInterface> =
PointsWithLabelGraphSeries()
override val basalScale = Scale()
override var baseBasalGraphSeries: LineGraphSeries<ScaledDataPoint> = LineGraphSeries()
override var tempBasalGraphSeries: LineGraphSeries<ScaledDataPoint> = LineGraphSeries()
override var basalLineGraphSeries: LineGraphSeries<ScaledDataPoint> = LineGraphSeries()
override var absoluteBasalGraphSeries: LineGraphSeries<ScaledDataPoint> = LineGraphSeries()
override var temporaryTargetSeries: LineGraphSeries<DataPoint> = LineGraphSeries()
override var maxIAValue = 0.0
override val actScale = Scale()
override var activitySeries: FixedLineGraphSeries<ScaledDataPoint> = FixedLineGraphSeries()
override var activityPredictionSeries: FixedLineGraphSeries<ScaledDataPoint> = FixedLineGraphSeries()
override var maxEpsValue = 0.0
override val epsScale = Scale()
override var epsSeries: PointsWithLabelGraphSeries<DataPointWithLabelInterface> =
PointsWithLabelGraphSeries()
override var maxTreatmentsValue = 0.0
override var treatmentsSeries: PointsWithLabelGraphSeries<DataPointWithLabelInterface> =
PointsWithLabelGraphSeries()
override var maxTherapyEventValue = 0.0
override var therapyEventSeries: PointsWithLabelGraphSeries<DataPointWithLabelInterface> =
PointsWithLabelGraphSeries()
override var maxIobValueFound = Double.MIN_VALUE
override val iobScale = Scale()
override var iobSeries: FixedLineGraphSeries<ScaledDataPoint> = FixedLineGraphSeries()
override var absIobSeries: FixedLineGraphSeries<ScaledDataPoint> = FixedLineGraphSeries()
override var iobPredictions1Series: PointsWithLabelGraphSeries<DataPointWithLabelInterface> =
PointsWithLabelGraphSeries()
//var iobPredictions2Series: PointsWithLabelGraphSeries<DataPointWithLabelInterface> = PointsWithLabelGraphSeries()
override var maxBGIValue = Double.MIN_VALUE
override val bgiScale = Scale()
override var minusBgiSeries: FixedLineGraphSeries<ScaledDataPoint> = FixedLineGraphSeries()
override var minusBgiHistSeries: FixedLineGraphSeries<ScaledDataPoint> = FixedLineGraphSeries()
override var maxCobValueFound = Double.MIN_VALUE
override val cobScale = Scale()
override var cobSeries: FixedLineGraphSeries<ScaledDataPoint> = FixedLineGraphSeries()
override var cobMinFailOverSeries: PointsWithLabelGraphSeries<DataPointWithLabelInterface> =
PointsWithLabelGraphSeries()
override var maxDevValueFound = Double.MIN_VALUE
override val devScale = Scale()
override var deviationsSeries: BarGraphSeries<DeviationDataPoint> = BarGraphSeries()
override var maxRatioValueFound = 5.0 //even if sens data equals 0 for all the period, minimum scale is between 95% and 105%
override var minRatioValueFound = -maxRatioValueFound
override val ratioScale = Scale()
override var ratioSeries: LineGraphSeries<ScaledDataPoint> = LineGraphSeries()
override var maxFromMaxValueFound = Double.MIN_VALUE
override var maxFromMinValueFound = Double.MIN_VALUE
override val dsMaxScale = Scale()
override val dsMinScale = Scale()
override var dsMaxSeries: LineGraphSeries<ScaledDataPoint> = LineGraphSeries()
override var dsMinSeries: LineGraphSeries<ScaledDataPoint> = LineGraphSeries()
override var heartRateScale = Scale()
override var heartRateGraphSeries: PointsWithLabelGraphSeries<DataPointWithLabelInterface> = PointsWithLabelGraphSeries()
}