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="Remove" />
</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" />
</component>
<component name="ProjectType">

View file

@ -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<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() {
}

View file

@ -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<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() {
}

View file

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

View file

@ -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<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();
}
@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() {
}

View file

@ -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<DataPoint> seriesNow = null;
PointsGraphSeries<BgReading> seriesInRage = null;
PointsGraphSeries<BgReading> seriesOutOfRange = null;
PointsGraphSeries<BgReading> predSeries = null;
PointsWithLabelGraphSeries<Treatment> 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<DataPoint>(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<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 ****
DataPoint[] nowPoints = new DataPoint[]{
new DataPoint(now, 0),

View file

@ -150,11 +150,23 @@
android:layout_gravity="center_horizontal"
android:textAppearance="?android:attr/textAppearanceSmall" />
<RelativeLayout
android:layout_width="match_parent"
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
android:id="@+id/overview_accepttemplayout"
android:layout_width="match_parent"