From 116865896beda38cf2f72ee248dba95eea722f37 Mon Sep 17 00:00:00 2001 From: Roumen Georgiev Date: Mon, 3 Jun 2019 15:06:40 +0300 Subject: [PATCH] Automation (#69) (#70) * Adding trigger AutosensValue * new trigger and tests * AS value in % * adding tests * fixed tests * fix for maxValue and tests * Using InputDouble * icon added * unavailable data and IS_NOT_AVAILABLE case * Fixing after comments * Autosens !=0 && IS_NOT_AVAILABLE doesn't exist enymore * cleanup --- .../dialogs/ChooseTriggerDialog.java | 2 + .../triggers/TriggerAutosensValue.java | 152 ++++++++++++++++++ app/src/main/res/values/strings.xml | 2 + .../triggers/TriggerAutosensValueTest.java | 132 +++++++++++++++ 4 files changed, 288 insertions(+) create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerAutosensValue.java create mode 100644 app/src/test/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerAutosensValueTest.java diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/ChooseTriggerDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/ChooseTriggerDialog.java index 956d802be0..353ce05e90 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/ChooseTriggerDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/dialogs/ChooseTriggerDialog.java @@ -27,6 +27,7 @@ import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerRec import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerTempTarget; import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerTime; import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerWifiSsid; +import info.nightscout.androidaps.plugins.general.automation.triggers.TriggerAutosensValue; public class ChooseTriggerDialog extends DialogFragment { @@ -44,6 +45,7 @@ public class ChooseTriggerDialog extends DialogFragment { add(new TriggerTempTarget()); add(new TriggerWifiSsid()); add(new TriggerLocation()); + add(new TriggerAutosensValue()); }}; private Unbinder mUnbinder; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerAutosensValue.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerAutosensValue.java new file mode 100644 index 0000000000..98c8928dcf --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerAutosensValue.java @@ -0,0 +1,152 @@ +package info.nightscout.androidaps.plugins.general.automation.triggers; + + +import android.support.v4.app.FragmentManager; +import android.widget.LinearLayout; + +import com.google.common.base.Optional; + +import org.json.JSONException; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.text.DecimalFormat; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.general.automation.elements.Comparator; +import info.nightscout.androidaps.plugins.general.automation.elements.InputDouble; +import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement; +import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder; +import info.nightscout.androidaps.plugins.general.automation.elements.StaticLabel; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensData; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.JsonHelper; +import info.nightscout.androidaps.utils.SP; +import info.nightscout.androidaps.utils.T; + +public class TriggerAutosensValue extends Trigger { + private static Logger log = LoggerFactory.getLogger(L.AUTOMATION); + private final int minValue = (int) (SP.getDouble("openapsama_autosens_min", 0.7d) * 100); + private final int maxValue = (int) (SP.getDouble("openapsama_autosens_max", 1.2d) * 100); + private final double step = 1; + private DecimalFormat decimalFormat = new DecimalFormat("1"); + private InputDouble value = new InputDouble(100, (double) minValue, (double) maxValue, step, decimalFormat); + private Comparator comparator = new Comparator(); + + public TriggerAutosensValue() { + super(); + } + + private TriggerAutosensValue(TriggerAutosensValue triggerAutosensValue) { + super(); + value = new InputDouble(triggerAutosensValue.value); + lastRun = triggerAutosensValue.lastRun; + comparator = new Comparator(triggerAutosensValue.comparator); + } + + public double getValue() { + return value.getValue(); + } + + public Comparator getComparator() { + return comparator; + } + + @Override + public synchronized boolean shouldRun() { + AutosensData autosensData = IobCobCalculatorPlugin.getPlugin().getLastAutosensData("Automation trigger"); + if (autosensData == null) + if (comparator.getValue() == Comparator.Compare.IS_NOT_AVAILABLE) + return true; + else + return false; + + if (lastRun > DateUtil.now() - T.mins(5).msecs()) + return false; + + boolean doRun = comparator.getValue().check((autosensData.autosensResult.ratio), getValue() / 100d); + if (doRun) { + if (L.isEnabled(L.AUTOMATION)) + log.debug("Ready for execution: " + friendlyDescription()); + return true; + } + return false; + } + + @Override + public synchronized String toJSON() { + JSONObject o = new JSONObject(); + try { + o.put("type", TriggerAutosensValue.class.getName()); + JSONObject data = new JSONObject(); + data.put("value", getValue()); + data.put("lastRun", lastRun); + data.put("comparator", comparator.getValue().toString()); + o.put("data", data); + } catch (JSONException e) { + e.printStackTrace(); + } + return o.toString(); + } + + @Override + Trigger fromJSON(String data) { + try { + JSONObject d = new JSONObject(data); + value.setValue(JsonHelper.safeGetDouble(d, "value")); + lastRun = JsonHelper.safeGetLong(d, "lastRun"); + comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator"))); + } catch (Exception e) { + e.printStackTrace(); + } + return this; + } + + @Override + public int friendlyName() { + return R.string.autosenslabel; + } + + @Override + public String friendlyDescription() { + return MainApp.gs(R.string.autosenscompared, MainApp.gs(comparator.getValue().getStringRes()), getValue()); + } + + @Override + public Optional icon() { + return Optional.of(R.drawable.as); + } + + @Override + public Trigger duplicate() { + return new TriggerAutosensValue(this); + } + + TriggerAutosensValue setValue(int requestedValue) { + this.value.setValue(requestedValue); + return this; + } + + TriggerAutosensValue lastRun(long lastRun) { + this.lastRun = lastRun; + return this; + } + + TriggerAutosensValue comparator(Comparator.Compare compare) { + this.comparator = new Comparator().setValue(compare); + return this; + } + + @Override + public void generateDialog(LinearLayout root, FragmentManager fragmentManager) { + new LayoutBuilder() + .add(new StaticLabel(R.string.autosenslabel)) + .add(comparator) + .add(new LabelWithElement(MainApp.gs(R.string.autosenslabel) + ": ", "", value)) + .build(root); + } +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f258c3ef9d..a8a5925d6f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1400,6 +1400,8 @@ not exists Temp target %1$s WiFi SSID %1$s %2$s + Autosens %1$s %2$s %% + Autosens % BG %3$s %1$s %2$s BG difference Current Location diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerAutosensValueTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerAutosensValueTest.java new file mode 100644 index 0000000000..ab1851aefc --- /dev/null +++ b/app/src/test/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerAutosensValueTest.java @@ -0,0 +1,132 @@ +package info.nightscout.androidaps.plugins.general.automation.triggers; + +import com.google.common.base.Optional; +import com.squareup.otto.Bus; + +import org.json.JSONException; +import org.json.JSONObject; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import info.AAPSMocker; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; +import info.nightscout.androidaps.plugins.general.automation.elements.Comparator; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensData; +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.SP; + +import static org.mockito.ArgumentMatchers.anyDouble; +import static org.powermock.api.mockito.PowerMockito.when; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({MainApp.class, Bus.class, ProfileFunctions.class, DateUtil.class, IobCobCalculatorPlugin.class, SP.class}) +public class TriggerAutosensValueTest { + + long now = 1514766900000L; + + @Test + public void shouldRunTest() { + Mockito.when(SP.getDouble(Mockito.eq("openapsama_autosens_max"), anyDouble())).thenReturn(1.2d); + Mockito.when(SP.getDouble(Mockito.eq("openapsama_autosens_min"), anyDouble())).thenReturn(0.7d); + when(IobCobCalculatorPlugin.getPlugin().getLastAutosensData("Automation trigger")).thenReturn(generateAutosensData()); + TriggerAutosensValue t = new TriggerAutosensValue().setValue(110).comparator(Comparator.Compare.IS_EQUAL); + Assert.assertEquals(110, t.getValue(), 0.01d); + Assert.assertEquals(Comparator.Compare.IS_EQUAL, t.getComparator().getValue()); + Assert.assertFalse(t.shouldRun()); + t = new TriggerAutosensValue().setValue(100).comparator(Comparator.Compare.IS_EQUAL); + Assert.assertEquals(100, t.getValue(), 0.01d); + Assert.assertTrue(t.shouldRun()); + t = new TriggerAutosensValue().setValue(50).comparator(Comparator.Compare.IS_EQUAL_OR_GREATER); + Assert.assertTrue(t.shouldRun()); + t = new TriggerAutosensValue().setValue(310).comparator(Comparator.Compare.IS_EQUAL_OR_LESSER); + Assert.assertTrue(t.shouldRun()); + t = new TriggerAutosensValue().setValue(420).comparator(Comparator.Compare.IS_EQUAL); + Assert.assertFalse(t.shouldRun()); + t = new TriggerAutosensValue().setValue(390).comparator(Comparator.Compare.IS_EQUAL_OR_LESSER); + Assert.assertTrue(t.shouldRun()); + t = new TriggerAutosensValue().setValue(390).comparator(Comparator.Compare.IS_EQUAL_OR_GREATER); + Assert.assertFalse(t.shouldRun()); + t = new TriggerAutosensValue().setValue(20).comparator(Comparator.Compare.IS_EQUAL_OR_GREATER); + Assert.assertTrue(t.shouldRun()); + t = new TriggerAutosensValue().setValue(390).comparator(Comparator.Compare.IS_EQUAL_OR_LESSER); + Assert.assertTrue(t.shouldRun()); + + when(IobCobCalculatorPlugin.getPlugin().getLastAutosensData("Automation trigger")).thenReturn(new AutosensData()); + t = new TriggerAutosensValue().setValue(80).comparator(Comparator.Compare.IS_EQUAL_OR_LESSER); + Assert.assertFalse(t.shouldRun()); + + // Test autosensData == null and Comparator == IS_NOT_AVAILABLE + when(IobCobCalculatorPlugin.getPlugin().getLastAutosensData("Automation trigger")).thenReturn(null); + t = new TriggerAutosensValue().comparator(Comparator.Compare.IS_NOT_AVAILABLE); + Assert.assertTrue(t.shouldRun()); + + t = new TriggerAutosensValue().setValue(214).comparator(Comparator.Compare.IS_EQUAL).lastRun(now - 1); + Assert.assertFalse(t.shouldRun()); + + } + + @Test + public void copyConstructorTest() { + TriggerAutosensValue t = new TriggerAutosensValue().setValue(213).comparator(Comparator.Compare.IS_EQUAL_OR_LESSER); + TriggerAutosensValue t1 = (TriggerAutosensValue) t.duplicate(); + Assert.assertEquals(213, t1.getValue(), 0.01d); + Assert.assertEquals(Comparator.Compare.IS_EQUAL_OR_LESSER, t.getComparator().getValue()); + } + + @Test + public void executeTest() { + TriggerAutosensValue t = new TriggerAutosensValue().setValue(213).comparator(Comparator.Compare.IS_EQUAL_OR_LESSER); + t.executed(1); + Assert.assertEquals(1l, t.getLastRun()); + } + + String ASJson = "{\"data\":{\"comparator\":\"IS_EQUAL\",\"lastRun\":0,\"value\":410},\"type\":\"info.nightscout.androidaps.plugins.general.automation.triggers.TriggerAutosensValue\"}"; + + @Test + public void toJSONTest() { + TriggerAutosensValue t = new TriggerAutosensValue().setValue(410).comparator(Comparator.Compare.IS_EQUAL); + Assert.assertEquals(ASJson, t.toJSON()); + } + + @Test + public void fromJSONTest() throws JSONException { + TriggerAutosensValue t = new TriggerAutosensValue().setValue(410).comparator(Comparator.Compare.IS_EQUAL); + + TriggerAutosensValue t2 = (TriggerAutosensValue) Trigger.instantiate(new JSONObject(t.toJSON())); + Assert.assertEquals(Comparator.Compare.IS_EQUAL, t2.getComparator().getValue()); + Assert.assertEquals(410, t2.getValue(), 0.01d); + } + + @Test + public void iconTest() { + Assert.assertEquals(Optional.of(R.drawable.as), new TriggerAutosensValue().icon()); + } + + + @Before + public void mock() { + AAPSMocker.mockMainApp(); + AAPSMocker.mockBus(); + AAPSMocker.mockIobCobCalculatorPlugin(); + AAPSMocker.mockProfileFunctions(); + AAPSMocker.mockSP(); + PowerMockito.mockStatic(DateUtil.class); + when(DateUtil.now()).thenReturn(now); + + } + + AutosensData generateAutosensData() { + AutosensData data = new AutosensData(); + return data; + } + +}