show predictions in graph

This commit is contained in:
Milos Kozak 2017-01-08 23:10:27 +01:00
parent 93b80746c6
commit e9b900d74a
8 changed files with 152 additions and 116 deletions

View file

@ -37,7 +37,7 @@
<ConfirmationsSetting value="0" id="Add" /> <ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" /> <ConfirmationsSetting value="0" id="Remove" />
</component> </component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" /> <output url="file://$PROJECT_DIR$/build/classes" />
</component> </component>
<component name="ProjectType"> <component name="ProjectType">

View file

@ -14,7 +14,7 @@ import info.nightscout.client.data.NSProfile;
import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.Round; 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 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 boolean enacted = false; // request was processed successfully and change has been made
public String comment = ""; public String comment = "";
@ -85,43 +85,6 @@ public class PumpEnactResult extends Object implements Parcelable {
return Html.fromHtml(ret); 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<PumpEnactResult> CREATOR = new Parcelable.Creator<PumpEnactResult>() {
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() { public PumpEnactResult() {
} }

View file

@ -16,7 +16,7 @@ import info.nightscout.utils.DecimalFormatter;
/** /**
* Created by mike on 09.06.2016. * Created by mike on 09.06.2016.
*/ */
public class APSResult implements Parcelable { public class APSResult {
public String reason; public String reason;
public double rate; public double rate;
public int duration; public int duration;
@ -51,36 +51,6 @@ public class APSResult implements Parcelable {
return Html.fromHtml(MainApp.sResources.getString(R.string.nochangerequested)); 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<APSResult> CREATOR = new Parcelable.Creator<APSResult>() {
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() { public APSResult() {
} }

View file

@ -93,8 +93,7 @@ public class DetermineBasalAdapterAMAJS {
String ret = mV8rt.executeStringScript("JSON.stringify(rT);"); String ret = mV8rt.executeStringScript("JSON.stringify(rT);");
if (Config.logAPSResult) log.debug("Result: " + ret);
log.debug("Result: " + ret);
V8Object v8ObjectReuslt = mV8rt.getObject("rT"); V8Object v8ObjectReuslt = mV8rt.getObject("rT");

View file

@ -5,20 +5,27 @@ import android.os.Parcelable;
import com.eclipsesource.v8.V8Object; import com.eclipsesource.v8.V8Object;
import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; 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.plugins.Loop.APSResult;
import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.IobTotal;
public class DetermineBasalResultAMA extends APSResult { public class DetermineBasalResultAMA extends APSResult {
public Date date;
public JSONObject json = new JSONObject(); public JSONObject json = new JSONObject();
public double eventualBG; public double eventualBG;
public double snoozeBG; public double snoozeBG;
public IobTotal iob; public IobTotal iob;
public DetermineBasalResultAMA(V8Object result, JSONObject j) { public DetermineBasalResultAMA(V8Object result, JSONObject j) {
date = new Date();
json = j; json = j;
if (result.contains("error")) { if (result.contains("error")) {
reason = result.getString("error"); reason = result.getString("error");
@ -69,6 +76,7 @@ public class DetermineBasalResultAMA extends APSResult {
} }
newResult.eventualBG = eventualBG; newResult.eventualBG = eventualBG;
newResult.snoozeBG = snoozeBG; newResult.snoozeBG = snoozeBG;
newResult.date = date;
return newResult; return newResult;
} }
@ -83,4 +91,69 @@ public class DetermineBasalResultAMA extends APSResult {
return null; return null;
} }
public List<BgReading> getPredictions() {
List<BgReading> 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;
}
} }

View file

@ -53,37 +53,6 @@ public class DetermineBasalResultMA extends APSResult {
result.release(); 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<DetermineBasalResultMA> CREATOR = new Parcelable.Creator<DetermineBasalResultMA>() {
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() { public DetermineBasalResultMA() {
} }

View file

@ -22,6 +22,8 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
@ -50,6 +52,7 @@ import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.GlucoseStatus; import info.nightscout.androidaps.data.GlucoseStatus;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.TempBasal; 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.LoopPlugin;
import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification; import info.nightscout.androidaps.plugins.Loop.events.EventNewOpenLoopNotification;
import info.nightscout.androidaps.plugins.Objectives.ObjectivesPlugin; 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.NewTreatmentDialog;
import info.nightscout.androidaps.plugins.Overview.Dialogs.WizardDialog; 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.EventDismissNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; 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.androidaps.plugins.Overview.graphExtensions.TimeAsXAxisLabelFormatter;
import info.nightscout.client.data.NSProfile; import info.nightscout.client.data.NSProfile;
import info.nightscout.utils.BolusWizard; import info.nightscout.utils.BolusWizard;
@ -106,6 +110,7 @@ public class OverviewFragment extends Fragment {
TextView iobView; TextView iobView;
TextView apsModeView; TextView apsModeView;
GraphView bgGraph; GraphView bgGraph;
CheckBox showPredictionView;
RecyclerView notificationsView; RecyclerView notificationsView;
LinearLayoutManager llm; LinearLayoutManager llm;
@ -162,12 +167,25 @@ public class OverviewFragment extends Fragment {
acceptTempLayout = (LinearLayout) view.findViewById(R.id.overview_accepttemplayout); acceptTempLayout = (LinearLayout) view.findViewById(R.id.overview_accepttemplayout);
quickWizardButton = (Button) view.findViewById(R.id.overview_quickwizard); quickWizardButton = (Button) view.findViewById(R.id.overview_quickwizard);
quickWizardLayout = (LinearLayout) view.findViewById(R.id.overview_quickwizardlayout); 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 = (RecyclerView) view.findViewById(R.id.overview_notifications);
notificationsView.setHasFixedSize(true); notificationsView.setHasFixedSize(true);
llm = new LinearLayoutManager(view.getContext()); llm = new LinearLayoutManager(view.getContext());
notificationsView.setLayoutManager(llm); 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() { treatmentButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
@ -613,6 +631,13 @@ public class OverviewFragment extends Fragment {
+ getString(R.string.basal) + ": " + DecimalFormatter.to2Decimal(basalIob.basaliob) + "U)"; + getString(R.string.basal) + ": " + DecimalFormatter.to2Decimal(basalIob.basaliob) + "U)";
iobView.setText(iobtext); 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 ******* // ****** GRAPH *******
// allign to hours // allign to hours
@ -623,9 +648,21 @@ public class OverviewFragment extends Fragment {
calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.MINUTE, 0);
calendar.add(Calendar.HOUR, 1); calendar.add(Calendar.HOUR, 1);
int hoursToFetch = 6; int hoursToFetch;
long toTime = calendar.getTimeInMillis() + 100000; // little bit more to avoid wrong rounding long toTime;
long fromTime = toTime - hoursToFetch * 60 * 60 * 1000L; 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 lowLine = SafeParse.stringToDouble(prefs.getString("low_mark", "0"));
Double highLine = SafeParse.stringToDouble(prefs.getString("high_mark", "0")); Double highLine = SafeParse.stringToDouble(prefs.getString("high_mark", "0"));
@ -644,6 +681,7 @@ public class OverviewFragment extends Fragment {
LineGraphSeries<DataPoint> seriesNow = null; LineGraphSeries<DataPoint> seriesNow = null;
PointsGraphSeries<BgReading> seriesInRage = null; PointsGraphSeries<BgReading> seriesInRage = null;
PointsGraphSeries<BgReading> seriesOutOfRange = null; PointsGraphSeries<BgReading> seriesOutOfRange = null;
PointsGraphSeries<BgReading> predSeries = null;
PointsWithLabelGraphSeries<Treatment> seriesTreatments = null; PointsWithLabelGraphSeries<Treatment> seriesTreatments = null;
// remove old data from graph // remove old data from graph
@ -652,11 +690,11 @@ public class OverviewFragment extends Fragment {
// **** HIGH and LOW targets graph **** // **** HIGH and LOW targets graph ****
DataPoint[] lowDataPoints = new DataPoint[]{ DataPoint[] lowDataPoints = new DataPoint[]{
new DataPoint(fromTime, lowLine), new DataPoint(fromTime, lowLine),
new DataPoint(toTime, lowLine) new DataPoint(endTime, lowLine)
}; };
DataPoint[] highDataPoints = new DataPoint[]{ DataPoint[] highDataPoints = new DataPoint[]{
new DataPoint(fromTime, highLine), new DataPoint(fromTime, highLine),
new DataPoint(toTime, highLine) new DataPoint(endTime, highLine)
}; };
bgGraph.addSeries(seriesLow = new LineGraphSeries<DataPoint>(lowDataPoints)); bgGraph.addSeries(seriesLow = new LineGraphSeries<DataPoint>(lowDataPoints));
seriesLow.setColor(Color.RED); seriesLow.setColor(Color.RED);
@ -673,7 +711,6 @@ public class OverviewFragment extends Fragment {
public boolean isTempBasal = false; public boolean isTempBasal = false;
} }
Double maxAllowedBasal = MainApp.getConfigBuilder().applyBasalConstraints(Constants.basalAbsoluteOnlyForCheckLimit);
Double maxBasalValueFound = 0d; Double maxBasalValueFound = 0d;
long now = new Date().getTime(); long now = new Date().getTime();
@ -702,7 +739,7 @@ public class OverviewFragment extends Fragment {
} }
// set manual x bounds to have nice steps // set manual x bounds to have nice steps
bgGraph.getViewport().setMaxX(toTime); bgGraph.getViewport().setMaxX(endTime);
bgGraph.getViewport().setMinX(fromTime); bgGraph.getViewport().setMinX(fromTime);
bgGraph.getViewport().setXAxisBoundsManual(true); bgGraph.getViewport().setXAxisBoundsManual(true);
bgGraph.getGridLabelRenderer().setLabelFormatter(new TimeAsXAxisLabelFormatter(getActivity(), "HH")); bgGraph.getGridLabelRenderer().setLabelFormatter(new TimeAsXAxisLabelFormatter(getActivity(), "HH"));
@ -751,6 +788,19 @@ public class OverviewFragment extends Fragment {
seriesOutOfRange.setColor(Color.RED); seriesOutOfRange.setColor(Color.RED);
} }
if (showPrediction) {
DetermineBasalResultAMA amaResult = (DetermineBasalResultAMA) finalLastRun.constraintsProcessed;
List<BgReading> predArray = amaResult.getPredictions();
BgReading[] pred = new BgReading[predArray.size()];
pred = predArray.toArray(pred);
if (pred.length > 0) {
bgGraph.addSeries(predSeries = new PointsGraphSeries<BgReading>(pred));
predSeries.setShape(PointsGraphSeries.Shape.POINT);
predSeries.setSize(4);
predSeries.setColor(Color.MAGENTA);
}
}
// **** NOW line **** // **** NOW line ****
DataPoint[] nowPoints = new DataPoint[]{ DataPoint[] nowPoints = new DataPoint[]{
new DataPoint(now, 0), new DataPoint(now, 0),

View file

@ -150,10 +150,22 @@
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:textAppearance="?android:attr/textAppearanceSmall" /> android:textAppearance="?android:attr/textAppearanceSmall" />
<com.jjoe64.graphview.GraphView <RelativeLayout
android:id="@+id/overview_bggraph"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="160dip" /> android:layout_height="match_parent">
<com.jjoe64.graphview.GraphView
android:id="@+id/overview_bggraph"
android:layout_width="match_parent"
android:layout_height="160dip" />
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/overview_showprediction"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true" />
</RelativeLayout>
<LinearLayout <LinearLayout
android:id="@+id/overview_accepttemplayout" android:id="@+id/overview_accepttemplayout"