Support heart rate in overview graph
This commit is contained in:
parent
7faa34aa50
commit
ecea212c83
15 changed files with 77 additions and 10 deletions
|
@ -327,6 +327,7 @@ class HistoryBrowseActivity : TranslatedDaggerAppCompatActivity() {
|
|||
var useRatioForScale = false
|
||||
var useDSForScale = false
|
||||
var useBGIForScale = false
|
||||
var useHRForScale = false
|
||||
when {
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.ABS.ordinal] -> useABSForScale = true
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal] -> useIobForScale = true
|
||||
|
@ -335,6 +336,7 @@ class HistoryBrowseActivity : TranslatedDaggerAppCompatActivity() {
|
|||
menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal] -> useBGIForScale = true
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal] -> useRatioForScale = true
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] -> useDSForScale = true
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.HR.ordinal] -> useHRForScale = true
|
||||
}
|
||||
val alignDevBgiScale = menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal] && menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal]
|
||||
|
||||
|
@ -345,6 +347,7 @@ class HistoryBrowseActivity : TranslatedDaggerAppCompatActivity() {
|
|||
if (menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal]) secondGraphData.addMinusBGI(useBGIForScale, if (alignDevBgiScale) 1.0 else 0.8)
|
||||
if (menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal]) secondGraphData.addRatio(useRatioForScale, if (useRatioForScale) 1.0 else 0.8)
|
||||
if (menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] && config.isDev()) secondGraphData.addDeviationSlope(useDSForScale, 1.0)
|
||||
if (menuChartSettings[g + 1][OverviewMenus.CharType.HR.ordinal] && config.isDev()) secondGraphData.addHeartRate(useHRForScale, 1.0)
|
||||
|
||||
// set manual x bounds to have nice steps
|
||||
secondGraphData.formatAxis(historyBrowserData.overviewData.fromTime, historyBrowserData.overviewData.endTime)
|
||||
|
|
|
@ -150,4 +150,7 @@ interface OverviewData {
|
|||
val dsMinScale: Scale
|
||||
var dsMaxSeries: LineGraphSeries<ScaledDataPoint>
|
||||
var dsMinSeries: LineGraphSeries<ScaledDataPoint>
|
||||
}
|
||||
var heartRateScale: Scale
|
||||
var heartRateGraphSeries: LineGraphSeries<DataPointWithLabelInterface>
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package info.nightscout.core.graph.data
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Paint
|
||||
import info.nightscout.database.entities.HeartRate
|
||||
import info.nightscout.shared.interfaces.ResourceHelper
|
||||
|
||||
class HeartRateDataPoint(
|
||||
private val data: HeartRate,
|
||||
private val rh: ResourceHelper,
|
||||
) : DataPointWithLabelInterface {
|
||||
|
||||
override fun getX(): Double = (data.timestamp - data.duration).toDouble()
|
||||
override fun getY(): Double = data.beatsPerMinute
|
||||
override fun setY(y: Double) {}
|
||||
|
||||
override val label: String = ""
|
||||
override val duration = data.duration
|
||||
override val shape = PointsWithLabelGraphSeries.Shape.HEARTRATE
|
||||
override val size = 1f
|
||||
override val paintStyle: Paint.Style = Paint.Style.FILL
|
||||
|
||||
override fun color(context: Context?): Int = rh.gac(context, info.nightscout.core.ui.R.attr.heartRateColor)
|
||||
}
|
|
@ -54,7 +54,8 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
|
|||
GENERAL_WITH_DURATION,
|
||||
COB_FAIL_OVER,
|
||||
IOB_PREDICTION,
|
||||
BUCKETED_BG
|
||||
BUCKETED_BG,
|
||||
HEARTRATE,
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -324,6 +325,10 @@ public class PointsWithLabelGraphSeries<E extends DataPointWithLabelInterface> e
|
|||
mPaint.setStrokeWidth(5);
|
||||
canvas.drawRect(endX - 3, bounds.top + py - 3, xPlusLength + 3, bounds.bottom + py + 3, mPaint);
|
||||
}
|
||||
} else if (value.getShape() == Shape.HEARTRATE) {
|
||||
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
|
||||
mPaint.setStrokeWidth(0);
|
||||
canvas.drawCircle(endX, endY, 1F, mPaint);
|
||||
}
|
||||
// set values above point
|
||||
}
|
||||
|
|
|
@ -15,7 +15,8 @@ interface OverviewMenus {
|
|||
BGI,
|
||||
SEN,
|
||||
ACT,
|
||||
DEVSLOPE
|
||||
DEVSLOPE,
|
||||
HR,
|
||||
}
|
||||
|
||||
val setting: List<Array<Boolean>>
|
||||
|
@ -23,4 +24,4 @@ interface OverviewMenus {
|
|||
fun setupChartMenu(context: Context, chartButton: ImageButton)
|
||||
fun enabledTypes(graph: Int): String
|
||||
fun isEnabledIn(type: CharType): Int
|
||||
}
|
||||
}
|
||||
|
|
|
@ -216,6 +216,7 @@
|
|||
<item name="inRangeBackground">@color/inRangeBackground</item>
|
||||
<item name="devSlopePosColor">@color/devSlopePos</item>
|
||||
<item name="devSlopeNegColor">@color/devSlopeNeg</item>
|
||||
<item name="heartRateColor">@color/heartRate</item>
|
||||
<item name="deviationGreyColor">@color/deviationGrey</item>
|
||||
<item name="deviationBlackColor">@color/deviationBlack</item>
|
||||
<item name="deviationGreenColor">@color/deviationGreen</item>
|
||||
|
|
|
@ -181,6 +181,7 @@
|
|||
<attr name="bolusDataPointColor" format="reference|color" />
|
||||
<attr name="profileSwitchColor" format="reference|color" />
|
||||
<attr name="originalBgValueColor" format="reference|color" />
|
||||
<attr name="heartRateColor" format="reference|color" />
|
||||
<attr name="therapyEvent_NS_MBG" format="reference|color" />
|
||||
<attr name="therapyEvent_FINGER_STICK_BG_VALUE" format="reference|color" />
|
||||
<attr name="therapyEvent_EXERCISE" format="reference|color" />
|
||||
|
@ -221,4 +222,4 @@
|
|||
<attr name="crossTargetColor" format="reference|color" />
|
||||
<!---Custom button -->
|
||||
<attr name="customBtnStyle" format="reference"/>
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
@ -153,6 +153,7 @@
|
|||
<color name="bgi">#00EEEE</color>
|
||||
<color name="devSlopePos">#FFFFFF00</color>
|
||||
<color name="devSlopeNeg">#FFFF00FF</color>
|
||||
<color name="heartRate">#FFFFFF66</color>
|
||||
<color name="actionsConfirm">#F6CE22</color>
|
||||
<color name="deviations">#FF0000</color>
|
||||
<color name="cobAlert">#7484E2</color>
|
||||
|
|
|
@ -219,6 +219,7 @@
|
|||
<item name="inRangeBackground">@color/inRangeBackground</item>
|
||||
<item name="devSlopePosColor">@color/devSlopePos</item>
|
||||
<item name="devSlopeNegColor">@color/devSlopeNeg</item>
|
||||
<item name="heartRateColor">@color/heartRate</item>
|
||||
<item name="deviationGreyColor">@color/deviationGrey</item>
|
||||
<item name="deviationBlackColor">@color/deviationBlack</item>
|
||||
<item name="deviationGreenColor">@color/deviationGreen</item>
|
||||
|
|
|
@ -87,6 +87,7 @@ class OverviewDataImpl @Inject constructor(
|
|||
dsMinSeries = LineGraphSeries()
|
||||
treatmentsSeries = PointsWithLabelGraphSeries()
|
||||
epsSeries = PointsWithLabelGraphSeries()
|
||||
heartRateGraphSeries = LineGraphSeries()
|
||||
}
|
||||
|
||||
override fun initRange() {
|
||||
|
@ -322,4 +323,6 @@ class OverviewDataImpl @Inject constructor(
|
|||
override val dsMinScale = Scale()
|
||||
override var dsMaxSeries: LineGraphSeries<ScaledDataPoint> = LineGraphSeries()
|
||||
override var dsMinSeries: LineGraphSeries<ScaledDataPoint> = LineGraphSeries()
|
||||
override var heartRateScale = Scale()
|
||||
override var heartRateGraphSeries: LineGraphSeries<DataPointWithLabelInterface> = LineGraphSeries()
|
||||
}
|
||||
|
|
|
@ -1030,6 +1030,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
|||
var useRatioForScale = false
|
||||
var useDSForScale = false
|
||||
var useBGIForScale = false
|
||||
var useHRForScale = false
|
||||
when {
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.ABS.ordinal] -> useABSForScale = true
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal] -> useIobForScale = true
|
||||
|
@ -1038,6 +1039,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
|||
menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal] -> useBGIForScale = true
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal] -> useRatioForScale = true
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] -> useDSForScale = true
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.HR.ordinal] -> useHRForScale = true
|
||||
}
|
||||
val alignDevBgiScale = menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal] && menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal]
|
||||
|
||||
|
@ -1052,6 +1054,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
|||
if (useDSForScale) 1.0 else 0.8,
|
||||
useRatioForScale
|
||||
)
|
||||
if (menuChartSettings[g + 1][OverviewMenus.CharType.HR.ordinal]) secondGraphData.addHeartRate(useHRForScale, if (useHRForScale) 1.0 else 0.8)
|
||||
|
||||
// set manual x bounds to have nice steps
|
||||
secondGraphData.formatAxis(overviewData.fromTime, overviewData.endTime)
|
||||
|
@ -1067,7 +1070,8 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
|||
menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal] ||
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal] ||
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal] ||
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal]
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] ||
|
||||
menuChartSettings[g + 1][OverviewMenus.CharType.HR.ordinal]
|
||||
).toVisibility()
|
||||
secondaryGraphsData[g].performUpdate()
|
||||
}
|
||||
|
|
|
@ -47,7 +47,8 @@ class OverviewMenusImpl @Inject constructor(
|
|||
BGI(R.string.overview_show_bgi, info.nightscout.core.ui.R.attr.bgiColor, info.nightscout.core.ui.R.attr.menuTextColor, primary = false, secondary = true, shortnameId = R.string.bgi_shortname),
|
||||
SEN(R.string.overview_show_sensitivity, info.nightscout.core.ui.R.attr.ratioColor, info.nightscout.core.ui.R.attr.menuTextColorInverse, primary = false, secondary = true, shortnameId = R.string.sensitivity_shortname),
|
||||
ACT(R.string.overview_show_activity, info.nightscout.core.ui.R.attr.activityColor, info.nightscout.core.ui.R.attr.menuTextColor, primary = true, secondary = false, shortnameId = R.string.activity_shortname),
|
||||
DEVSLOPE(R.string.overview_show_deviation_slope, info.nightscout.core.ui.R.attr.devSlopePosColor, info.nightscout.core.ui.R.attr.menuTextColor, primary = false, secondary = true, shortnameId = R.string.devslope_shortname)
|
||||
DEVSLOPE(R.string.overview_show_deviation_slope, info.nightscout.core.ui.R.attr.devSlopePosColor, info.nightscout.core.ui.R.attr.menuTextColor, primary = false, secondary = true, shortnameId = R.string.devslope_shortname),
|
||||
HR(R.string.overview_show_heartRate, info.nightscout.core.ui.R.attr.heartRateColor, info.nightscout.core.ui.R.attr.menuTextColor, primary = false, secondary = true, shortnameId = R.string.heartRate_shortname),
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -202,4 +203,4 @@ class OverviewMenusImpl @Inject constructor(
|
|||
return -1
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -258,5 +258,14 @@ class GraphData(
|
|||
// draw it
|
||||
graph.onDataChanged(false, false)
|
||||
}
|
||||
}
|
||||
|
||||
fun addHeartRate(useForScale: Boolean, scale: Double) {
|
||||
val maxHR = overviewData.heartRateGraphSeries.highestValueY
|
||||
if (useForScale) {
|
||||
minY = 0.0
|
||||
maxY = maxHR
|
||||
}
|
||||
addSeries(overviewData.heartRateGraphSeries)
|
||||
overviewData.heartRateScale.multiplier = maxY * scale / maxHR
|
||||
}
|
||||
}
|
||||
|
|
|
@ -291,6 +291,7 @@
|
|||
|
||||
<string name="overview_show_predictions">Predictions</string>
|
||||
<string name="overview_show_treatments">Treatments</string>
|
||||
<string name="overview_show_heartRate">Heart Rate</string>
|
||||
<string name="overview_show_deviation_slope">Deviation slope</string>
|
||||
<string name="overview_show_activity">Activity</string>
|
||||
<string name="overview_show_bgi">Blood Glucose Impact</string>
|
||||
|
@ -308,6 +309,7 @@
|
|||
<string name="abs_insulin_shortname">ABS</string>
|
||||
<string name="devslope_shortname">DEVSLOPE</string>
|
||||
<string name="treatments_shortname">TREAT</string>
|
||||
<string name="heartRate_shortname">HR</string>
|
||||
<string name="sensitivity_shortname">SENS</string>
|
||||
<string name="graph_scale">Graph scale</string>
|
||||
<string name="graph_menu_divider_header">Graph</string>
|
||||
|
|
|
@ -3,6 +3,7 @@ package info.nightscout.workflow
|
|||
import android.content.Context
|
||||
import androidx.work.WorkerParameters
|
||||
import androidx.work.workDataOf
|
||||
import com.jjoe64.graphview.series.LineGraphSeries
|
||||
import info.nightscout.core.events.EventIobCalculationProgress
|
||||
import info.nightscout.core.graph.OverviewData
|
||||
import info.nightscout.core.graph.data.BolusDataPoint
|
||||
|
@ -10,6 +11,8 @@ import info.nightscout.core.graph.data.CarbsDataPoint
|
|||
import info.nightscout.core.graph.data.DataPointWithLabelInterface
|
||||
import info.nightscout.core.graph.data.EffectiveProfileSwitchDataPoint
|
||||
import info.nightscout.core.graph.data.ExtendedBolusDataPoint
|
||||
import info.nightscout.core.graph.data.FixedLineGraphSeries
|
||||
import info.nightscout.core.graph.data.HeartRateDataPoint
|
||||
import info.nightscout.core.graph.data.PointsWithLabelGraphSeries
|
||||
import info.nightscout.core.graph.data.TherapyEventDataPoint
|
||||
import info.nightscout.core.utils.receivers.DataWorkerStorage
|
||||
|
@ -129,6 +132,11 @@ class PrepareTreatmentsDataWorker(
|
|||
data.overviewData.therapyEventSeries = PointsWithLabelGraphSeries(filteredTherapyEvents.toTypedArray())
|
||||
data.overviewData.epsSeries = PointsWithLabelGraphSeries(filteredEps.toTypedArray())
|
||||
|
||||
data.overviewData.heartRateGraphSeries = LineGraphSeries<DataPointWithLabelInterface>(
|
||||
repository.getHeartRatesFromTimeToTime(fromTime, endTime)
|
||||
.map { hr -> HeartRateDataPoint(hr, rh) }
|
||||
.toTypedArray()).apply { color = rh.gac(null, info.nightscout.core.ui.R.attr.heartRateColor) }
|
||||
|
||||
rxBus.send(EventIobCalculationProgress(CalculationWorkflow.ProgressData.PREPARE_TREATMENTS_DATA, 100, null))
|
||||
return Result.success()
|
||||
}
|
||||
|
@ -149,4 +157,4 @@ class PrepareTreatmentsDataWorker(
|
|||
|
||||
private fun <E : DataPointWithLabelInterface> List<E>.filterTimeframe(fromTime: Long, endTime: Long): List<E> =
|
||||
filter { it.x + it.duration >= fromTime && it.x <= endTime }
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue