carbs with duration

This commit is contained in:
Milos Kozak 2021-03-30 22:05:44 +02:00
parent 1ae4823a9a
commit 07d060c2b5
24 changed files with 2950 additions and 143 deletions

View file

@ -3,6 +3,8 @@ package info.nightscout.androidaps.dependencyInjection
import dagger.Module import dagger.Module
import dagger.android.ContributesAndroidInjector import dagger.android.ContributesAndroidInjector
import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.GlucoseValueDataPoint
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.TherapyEventDataPoint
import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationWithAction import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationWithAction
@Module @Module

View file

@ -47,10 +47,10 @@ import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus
import info.nightscout.androidaps.plugins.general.overview.activities.QuickWizardListActivity import info.nightscout.androidaps.plugins.general.overview.activities.QuickWizardListActivity
import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.GlucoseValueDataPoint
import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationStore import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationStore
import info.nightscout.androidaps.plugins.general.wear.events.EventWearInitiateAction import info.nightscout.androidaps.plugins.general.wear.events.EventWearInitiateAction
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
import info.nightscout.androidaps.plugins.source.DexcomPlugin import info.nightscout.androidaps.plugins.source.DexcomPlugin
@ -778,7 +778,8 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
if (config.APS && lastRun?.constraintsProcessed != null) { if (config.APS && lastRun?.constraintsProcessed != null) {
if (lastRun.constraintsProcessed!!.carbsReq > 0) { if (lastRun.constraintsProcessed!!.carbsReq > 0) {
//only display carbsreq when carbs have not been entered recently //only display carbsreq when carbs have not been entered recently
val lastCarbsTime = repository.getLastBolusRecord()?.timestamp ?: 0L val lastCarb = repository.getLastCarbsRecordWrapped().blockingGet()
val lastCarbsTime = if (lastCarb is ValueWrapper.Existing) lastCarb.value.timestamp else 0L
if (lastCarbsTime < lastRun.lastAPSRun) { if (lastCarbsTime < lastRun.lastAPSRun) {
cobText = cobText + " | " + lastRun.constraintsProcessed!!.carbsReq + " " + resourceHelper.gs(R.string.required) cobText = cobText + " | " + lastRun.constraintsProcessed!!.carbsReq + " " + resourceHelper.gs(R.string.required)
} }
@ -862,7 +863,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
// **** BG **** // **** BG ****
if (predictionsAvailable && menuChartSettings[0][OverviewMenus.CharType.PRE.ordinal]) if (predictionsAvailable && menuChartSettings[0][OverviewMenus.CharType.PRE.ordinal])
graphData.addBgReadings(fromTime, toTime, lowLine, highLine, apsResult?.predictions) graphData.addBgReadings(fromTime, toTime, lowLine, highLine, apsResult?.predictions?.map { bg-> GlucoseValueDataPoint(bg, defaultValueHelper, profileFunction, resourceHelper) }?.toMutableList())
else graphData.addBgReadings(fromTime, toTime, lowLine, highLine, null) else graphData.addBgReadings(fromTime, toTime, lowLine, highLine, null)
// Treatments // Treatments

View file

@ -11,7 +11,8 @@ import com.jjoe64.graphview.series.Series
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.* import info.nightscout.androidaps.data.IobTotal
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.AppRepository
import info.nightscout.androidaps.database.ValueWrapper import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.database.entities.Bolus import info.nightscout.androidaps.database.entities.Bolus
@ -22,11 +23,7 @@ import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.* import info.nightscout.androidaps.plugins.general.overview.graphExtensions.*
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.*
import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.DefaultValueHelper
import info.nightscout.androidaps.utils.Round
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.extensions.target import info.nightscout.androidaps.utils.extensions.target
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import java.util.* import java.util.*
@ -51,6 +48,7 @@ class GraphData(
@Inject lateinit var repository: AppRepository @Inject lateinit var repository: AppRepository
@Inject lateinit var dateUtil: DateUtil @Inject lateinit var dateUtil: DateUtil
@Inject lateinit var defaultValueHelper: DefaultValueHelper @Inject lateinit var defaultValueHelper: DefaultValueHelper
@Inject lateinit var translator: Translator
var maxY = Double.MIN_VALUE var maxY = Double.MIN_VALUE
private var minY = Double.MAX_VALUE private var minY = Double.MAX_VALUE
@ -77,7 +75,7 @@ class GraphData(
for (bg in bgReadingsArray!!) { for (bg in bgReadingsArray!!) {
if (bg.timestamp < fromTime || bg.timestamp > toTime) continue if (bg.timestamp < fromTime || bg.timestamp > toTime) continue
if (bg.value > maxBgValue) maxBgValue = bg.value if (bg.value > maxBgValue) maxBgValue = bg.value
bgListArray.add(GlucoseValueDataPoint(injector, bg)) bgListArray.add(GlucoseValueDataPoint(bg, defaultValueHelper, profileFunction, resourceHelper))
} }
if (predictions != null) { if (predictions != null) {
predictions.sortWith(Comparator { o1: GlucoseValueDataPoint, o2: GlucoseValueDataPoint -> o1.x.compareTo(o2.x) }) predictions.sortWith(Comparator { o1: GlucoseValueDataPoint, o2: GlucoseValueDataPoint -> o1.x.compareTo(o2.x) })
@ -247,7 +245,7 @@ class GraphData(
it.y = getNearestBg(it.x.toLong()) it.y = getNearestBg(it.x.toLong())
filteredTreatments.add(it) filteredTreatments.add(it)
} }
repository.getCarbsIncludingInvalidFromTimeToTime(fromTime, endTime, true).blockingGet() repository.getCarbsIncludingInvalidFromTimeToTimeExpanded(fromTime, endTime, true).blockingGet()
.map { CarbsDataPoint(it, resourceHelper) } .map { CarbsDataPoint(it, resourceHelper) }
.forEach { .forEach {
it.y = getNearestBg(it.x.toLong()) it.y = getNearestBg(it.x.toLong())
@ -273,7 +271,7 @@ class GraphData(
// Careportal // Careportal
// databaseHelper.getCareportalEventsFromTime(fromTime - 6 * 60 * 60 * 1000, true) // databaseHelper.getCareportalEventsFromTime(fromTime - 6 * 60 * 60 * 1000, true)
repository.compatGetTherapyEventDataFromToTime(fromTime - T.hours(6).msecs(), endTime).blockingGet() repository.compatGetTherapyEventDataFromToTime(fromTime - T.hours(6).msecs(), endTime).blockingGet()
.map { TherapyEventDataPoint(injector, it) } .map { TherapyEventDataPoint(it, resourceHelper, profileFunction, translator) }
.filterTimeframe(fromTime, endTime) .filterTimeframe(fromTime, endTime)
.forEach { .forEach {
if (it.y == 0.0) it.y = getNearestBg(it.x.toLong()) if (it.y == 0.0) it.y = getNearestBg(it.x.toLong())

View file

@ -1,12 +1,10 @@
package info.nightscout.androidaps.data package info.nightscout.androidaps.plugins.general.overview.graphExtensions
import android.graphics.Color import android.graphics.Color
import info.nightscout.androidaps.core.R import info.nightscout.androidaps.core.R
import info.nightscout.androidaps.database.entities.Bolus import info.nightscout.androidaps.database.entities.Bolus
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries
import info.nightscout.androidaps.utils.DecimalFormatter.toPumpSupportedBolus
import info.nightscout.androidaps.utils.DefaultValueHelper import info.nightscout.androidaps.utils.DefaultValueHelper
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import javax.inject.Inject import javax.inject.Inject
@ -22,7 +20,7 @@ class BolusDataPoint @Inject constructor(
override fun getX(): Double = data.timestamp.toDouble() override fun getX(): Double = data.timestamp.toDouble()
override fun getY(): Double = if (data.type == Bolus.Type.SMB) defaultValueHelper.determineLowLine() else yValue override fun getY(): Double = if (data.type == Bolus.Type.SMB) defaultValueHelper.determineLowLine() else yValue
override fun getLabel(): String = toPumpSupportedBolus(data.amount, activePlugin.activePump, resourceHelper) override fun getLabel(): String = DecimalFormatter.toPumpSupportedBolus(data.amount, activePlugin.activePump, resourceHelper)
override fun getDuration(): Long = 0 override fun getDuration(): Long = 0
override fun getSize(): Float = 2f override fun getSize(): Float = 2f

View file

@ -1,9 +1,7 @@
package info.nightscout.androidaps.data package info.nightscout.androidaps.plugins.general.overview.graphExtensions
import info.nightscout.androidaps.core.R import info.nightscout.androidaps.core.R
import info.nightscout.androidaps.database.entities.Carbs import info.nightscout.androidaps.database.entities.Carbs
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import javax.inject.Inject import javax.inject.Inject
@ -20,7 +18,7 @@ class CarbsDataPoint @Inject constructor(
override fun getDuration(): Long = 0 override fun getDuration(): Long = 0
override fun getSize(): Float = 2f override fun getSize(): Float = 2f
override fun getShape(): PointsWithLabelGraphSeries.Shape = PointsWithLabelGraphSeries.Shape.BOLUS override fun getShape(): PointsWithLabelGraphSeries.Shape = PointsWithLabelGraphSeries.Shape.CARBS
override fun getColor(): Int = override fun getColor(): Int =
if (data.isValid) resourceHelper.gc(R.color.carbs) if (data.isValid) resourceHelper.gc(R.color.carbs)

View file

@ -1,29 +1,20 @@
package info.nightscout.androidaps.data package info.nightscout.androidaps.plugins.general.overview.graphExtensions
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.core.R import info.nightscout.androidaps.core.R
import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.database.entities.GlucoseValue
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries
import info.nightscout.androidaps.utils.DefaultValueHelper import info.nightscout.androidaps.utils.DefaultValueHelper
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import javax.inject.Inject import javax.inject.Inject
class GlucoseValueDataPoint @Inject constructor( class GlucoseValueDataPoint @Inject constructor(
val injector: HasAndroidInjector, val data: GlucoseValue,
val data: GlucoseValue private val defaultValueHelper: DefaultValueHelper,
private val profileFunction: ProfileFunction,
private val resourceHelper: ResourceHelper
) : DataPointWithLabelInterface { ) : DataPointWithLabelInterface {
@Inject lateinit var defaultValueHelper: DefaultValueHelper
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var resourceHelper: ResourceHelper
init {
injector.androidInjector().inject(this)
}
fun valueToUnits(units: String): Double = fun valueToUnits(units: String): Double =
if (units == Constants.MGDL) data.value else data.value * Constants.MGDL_TO_MMOLL if (units == Constants.MGDL) data.value else data.value * Constants.MGDL_TO_MMOLL
@ -59,11 +50,11 @@ class GlucoseValueDataPoint @Inject constructor(
val predictionColor: Int val predictionColor: Int
get() { get() {
return when (data.sourceSensor) { return when (data.sourceSensor) {
GlucoseValue.SourceSensor.IOB_PREDICTION -> resourceHelper.gc(R.color.iob) GlucoseValue.SourceSensor.IOB_PREDICTION -> resourceHelper.gc(R.color.iob)
GlucoseValue.SourceSensor.COB_PREDICTION -> resourceHelper.gc(R.color.cob) GlucoseValue.SourceSensor.COB_PREDICTION -> resourceHelper.gc(R.color.cob)
GlucoseValue.SourceSensor.aCOB_PREDICTION -> -0x7f000001 and resourceHelper.gc(R.color.cob) GlucoseValue.SourceSensor.aCOB_PREDICTION -> -0x7f000001 and resourceHelper.gc(R.color.cob)
GlucoseValue.SourceSensor.UAM_PREDICTION -> resourceHelper.gc(R.color.uam) GlucoseValue.SourceSensor.UAM_PREDICTION -> resourceHelper.gc(R.color.uam)
GlucoseValue.SourceSensor.ZT_PREDICTION -> resourceHelper.gc(R.color.zt) GlucoseValue.SourceSensor.ZT_PREDICTION -> resourceHelper.gc(R.color.zt)
else -> R.color.white else -> R.color.white
} }
} }

View file

@ -1,35 +1,25 @@
package info.nightscout.androidaps.data package info.nightscout.androidaps.plugins.general.overview.graphExtensions
import android.graphics.Color import android.graphics.Color
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Constants import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.core.R import info.nightscout.androidaps.core.R
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.database.entities.TherapyEvent import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.interfaces.Interval import info.nightscout.androidaps.interfaces.Interval
import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.ProfileFunction
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries
import info.nightscout.androidaps.utils.DefaultValueHelper
import info.nightscout.androidaps.utils.Translator import info.nightscout.androidaps.utils.Translator
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import javax.inject.Inject import javax.inject.Inject
class TherapyEventDataPoint @Inject constructor( class TherapyEventDataPoint @Inject constructor(
val injector: HasAndroidInjector, val data: TherapyEvent,
val data: TherapyEvent private val resourceHelper: ResourceHelper,
private val profileFunction: ProfileFunction,
private val translator: Translator
) : DataPointWithLabelInterface, Interval { ) : DataPointWithLabelInterface, Interval {
@Inject lateinit var defaultValueHelper: DefaultValueHelper
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var translator: Translator
private var yValue = 0.0 private var yValue = 0.0
init {
injector.androidInjector().inject(this)
}
override fun getX(): Double { override fun getX(): Double {
return data.timestamp.toDouble() return data.timestamp.toDouble()
} }

View file

@ -120,7 +120,7 @@ class UploadChunk @Inject constructor(
.forEach { bolus -> .forEach { bolus ->
result.add(BolusElement(bolus)) result.add(BolusElement(bolus))
} }
repository.getCarbsDataFromTimeToTime(start, end, true) repository.getCarbsDataFromTimeToTimeExpanded(start, end, true)
.blockingGet() .blockingGet()
.forEach { carb -> .forEach { carb ->
result.add(WizardElement(carb)) result.add(WizardElement(carb))

View file

@ -24,6 +24,7 @@ import com.google.android.gms.wearable.WearableListenerService;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
import javax.inject.Inject; import javax.inject.Inject;
@ -31,7 +32,7 @@ import dagger.android.AndroidInjection;
import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.GlucoseValueDataPoint; import info.nightscout.androidaps.plugins.general.overview.graphExtensions.GlucoseValueDataPoint;
import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.database.AppRepository; import info.nightscout.androidaps.database.AppRepository;
@ -530,12 +531,15 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
.stream() .stream()
.filter(bolus -> bolus.getType() != Bolus.Type.PRIMING) .filter(bolus -> bolus.getType() != Bolus.Type.PRIMING)
.forEach(bolus -> boluses.add(treatmentMap(bolus.getTimestamp(), bolus.getAmount(), 0, bolus.getType() == Bolus.Type.SMB, bolus.isValid()))); .forEach(bolus -> boluses.add(treatmentMap(bolus.getTimestamp(), bolus.getAmount(), 0, bolus.getType() == Bolus.Type.SMB, bolus.isValid())));
repository.getCarbsIncludingInvalidFromTime(startTimeWindow, true).blockingGet() repository.getCarbsDataFromTimeExpanded(startTimeWindow, true).blockingGet()
.forEach(carb -> boluses.add(treatmentMap(carb.getTimestamp(), 0, carb.getAmount(), false, carb.isValid()))); .forEach(carb -> boluses.add(treatmentMap(carb.getTimestamp(), 0, carb.getAmount(), false, carb.isValid())));
final LoopPlugin.LastRun finalLastRun = loopPlugin.getLastRun(); final LoopPlugin.LastRun finalLastRun = loopPlugin.getLastRun();
if (sp.getBoolean("wear_predictions", true) && finalLastRun != null && finalLastRun.getRequest().getHasPredictions() && finalLastRun.getConstraintsProcessed() != null) { if (sp.getBoolean("wear_predictions", true) && finalLastRun != null && finalLastRun.getRequest().getHasPredictions() && finalLastRun.getConstraintsProcessed() != null) {
List<GlucoseValueDataPoint> predArray = finalLastRun.getConstraintsProcessed().getPredictions(); List<GlucoseValueDataPoint> predArray =
finalLastRun.getConstraintsProcessed().getPredictions()
.stream().map( bg -> new GlucoseValueDataPoint(bg, defaultValueHelper, profileFunction, resourceHelper))
.collect(Collectors.toList());
if (!predArray.isEmpty()) { if (!predArray.isEmpty()) {
final String units = profileFunction.getUnits(); final String units = profileFunction.getUnits();

View file

@ -28,7 +28,6 @@ import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.DecimalFormatter import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.extensions.expandCarbs
import info.nightscout.androidaps.utils.extensions.iobCalc import info.nightscout.androidaps.utils.extensions.iobCalc
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.rx.AapsSchedulers
@ -532,8 +531,7 @@ open class IobCobCalculatorPlugin @Inject constructor(
var displayCob: Double? = null var displayCob: Double? = null
var futureCarbs = 0.0 var futureCarbs = 0.0
val now = DateUtil.now() val now = DateUtil.now()
val carbs = repository.getCarbsDataFromTime(now, true) val carbs = repository.getCarbsDataFromTimeExpanded(now, true).blockingGet()
.blockingGet()
if (autosensData != null) { if (autosensData != null) {
displayCob = autosensData.cob displayCob = autosensData.cob
carbs.forEach { carb -> carbs.forEach { carb ->
@ -603,8 +601,7 @@ open class IobCobCalculatorPlugin @Inject constructor(
sp.getDouble(R.string.key_absorption_cutoff, Constants.DEFAULT_MAX_ABSORPTION_TIME) sp.getDouble(R.string.key_absorption_cutoff, Constants.DEFAULT_MAX_ABSORPTION_TIME)
} }
val absorptionTimeAgo = now - (maxAbsorptionHours * T.hours(1).msecs()).toLong() val absorptionTimeAgo = now - (maxAbsorptionHours * T.hours(1).msecs()).toLong()
repository.getCarbsDataFromTimeToTime(absorptionTimeAgo + 1, now, true) repository.getCarbsDataFromTimeToTimeExpanded(absorptionTimeAgo + 1, now, true)
.map { it.map { c -> c.expandCarbs() }.flatten() }
.blockingGet() .blockingGet()
.forEach { .forEach {
if (it.amount > 0) { if (it.amount > 0) {

View file

@ -189,7 +189,7 @@ class IobCobOref1Thread internal constructor(
aapsLogger.debug(LTag.AUTOSENS, ">>>>> bucketed_data.size()=" + bucketedData.size + " i=" + i + " hourAgoData=" + "null") aapsLogger.debug(LTag.AUTOSENS, ">>>>> bucketed_data.size()=" + bucketedData.size + " i=" + i + " hourAgoData=" + "null")
} }
} }
val recentCarbTreatments = repository.getCarbsDataFromTimeToTime(bgTime - T.mins(5).msecs(), bgTime, true).blockingGet() val recentCarbTreatments = repository.getCarbsDataFromTimeToTimeExpanded(bgTime - T.mins(5).msecs(), bgTime, true).blockingGet()
for (recentCarbTreatment in recentCarbTreatments) { for (recentCarbTreatment in recentCarbTreatments) {
autosensData.carbsFromBolus += recentCarbTreatment.amount autosensData.carbsFromBolus += recentCarbTreatment.amount
val isAAPSOrWeighted = sensitivityAAPSPlugin.isEnabled() || sensitivityWeightedAveragePlugin.isEnabled() val isAAPSOrWeighted = sensitivityAAPSPlugin.isEnabled() || sensitivityWeightedAveragePlugin.isEnabled()

View file

@ -188,7 +188,7 @@ class IobCobThread @Inject internal constructor(
aapsLogger.debug(LTag.AUTOSENS, ">>>>> bucketed_data.size()=" + bucketedData.size + " i=" + i + " hourAgoData=" + "null") aapsLogger.debug(LTag.AUTOSENS, ">>>>> bucketed_data.size()=" + bucketedData.size + " i=" + i + " hourAgoData=" + "null")
} }
} }
val recentCarbTreatments = repository.getCarbsDataFromTimeToTime(bgTime - T.mins(5).msecs(), bgTime, true).blockingGet() val recentCarbTreatments = repository.getCarbsDataFromTimeToTimeExpanded(bgTime - T.mins(5).msecs(), bgTime, true).blockingGet()
for (recentCarbTreatment in recentCarbTreatments) { for (recentCarbTreatment in recentCarbTreatments) {
autosensData.carbsFromBolus += recentCarbTreatment.amount autosensData.carbsFromBolus += recentCarbTreatment.amount
val isAAPSOrWeighted = sensitivityAAPSPlugin.isEnabled() || sensitivityWeightedAveragePlugin.isEnabled() val isAAPSOrWeighted = sensitivityAAPSPlugin.isEnabled() || sensitivityWeightedAveragePlugin.isEnabled()

View file

@ -293,7 +293,7 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
ml.carbs?.let { carbs -> ml.carbs?.let { carbs ->
holder.binding.carbsDate.text = dateUtil.timeString(carbs.timestamp) holder.binding.carbsDate.text = dateUtil.timeString(carbs.timestamp)
holder.binding.carbs.text = resourceHelper.gs(R.string.format_carbs, carbs.amount.toInt()) holder.binding.carbs.text = resourceHelper.gs(R.string.format_carbs, carbs.amount.toInt())
holder.binding.carbsDuration.text = resourceHelper.gs(R.string.format_mins, T.msecs(carbs.duration).mins().toInt()) holder.binding.carbsDuration.text = if (carbs.duration> 0) resourceHelper.gs(R.string.format_mins, T.msecs(carbs.duration).mins().toInt()) else ""
holder.binding.carbsNs.visibility = (NSUpload.isIdValid(carbs.interfaceIDs.nightscoutId)).toVisibility() holder.binding.carbsNs.visibility = (NSUpload.isIdValid(carbs.interfaceIDs.nightscoutId)).toVisibility()
holder.binding.carbsPump.visibility = (carbs.interfaceIDs.pumpId != null).toVisibility() holder.binding.carbsPump.visibility = (carbs.interfaceIDs.pumpId != null).toVisibility()
holder.binding.carbsInvalid.visibility = carbs.isValid.not().toVisibility() holder.binding.carbsInvalid.visibility = carbs.isValid.not().toVisibility()

View file

@ -65,7 +65,7 @@ class TddCalculator @Inject constructor(
tdd.bolus += t.amount tdd.bolus += t.amount
result.put(midnight, tdd) result.put(midnight, tdd)
} }
repository.getCarbsDataFromTimeToTime(startTime, endTime, true).blockingGet().forEach { t-> repository.getCarbsDataFromTimeToTimeExpanded(startTime, endTime, true).blockingGet().forEach { t->
val midnight = MidnightTime.calc(t.timestamp) val midnight = MidnightTime.calc(t.timestamp)
val tdd = result[midnight] ?: TDD(midnight, 0.0, 0.0, 0.0) val tdd = result[midnight] ?: TDD(midnight, 0.0, 0.0, 0.0)
tdd.carbs += t.amount tdd.carbs += t.amount

View file

@ -205,6 +205,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_marginStart="10dp"
android:textStyle="bold" /> android:textStyle="bold" />
<TextView <TextView

View file

@ -2,10 +2,8 @@ package info.nightscout.androidaps.core.di
import dagger.Module import dagger.Module
import dagger.android.ContributesAndroidInjector import dagger.android.ContributesAndroidInjector
import info.nightscout.androidaps.data.GlucoseValueDataPoint
import info.nightscout.androidaps.data.Profile import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.data.PumpEnactResult
import info.nightscout.androidaps.data.TherapyEventDataPoint
import info.nightscout.androidaps.db.ExtendedBolus import info.nightscout.androidaps.db.ExtendedBolus
import info.nightscout.androidaps.db.ProfileSwitch import info.nightscout.androidaps.db.ProfileSwitch
import info.nightscout.androidaps.db.TemporaryBasal import info.nightscout.androidaps.db.TemporaryBasal
@ -31,6 +29,4 @@ abstract class CoreDataClassesModule {
@ContributesAndroidInjector abstract fun profileSwitchInjector(): ProfileSwitch @ContributesAndroidInjector abstract fun profileSwitchInjector(): ProfileSwitch
@ContributesAndroidInjector abstract fun temporaryBasalInjector(): TemporaryBasal @ContributesAndroidInjector abstract fun temporaryBasalInjector(): TemporaryBasal
@ContributesAndroidInjector abstract fun extendedBolusInjector(): ExtendedBolus @ContributesAndroidInjector abstract fun extendedBolusInjector(): ExtendedBolus
@ContributesAndroidInjector abstract fun glucoseValueDataPointInjector(): GlucoseValueDataPoint
@ContributesAndroidInjector abstract fun therapyEventDataPointInjector(): TherapyEventDataPoint
} }

View file

@ -3,7 +3,6 @@ package info.nightscout.androidaps.plugins.aps.loop
import android.text.Spanned import android.text.Spanned
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.core.R import info.nightscout.androidaps.core.R
import info.nightscout.androidaps.data.GlucoseValueDataPoint
import info.nightscout.androidaps.data.IobTotal import info.nightscout.androidaps.data.IobTotal
import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.database.entities.GlucoseValue
import info.nightscout.androidaps.interfaces.ActivePluginProvider import info.nightscout.androidaps.interfaces.ActivePluginProvider
@ -185,9 +184,9 @@ open class APSResult @Inject constructor(val injector: HasAndroidInjector) {
return json return json
} }
val predictions: MutableList<GlucoseValueDataPoint> val predictions: MutableList<GlucoseValue>
get() { get() {
val array: MutableList<GlucoseValueDataPoint> = ArrayList() val array: MutableList<GlucoseValue> = ArrayList()
val startTime = date val startTime = date
json?.let { json -> json?.let { json ->
if (json.has("predBGs")) { if (json.has("predBGs")) {
@ -203,7 +202,7 @@ open class APSResult @Inject constructor(val injector: HasAndroidInjector) {
sourceSensor = GlucoseValue.SourceSensor.IOB_PREDICTION, sourceSensor = GlucoseValue.SourceSensor.IOB_PREDICTION,
trendArrow = GlucoseValue.TrendArrow.NONE trendArrow = GlucoseValue.TrendArrow.NONE
) )
array.add(GlucoseValueDataPoint(injector, gv)) array.add(gv)
} }
} }
if (predBGs.has("aCOB")) { if (predBGs.has("aCOB")) {
@ -217,7 +216,7 @@ open class APSResult @Inject constructor(val injector: HasAndroidInjector) {
sourceSensor = GlucoseValue.SourceSensor.aCOB_PREDICTION, sourceSensor = GlucoseValue.SourceSensor.aCOB_PREDICTION,
trendArrow = GlucoseValue.TrendArrow.NONE trendArrow = GlucoseValue.TrendArrow.NONE
) )
array.add(GlucoseValueDataPoint(injector, gv)) array.add(gv)
} }
} }
if (predBGs.has("COB")) { if (predBGs.has("COB")) {
@ -231,7 +230,7 @@ open class APSResult @Inject constructor(val injector: HasAndroidInjector) {
sourceSensor = GlucoseValue.SourceSensor.COB_PREDICTION, sourceSensor = GlucoseValue.SourceSensor.COB_PREDICTION,
trendArrow = GlucoseValue.TrendArrow.NONE trendArrow = GlucoseValue.TrendArrow.NONE
) )
array.add(GlucoseValueDataPoint(injector, gv)) array.add(gv)
} }
} }
if (predBGs.has("UAM")) { if (predBGs.has("UAM")) {
@ -245,7 +244,7 @@ open class APSResult @Inject constructor(val injector: HasAndroidInjector) {
sourceSensor = GlucoseValue.SourceSensor.UAM_PREDICTION, sourceSensor = GlucoseValue.SourceSensor.UAM_PREDICTION,
trendArrow = GlucoseValue.TrendArrow.NONE trendArrow = GlucoseValue.TrendArrow.NONE
) )
array.add(GlucoseValueDataPoint(injector, gv)) array.add(gv)
} }
} }
if (predBGs.has("ZT")) { if (predBGs.has("ZT")) {
@ -259,7 +258,7 @@ open class APSResult @Inject constructor(val injector: HasAndroidInjector) {
sourceSensor = GlucoseValue.SourceSensor.ZT_PREDICTION, sourceSensor = GlucoseValue.SourceSensor.ZT_PREDICTION,
trendArrow = GlucoseValue.TrendArrow.NONE trendArrow = GlucoseValue.TrendArrow.NONE
) )
array.add(GlucoseValueDataPoint(injector, gv)) array.add(gv)
} }
} }
} }

View file

@ -18,15 +18,12 @@ package info.nightscout.androidaps.plugins.general.overview.graphExtensions;
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* with the "Linking Exception" along with this program; if not, * with the "Linking Exception" along with this program; if not,
* write to the author Jonas Gehring <g.jjoe64@gmail.com>. * write to the author Jonas Gehring <g.jjoe64@gmail.com>.
* <p> */
/*
* Added by mike * Added by mike
*/ */
/**
* Added by mike
*/
import android.content.Context;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Path; import android.graphics.Path;
@ -61,6 +58,7 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
TRIANGLE, TRIANGLE,
RECTANGLE, RECTANGLE,
BOLUS, BOLUS,
CARBS,
SMB, SMB,
EXTENDEDBOLUS, EXTENDEDBOLUS,
PROFILE, PROFILE,
@ -233,7 +231,18 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
mPaint.setStyle(Paint.Style.FILL_AND_STROKE); mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
drawArrows(points, canvas, mPaint); drawArrows(points, canvas, mPaint);
if (value.getLabel() != null) { if (value.getLabel() != null) {
drawLabel45(endX, endY, value, canvas, scaledPxSize, scaledTextSize); drawLabel45Right(endX, endY, value, canvas, scaledPxSize, scaledTextSize);
}
} else if (value.getShape() == Shape.CARBS) {
mPaint.setStrokeWidth(0);
Point[] points = new Point[3];
points[0] = new Point((int) endX, (int) (endY - scaledPxSize));
points[1] = new Point((int) (endX + scaledPxSize), (int) (endY + scaledPxSize * 0.67));
points[2] = new Point((int) (endX - scaledPxSize), (int) (endY + scaledPxSize * 0.67));
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
drawArrows(points, canvas, mPaint);
if (value.getLabel() != null) {
drawLabel45Left(endX, endY, value, canvas, scaledPxSize, scaledTextSize);
} }
} else if (value.getShape() == Shape.SMB) { } else if (value.getShape() == Shape.SMB) {
mPaint.setStrokeWidth(2); mPaint.setStrokeWidth(2);
@ -282,21 +291,21 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
mPaint.setStrokeWidth(0); mPaint.setStrokeWidth(0);
canvas.drawCircle(endX, endY, scaledPxSize, mPaint); canvas.drawCircle(endX, endY, scaledPxSize, mPaint);
if (value.getLabel() != null) { if (value.getLabel() != null) {
drawLabel45(endX, endY, value, canvas, scaledPxSize, scaledTextSize); drawLabel45Right(endX, endY, value, canvas, scaledPxSize, scaledTextSize);
} }
} else if (value.getShape() == Shape.ANNOUNCEMENT) { } else if (value.getShape() == Shape.ANNOUNCEMENT) {
mPaint.setStyle(Paint.Style.FILL_AND_STROKE); mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setStrokeWidth(0); mPaint.setStrokeWidth(0);
canvas.drawCircle(endX, endY, scaledPxSize, mPaint); canvas.drawCircle(endX, endY, scaledPxSize, mPaint);
if (value.getLabel() != null) { if (value.getLabel() != null) {
drawLabel45(endX, endY, value, canvas, scaledPxSize, scaledTextSize); drawLabel45Right(endX, endY, value, canvas, scaledPxSize, scaledTextSize);
} }
} else if (value.getShape() == Shape.GENERAL) { } else if (value.getShape() == Shape.GENERAL) {
mPaint.setStyle(Paint.Style.FILL_AND_STROKE); mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setStrokeWidth(0); mPaint.setStrokeWidth(0);
canvas.drawCircle(endX, endY, scaledPxSize, mPaint); canvas.drawCircle(endX, endY, scaledPxSize, mPaint);
if (value.getLabel() != null) { if (value.getLabel() != null) {
drawLabel45(endX, endY, value, canvas, scaledPxSize, scaledTextSize); drawLabel45Right(endX, endY, value, canvas, scaledPxSize, scaledTextSize);
} }
} else if (value.getShape() == Shape.EXERCISE) { } else if (value.getShape() == Shape.EXERCISE) {
mPaint.setStrokeWidth(0); mPaint.setStrokeWidth(0);
@ -380,29 +389,29 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
canvas.restore(); canvas.restore();
} }
void drawLabel45(float endX, float endY, E value, Canvas canvas, Float scaledPxSize, Float scaledTextSize) { void drawLabel45Right(float endX, float endY, E value, Canvas canvas, Float scaledPxSize, Float scaledTextSize) {
if (value.getLabel().startsWith("~")) { float px = endX;
float px = endX; float py = endY - scaledPxSize;
float py = endY + scaledPxSize; canvas.save();
canvas.save(); canvas.rotate(-45, px, py);
canvas.rotate(-45, px, py); mPaint.setTextSize((float) (scaledTextSize * 0.8));
mPaint.setTextSize((float) (scaledTextSize * 0.8)); mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL));
mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); mPaint.setFakeBoldText(true);
mPaint.setFakeBoldText(true); canvas.drawText(value.getLabel(), px + scaledPxSize, py, mPaint);
mPaint.setTextAlign(Paint.Align.RIGHT); canvas.restore();
canvas.drawText(value.getLabel().substring(1), px - scaledPxSize, py, mPaint);
mPaint.setTextAlign(Paint.Align.LEFT);
canvas.restore();
} else {
float px = endX;
float py = endY - scaledPxSize;
canvas.save();
canvas.rotate(-45, px, py);
mPaint.setTextSize((float) (scaledTextSize * 0.8));
mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL));
mPaint.setFakeBoldText(true);
canvas.drawText(value.getLabel(), px + scaledPxSize, py, mPaint);
canvas.restore();
}
} }
}
void drawLabel45Left(float endX, float endY, E value, Canvas canvas, Float scaledPxSize, Float scaledTextSize) {
float px = endX;
float py = endY + scaledPxSize;
canvas.save();
canvas.rotate(-45, px, py);
mPaint.setTextSize((float) (scaledTextSize * 0.8));
mPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL));
mPaint.setFakeBoldText(true);
mPaint.setTextAlign(Paint.Align.RIGHT);
canvas.drawText(value.getLabel(), px - scaledPxSize, py, mPaint);
mPaint.setTextAlign(Paint.Align.LEFT);
canvas.restore();
}
}

View file

@ -5,31 +5,7 @@ import info.nightscout.androidaps.database.entities.Carbs
import info.nightscout.androidaps.database.entities.TherapyEvent import info.nightscout.androidaps.database.entities.TherapyEvent
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.JsonHelper import info.nightscout.androidaps.utils.JsonHelper
import info.nightscout.androidaps.utils.T
import org.json.JSONObject import org.json.JSONObject
import java.util.concurrent.TimeUnit
import kotlin.math.roundToInt
fun Carbs.expandCarbs(): List<Carbs> =
mutableListOf<Carbs>().also { carbs ->
if (this.duration == 0L) {
carbs.add(this)
} else {
var remainingCarbs = this.amount
val ticks = T.msecs(this.duration).hours() * 4 //duration guaranteed to be integer greater zero
for (i in 0 until ticks) {
val carbTime = this.timestamp + i * 15 * 60 * 1000
val smallCarbAmount = (1.0 * remainingCarbs / (ticks - i)).roundToInt() //on last iteration (ticks-i) is 1 -> smallCarbAmount == remainingCarbs
remainingCarbs -= smallCarbAmount.toLong()
if (smallCarbAmount > 0)
carbs.add(Carbs(
timestamp = carbTime,
amount = smallCarbAmount.toDouble(),
duration = 0
))
}
}
}
fun Carbs.toJson(): JSONObject = fun Carbs.toJson(): JSONObject =
JSONObject() JSONObject()

File diff suppressed because it is too large Load diff

View file

@ -12,6 +12,7 @@ import io.reactivex.subjects.PublishSubject
import java.util.concurrent.Callable import java.util.concurrent.Callable
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
import kotlin.math.roundToInt
@Singleton @Singleton
open class AppRepository @Inject internal constructor( open class AppRepository @Inject internal constructor(
@ -310,6 +311,27 @@ open class AppRepository @Inject internal constructor(
database.bolusDao.deleteAllEntries() database.bolusDao.deleteAllEntries()
// CARBS // CARBS
val timeBackForExpand = 8 * 60 * 60 * 1000
private fun expandCarbs(carbs: Carbs): List<Carbs> =
if (carbs.duration == 0L) {
listOf(carbs)
} else {
var remainingCarbs = carbs.amount
val ticks = (carbs.duration / 1000 / 60 / 15).coerceAtLeast(1L)
(0 until ticks).map {
val carbTime = carbs.timestamp + it * 15 * 60 * 1000
val smallCarbAmount = (1.0 * remainingCarbs / (ticks - it)).roundToInt() //on last iteration (ticks-i) is 1 -> smallCarbAmount == remainingCarbs
remainingCarbs -= smallCarbAmount.toLong()
Carbs(timestamp = carbTime, amount = smallCarbAmount.toDouble(), duration = 0)
}.filter { it.amount != 0.0 }
}
private fun Single<List<Carbs>>.expand() = this.map { it.map(::expandCarbs).flatten() }
private fun Single<List<Carbs>>.filterOutExtended() = this.map { it.filter { c -> c.duration == 0L } }
private fun Single<List<Carbs>>.fromTo(from: Long, to: Long) = this.map { it.filter { c -> c.timestamp in from..to } }
private fun Single<List<Carbs>>.sort() = this.map { it.sortedBy { c -> c.timestamp } }
/* /*
* returns a Pair of the next entity to sync and the ID of the "update". * returns a Pair of the next entity to sync and the ID of the "update".
* The update id might either be the entry id itself if it is a new entry - or the id * The update id might either be the entry id itself if it is a new entry - or the id
@ -339,6 +361,11 @@ open class AppRepository @Inject internal constructor(
fun getLastCarbsRecord(): Carbs? = fun getLastCarbsRecord(): Carbs? =
database.carbsDao.getLastCarbsRecord() database.carbsDao.getLastCarbsRecord()
fun getLastCarbsRecordWrapped(): Single<ValueWrapper<Carbs>> =
database.carbsDao.getLastCarbsRecordMaybe()
.subscribeOn(Schedulers.io())
.toWrappedSingle()
fun getOldestCarbsRecord(): Carbs? = fun getOldestCarbsRecord(): Carbs? =
database.carbsDao.getOldestCarbsRecord() database.carbsDao.getOldestCarbsRecord()
@ -347,18 +374,35 @@ open class AppRepository @Inject internal constructor(
.map { if (!ascending) it.reversed() else it } .map { if (!ascending) it.reversed() else it }
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
fun getCarbsDataFromTimeExpanded(timestamp: Long, ascending: Boolean): Single<List<Carbs>> =
database.carbsDao.getCarbsFromTime(timestamp - timeBackForExpand)
.expand()
.map { if (!ascending) it.reversed() else it }
.subscribeOn(Schedulers.io())
fun getCarbsDataFromTimeToTime(from: Long, to: Long, ascending: Boolean): Single<List<Carbs>> = fun getCarbsDataFromTimeToTime(from: Long, to: Long, ascending: Boolean): Single<List<Carbs>> =
database.carbsDao.getCarbsFromTimeToTime(from, to) database.carbsDao.getCarbsFromTimeToTime(from, to)
.map { if (!ascending) it.reversed() else it } .map { if (!ascending) it.reversed() else it }
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
fun getCarbsIncludingInvalidFromTime(timestamp: Long, ascending: Boolean): Single<List<Carbs>> = fun getCarbsDataFromTimeToTimeExpanded(from: Long, to: Long, ascending: Boolean): Single<List<Carbs>> =
database.carbsDao.getCarbsIncludingInvalidFromTime(timestamp) database.carbsDao.getCarbsFromTimeToTime(from - timeBackForExpand, to)
.expand()
.fromTo(from, to)
.sort()
.map { if (!ascending) it.reversed() else it } .map { if (!ascending) it.reversed() else it }
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
fun getCarbsIncludingInvalidFromTimeToTime(from: Long, to: Long, ascending: Boolean): Single<List<Carbs>> = fun getCarbsIncludingInvalidFromTime(timestamp: Long, ascending: Boolean): Single<List<Carbs>> =
database.carbsDao.getCarbsIncludingInvalidFromTimeToTime(from, to) database.carbsDao.getCarbsIncludingInvalidFromTime(timestamp - timeBackForExpand)
.map { if (!ascending) it.reversed() else it }
.subscribeOn(Schedulers.io())
fun getCarbsIncludingInvalidFromTimeToTimeExpanded(from: Long, to: Long, ascending: Boolean): Single<List<Carbs>> =
database.carbsDao.getCarbsIncludingInvalidFromTimeToTime(from - timeBackForExpand, to)
.expand()
.fromTo(from, to)
.sort()
.map { if (!ascending) it.reversed() else it } .map { if (!ascending) it.reversed() else it }
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())

View file

@ -26,6 +26,9 @@ internal interface CarbsDao : TraceableDao<Carbs> {
@Query("SELECT * FROM $TABLE_CARBS WHERE isValid = 1 AND referenceId IS NULL ORDER BY id DESC LIMIT 1") @Query("SELECT * FROM $TABLE_CARBS WHERE isValid = 1 AND referenceId IS NULL ORDER BY id DESC LIMIT 1")
fun getLastCarbsRecord(): Carbs? fun getLastCarbsRecord(): Carbs?
@Query("SELECT * FROM $TABLE_CARBS WHERE isValid = 1 AND referenceId IS NULL ORDER BY id DESC LIMIT 1")
fun getLastCarbsRecordMaybe(): Maybe<Carbs>
@Query("SELECT * FROM $TABLE_CARBS WHERE isValid = 1 AND referenceId IS NULL ORDER BY id ASC LIMIT 1") @Query("SELECT * FROM $TABLE_CARBS WHERE isValid = 1 AND referenceId IS NULL ORDER BY id ASC LIMIT 1")
fun getOldestCarbsRecord(): Carbs? fun getOldestCarbsRecord(): Carbs?