Profile tests
This commit is contained in:
parent
7961a9f00a
commit
f7621c4cc5
20 changed files with 277 additions and 93 deletions
|
@ -238,6 +238,7 @@ dependencies {
|
|||
testCompile "org.powermock:powermock-module-junit4:${powermockVersion}"
|
||||
testCompile "joda-time:joda-time:2.9.4.2"
|
||||
testCompile "com.google.truth:truth:0.39"
|
||||
testCompile "org.skyscreamer:jsonassert:1.5.0"
|
||||
|
||||
androidTestCompile "org.mockito:mockito-core:2.7.22"
|
||||
androidTestCompile "com.google.dexmaker:dexmaker:${dexmakerVersion}"
|
||||
|
|
|
@ -2,8 +2,6 @@ package info.nightscout.androidaps.data;
|
|||
|
||||
import android.support.v4.util.LongSparseArray;
|
||||
|
||||
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
@ -19,41 +17,43 @@ import info.nightscout.androidaps.MainApp;
|
|||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.interfaces.PumpDescription;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
|
||||
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
|
||||
import info.nightscout.androidaps.plugins.Overview.notifications.Notification;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
import info.nightscout.utils.DecimalFormatter;
|
||||
import info.nightscout.utils.FabricPrivacy;
|
||||
import info.nightscout.utils.ToastUtils;
|
||||
|
||||
public class Profile {
|
||||
private static Logger log = LoggerFactory.getLogger(Profile.class);
|
||||
|
||||
private JSONObject json;
|
||||
private String units = null;
|
||||
private double dia = Constants.defaultDIA;
|
||||
private TimeZone timeZone = TimeZone.getDefault();
|
||||
private String units;
|
||||
private double dia;
|
||||
private TimeZone timeZone;
|
||||
private JSONArray isf;
|
||||
private LongSparseArray<Double> isf_v = null; // oldest at index 0
|
||||
private LongSparseArray<Double> isf_v; // oldest at index 0
|
||||
private JSONArray ic;
|
||||
private LongSparseArray<Double> ic_v = null; // oldest at index 0
|
||||
private LongSparseArray<Double> ic_v; // oldest at index 0
|
||||
private JSONArray basal;
|
||||
private LongSparseArray<Double> basal_v = null; // oldest at index 0
|
||||
private LongSparseArray<Double> basal_v; // oldest at index 0
|
||||
private JSONArray targetLow;
|
||||
private LongSparseArray<Double> targetLow_v = null; // oldest at index 0
|
||||
private LongSparseArray<Double> targetLow_v; // oldest at index 0
|
||||
private JSONArray targetHigh;
|
||||
private LongSparseArray<Double> targetHigh_v = null; // oldest at index 0
|
||||
private LongSparseArray<Double> targetHigh_v; // oldest at index 0
|
||||
|
||||
private int percentage = 100;
|
||||
private int timeshift = 0;
|
||||
private int percentage;
|
||||
private int timeshift;
|
||||
|
||||
private boolean isValid = true;
|
||||
private boolean isValidated = false;
|
||||
protected boolean isValid;
|
||||
protected boolean isValidated;
|
||||
|
||||
// Default constructor for tests
|
||||
protected Profile() {
|
||||
}
|
||||
|
||||
// Constructor from profileStore JSON
|
||||
public Profile(JSONObject json, String units) {
|
||||
this(json, 100, 0);
|
||||
init(json, 100, 0);
|
||||
if (this.units == null) {
|
||||
if (units != null)
|
||||
this.units = units;
|
||||
|
@ -65,6 +65,22 @@ public class Profile {
|
|||
}
|
||||
|
||||
public Profile(JSONObject json, int percentage, int timeshift) {
|
||||
init(json, percentage, timeshift);
|
||||
}
|
||||
|
||||
protected void init(JSONObject json, int percentage, int timeshift) {
|
||||
units = null;
|
||||
dia = Constants.defaultDIA;
|
||||
timeZone = TimeZone.getDefault();
|
||||
isf_v = null;
|
||||
ic_v = null;
|
||||
basal_v = null;
|
||||
targetLow_v = null;
|
||||
targetHigh_v = null;
|
||||
|
||||
isValid = true;
|
||||
isValidated = false;
|
||||
|
||||
this.percentage = percentage;
|
||||
this.timeshift = timeshift;
|
||||
this.json = json;
|
||||
|
@ -92,7 +108,7 @@ public class Profile {
|
|||
public String log() {
|
||||
String ret = "\n";
|
||||
for (Integer hour = 0; hour < 24; hour++) {
|
||||
double value = getBasal((Integer) (hour * 60 * 60));
|
||||
double value = getBasalTimeFromMidnight((Integer) (hour * 60 * 60));
|
||||
ret += "NS basal value for " + hour + ":00 is " + value + "\n";
|
||||
}
|
||||
ret += "NS units: " + getUnits();
|
||||
|
@ -114,6 +130,10 @@ public class Profile {
|
|||
}
|
||||
|
||||
// mmol or mg/dl
|
||||
public void setUnits(String units) {
|
||||
this.units = units;
|
||||
}
|
||||
|
||||
public String getUnits() {
|
||||
return units;
|
||||
}
|
||||
|
@ -199,7 +219,7 @@ public class Profile {
|
|||
for (int i = 0; i < basal_v.size(); i++) {
|
||||
if (basal_v.valueAt(i) < description.basalMinimumRate) {
|
||||
basal_v.setValueAt(i, description.basalMinimumRate);
|
||||
MainApp.bus().post(new EventNewNotification(new Notification(Notification.MINIMAL_BASAL_VALUE_REPLACED, String.format(MainApp.gs(R.string.minimalbasalvaluereplaced), from), Notification.NORMAL)));
|
||||
sendBelowMinimumNotification(from);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -213,6 +233,10 @@ public class Profile {
|
|||
return isValid;
|
||||
}
|
||||
|
||||
protected void sendBelowMinimumNotification(String from) {
|
||||
MainApp.bus().post(new EventNewNotification(new Notification(Notification.MINIMAL_BASAL_VALUE_REPLACED, String.format(MainApp.gs(R.string.minimalbasalvaluereplaced), from), Notification.NORMAL)));
|
||||
}
|
||||
|
||||
private void validate(LongSparseArray array) {
|
||||
if (array.size() == 0) {
|
||||
isValid = false;
|
||||
|
@ -226,6 +250,7 @@ public class Profile {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
private Double getValueToTime(JSONArray array, Integer timeAsSeconds) {
|
||||
Double lastValue = null;
|
||||
|
||||
|
@ -245,6 +270,7 @@ public class Profile {
|
|||
}
|
||||
return lastValue;
|
||||
}
|
||||
*/
|
||||
|
||||
Integer getShitfTimeSecs(Integer originalTime) {
|
||||
Integer shiftedTime = originalTime + timeshift * 60 * 60;
|
||||
|
@ -286,7 +312,7 @@ public class Profile {
|
|||
return multiplier;
|
||||
}
|
||||
|
||||
private Double getValueToTime(LongSparseArray<Double> array, Integer timeAsSeconds) {
|
||||
private double getValueToTime(LongSparseArray<Double> array, Integer timeAsSeconds) {
|
||||
Double lastValue = null;
|
||||
|
||||
for (Integer index = 0; index < array.size(); index++) {
|
||||
|
@ -301,7 +327,7 @@ public class Profile {
|
|||
return lastValue;
|
||||
}
|
||||
|
||||
private String format_HH_MM(Integer timeAsSeconds) {
|
||||
protected String format_HH_MM(Integer timeAsSeconds) {
|
||||
String time;
|
||||
int hour = timeAsSeconds / 60 / 60;
|
||||
int minutes = (timeAsSeconds - hour * 60 * 60) / 60;
|
||||
|
@ -328,15 +354,15 @@ public class Profile {
|
|||
return retValue;
|
||||
}
|
||||
|
||||
public Double getIsf() {
|
||||
return getIsf(secondsFromMidnight(System.currentTimeMillis()));
|
||||
public double getIsf() {
|
||||
return getIsfTimeFromMidnight(secondsFromMidnight(System.currentTimeMillis()));
|
||||
}
|
||||
|
||||
public Double getIsf(long time) {
|
||||
return getIsf(secondsFromMidnight(time));
|
||||
public double getIsf(long time) {
|
||||
return getIsfTimeFromMidnight(secondsFromMidnight(time));
|
||||
}
|
||||
|
||||
public Double getIsf(Integer timeAsSeconds) {
|
||||
double getIsfTimeFromMidnight(int timeAsSeconds) {
|
||||
if (isf_v == null)
|
||||
isf_v = convertToSparseArray(isf);
|
||||
return getValueToTime(isf_v, timeAsSeconds);
|
||||
|
@ -348,15 +374,15 @@ public class Profile {
|
|||
return getValuesList(isf_v, null, new DecimalFormat("0.0"), getUnits() + "/U");
|
||||
}
|
||||
|
||||
public Double getIc() {
|
||||
return getIc(secondsFromMidnight(System.currentTimeMillis()));
|
||||
public double getIc() {
|
||||
return getIcTimeFromMidnight(secondsFromMidnight(System.currentTimeMillis()));
|
||||
}
|
||||
|
||||
public Double getIc(long time) {
|
||||
return getIc(secondsFromMidnight(time));
|
||||
public double getIc(long time) {
|
||||
return getIcTimeFromMidnight(secondsFromMidnight(time));
|
||||
}
|
||||
|
||||
public Double getIc(Integer timeAsSeconds) {
|
||||
public double getIcTimeFromMidnight(int timeAsSeconds) {
|
||||
if (ic_v == null)
|
||||
ic_v = convertToSparseArray(ic);
|
||||
return getValueToTime(ic_v, timeAsSeconds);
|
||||
|
@ -365,18 +391,18 @@ public class Profile {
|
|||
public String getIcList() {
|
||||
if (ic_v == null)
|
||||
ic_v = convertToSparseArray(ic);
|
||||
return getValuesList(ic_v, null, new DecimalFormat("0.0"), " g/U");
|
||||
return getValuesList(ic_v, null, new DecimalFormat("0.0"), "g/U");
|
||||
}
|
||||
|
||||
public Double getBasal() {
|
||||
return getBasal(secondsFromMidnight(System.currentTimeMillis()));
|
||||
public double getBasal() {
|
||||
return getBasalTimeFromMidnight(secondsFromMidnight(System.currentTimeMillis()));
|
||||
}
|
||||
|
||||
public Double getBasal(long time) {
|
||||
return getBasal(secondsFromMidnight(time));
|
||||
public double getBasal(long time) {
|
||||
return getBasalTimeFromMidnight(secondsFromMidnight(time));
|
||||
}
|
||||
|
||||
public synchronized Double getBasal(Integer timeAsSeconds) {
|
||||
public synchronized double getBasalTimeFromMidnight(int timeAsSeconds) {
|
||||
if (basal_v == null) {
|
||||
basal_v = convertToSparseArray(basal);
|
||||
}
|
||||
|
@ -386,17 +412,17 @@ public class Profile {
|
|||
public String getBasalList() {
|
||||
if (basal_v == null)
|
||||
basal_v = convertToSparseArray(basal);
|
||||
return getValuesList(basal_v, null, new DecimalFormat("0.00"), "U");
|
||||
return getValuesList(basal_v, null, new DecimalFormat("0.00"), "U/h");
|
||||
}
|
||||
|
||||
public class BasalValue {
|
||||
public BasalValue(Integer timeAsSeconds, Double value) {
|
||||
public BasalValue(int timeAsSeconds, double value) {
|
||||
this.timeAsSeconds = timeAsSeconds;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public Integer timeAsSeconds;
|
||||
public Double value;
|
||||
public int timeAsSeconds;
|
||||
public double value;
|
||||
}
|
||||
|
||||
public synchronized BasalValue[] getBasalValues() {
|
||||
|
@ -406,7 +432,7 @@ public class Profile {
|
|||
|
||||
for (Integer index = 0; index < basal_v.size(); index++) {
|
||||
Integer tas = (int) basal_v.keyAt(index);
|
||||
Double value = basal_v.valueAt(index);
|
||||
double value = basal_v.valueAt(index);
|
||||
ret[index] = new BasalValue(tas, value);
|
||||
}
|
||||
return ret;
|
||||
|
@ -416,33 +442,33 @@ public class Profile {
|
|||
return getTarget(secondsFromMidnight(System.currentTimeMillis()));
|
||||
}
|
||||
|
||||
private double getTarget(Integer time) {
|
||||
return (getTargetLow(time) + getTargetHigh(time))/2;
|
||||
protected double getTarget(int timeAsSeconds) {
|
||||
return (getTargetLowTimeFromMidnight(timeAsSeconds) + getTargetHighTimeFromMidnight(timeAsSeconds))/2;
|
||||
}
|
||||
|
||||
public Double getTargetLow() {
|
||||
return getTargetLow(secondsFromMidnight(System.currentTimeMillis()));
|
||||
public double getTargetLow() {
|
||||
return getTargetLowTimeFromMidnight(secondsFromMidnight(System.currentTimeMillis()));
|
||||
}
|
||||
|
||||
public Double getTargetLow(long time) {
|
||||
return getTargetLow(secondsFromMidnight(time));
|
||||
public double getTargetLow(long time) {
|
||||
return getTargetLowTimeFromMidnight(secondsFromMidnight(time));
|
||||
}
|
||||
|
||||
public Double getTargetLow(Integer timeAsSeconds) {
|
||||
public double getTargetLowTimeFromMidnight(int timeAsSeconds) {
|
||||
if (targetLow_v == null)
|
||||
targetLow_v = convertToSparseArray(targetLow);
|
||||
return getValueToTime(targetLow_v, timeAsSeconds);
|
||||
}
|
||||
|
||||
public Double getTargetHigh() {
|
||||
return getTargetHigh(secondsFromMidnight(System.currentTimeMillis()));
|
||||
public double getTargetHigh() {
|
||||
return getTargetHighTimeFromMidnight(secondsFromMidnight(System.currentTimeMillis()));
|
||||
}
|
||||
|
||||
public Double getTargetHigh(long time) {
|
||||
return getTargetHigh(secondsFromMidnight(time));
|
||||
public double getTargetHigh(long time) {
|
||||
return getTargetHighTimeFromMidnight(secondsFromMidnight(time));
|
||||
}
|
||||
|
||||
public Double getTargetHigh(Integer timeAsSeconds) {
|
||||
public double getTargetHighTimeFromMidnight(int timeAsSeconds) {
|
||||
if (targetHigh_v == null)
|
||||
targetHigh_v = convertToSparseArray(targetHigh);
|
||||
return getValueToTime(targetHigh_v, timeAsSeconds);
|
||||
|
@ -457,15 +483,15 @@ public class Profile {
|
|||
}
|
||||
|
||||
public double getMaxDailyBasal() {
|
||||
Double max = 0d;
|
||||
for (Integer hour = 0; hour < 24; hour++) {
|
||||
double value = getBasal((Integer) (hour * 60 * 60));
|
||||
double max = 0d;
|
||||
for (int hour = 0; hour < 24; hour++) {
|
||||
double value = getBasalTimeFromMidnight((Integer) (hour * 60 * 60));
|
||||
if (value > max) max = value;
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
public static Integer secondsFromMidnight() {
|
||||
public static int secondsFromMidnight() {
|
||||
Calendar c = Calendar.getInstance();
|
||||
long now = c.getTimeInMillis();
|
||||
c.set(Calendar.HOUR_OF_DAY, 0);
|
||||
|
@ -476,7 +502,7 @@ public class Profile {
|
|||
return (int) (passed / 1000);
|
||||
}
|
||||
|
||||
public static Integer secondsFromMidnight(long date) {
|
||||
public static int secondsFromMidnight(long date) {
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.setTimeInMillis(date);
|
||||
c.set(Calendar.HOUR_OF_DAY, 0);
|
||||
|
@ -487,22 +513,22 @@ public class Profile {
|
|||
return (int) (passed / 1000);
|
||||
}
|
||||
|
||||
public static Double toMgdl(Double value, String units) {
|
||||
public static double toMgdl(double value, String units) {
|
||||
if (units.equals(Constants.MGDL)) return value;
|
||||
else return value * Constants.MMOLL_TO_MGDL;
|
||||
}
|
||||
|
||||
public static Double toMmol(Double value, String units) {
|
||||
public static double toMmol(double value, String units) {
|
||||
if (units.equals(Constants.MGDL)) return value * Constants.MGDL_TO_MMOLL;
|
||||
else return value;
|
||||
}
|
||||
|
||||
public static Double fromMgdlToUnits(Double value, String units) {
|
||||
public static double fromMgdlToUnits(double value, String units) {
|
||||
if (units.equals(Constants.MGDL)) return value;
|
||||
else return value * Constants.MGDL_TO_MMOLL;
|
||||
}
|
||||
|
||||
public static Double toUnits(Double valueInMgdl, Double valueInMmol, String units) {
|
||||
public static double toUnits(Double valueInMgdl, Double valueInMmol, String units) {
|
||||
if (units.equals(Constants.MGDL)) return valueInMgdl;
|
||||
else return valueInMmol;
|
||||
}
|
||||
|
@ -528,7 +554,7 @@ public class Profile {
|
|||
public double percentageBasalSum() {
|
||||
double result = 0d;
|
||||
for (int i = 0; i < 24; i++) {
|
||||
result += getBasal((Integer) (i * 60 * 60));
|
||||
result += getBasalTimeFromMidnight(i * 60 * 60);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -537,7 +563,7 @@ public class Profile {
|
|||
public double baseBasalSum() {
|
||||
double result = 0d;
|
||||
for (int i = 0; i < 24; i++) {
|
||||
result += getBasal((Integer) (i * 60 * 60)) / getMultiplier(basal_v);
|
||||
result += getBasalTimeFromMidnight(i * 60 * 60) / getMultiplier(basal_v);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -110,11 +110,6 @@ public class IobCobThread extends Thread {
|
|||
return; // profile not set yet
|
||||
}
|
||||
|
||||
if (profile.getIsf(bgTime) == null) {
|
||||
log.debug("Aborting calculation thread (no ISF): " + from);
|
||||
return; // profile not set yet
|
||||
}
|
||||
|
||||
if (Config.logAutosensData)
|
||||
log.debug("Processing calculation thread: " + from + " (" + i + "/" + bucketed_data.size() + ")");
|
||||
|
||||
|
|
|
@ -204,7 +204,7 @@ public class DetermineBasalAdapterAMAJS {
|
|||
mProfile.put("max_bg", maxBg);
|
||||
mProfile.put("target_bg", targetBg);
|
||||
mProfile.put("carb_ratio", profile.getIc());
|
||||
mProfile.put("sens", Profile.toMgdl(profile.getIsf().doubleValue(), units));
|
||||
mProfile.put("sens", Profile.toMgdl(profile.getIsf(), units));
|
||||
mProfile.put("max_daily_safety_multiplier", SP.getInt("openapsama_max_daily_safety_multiplier", 3));
|
||||
mProfile.put("current_basal_safety_multiplier", SP.getDouble("openapsama_current_basal_safety_multiplier", 4d));
|
||||
mProfile.put("skip_neutral_temps", true);
|
||||
|
|
|
@ -212,9 +212,9 @@ public class OpenAPSAMAPlugin implements PluginBase, APSInterface {
|
|||
|
||||
if (!HardLimits.checkOnlyHardLimits(profile.getDia(), "dia", HardLimits.MINDIA, HardLimits.MAXDIA))
|
||||
return;
|
||||
if (!HardLimits.checkOnlyHardLimits(profile.getIc(profile.secondsFromMidnight()), "carbratio", HardLimits.MINIC, HardLimits.MAXIC))
|
||||
if (!HardLimits.checkOnlyHardLimits(profile.getIcTimeFromMidnight(profile.secondsFromMidnight()), "carbratio", HardLimits.MINIC, HardLimits.MAXIC))
|
||||
return;
|
||||
if (!HardLimits.checkOnlyHardLimits(Profile.toMgdl(profile.getIsf().doubleValue(), units), "sens", HardLimits.MINISF, HardLimits.MAXISF))
|
||||
if (!HardLimits.checkOnlyHardLimits(Profile.toMgdl(profile.getIsf(), units), "sens", HardLimits.MINISF, HardLimits.MAXISF))
|
||||
return;
|
||||
if (!HardLimits.checkOnlyHardLimits(profile.getMaxDailyBasal(), "max_daily_basal", 0.05, HardLimits.maxBasal()))
|
||||
return;
|
||||
|
|
|
@ -172,7 +172,7 @@ public class DetermineBasalAdapterMAJS {
|
|||
mProfile.put("max_bg", maxBg);
|
||||
mProfile.put("target_bg", targetBg);
|
||||
mProfile.put("carb_ratio", profile.getIc());
|
||||
mProfile.put("sens", Profile.toMgdl(profile.getIsf().doubleValue(), units));
|
||||
mProfile.put("sens", Profile.toMgdl(profile.getIsf(), units));
|
||||
|
||||
mProfile.put("current_basal", basalRate);
|
||||
|
||||
|
|
|
@ -212,9 +212,9 @@ public class OpenAPSMAPlugin implements PluginBase, APSInterface {
|
|||
|
||||
if (!checkOnlyHardLimits(profile.getDia(), "dia", HardLimits.MINDIA, HardLimits.MAXDIA))
|
||||
return;
|
||||
if (!checkOnlyHardLimits(profile.getIc(profile.secondsFromMidnight()), "carbratio", HardLimits.MINIC, HardLimits.MAXIC))
|
||||
if (!checkOnlyHardLimits(profile.getIcTimeFromMidnight(profile.secondsFromMidnight()), "carbratio", HardLimits.MINIC, HardLimits.MAXIC))
|
||||
return;
|
||||
if (!checkOnlyHardLimits(Profile.toMgdl(profile.getIsf().doubleValue(), units), "sens", HardLimits.MINISF, HardLimits.MAXISF))
|
||||
if (!checkOnlyHardLimits(Profile.toMgdl(profile.getIsf(), units), "sens", HardLimits.MINISF, HardLimits.MAXISF))
|
||||
return;
|
||||
if (!checkOnlyHardLimits(profile.getMaxDailyBasal(), "max_daily_basal", 0.05, HardLimits.maxBasal()))
|
||||
return;
|
||||
|
|
|
@ -228,7 +228,7 @@ public class DetermineBasalAdapterSMBJS {
|
|||
mProfile.put("max_bg", maxBg);
|
||||
mProfile.put("target_bg", targetBg);
|
||||
mProfile.put("carb_ratio", profile.getIc());
|
||||
mProfile.put("sens", Profile.toMgdl(profile.getIsf().doubleValue(), units));
|
||||
mProfile.put("sens", Profile.toMgdl(profile.getIsf(), units));
|
||||
mProfile.put("max_daily_safety_multiplier", SP.getInt("openapsama_max_daily_safety_multiplier", 3));
|
||||
mProfile.put("current_basal_safety_multiplier", SP.getDouble("openapsama_current_basal_safety_multiplier", 4d));
|
||||
|
||||
|
|
|
@ -216,9 +216,9 @@ public class OpenAPSSMBPlugin implements PluginBase, APSInterface {
|
|||
maxBasal = verifyHardLimits(maxBasal, "max_basal", 0.1, HardLimits.maxBasal());
|
||||
|
||||
if (!checkOnlyHardLimits(profile.getDia(), "dia", HardLimits.MINDIA, HardLimits.MAXDIA)) return;
|
||||
if (!checkOnlyHardLimits(profile.getIc(profile.secondsFromMidnight()), "carbratio", HardLimits.MINIC, HardLimits.MAXIC))
|
||||
if (!checkOnlyHardLimits(profile.getIcTimeFromMidnight(profile.secondsFromMidnight()), "carbratio", HardLimits.MINIC, HardLimits.MAXIC))
|
||||
return;
|
||||
if (!checkOnlyHardLimits(Profile.toMgdl(profile.getIsf().doubleValue(), units), "sens", HardLimits.MINISF, HardLimits.MAXISF))
|
||||
if (!checkOnlyHardLimits(Profile.toMgdl(profile.getIsf(), units), "sens", HardLimits.MINISF, HardLimits.MAXISF))
|
||||
return;
|
||||
if (!checkOnlyHardLimits(profile.getMaxDailyBasal(), "max_daily_basal", 0.05, HardLimits.maxBasal())) return;
|
||||
if (!checkOnlyHardLimits(pump.getBaseBasalRate(), "current_basal", 0.01, HardLimits.maxBasal())) return;
|
||||
|
|
|
@ -184,7 +184,7 @@ public abstract class AbstractDanaRPlugin implements PluginBase, PumpInterface,
|
|||
int basalIncrement = pump.basal48Enable ? 30 * 60 : 60 * 60;
|
||||
for (int h = 0; h < basalValues; h++) {
|
||||
Double pumpValue = pump.pumpProfiles[pump.activeProfile][h];
|
||||
Double profileValue = profile.getBasal((Integer) (h * basalIncrement));
|
||||
Double profileValue = profile.getBasalTimeFromMidnight((Integer) (h * basalIncrement));
|
||||
if (profileValue == null) return true;
|
||||
if (Math.abs(pumpValue - profileValue) > getPumpDescription().basalStep) {
|
||||
log.debug("Diff found. Hour: " + h + " Pump: " + pumpValue + " Profile: " + profileValue);
|
||||
|
|
|
@ -241,7 +241,7 @@ public class DanaRPump {
|
|||
for (Integer hour = 0; hour < 24; hour++) {
|
||||
//Some values get truncated to the next lower one.
|
||||
// -> round them to two decimals and make sure we are a small delta larger (that will get truncated)
|
||||
double value = Math.round(100d * nsProfile.getBasal((Integer) (hour * 60 * 60)))/100d + 0.00001;
|
||||
double value = Math.round(100d * nsProfile.getBasalTimeFromMidnight((Integer) (hour * 60 * 60)))/100d + 0.00001;
|
||||
if (Config.logDanaMessageDetail)
|
||||
log.debug("NS basal value for " + hour + ":00 is " + value);
|
||||
record[hour] = value;
|
||||
|
|
|
@ -428,7 +428,7 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface,
|
|||
int basalIncrement = pump.basal48Enable ? 30 * 60 : 60 * 60;
|
||||
for (int h = 0; h < basalValues; h++) {
|
||||
Double pumpValue = pump.pumpProfiles[pump.activeProfile][h];
|
||||
Double profileValue = profile.getBasal((Integer) (h * basalIncrement));
|
||||
Double profileValue = profile.getBasalTimeFromMidnight((Integer) (h * basalIncrement));
|
||||
if (profileValue == null) return true;
|
||||
if (Math.abs(pumpValue - profileValue) > getPumpDescription().basalStep) {
|
||||
log.debug("Diff found. Hour: " + h + " Pump: " + pumpValue + " Profile: " + profileValue);
|
||||
|
|
|
@ -52,12 +52,12 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface {
|
|||
private PumpDescription pumpDescription = new PumpDescription();
|
||||
|
||||
private static void loadFakingStatus() {
|
||||
fromNSAreCommingFakedExtendedBoluses = SP.getBoolean("fromNSAreCommingFakedExtendedBoluses", false);
|
||||
fromNSAreCommingFakedExtendedBoluses = SP.getBoolean(R.string.key_fromNSAreCommingFakedExtendedBoluses, false);
|
||||
}
|
||||
|
||||
public static void setFakingStatus(boolean newStatus) {
|
||||
fromNSAreCommingFakedExtendedBoluses = newStatus;
|
||||
SP.putBoolean("fromNSAreCommingFakedExtendedBoluses", fromNSAreCommingFakedExtendedBoluses);
|
||||
SP.putBoolean(R.string.key_fromNSAreCommingFakedExtendedBoluses, fromNSAreCommingFakedExtendedBoluses);
|
||||
}
|
||||
|
||||
public static boolean getFakingStatus() {
|
||||
|
@ -73,7 +73,7 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface {
|
|||
return plugin;
|
||||
}
|
||||
|
||||
private VirtualPumpPlugin() {
|
||||
public VirtualPumpPlugin() {
|
||||
pumpDescription.isBolusCapable = true;
|
||||
pumpDescription.bolusStep = 0.1d;
|
||||
|
||||
|
@ -245,7 +245,7 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface {
|
|||
public double getBaseBasalRate() {
|
||||
Profile profile = MainApp.getConfigBuilder().getProfile();
|
||||
if (profile != null)
|
||||
return profile.getBasal() != null ? profile.getBasal() : 0d;
|
||||
return profile.getBasal();
|
||||
else
|
||||
return 0d;
|
||||
}
|
||||
|
|
|
@ -33,8 +33,8 @@ public class ProfileGraph extends GraphView {
|
|||
List<DataPoint> basalArray = new ArrayList<>();
|
||||
|
||||
for (int hour = 0; hour < 24; hour++) {
|
||||
basalArray.add(new DataPoint(hour, profile.getBasal(new Integer(hour*60*60))));
|
||||
basalArray.add(new DataPoint(hour+1, profile.getBasal(new Integer(hour*60*60))));
|
||||
basalArray.add(new DataPoint(hour, profile.getBasalTimeFromMidnight(new Integer(hour*60*60))));
|
||||
basalArray.add(new DataPoint(hour+1, profile.getBasalTimeFromMidnight(new Integer(hour*60*60))));
|
||||
}
|
||||
DataPoint[] basalDataPoints = new DataPoint[basalArray.size()];
|
||||
basalDataPoints = basalArray.toArray(basalDataPoints);
|
||||
|
|
|
@ -586,7 +586,7 @@ public class ActionStringHandler {
|
|||
}
|
||||
final Profile profile = MainApp.getConfigBuilder().getProfile();
|
||||
|
||||
if (profile == null || profile.getBasal() == null) {
|
||||
if (profile == null) {
|
||||
msg += MainApp.sResources.getString(R.string.notloadedplugins) + "\n";
|
||||
}
|
||||
if (!"".equals(msg)) {
|
||||
|
|
|
@ -52,7 +52,7 @@ public class KeepAliveReceiver extends BroadcastReceiver {
|
|||
private void checkPump() {
|
||||
final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
|
||||
final Profile profile = MainApp.getConfigBuilder().getProfile();
|
||||
if (pump != null && profile != null && profile.getBasal() != null) {
|
||||
if (pump != null && profile != null) {
|
||||
Date lastConnection = pump.lastDataTime();
|
||||
boolean isStatusOutdated = lastConnection.getTime() + STATUS_UPDATE_FREQUENCY < System.currentTimeMillis();
|
||||
boolean isBasalOutdated = Math.abs(profile.getBasal() - pump.getBaseBasalRate()) > pump.getPumpDescription().basalStep;
|
||||
|
|
|
@ -76,7 +76,7 @@ public class LocalAlertUtils {
|
|||
|
||||
final PumpInterface pump = ConfigBuilderPlugin.getActivePump();
|
||||
final Profile profile = MainApp.getConfigBuilder().getProfile();
|
||||
if (pump != null && profile != null && profile.getBasal() != null) {
|
||||
if (pump != null && profile != null) {
|
||||
Date lastConnection = pump.lastDataTime();
|
||||
long earliestAlarmTime = lastConnection.getTime() + pumpUnreachableThreshold();
|
||||
if (SP.getLong("nextPumpDisconnectedAlarm", 0l) < earliestAlarmTime) {
|
||||
|
|
|
@ -980,5 +980,6 @@
|
|||
<string name="overview_show_cob">Carbs On Board</string>
|
||||
<string name="overview_show_iob">Insulin On Board</string>
|
||||
<string name="overview_show_basals">Basals</string>
|
||||
<string name="key_fromNSAreCommingFakedExtendedBoluses" translatable="false">fromNSAreCommingFakedExtendedBoluses</string>
|
||||
</resources>
|
||||
|
||||
|
|
|
@ -0,0 +1,161 @@
|
|||
package info.nightscout.androidaps.data;
|
||||
|
||||
import com.squareup.otto.Bus;
|
||||
import com.squareup.otto.ThreadEnforcer;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.powermock.api.mockito.PowerMockito;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
import org.skyscreamer.jsonassert.JSONAssert;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import info.nightscout.androidaps.Constants;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.interfaces.PumpInterface;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
|
||||
import info.nightscout.utils.FabricPrivacy;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* Created by mike on 18.03.2018.
|
||||
*/
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@PrepareForTest({MainApp.class, ConfigBuilderPlugin.class, VirtualPumpPlugin.class, FabricPrivacy.class})
|
||||
public class ProfileTest extends Profile {
|
||||
|
||||
PumpInterface pump = new VirtualPumpPlugin();
|
||||
String validProfile = "{\"dia\":\"3\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"},{\"time\":\"2:00\",\"value\":\"110\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}";
|
||||
String belowLimitValidProfile = "{\"dia\":\"3\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.001\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}";
|
||||
String notStartingAtZeroValidProfile = "{\"dia\":\"3\",\"carbratio\":[{\"time\":\"00:30\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}";
|
||||
String noUnitsValidProfile = "{\"dia\":\"3\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\"}";
|
||||
String wrongProfile = "{\"dia\":\"3\",\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}";
|
||||
|
||||
//String profileStore = "{\"defaultProfile\":\"Default\",\"store\":{\"Default\":" + validProfile + "}}";
|
||||
|
||||
boolean notificationBelowLimitSent = false;
|
||||
|
||||
@Test
|
||||
public void doTests() throws Exception {
|
||||
prepareMock();
|
||||
|
||||
|
||||
// Test valid profile
|
||||
init(new JSONObject(validProfile), 100, 0);
|
||||
Assert.assertEquals(true, isValid("Test"));
|
||||
Assert.assertEquals(true, log().contains("NS units: mmol"));
|
||||
JSONAssert.assertEquals(validProfile, getData(), false);
|
||||
Assert.assertEquals(3.0d, getDia(), 0.01d);
|
||||
Assert.assertEquals(TimeZone.getTimeZone("UTC"), getTimeZone());
|
||||
Assert.assertEquals("00:30", format_HH_MM(30 * 60));
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.set(Calendar.HOUR_OF_DAY, 1);
|
||||
c.set(Calendar.MINUTE, 0);
|
||||
c.set(Calendar.SECOND, 0);
|
||||
c.set(Calendar.MILLISECOND, 0);
|
||||
Assert.assertEquals(100d, getIsf(c.getTimeInMillis()), 0.01d);
|
||||
c.set(Calendar.HOUR_OF_DAY, 2);
|
||||
Assert.assertEquals(110d, getIsf(c.getTimeInMillis()), 0.01d);
|
||||
Assert.assertEquals(110d, getIsfTimeFromMidnight(2 * 60 * 60), 0.01d);
|
||||
Assert.assertEquals("00:00 100,0 mmol/U\n" + "02:00 110,0 mmol/U", getIsfList());
|
||||
Assert.assertEquals(30d, getIc(c.getTimeInMillis()), 0.01d);
|
||||
Assert.assertEquals(30d, getIcTimeFromMidnight(2 * 60 * 60), 0.01d);
|
||||
Assert.assertEquals("00:00 30,0 g/U", getIcList());
|
||||
Assert.assertEquals(0.1d, getBasal(c.getTimeInMillis()), 0.01d);
|
||||
Assert.assertEquals(0.1d, getBasalTimeFromMidnight(2 * 60 * 60), 0.01d);
|
||||
Assert.assertEquals("00:00 0,10 U/h", getBasalList());
|
||||
Assert.assertEquals(0.1d, getBasalValues()[0].value);
|
||||
Assert.assertEquals(0.1d, getMaxDailyBasal());
|
||||
Assert.assertEquals(2.4d, percentageBasalSum(), 0.01d);
|
||||
Assert.assertEquals(2.4d, baseBasalSum(), 0.01d);
|
||||
Assert.assertEquals(4.5d, getTarget(2 * 60 * 60), 0.01d);
|
||||
Assert.assertEquals(4d, getTargetLow(c.getTimeInMillis()), 0.01d);
|
||||
Assert.assertEquals(4d, getTargetLowTimeFromMidnight(2 * 60 * 60), 0.01d);
|
||||
Assert.assertEquals(5d, getTargetHigh(c.getTimeInMillis()), 0.01d);
|
||||
Assert.assertEquals(5d, getTargetHighTimeFromMidnight(2 * 60 * 60), 0.01d);
|
||||
Assert.assertEquals("00:00 4,0 - 5,0 mmol", getTargetList());
|
||||
Assert.assertEquals(100, getPercentage());
|
||||
Assert.assertEquals(0, getTimeshift());
|
||||
|
||||
Assert.assertEquals(0.1d, toMgdl(0.1d, Constants.MGDL));
|
||||
Assert.assertEquals(18d, toMgdl(1d, Constants.MMOL));
|
||||
Assert.assertEquals(1d, toMmol(18d, Constants.MGDL));
|
||||
Assert.assertEquals(18d, toMmol(18d, Constants.MMOL));
|
||||
Assert.assertEquals(18d, fromMgdlToUnits(18d, Constants.MGDL));
|
||||
Assert.assertEquals(1d, fromMgdlToUnits(18d, Constants.MMOL));
|
||||
Assert.assertEquals(18d, toUnits(18d, 1d, Constants.MGDL));
|
||||
Assert.assertEquals(1d, toUnits(18d, 1d, Constants.MMOL));
|
||||
Assert.assertEquals("18", toUnitsString(18d, 1d, Constants.MGDL));
|
||||
Assert.assertEquals("1,0", toUnitsString(18d, 1d, Constants.MMOL));
|
||||
Assert.assertEquals("5 - 6", toTargetRangeString(5d, 6d, Constants.MGDL, Constants.MGDL));
|
||||
|
||||
//Test basal profile below limit
|
||||
Assert.assertEquals(false, notificationBelowLimitSent);
|
||||
init(new JSONObject(belowLimitValidProfile), 100, 0);
|
||||
isValid("Test");
|
||||
Assert.assertEquals(true, notificationBelowLimitSent);
|
||||
|
||||
|
||||
// Test profile w/o units
|
||||
init(new JSONObject(noUnitsValidProfile), 100, 0);
|
||||
Assert.assertEquals(null, getUnits());
|
||||
Profile nup = new Profile(new JSONObject(noUnitsValidProfile), Constants.MMOL);
|
||||
Assert.assertEquals(Constants.MMOL, nup.getUnits());
|
||||
// failover to MGDL
|
||||
nup = new Profile(new JSONObject(noUnitsValidProfile), null);
|
||||
Assert.assertEquals(Constants.MGDL, nup.getUnits());
|
||||
|
||||
//Test profile not starting at midnight
|
||||
init(new JSONObject(notStartingAtZeroValidProfile), 100, 0);
|
||||
Assert.assertEquals(30.0d, getIc(0), 0.01d);
|
||||
|
||||
// Test wrong profile
|
||||
init(new JSONObject(wrongProfile), 100, 0);
|
||||
Assert.assertEquals(false, isValid("Test"));
|
||||
|
||||
// Test percentage functionality
|
||||
init(new JSONObject(validProfile), 50, 0);
|
||||
Assert.assertEquals(0.05d, getBasal(c.getTimeInMillis()), 0.01d);
|
||||
Assert.assertEquals(1.2d, percentageBasalSum(), 0.01d);
|
||||
Assert.assertEquals(60d, getIc(c.getTimeInMillis()), 0.01d);
|
||||
Assert.assertEquals(220d, getIsf(c.getTimeInMillis()), 0.01d);
|
||||
|
||||
// Test timeshift functionality
|
||||
init(new JSONObject(validProfile), 100, 1);
|
||||
Assert.assertEquals(
|
||||
"00:00 110,0 mmol/U\n" +
|
||||
"01:00 100,0 mmol/U\n" +
|
||||
"03:00 110,0 mmol/U", getIsfList());
|
||||
}
|
||||
|
||||
private void prepareMock() throws Exception {
|
||||
ConfigBuilderPlugin configBuilderPlugin = mock(ConfigBuilderPlugin.class);
|
||||
PowerMockito.mockStatic(ConfigBuilderPlugin.class);
|
||||
|
||||
MainApp mainApp = mock(MainApp.class);
|
||||
PowerMockito.mockStatic(MainApp.class);
|
||||
when(MainApp.instance()).thenReturn(mainApp);
|
||||
when(MainApp.getConfigBuilder()).thenReturn(configBuilderPlugin);
|
||||
when(MainApp.getConfigBuilder().getActivePump()).thenReturn(pump);
|
||||
|
||||
PowerMockito.mockStatic(FabricPrivacy.class);
|
||||
// PowerMockito.doNothing().when(FabricPrivacy.log(""));
|
||||
|
||||
Bus bus = new Bus(ThreadEnforcer.ANY);
|
||||
when(MainApp.bus()).thenReturn(bus);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void sendBelowMinimumNotification(String from) {
|
||||
notificationBelowLimitSent = true;
|
||||
}
|
||||
}
|
|
@ -33,7 +33,7 @@ import static org.mockito.Mockito.when;
|
|||
*/
|
||||
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@PrepareForTest({MainApp.class, ConfigBuilderPlugin.class, ConfigBuilderPlugin.class, ToastUtils.class, Context.class})
|
||||
@PrepareForTest({MainApp.class, ConfigBuilderPlugin.class, ToastUtils.class, Context.class})
|
||||
public class CommandQueueTest extends CommandQueue {
|
||||
|
||||
String profileJson = "{\"dia\":\"3\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}";
|
||||
|
|
Loading…
Reference in a new issue