Merge pull request #1292 from Andries-Smit/new-profile-editor
profile editor add DIA and Target Chart
This commit is contained in:
commit
064642339e
13 changed files with 251 additions and 49 deletions
|
@ -18,10 +18,11 @@ class ActivityGraph : GraphView {
|
|||
|
||||
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
|
||||
|
||||
fun show(insulin: Insulin) {
|
||||
fun show(insulin: Insulin, diaSample: Double? = null) {
|
||||
removeAllSeries()
|
||||
val dia = diaSample ?: insulin.dia
|
||||
mSecondScale = null
|
||||
val hours = floor(insulin.dia + 1).toLong()
|
||||
val hours = floor(dia + 1).toLong()
|
||||
val bolus = Bolus(
|
||||
timestamp = 0,
|
||||
amount = 1.0,
|
||||
|
@ -31,7 +32,7 @@ class ActivityGraph : GraphView {
|
|||
val iobArray: MutableList<DataPoint> = ArrayList()
|
||||
var time: Long = 0
|
||||
while (time <= T.hours(hours).msecs()) {
|
||||
val iob = insulin.iobCalcForTreatment(bolus, time, insulin.dia)
|
||||
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()
|
||||
|
|
|
@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.profile.local
|
|||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
@ -20,7 +21,6 @@ import info.nightscout.androidaps.dialogs.ProfileSwitchDialog
|
|||
import info.nightscout.androidaps.interfaces.ActivePlugin
|
||||
import info.nightscout.androidaps.interfaces.GlucoseUnit
|
||||
import info.nightscout.androidaps.interfaces.Profile
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.plugins.profile.local.events.EventLocalProfileChanged
|
||||
|
@ -31,8 +31,10 @@ import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
|||
import info.nightscout.androidaps.utils.ui.SpinnerHelper
|
||||
import info.nightscout.androidaps.utils.ui.TimeListEdit
|
||||
import info.nightscout.shared.SafeParse
|
||||
import info.nightscout.shared.logging.AAPSLogger
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import io.reactivex.rxkotlin.plusAssign
|
||||
import java.math.RoundingMode
|
||||
import java.text.DecimalFormat
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -61,6 +63,8 @@ class LocalProfileFragment : DaggerFragment() {
|
|||
binding.basalGraph.show(ProfileSealed.Pure(it))
|
||||
binding.icGraph.show(ProfileSealed.Pure(it))
|
||||
binding.isfGraph.show(ProfileSealed.Pure(it))
|
||||
binding.targetGraph.show(ProfileSealed.Pure(it))
|
||||
binding.insulinGraph.show(activePlugin.activeInsulin, SafeParse.stringToDouble(binding.dia.text))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,14 +134,22 @@ class LocalProfileFragment : DaggerFragment() {
|
|||
binding.name.addTextChangedListener(textWatch)
|
||||
binding.dia.setParams(currentProfile.dia, hardLimits.minDia(), hardLimits.maxDia(), 0.1, DecimalFormat("0.0"), false, null, textWatch)
|
||||
binding.dia.tag = "LP_DIA"
|
||||
TimeListEdit(context, aapsLogger, dateUtil, view, R.id.ic_holder, "IC", rh.gs(R.string.ic_label), currentProfile.ic, null, hardLimits.minIC(), hardLimits.maxIC(), 0.1, DecimalFormat("0.0"), save)
|
||||
basalView = TimeListEdit(context, aapsLogger, dateUtil, view, R.id.basal_holder, "BASAL", rh.gs(R.string.basal_label) + ": " + sumLabel(), currentProfile.basal, null, pumpDescription.basalMinimumRate, pumpDescription.basalMaximumRate, 0.01, DecimalFormat("0.00"), save)
|
||||
TimeListEdit(context, aapsLogger, dateUtil, view, R.id.ic_holder, "IC", rh.gs(R.string.ic_long_label), currentProfile.ic, null, doubleArrayOf(hardLimits.minIC(), hardLimits.maxIC()), null, 0.1, DecimalFormat ("0.0"), save)
|
||||
basalView = TimeListEdit(context, aapsLogger, dateUtil, view, R.id.basal_holder, "BASAL", rh.gs(R.string.basal_long_label) + ": " + sumLabel(), currentProfile.basal, null, doubleArrayOf(pumpDescription.basalMinimumRate, pumpDescription.basalMaximumRate), null, 0.01, DecimalFormat("0.00"), save)
|
||||
if (units == Constants.MGDL) {
|
||||
TimeListEdit(context, aapsLogger, dateUtil, view, R.id.isf_holder, "ISF", rh.gs(R.string.isf_label), currentProfile.isf, null, HardLimits.MIN_ISF, HardLimits.MAX_ISF, 1.0, DecimalFormat("0"), save)
|
||||
TimeListEdit(context, aapsLogger, dateUtil, view, R.id.target, "TARGET", rh.gs(R.string.target_label), currentProfile.targetLow, currentProfile.targetHigh, HardLimits.VERY_HARD_LIMIT_TARGET_BG[0], HardLimits.VERY_HARD_LIMIT_TARGET_BG[1], 1.0, DecimalFormat("0"), save)
|
||||
val isfRange = doubleArrayOf(HardLimits.MIN_ISF, HardLimits.MAX_ISF)
|
||||
TimeListEdit(context, aapsLogger, dateUtil, view, R.id.isf_holder, "ISF", rh.gs(R.string.isf_long_label), currentProfile.isf, null, isfRange , null, 1.0, DecimalFormat("0"), save)
|
||||
TimeListEdit(context, aapsLogger, dateUtil, view, R.id.target_holder, "TARGET", rh.gs(R.string.target_long_label), currentProfile.targetLow, currentProfile.targetHigh, HardLimits.VERY_HARD_LIMIT_MIN_BG, HardLimits.VERY_HARD_LIMIT_TARGET_BG, 1.0, DecimalFormat("0"), save)
|
||||
} else {
|
||||
TimeListEdit(context, aapsLogger, dateUtil, view, R.id.isf_holder, "ISF", rh.gs(R.string.isf_label), currentProfile.isf, null, Profile.fromMgdlToUnits(HardLimits.MIN_ISF, GlucoseUnit.MMOL), Profile.fromMgdlToUnits(HardLimits.MAX_ISF, GlucoseUnit.MMOL), 0.1, DecimalFormat("0.0"), save)
|
||||
TimeListEdit(context, aapsLogger, dateUtil, view, R.id.target, "TARGET", rh.gs(R.string.target_label), currentProfile.targetLow, currentProfile.targetHigh, Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_TARGET_BG[0], GlucoseUnit.MMOL), Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_TARGET_BG[1], GlucoseUnit.MMOL), 0.1, DecimalFormat("0.0"), save)
|
||||
val isfRange = doubleArrayOf(roundUp(Profile.fromMgdlToUnits(HardLimits.MIN_ISF, GlucoseUnit.MMOL)),
|
||||
roundDown(Profile.fromMgdlToUnits(HardLimits.MAX_ISF, GlucoseUnit.MMOL)))
|
||||
TimeListEdit(context, aapsLogger, dateUtil, view, R.id.isf_holder, "ISF", rh.gs(R.string.isf_long_label), currentProfile.isf, null,isfRange , null, 0.1, DecimalFormat("0.0"), save)
|
||||
val range1 = doubleArrayOf(roundUp(Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_MIN_BG[0], GlucoseUnit.MMOL)),
|
||||
roundDown(Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_MIN_BG[1], GlucoseUnit.MMOL)))
|
||||
val range2 = doubleArrayOf(roundUp(Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_MAX_BG[0], GlucoseUnit.MMOL)),
|
||||
roundDown(Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_MAX_BG[1], GlucoseUnit.MMOL)))
|
||||
Log.i("TimeListEdit", "build: range1" + range1[0] + " " + range1[1] + " range2" + range2[0] + " " + range2[1])
|
||||
TimeListEdit(context, aapsLogger, dateUtil, view, R.id.target_holder, "TARGET", rh.gs(R.string.target_long_label), currentProfile.targetLow, currentProfile.targetHigh, range1 , range2, 0.1, DecimalFormat("0.0"), save)
|
||||
}
|
||||
|
||||
// Spinner
|
||||
|
@ -175,6 +187,8 @@ class LocalProfileFragment : DaggerFragment() {
|
|||
binding.basalGraph.show(ProfileSealed.Pure(it))
|
||||
binding.icGraph.show(ProfileSealed.Pure(it))
|
||||
binding.isfGraph.show(ProfileSealed.Pure(it))
|
||||
binding.targetGraph.show(ProfileSealed.Pure(it))
|
||||
binding.insulinGraph.show(activePlugin.activeInsulin, SafeParse.stringToDouble(binding.dia.text))
|
||||
}
|
||||
|
||||
binding.profileAdd.setOnClickListener {
|
||||
|
@ -265,6 +279,14 @@ class LocalProfileFragment : DaggerFragment() {
|
|||
updateGUI()
|
||||
}
|
||||
|
||||
private fun roundUp(number: Double): Double {
|
||||
return number.toBigDecimal().setScale(1, RoundingMode.UP).toDouble()
|
||||
}
|
||||
|
||||
private fun roundDown(number: Double): Double {
|
||||
return number.toBigDecimal().setScale(1, RoundingMode.DOWN).toDouble()
|
||||
}
|
||||
|
||||
private fun updateGUI() {
|
||||
if (_binding == null) return
|
||||
val isValid = localProfilePlugin.isValidEditState(activity)
|
||||
|
|
|
@ -57,6 +57,8 @@ public class TimeListEdit {
|
|||
private final double step;
|
||||
private final double min;
|
||||
private final double max;
|
||||
private final double min2;
|
||||
private final double max2;
|
||||
private final NumberFormat formatter;
|
||||
private final Runnable save;
|
||||
private LinearLayout layout;
|
||||
|
@ -68,7 +70,7 @@ public class TimeListEdit {
|
|||
Context context,
|
||||
AAPSLogger aapsLogger,
|
||||
DateUtil dateUtil,
|
||||
View view, int resLayoutId, String tagPrefix, String label, JSONArray data1, JSONArray data2, double min, double max, double step, NumberFormat formatter, Runnable save) {
|
||||
View view, int resLayoutId, String tagPrefix, String label, JSONArray data1, JSONArray data2, double[] range1, double[] range2, double step, NumberFormat formatter, Runnable save) {
|
||||
this.context = context;
|
||||
this.aapsLogger = aapsLogger;
|
||||
this.dateUtil = dateUtil;
|
||||
|
@ -79,8 +81,10 @@ public class TimeListEdit {
|
|||
this.data1 = data1;
|
||||
this.data2 = data2;
|
||||
this.step = step;
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
this.min = range1[0];
|
||||
this.max = range1[1];
|
||||
this.min2 = range2 != null ? range2[0] : 0;
|
||||
this.max2 = range2 != null ? range2[1] : 0;
|
||||
this.formatter = formatter;
|
||||
this.save = save;
|
||||
buildView();
|
||||
|
@ -177,7 +181,13 @@ public class TimeListEdit {
|
|||
numberPickers1[position].setTextWatcher(new TextWatcher() {
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
editItem(position, secondFromMidnight(position), SafeParse.stringToDouble(numberPickers1[position].getText()), value2(position));
|
||||
Double value1 = SafeParse.stringToDouble(numberPickers1[position].getText());
|
||||
Double value2 = value2(position);
|
||||
if (data2 != null && value1 > value2) {
|
||||
value2 = value1;
|
||||
numberPickers2[position].setValue(value2);
|
||||
}
|
||||
editItem(position, secondFromMidnight(position), value1, value2);
|
||||
callSave();
|
||||
log();
|
||||
}
|
||||
|
@ -197,7 +207,13 @@ public class TimeListEdit {
|
|||
numberPickers2[position].setTextWatcher(new TextWatcher() {
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
editItem(position, secondFromMidnight(position), value1(position), SafeParse.stringToDouble(numberPickers2[position].getText()));
|
||||
Double value1 = value1(position);
|
||||
Double value2 = SafeParse.stringToDouble(numberPickers2[position].getText());
|
||||
if (data2 != null && value2 < value1) {
|
||||
value1 = value2;
|
||||
numberPickers1[position].setValue(value1);
|
||||
}
|
||||
editItem(position, secondFromMidnight(position), value1, value2);
|
||||
callSave();
|
||||
log();
|
||||
}
|
||||
|
@ -246,7 +262,7 @@ public class TimeListEdit {
|
|||
fillSpinner(timeSpinner, secondFromMidnight(i), previous, next);
|
||||
|
||||
editText1.setParams(value1(i), min, max, step, formatter, false, null);
|
||||
editText2.setParams(value2(i), min, max, step, formatter, false, null);
|
||||
editText2.setParams(value2(i), min2, max2, step, formatter, false, null);
|
||||
|
||||
if (data2 == null) {
|
||||
editText2.setVisibility(View.GONE);
|
||||
|
|
|
@ -35,6 +35,40 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="2dip"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:background="@color/list_delimiter" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:labelFor="@+id/name"
|
||||
android:text="@string/profile_name"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_weight="1"
|
||||
android:ems="10"
|
||||
android:importantForAutofill="no"
|
||||
android:inputType="text" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
@ -152,32 +186,13 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:labelFor="@+id/name"
|
||||
android:text="@string/profile_name"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_weight="1"
|
||||
android:ems="10"
|
||||
android:importantForAutofill="no"
|
||||
android:inputType="text" />
|
||||
|
||||
</LinearLayout>
|
||||
android:gravity="center_horizontal"
|
||||
android:text="@string/dia_label"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="20sp" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
@ -210,6 +225,12 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<info.nightscout.androidaps.plugins.insulin.ActivityGraph
|
||||
android:id="@+id/insulin_graph"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="100dip"
|
||||
android:layout_margin="20dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
|
@ -277,10 +298,22 @@
|
|||
|
||||
<LinearLayout
|
||||
android:id="@+id/target"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/target_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:orientation="vertical">
|
||||
android:orientation="vertical" />
|
||||
|
||||
<info.nightscout.androidaps.utils.ui.TargetBgProfileGraph
|
||||
android:id="@+id/target_graph"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="100dip"
|
||||
android:layout_margin="20dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
|
|
@ -151,6 +151,7 @@ class ProfileViewerDialog : DaggerDialogFragment() {
|
|||
binding.basalGraph.show(profile1, profile2)
|
||||
binding.isfGraph.show(profile1, profile2)
|
||||
binding.icGraph.show(profile1, profile2)
|
||||
binding.targetGraph.show(profile1, profile2)
|
||||
}
|
||||
|
||||
binding.noprofile.visibility = View.GONE
|
||||
|
@ -171,6 +172,7 @@ class ProfileViewerDialog : DaggerDialogFragment() {
|
|||
binding.basalGraph.show(it)
|
||||
binding.isfGraph.show(it)
|
||||
binding.icGraph.show(it)
|
||||
binding.targetGraph.show(it)
|
||||
|
||||
binding.noprofile.visibility = View.GONE
|
||||
val validity = it.isValid("ProfileViewDialog", activePlugin.activePump, config, rh, rxBus, hardLimits, false)
|
||||
|
|
|
@ -43,7 +43,7 @@ public class AreaGraphSeries<E extends DoubleDataPoint> extends BaseSeries<E> {
|
|||
/**
|
||||
* the thickness of the line.
|
||||
* This option will be ignored if you are
|
||||
* using a custom paint via {@link #setCustomPaint(android.graphics.Paint)}
|
||||
* using a custom paint via {@link #setCustomPaint(Paint)}
|
||||
*/
|
||||
private int thickness = 5;
|
||||
|
||||
|
@ -342,7 +342,7 @@ public class AreaGraphSeries<E extends DoubleDataPoint> extends BaseSeries<E> {
|
|||
/**
|
||||
* the thickness of the line.
|
||||
* This option will be ignored if you are
|
||||
* using a custom paint via {@link #setCustomPaint(android.graphics.Paint)}
|
||||
* using a custom paint via {@link #setCustomPaint(Paint)}
|
||||
*
|
||||
* @return the thickness of the line
|
||||
*/
|
||||
|
@ -353,7 +353,7 @@ public class AreaGraphSeries<E extends DoubleDataPoint> extends BaseSeries<E> {
|
|||
/**
|
||||
* the thickness of the line.
|
||||
* This option will be ignored if you are
|
||||
* using a custom paint via {@link #setCustomPaint(android.graphics.Paint)}
|
||||
* using a custom paint via {@link #setCustomPaint(Paint)}
|
||||
*
|
||||
* @param thickness thickness of the line
|
||||
*/
|
|
@ -2,12 +2,14 @@ package info.nightscout.androidaps.utils.ui
|
|||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import com.jjoe64.graphview.DefaultLabelFormatter
|
||||
import com.jjoe64.graphview.GraphView
|
||||
import com.jjoe64.graphview.series.DataPoint
|
||||
import com.jjoe64.graphview.series.LineGraphSeries
|
||||
import info.nightscout.androidaps.core.R
|
||||
import info.nightscout.androidaps.interfaces.Profile
|
||||
import info.nightscout.androidaps.utils.Round
|
||||
import java.text.NumberFormat
|
||||
import java.util.ArrayList
|
||||
import kotlin.math.max
|
||||
|
||||
|
@ -36,6 +38,10 @@ class BasalProfileGraph : GraphView {
|
|||
viewport.setMaxY(Round.ceilTo(profile.getMaxDailyBasal() * 1.1, 0.5))
|
||||
gridLabelRenderer.numHorizontalLabels = 13
|
||||
gridLabelRenderer.verticalLabelsColor = basalSeries.color
|
||||
|
||||
val nf: NumberFormat = NumberFormat.getInstance()
|
||||
nf.maximumFractionDigits = 1
|
||||
gridLabelRenderer.setLabelFormatter(DefaultLabelFormatter(nf, nf))
|
||||
}
|
||||
|
||||
fun show(profile1: Profile, profile2: Profile) {
|
||||
|
|
|
@ -2,12 +2,14 @@ package info.nightscout.androidaps.utils.ui
|
|||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import com.jjoe64.graphview.DefaultLabelFormatter
|
||||
import com.jjoe64.graphview.GraphView
|
||||
import com.jjoe64.graphview.series.DataPoint
|
||||
import com.jjoe64.graphview.series.LineGraphSeries
|
||||
import info.nightscout.androidaps.core.R
|
||||
import info.nightscout.androidaps.interfaces.Profile
|
||||
import info.nightscout.androidaps.utils.Round
|
||||
import java.text.NumberFormat
|
||||
import java.util.*
|
||||
import kotlin.math.max
|
||||
|
||||
|
@ -39,6 +41,10 @@ class IcProfileGraph : GraphView {
|
|||
viewport.setMaxY(Round.ceilTo(maxIc * 1.1, 0.5))
|
||||
gridLabelRenderer.numHorizontalLabels = 13
|
||||
gridLabelRenderer.verticalLabelsColor = icSeries.color
|
||||
|
||||
val nf: NumberFormat = NumberFormat.getInstance()
|
||||
nf.maximumFractionDigits = 1
|
||||
gridLabelRenderer.setLabelFormatter(DefaultLabelFormatter(nf, nf))
|
||||
}
|
||||
|
||||
fun show(profile1: Profile, profile2: Profile) {
|
||||
|
|
|
@ -2,13 +2,14 @@ package info.nightscout.androidaps.utils.ui
|
|||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import com.jjoe64.graphview.DefaultLabelFormatter
|
||||
import com.jjoe64.graphview.GraphView
|
||||
import com.jjoe64.graphview.series.DataPoint
|
||||
import com.jjoe64.graphview.series.LineGraphSeries
|
||||
import info.nightscout.androidaps.core.R
|
||||
import info.nightscout.androidaps.interfaces.Profile
|
||||
import info.nightscout.androidaps.utils.Round
|
||||
import java.util.ArrayList
|
||||
import java.text.NumberFormat
|
||||
import kotlin.math.max
|
||||
|
||||
class IsfProfileGraph : GraphView {
|
||||
|
@ -31,15 +32,20 @@ class IsfProfileGraph : GraphView {
|
|||
val isfSeries: LineGraphSeries<DataPoint> = LineGraphSeries(isfDataPoints)
|
||||
addSeries(isfSeries)
|
||||
isfSeries.thickness = 8
|
||||
isfSeries.isDrawBackground = false
|
||||
viewport.isXAxisBoundsManual = true
|
||||
viewport.setMinX(0.0)
|
||||
viewport.setMaxX(24.0)
|
||||
viewport.isYAxisBoundsManual = true
|
||||
viewport.setMinY(0.0)
|
||||
viewport.setMaxY(Round.ceilTo(maxIsf * 1.1, 0.5))
|
||||
val maxY = Round.ceilTo(maxIsf * 1.1, 0.5)
|
||||
viewport.setMaxY(maxY)
|
||||
gridLabelRenderer.numHorizontalLabels = 13
|
||||
gridLabelRenderer.labelVerticalWidth = 40
|
||||
gridLabelRenderer.verticalLabelsColor = isfSeries.color
|
||||
|
||||
val nf: NumberFormat = NumberFormat.getInstance()
|
||||
nf.maximumFractionDigits = 1
|
||||
gridLabelRenderer.setLabelFormatter(DefaultLabelFormatter(nf, nf))
|
||||
}
|
||||
|
||||
fun show(profile1: Profile, profile2: Profile) {
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
package info.nightscout.androidaps.utils.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import com.jjoe64.graphview.DefaultLabelFormatter
|
||||
import com.jjoe64.graphview.GraphView
|
||||
import info.nightscout.androidaps.core.R
|
||||
import info.nightscout.androidaps.interfaces.GlucoseUnit
|
||||
import info.nightscout.androidaps.interfaces.Profile
|
||||
import info.nightscout.androidaps.utils.Round
|
||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.AreaGraphSeries
|
||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DoubleDataPoint
|
||||
import java.text.NumberFormat
|
||||
import java.util.ArrayList
|
||||
import kotlin.math.max
|
||||
|
||||
class TargetBgProfileGraph : GraphView {
|
||||
|
||||
constructor(context: Context?) : super(context)
|
||||
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
|
||||
|
||||
fun show(profile: Profile) {
|
||||
|
||||
removeAllSeries()
|
||||
val targetArray: MutableList<DoubleDataPoint> = ArrayList()
|
||||
var maxValue = 0.0
|
||||
val units = profile.units
|
||||
for (hour in 0..23) {
|
||||
val valueLow = Profile.fromMgdlToUnits(profile.getTargetLowMgdlTimeFromMidnight(hour * 60 * 60), units)
|
||||
val valueHigh = Profile.fromMgdlToUnits(profile.getTargetHighMgdlTimeFromMidnight(hour * 60 * 60), units)
|
||||
maxValue = max(maxValue, valueHigh)
|
||||
targetArray.add(DoubleDataPoint(hour.toDouble(), valueLow, valueHigh))
|
||||
targetArray.add(DoubleDataPoint((hour + 1).toDouble(), valueLow, valueHigh))
|
||||
}
|
||||
val targetDataPoints: Array<DoubleDataPoint> = Array(targetArray.size) { i -> targetArray[i] }
|
||||
val targetSeries: AreaGraphSeries<DoubleDataPoint> = AreaGraphSeries(targetDataPoints)
|
||||
addSeries(targetSeries)
|
||||
targetSeries.isDrawBackground = true
|
||||
|
||||
viewport.isXAxisBoundsManual = true
|
||||
viewport.setMinX(0.0)
|
||||
viewport.setMaxX(24.0)
|
||||
viewport.isYAxisBoundsManual = true
|
||||
viewport.setMinY(0.0)
|
||||
viewport.setMaxY(Round.ceilTo(maxValue * 1.1, 0.5))
|
||||
gridLabelRenderer.numHorizontalLabels = 13
|
||||
gridLabelRenderer.verticalLabelsColor = targetSeries.color
|
||||
|
||||
val nf: NumberFormat = NumberFormat.getInstance()
|
||||
nf.maximumFractionDigits = if (units == GlucoseUnit.MMOL) 1 else 0
|
||||
gridLabelRenderer.setLabelFormatter(DefaultLabelFormatter(nf, nf))
|
||||
}
|
||||
|
||||
fun show(profile1: Profile, profile2: Profile) {
|
||||
|
||||
removeAllSeries()
|
||||
val targetArray1: MutableList<DoubleDataPoint> = ArrayList()
|
||||
var maxValue = 0.0
|
||||
val units = profile1.units
|
||||
for (hour in 0..23) {
|
||||
val valueLow = Profile.fromMgdlToUnits(profile1.getTargetLowMgdlTimeFromMidnight(hour * 60 * 60), units)
|
||||
val valueHigh = Profile.fromMgdlToUnits(profile1.getTargetHighMgdlTimeFromMidnight(hour * 60 * 60), units)
|
||||
maxValue = max(maxValue, valueHigh)
|
||||
targetArray1.add(DoubleDataPoint(hour.toDouble(), valueLow, valueHigh))
|
||||
targetArray1.add(DoubleDataPoint((hour + 1).toDouble(), valueLow, valueHigh))
|
||||
}
|
||||
val targetDataPoints1: Array<DoubleDataPoint> = Array(targetArray1.size) { i -> targetArray1[i] }
|
||||
val targetSeries1: AreaGraphSeries<DoubleDataPoint> = AreaGraphSeries(targetDataPoints1)
|
||||
addSeries(targetSeries1)
|
||||
targetSeries1.isDrawBackground = true
|
||||
|
||||
val targetArray2: MutableList<DoubleDataPoint> = ArrayList()
|
||||
for (hour in 0..23) {
|
||||
val valueLow = Profile.fromMgdlToUnits(profile2.getTargetLowMgdlTimeFromMidnight(hour * 60 * 60), units)
|
||||
val valueHigh = Profile.fromMgdlToUnits(profile2.getTargetHighMgdlTimeFromMidnight(hour * 60 * 60), units)
|
||||
maxValue = max(maxValue, valueHigh)
|
||||
targetArray2.add(DoubleDataPoint(hour.toDouble(), valueLow, valueHigh))
|
||||
targetArray2.add(DoubleDataPoint((hour + 1).toDouble(), valueLow, valueHigh))
|
||||
}
|
||||
val targetDataPoints2: Array<DoubleDataPoint> = Array(targetArray2.size) { i -> targetArray2[i] }
|
||||
val targetSeries2: AreaGraphSeries<DoubleDataPoint> = AreaGraphSeries(targetDataPoints2)
|
||||
addSeries(targetSeries2)
|
||||
targetSeries2.isDrawBackground = false
|
||||
targetSeries2.color = context.getColor(R.color.examinedProfile)
|
||||
|
||||
viewport.isXAxisBoundsManual = true
|
||||
viewport.setMinX(0.0)
|
||||
viewport.setMaxX(24.0)
|
||||
viewport.isYAxisBoundsManual = true
|
||||
viewport.setMinY(0.0)
|
||||
viewport.setMaxY(Round.ceilTo(maxValue * 1.1, 0.5))
|
||||
gridLabelRenderer.numHorizontalLabels = 13
|
||||
gridLabelRenderer.verticalLabelsColor = targetSeries1.color
|
||||
|
||||
val nf: NumberFormat = NumberFormat.getInstance()
|
||||
nf.maximumFractionDigits = if (units == GlucoseUnit.MMOL) 1 else 0
|
||||
gridLabelRenderer.setLabelFormatter(DefaultLabelFormatter(nf, nf))
|
||||
}
|
||||
}
|
|
@ -434,6 +434,12 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<info.nightscout.androidaps.utils.ui.TargetBgProfileGraph
|
||||
android:id="@+id/target_graph"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="100dip"
|
||||
android:layout_margin="20dp" />
|
||||
|
||||
<include
|
||||
android:id="@+id/close_layout"
|
||||
layout="@layout/close" />
|
||||
|
|
|
@ -111,6 +111,11 @@
|
|||
<string name="isf_label">ISF</string>
|
||||
<string name="basal_label">Basal</string>
|
||||
<string name="target_label">Target</string>
|
||||
<string name="dia_long_label">Duration of Insulin Action</string>
|
||||
<string name="ic_long_label">Insulin to Carb ratio</string>
|
||||
<string name="isf_long_label">Insulin Sensitivity Factor</string>
|
||||
<string name="basal_long_label">Basel rate</string>
|
||||
<string name="target_long_label">Blood Glucose Target</string>
|
||||
<string name="initializing">Initializing ...</string>
|
||||
<string name="serialnumber">Serial number</string>
|
||||
<string name="battery_label">Battery</string>
|
||||
|
|
Loading…
Reference in a new issue