From e9b900d74a50d003b3eafa40f5bee3972730ddbd Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Sun, 8 Jan 2017 23:10:27 +0100 Subject: [PATCH] show predictions in graph --- .idea/misc.xml | 2 +- .../androidaps/data/PumpEnactResult.java | 39 +--------- .../androidaps/plugins/Loop/APSResult.java | 32 +------- .../DetermineBasalAdapterAMAJS.java | 3 +- .../OpenAPSAMA/DetermineBasalResultAMA.java | 75 ++++++++++++++++++- .../OpenAPSMA/DetermineBasalResultMA.java | 31 -------- .../plugins/Overview/OverviewFragment.java | 68 ++++++++++++++--- app/src/main/res/layout/overview_fragment.xml | 18 ++++- 8 files changed, 152 insertions(+), 116 deletions(-) diff --git a/.idea/misc.xml b/.idea/misc.xml index 5d19981032..fbb68289f4 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -37,7 +37,7 @@ - + diff --git a/app/src/main/java/info/nightscout/androidaps/data/PumpEnactResult.java b/app/src/main/java/info/nightscout/androidaps/data/PumpEnactResult.java index 38a340acb0..7ce7c14678 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/PumpEnactResult.java +++ b/app/src/main/java/info/nightscout/androidaps/data/PumpEnactResult.java @@ -14,7 +14,7 @@ import info.nightscout.client.data.NSProfile; import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.Round; -public class PumpEnactResult extends Object implements Parcelable { +public class PumpEnactResult extends Object { public boolean success = false; // request was processed successfully (but possible no change was needed) public boolean enacted = false; // request was processed successfully and change has been made public String comment = ""; @@ -85,43 +85,6 @@ public class PumpEnactResult extends Object implements Parcelable { return Html.fromHtml(ret); } - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(success ? 1 : 0); - dest.writeInt(enacted ? 1 : 0); - dest.writeInt(isPercent ? 1 : 0); - dest.writeString(comment); - dest.writeInt(duration); - dest.writeDouble(absolute); - dest.writeInt(percent); - } - - public final Parcelable.Creator CREATOR = new Parcelable.Creator() { - public PumpEnactResult createFromParcel(Parcel in) { - return new PumpEnactResult(in); - } - - public PumpEnactResult[] newArray(int size) { - return new PumpEnactResult[size]; - } - }; - - protected PumpEnactResult(Parcel in) { - success = in.readInt() == 1 ? true : false; - enacted = in.readInt() == 1 ? true : false; - isPercent = in.readInt() == 1 ? true : false; - duration = in.readInt(); - comment = in.readString(); - absolute = in.readDouble(); - percent = in.readInt(); - - } - public PumpEnactResult() { } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/APSResult.java b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/APSResult.java index 58ab564f6e..69e161524f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/APSResult.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/APSResult.java @@ -16,7 +16,7 @@ import info.nightscout.utils.DecimalFormatter; /** * Created by mike on 09.06.2016. */ -public class APSResult implements Parcelable { +public class APSResult { public String reason; public double rate; public int duration; @@ -51,36 +51,6 @@ public class APSResult implements Parcelable { return Html.fromHtml(MainApp.sResources.getString(R.string.nochangerequested)); } - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeString(reason); - dest.writeDouble(rate); - dest.writeInt(duration); - dest.writeInt(changeRequested ? 1 : 0); - } - - public final Parcelable.Creator CREATOR = new Parcelable.Creator() { - public APSResult createFromParcel(Parcel in) { - return new APSResult(in); - } - - public APSResult[] newArray(int size) { - return new APSResult[size]; - } - }; - - protected APSResult(Parcel in) { - reason = in.readString(); - rate = in.readDouble(); - duration = in.readInt(); - changeRequested = in.readInt() == 1; - } - public APSResult() { } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalAdapterAMAJS.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalAdapterAMAJS.java index 77e7babd51..7cb680e68c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalAdapterAMAJS.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalAdapterAMAJS.java @@ -93,8 +93,7 @@ public class DetermineBasalAdapterAMAJS { String ret = mV8rt.executeStringScript("JSON.stringify(rT);"); - if (Config.logAPSResult) - log.debug("Result: " + ret); + log.debug("Result: " + ret); V8Object v8ObjectReuslt = mV8rt.getObject("rT"); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalResultAMA.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalResultAMA.java index 38d13aad2a..ee877c8260 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalResultAMA.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSAMA/DetermineBasalResultAMA.java @@ -5,20 +5,27 @@ import android.os.Parcelable; import com.eclipsesource.v8.V8Object; +import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.plugins.Loop.APSResult; import info.nightscout.androidaps.data.IobTotal; public class DetermineBasalResultAMA extends APSResult { - + public Date date; public JSONObject json = new JSONObject(); public double eventualBG; public double snoozeBG; public IobTotal iob; public DetermineBasalResultAMA(V8Object result, JSONObject j) { + date = new Date(); json = j; if (result.contains("error")) { reason = result.getString("error"); @@ -69,6 +76,7 @@ public class DetermineBasalResultAMA extends APSResult { } newResult.eventualBG = eventualBG; newResult.snoozeBG = snoozeBG; + newResult.date = date; return newResult; } @@ -83,4 +91,69 @@ public class DetermineBasalResultAMA extends APSResult { return null; } + public List getPredictions() { + List array = new ArrayList<>(); + try { + long startTime = date.getTime(); + if (json.has("predBGs")) { + JSONObject predBGs = json.getJSONObject("predBGs"); + if (predBGs.has("IOB")) { + JSONArray iob = predBGs.getJSONArray("IOB"); + for (int i = 1; i < iob.length(); i ++) { + BgReading bg = new BgReading(); + bg.value = iob.getInt(i); + bg.timeIndex = startTime + i * 5 * 60 * 1000L; + array.add(bg); + } + } + if (predBGs.has("aCOB")) { + JSONArray iob = predBGs.getJSONArray("aCOB"); + for (int i = 1; i < iob.length(); i ++) { + BgReading bg = new BgReading(); + bg.value = iob.getInt(i); + bg.timeIndex = startTime + i * 5 * 60 * 1000L; + array.add(bg); + } + } + if (predBGs.has("COB")) { + JSONArray iob = predBGs.getJSONArray("COB"); + for (int i = 1; i < iob.length(); i ++) { + BgReading bg = new BgReading(); + bg.value = iob.getInt(i); + bg.timeIndex = startTime + i * 5 * 60 * 1000L; + array.add(bg); + } + } + } + } catch (JSONException e) { + e.printStackTrace(); + } + return array; + } + + public long getLatestPredictionsTime() { + long latest = 0; + try { + long startTime = date.getTime(); + if (json.has("predBGs")) { + JSONObject predBGs = json.getJSONObject("predBGs"); + if (predBGs.has("IOB")) { + JSONArray iob = predBGs.getJSONArray("IOB"); + latest = Math.max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L); + } + if (predBGs.has("aCOB")) { + JSONArray iob = predBGs.getJSONArray("aCOB"); + latest = Math.max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L); + } + if (predBGs.has("COB")) { + JSONArray iob = predBGs.getJSONArray("COB"); + latest = Math.max(latest, startTime + (iob.length() - 1) * 5 * 60 * 1000L); + } + } + } catch (JSONException e) { + e.printStackTrace(); + } + + return latest; + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalResultMA.java b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalResultMA.java index 662cf82600..cb0e67249f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalResultMA.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/OpenAPSMA/DetermineBasalResultMA.java @@ -53,37 +53,6 @@ public class DetermineBasalResultMA extends APSResult { result.release(); } - @Override - public void writeToParcel(Parcel dest, int flags) { - super.writeToParcel(dest, flags); - dest.writeString(json.toString()); - dest.writeDouble(eventualBG); - dest.writeDouble(snoozeBG); - dest.writeString(mealAssist); - } - - public final Parcelable.Creator CREATOR = new Parcelable.Creator() { - public DetermineBasalResultMA createFromParcel(Parcel in) { - return new DetermineBasalResultMA(in); - } - - public DetermineBasalResultMA[] newArray(int size) { - return new DetermineBasalResultMA[size]; - } - }; - - private DetermineBasalResultMA(Parcel in) { - super(in); - try { - json = new JSONObject(in.readString()); - } catch (JSONException e) { - e.printStackTrace(); - } - eventualBG = in.readDouble(); - snoozeBG = in.readDouble(); - mealAssist = in.readString(); - } - public DetermineBasalResultMA() { } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java index 8c099d2c1e..8b5ffc112f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java @@ -22,6 +22,8 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; +import android.widget.CheckBox; +import android.widget.CompoundButton; import android.widget.LinearLayout; import android.widget.TextView; @@ -50,6 +52,7 @@ import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.GlucoseStatus; +import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.TempBasal; @@ -69,12 +72,13 @@ import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.Loop.LoopPlugin; import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification; import info.nightscout.androidaps.plugins.Objectives.ObjectivesPlugin; -import info.nightscout.androidaps.data.IobTotal; +import info.nightscout.androidaps.plugins.OpenAPSAMA.DetermineBasalResultAMA; +import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin; import info.nightscout.androidaps.plugins.Overview.Dialogs.NewTreatmentDialog; import info.nightscout.androidaps.plugins.Overview.Dialogs.WizardDialog; -import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.Overview.graphExtensions.PointsWithLabelGraphSeries; import info.nightscout.androidaps.plugins.Overview.graphExtensions.TimeAsXAxisLabelFormatter; import info.nightscout.client.data.NSProfile; import info.nightscout.utils.BolusWizard; @@ -106,6 +110,7 @@ public class OverviewFragment extends Fragment { TextView iobView; TextView apsModeView; GraphView bgGraph; + CheckBox showPredictionView; RecyclerView notificationsView; LinearLayoutManager llm; @@ -162,12 +167,25 @@ public class OverviewFragment extends Fragment { acceptTempLayout = (LinearLayout) view.findViewById(R.id.overview_accepttemplayout); quickWizardButton = (Button) view.findViewById(R.id.overview_quickwizard); quickWizardLayout = (LinearLayout) view.findViewById(R.id.overview_quickwizardlayout); + showPredictionView = (CheckBox) view.findViewById(R.id.overview_showprediction); notificationsView = (RecyclerView) view.findViewById(R.id.overview_notifications); notificationsView.setHasFixedSize(true); llm = new LinearLayoutManager(view.getContext()); notificationsView.setLayoutManager(llm); + showPredictionView.setChecked(prefs.getBoolean("showprediction", false)); + + showPredictionView.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + SharedPreferences.Editor editor = prefs.edit(); + editor.putBoolean("showprediction", showPredictionView.isChecked()); + editor.apply(); + updateGUI(); + } + }); + treatmentButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { @@ -613,6 +631,13 @@ public class OverviewFragment extends Fragment { + getString(R.string.basal) + ": " + DecimalFormatter.to2Decimal(basalIob.basaliob) + "U)"; iobView.setText(iobtext); + boolean showPrediction = showPredictionView.isChecked() && finalLastRun != null && finalLastRun.constraintsProcessed.getClass().equals(DetermineBasalResultAMA.class); + if (MainApp.getSpecificPlugin(OpenAPSAMAPlugin.class) != null && MainApp.getSpecificPlugin(OpenAPSAMAPlugin.class).isEnabled(PluginBase.APS)) { + showPredictionView.setVisibility(View.VISIBLE); + } else { + showPredictionView.setVisibility(View.GONE); + } + // ****** GRAPH ******* // allign to hours @@ -623,9 +648,21 @@ public class OverviewFragment extends Fragment { calendar.set(Calendar.MINUTE, 0); calendar.add(Calendar.HOUR, 1); - int hoursToFetch = 6; - long toTime = calendar.getTimeInMillis() + 100000; // little bit more to avoid wrong rounding - long fromTime = toTime - hoursToFetch * 60 * 60 * 1000L; + int hoursToFetch; + long toTime; + long fromTime; + long endTime; + if (showPrediction) { + hoursToFetch = 3; + toTime = calendar.getTimeInMillis() + 100000; // little bit more to avoid wrong rounding + fromTime = toTime - hoursToFetch * 60 * 60 * 1000L; + endTime = toTime + hoursToFetch * 60 * 60 * 1000L; + } else { + hoursToFetch = 6; + toTime = calendar.getTimeInMillis() + 100000; // little bit more to avoid wrong rounding + fromTime = toTime - hoursToFetch * 60 * 60 * 1000L; + endTime = toTime; + } Double lowLine = SafeParse.stringToDouble(prefs.getString("low_mark", "0")); Double highLine = SafeParse.stringToDouble(prefs.getString("high_mark", "0")); @@ -644,6 +681,7 @@ public class OverviewFragment extends Fragment { LineGraphSeries seriesNow = null; PointsGraphSeries seriesInRage = null; PointsGraphSeries seriesOutOfRange = null; + PointsGraphSeries predSeries = null; PointsWithLabelGraphSeries seriesTreatments = null; // remove old data from graph @@ -652,11 +690,11 @@ public class OverviewFragment extends Fragment { // **** HIGH and LOW targets graph **** DataPoint[] lowDataPoints = new DataPoint[]{ new DataPoint(fromTime, lowLine), - new DataPoint(toTime, lowLine) + new DataPoint(endTime, lowLine) }; DataPoint[] highDataPoints = new DataPoint[]{ new DataPoint(fromTime, highLine), - new DataPoint(toTime, highLine) + new DataPoint(endTime, highLine) }; bgGraph.addSeries(seriesLow = new LineGraphSeries(lowDataPoints)); seriesLow.setColor(Color.RED); @@ -673,7 +711,6 @@ public class OverviewFragment extends Fragment { public boolean isTempBasal = false; } - Double maxAllowedBasal = MainApp.getConfigBuilder().applyBasalConstraints(Constants.basalAbsoluteOnlyForCheckLimit); Double maxBasalValueFound = 0d; long now = new Date().getTime(); @@ -702,7 +739,7 @@ public class OverviewFragment extends Fragment { } // set manual x bounds to have nice steps - bgGraph.getViewport().setMaxX(toTime); + bgGraph.getViewport().setMaxX(endTime); bgGraph.getViewport().setMinX(fromTime); bgGraph.getViewport().setXAxisBoundsManual(true); bgGraph.getGridLabelRenderer().setLabelFormatter(new TimeAsXAxisLabelFormatter(getActivity(), "HH")); @@ -751,6 +788,19 @@ public class OverviewFragment extends Fragment { seriesOutOfRange.setColor(Color.RED); } + if (showPrediction) { + DetermineBasalResultAMA amaResult = (DetermineBasalResultAMA) finalLastRun.constraintsProcessed; + List predArray = amaResult.getPredictions(); + BgReading[] pred = new BgReading[predArray.size()]; + pred = predArray.toArray(pred); + if (pred.length > 0) { + bgGraph.addSeries(predSeries = new PointsGraphSeries(pred)); + predSeries.setShape(PointsGraphSeries.Shape.POINT); + predSeries.setSize(4); + predSeries.setColor(Color.MAGENTA); + } + } + // **** NOW line **** DataPoint[] nowPoints = new DataPoint[]{ new DataPoint(now, 0), diff --git a/app/src/main/res/layout/overview_fragment.xml b/app/src/main/res/layout/overview_fragment.xml index 775f0dea71..474d38f0c0 100644 --- a/app/src/main/res/layout/overview_fragment.xml +++ b/app/src/main/res/layout/overview_fragment.xml @@ -150,10 +150,22 @@ android:layout_gravity="center_horizontal" android:textAppearance="?android:attr/textAppearanceSmall" /> - + android:layout_height="match_parent"> + + + + +