TriggerIob, refactoring, lint cleanup, tests

This commit is contained in:
Milos Kozak 2019-04-21 10:04:30 +02:00
parent 27783fe33e
commit 8ca3d7cba2
40 changed files with 818 additions and 630 deletions

View file

@ -17,9 +17,13 @@ public class AutomationEvent {
private List<Action> actions = new ArrayList<>();
private String title;
public void setTitle(String title) { this.title = title; }
public void setTitle(String title) {
this.title = title;
}
public void setTrigger(Trigger trigger) { this.trigger = trigger; }
public void setTrigger(Trigger trigger) {
this.trigger = trigger;
}
public Trigger getTrigger() {
return trigger;
@ -29,7 +33,9 @@ public class AutomationEvent {
return actions;
}
public void addAction(Action action) { actions.add(action); }
public void addAction(Action action) {
actions.add(action);
}
public String getTitle() {
return title;

View file

@ -48,13 +48,17 @@ public class AutomationFragment extends SubscriberFragment {
private EventListAdapter mEventListAdapter;
FragmentManager mFragmentManager;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.automation_fragment, container, false);
unbinder = ButterKnife.bind(this, view);
mFragmentManager = getFragmentManager();
final AutomationPlugin plugin = AutomationPlugin.getPlugin();
mEventListAdapter = new EventListAdapter(plugin.getAutomationEvents(), getFragmentManager());
mEventListView.setLayoutManager(new LinearLayoutManager(getContext()));
@ -88,10 +92,35 @@ public class AutomationFragment extends SubscriberFragment {
}
@OnClick(R.id.fabAddEvent)
@SuppressWarnings("unused")
void onClickAddEvent(View v) {
EditEventDialog dialog = EditEventDialog.newInstance(new AutomationEvent(), true);
if (getFragmentManager() != null) {
dialog.show(getFragmentManager(), "EditEventDialog");
}
}
public static void changeConnector(final FragmentManager fragmentManager, final Trigger trigger, final TriggerConnector connector, final TriggerConnector.Type newConnectorType) {
if (connector.size() > 2) {
// split connector
int pos = connector.pos(trigger) - 1;
TriggerConnector newConnector = new TriggerConnector(newConnectorType);
// move trigger from pos and pos+1 into new connector
for (int i = 0; i < 2; ++i) {
Trigger t = connector.get(pos);
newConnector.add(t);
connector.remove(t);
}
connector.add(pos, newConnector);
} else {
connector.changeConnectorType(newConnectorType);
}
connector.simplify().rebuildView(fragmentManager);
}
/**
* RecyclerViewAdapter to display event lists.
@ -100,7 +129,7 @@ public class AutomationFragment extends SubscriberFragment {
private final List<AutomationEvent> mEventList;
private final FragmentManager mFragmentManager;
public EventListAdapter(List<AutomationEvent> events, FragmentManager fragmentManager) {
EventListAdapter(List<AutomationEvent> events, FragmentManager fragmentManager) {
this.mEventList = events;
this.mFragmentManager = fragmentManager;
}
@ -174,7 +203,7 @@ public class AutomationFragment extends SubscriberFragment {
final Context context;
final ImageView iconTrash;
public ViewHolder(View view, Context context) {
ViewHolder(View view, Context context) {
super(view);
this.context = context;
eventTitle = view.findViewById(R.id.viewEventTitle);
@ -231,7 +260,7 @@ public class AutomationFragment extends SubscriberFragment {
LinearLayout layoutText;
ImageView iconTrash;
public ViewHolder(View view) {
ViewHolder(View view) {
super(view);
layoutText = view.findViewById(R.id.layoutText);
actionTitle = view.findViewById(R.id.viewActionTitle);
@ -244,37 +273,33 @@ public class AutomationFragment extends SubscriberFragment {
/**
* Custom Adapter to display triggers dynamically with nested linear layouts.
*/
public static class TriggerListAdapter {
public class TriggerListAdapter {
private final LinearLayout mRootLayout;
private final FragmentManager mFragmentManager;
private final Context mContext;
private final TriggerConnector mRootConnector;
private final FragmentManager mFragmentManager;
public TriggerListAdapter(Context context, FragmentManager fragmentManager, LinearLayout rootLayout, TriggerConnector rootTrigger) {
public TriggerListAdapter(FragmentManager fragmentManager, Context context, LinearLayout rootLayout, TriggerConnector rootTrigger) {
mRootLayout = rootLayout;
mContext = context;
mFragmentManager = fragmentManager;
mContext = context;
mRootConnector = rootTrigger;
build();
build(fragmentManager);
}
public Context getContext() {
return mContext;
}
public LinearLayout getRootLayout() {
return mRootLayout;
}
public FragmentManager getFragmentManager() {
FragmentManager getFM() {
return mFragmentManager;
}
public void destroy() {
void destroy() {
mRootLayout.removeAllViews();
}
private void build() {
private void build(FragmentManager fragmentManager) {
for (int i = 0; i < mRootConnector.size(); ++i) {
final Trigger trigger = mRootConnector.get(i);
@ -284,22 +309,22 @@ public class AutomationFragment extends SubscriberFragment {
}
// trigger layout
mRootLayout.addView(trigger.createView(mContext, mFragmentManager));
trigger.generateDialog(mRootLayout, fragmentManager);
// buttons
createButtons(trigger);
createButtons(fragmentManager, trigger);
}
if (mRootConnector.size() == 0) {
Button buttonAdd = new Button(mContext);
buttonAdd.setText("Add New");
buttonAdd.setText(MainApp.gs(R.string.addnew));
buttonAdd.setOnClickListener(v -> {
ChooseTriggerDialog dialog = ChooseTriggerDialog.newInstance();
dialog.setOnClickListener(newTriggerObject -> {
mRootConnector.add(newTriggerObject);
rebuild();
rebuild(fragmentManager);
});
dialog.show(mFragmentManager, "ChooseTriggerDialog");
dialog.show(fragmentManager, "ChooseTriggerDialog");
});
mRootLayout.addView(buttonAdd);
}
@ -329,8 +354,8 @@ public class AutomationFragment extends SubscriberFragment {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (position != initialPosition) {
// conector type changed
changeConnector(trigger, connector, TriggerConnector.Type.values()[position]);
// connector type changed
changeConnector(getFM(), trigger, connector, TriggerConnector.Type.values()[position]);
}
}
@ -341,7 +366,7 @@ public class AutomationFragment extends SubscriberFragment {
mRootLayout.addView(spinner);
}
private void createButtons(Trigger trigger) {
private void createButtons(FragmentManager fragmentManager, Trigger trigger) {
// do not create buttons for TriggerConnector
if (trigger instanceof TriggerConnector) {
return;
@ -355,64 +380,42 @@ public class AutomationFragment extends SubscriberFragment {
// Button [-]
Button buttonRemove = new Button(mContext);
buttonRemove.setText("del");
buttonRemove.setText(MainApp.gs(R.string.delete_short));
buttonRemove.setOnClickListener(v -> {
final TriggerConnector connector = trigger.getConnector();
connector.remove(trigger);
connector.simplify().rebuildView();
connector.simplify().rebuildView(getFM());
});
buttonLayout.addView(buttonRemove);
// Button [+]
Button buttonAdd = new Button(mContext);
buttonAdd.setText("add");
buttonAdd.setText(MainApp.gs(R.string.add_short));
buttonAdd.setOnClickListener(v -> {
ChooseTriggerDialog dialog = ChooseTriggerDialog.newInstance();
dialog.show(mFragmentManager, "ChooseTriggerDialog");
dialog.show(fragmentManager, "ChooseTriggerDialog");
dialog.setOnClickListener(newTriggerObject -> {
TriggerConnector connector = trigger.getConnector();
connector.add(connector.pos(trigger) + 1, newTriggerObject);
connector.simplify().rebuildView();
connector.simplify().rebuildView(getFM());
});
});
buttonLayout.addView(buttonAdd);
// Button [*]
Button buttonCopy = new Button(mContext);
buttonCopy.setText("copy");
buttonCopy.setText(MainApp.gs(R.string.copy_short));
buttonCopy.setOnClickListener(v -> {
TriggerConnector connector = trigger.getConnector();
connector.add(connector.pos(trigger) + 1, trigger.duplicate());
connector.simplify().rebuildView();
connector.simplify().rebuildView(getFM());
});
buttonLayout.addView(buttonCopy);
}
public static void changeConnector(final Trigger trigger, final TriggerConnector connector, final TriggerConnector.Type newConnectorType) {
if (connector.size() > 2) {
// split connector
int pos = connector.pos(trigger) - 1;
TriggerConnector newConnector = new TriggerConnector(newConnectorType);
// move trigger from pos and pos+1 into new connector
for (int i = 0; i < 2; ++i) {
Trigger t = connector.get(pos);
newConnector.add(t);
connector.remove(t);
}
connector.add(pos, newConnector);
} else {
connector.changeConnectorType(newConnectorType);
}
connector.simplify().rebuildView();
}
public void rebuild() {
public void rebuild(FragmentManager fragmentManager) {
destroy();
build();
build(fragmentManager);
}
}

View file

@ -39,7 +39,7 @@ public class AutomationPlugin extends PluginBase {
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
private final String key_AUTOMATION_EVENTS = "AUTOMATION_EVENTS";
static AutomationPlugin plugin = null;
private static AutomationPlugin plugin = null;
public static AutomationPlugin getPlugin() {
if (plugin == null)
@ -176,7 +176,7 @@ public class AutomationPlugin extends PluginBase {
processActions();
}
synchronized void processActions() {
private synchronized void processActions() {
if (L.isEnabled(L.AUTOMATION))
log.debug("processActions");
for (AutomationEvent event : getAutomationEvents()) {

View file

@ -7,6 +7,8 @@ import com.google.common.base.Optional;
import org.json.JSONException;
import org.json.JSONObject;
import javax.annotation.Nullable;
import info.nightscout.androidaps.queue.Callback;
/*
@ -43,13 +45,17 @@ import info.nightscout.androidaps.queue.Callback;
public abstract class Action {
public abstract int friendlyName();
public abstract String shortDescription();
public abstract void doAction(Callback callback);
public void generateDialog(LinearLayout root) { }
public void generateDialog(LinearLayout root) {
}
public boolean hasDialog() { return false; }
public boolean hasDialog() {
return false;
}
public String toJSON() {
JSONObject o = new JSONObject();
@ -67,6 +73,7 @@ public abstract class Action {
return this;
}
@Nullable
public static Action instantiate(JSONObject object) {
try {
String type = object.getString("type");

View file

@ -7,8 +7,8 @@ import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.events.EventRefreshOverview;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.queue.Callback;
public class ActionLoopDisable extends Action {

View file

@ -7,8 +7,8 @@ import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.events.EventRefreshOverview;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.queue.Callback;
public class ActionLoopEnable extends Action {

View file

@ -6,8 +6,8 @@ import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.events.EventRefreshOverview;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
import info.nightscout.androidaps.queue.Callback;

View file

@ -10,10 +10,10 @@ import org.json.JSONObject;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
import info.nightscout.androidaps.plugins.general.automation.elements.InputBg;
import info.nightscout.androidaps.plugins.general.automation.elements.InputDuration;
import info.nightscout.androidaps.plugins.general.automation.elements.Label;
@ -25,13 +25,9 @@ import info.nightscout.androidaps.utils.JsonHelper;
public class ActionStartTempTarget extends Action {
String reason = "";
InputBg value;
InputBg value = new InputBg();
InputDuration duration = new InputDuration(0, InputDuration.TimeUnit.MINUTES);
TempTarget tempTarget;
public ActionStartTempTarget() {
value = new InputBg(ProfileFunctions.getInstance().getProfileUnits());
}
private TempTarget tempTarget;
@Override
public int friendlyName() {
@ -40,13 +36,25 @@ public class ActionStartTempTarget extends Action {
@Override
public String shortDescription() {
tempTarget = new TempTarget().date(DateUtil.now()).duration((int) duration.getMinutes()).reason(reason).source(Source.USER).low(value.getMgdl()).high(value.getMgdl());
tempTarget = new TempTarget()
.date(DateUtil.now())
.duration(duration.getMinutes())
.reason(reason)
.source(Source.USER)
.low(Profile.toMgdl(value.getValue(), value.getUnits()))
.high(Profile.toMgdl(value.getValue(), value.getUnits()));
return MainApp.gs(R.string.starttemptarget) + ": " + (tempTarget == null ? "null" : tempTarget.friendlyDescription(value.getUnits()));
}
@Override
public void doAction(Callback callback) {
tempTarget = new TempTarget().date(DateUtil.now()).duration((int) duration.getMinutes()).reason(reason).source(Source.USER).low(value.getMgdl()).high(value.getMgdl());
tempTarget = new TempTarget()
.date(DateUtil.now())
.duration(duration.getMinutes())
.reason(reason)
.source(Source.USER)
.low(Profile.toMgdl(value.getValue(), value.getUnits()))
.high(Profile.toMgdl(value.getValue(), value.getUnits()));
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
if (callback != null)
callback.result(new PumpEnactResult().success(true).comment(R.string.ok)).run();
@ -74,7 +82,7 @@ public class ActionStartTempTarget extends Action {
o.put("type", ActionStartTempTarget.class.getName());
JSONObject data = new JSONObject();
data.put("reason", reason);
data.put("valueInMg", value.getMgdl());
data.put("value", value.getValue());
data.put("units", value.getUnits());
data.put("durationInMinutes", duration.getMinutes());
o.put("data", data);
@ -90,7 +98,7 @@ public class ActionStartTempTarget extends Action {
JSONObject d = new JSONObject(data);
reason = JsonHelper.safeGetString(d, "reason");
value.setUnits(JsonHelper.safeGetString(d, "units"));
value.setMgdl(JsonHelper.safeGetInt(d, "valueInMg"));
value.setValue(JsonHelper.safeGetInt(d, "value"));
duration.setMinutes(JsonHelper.safeGetInt(d, "durationInMinutes"));
} catch (JSONException e) {
e.printStackTrace();

View file

@ -17,7 +17,7 @@ import info.nightscout.androidaps.utils.JsonHelper;
public class ActionStopTempTarget extends Action {
String reason = "";
TempTarget tempTarget;
private TempTarget tempTarget;
public ActionStopTempTarget() {
}

View file

@ -122,6 +122,7 @@ public class ChooseActionDialog extends DialogFragment {
}
@OnClick(R.id.ok)
@SuppressWarnings("unused")
public void onButtonOk(View view) {
if (mClickListener != null)
mClickListener.onClick(instantiateAction());
@ -130,6 +131,7 @@ public class ChooseActionDialog extends DialogFragment {
}
@OnClick(R.id.cancel)
@SuppressWarnings("unused")
public void onButtonCancel(View view) {
dismiss();
}

View file

@ -117,6 +117,7 @@ public class ChooseTriggerDialog extends DialogFragment {
}
@OnClick(R.id.ok)
@SuppressWarnings("unused")
public void onButtonOk(View view) {
if (mClickListener != null)
mClickListener.onClick(instantiateTrigger());
@ -125,6 +126,7 @@ public class ChooseTriggerDialog extends DialogFragment {
}
@OnClick(R.id.cancel)
@SuppressWarnings("unused")
public void onButtonCancel(View view) {
dismiss();
}

View file

@ -63,10 +63,11 @@ public class EditActionDialog extends DialogFragment {
e.printStackTrace();
}
if (mAction != null) {
mViewActionTitle.setText(mAction.friendlyName());
mRootLayout.removeAllViews();
mAction.generateDialog(mRootLayout);
}
return view;
}
@ -78,6 +79,7 @@ public class EditActionDialog extends DialogFragment {
}
@OnClick(R.id.ok)
@SuppressWarnings("unused")
public void onButtonOk(View view) {
resultAction.apply(mAction);
dismiss();
@ -85,6 +87,7 @@ public class EditActionDialog extends DialogFragment {
}
@OnClick(R.id.cancel)
@SuppressWarnings("unused")
public void onButtonCancel(View view) {
dismiss();
}

View file

@ -104,6 +104,7 @@ public class EditEventDialog extends DialogFragment {
});
mEditTrigger.setOnClickListener(v -> {
EditTriggerDialog dialog = EditTriggerDialog.newInstance(mEvent.getTrigger());
if (getFragmentManager() != null)
dialog.show(getFragmentManager(), "EditTriggerDialog");
});
@ -119,6 +120,7 @@ public class EditEventDialog extends DialogFragment {
});
mEditAction.setOnClickListener(v -> {
ChooseActionDialog dialog = ChooseActionDialog.newInstance();
if (getFragmentManager() != null)
dialog.show(getFragmentManager(), "ChooseActionDialog");
});
@ -142,6 +144,7 @@ public class EditEventDialog extends DialogFragment {
}
@OnClick(R.id.ok)
@SuppressWarnings("unused")
public void onButtonOk(View view) {
// check for title
String title = mEditEventTitle.getText().toString();
@ -179,6 +182,7 @@ public class EditEventDialog extends DialogFragment {
}
@OnClick(R.id.cancel)
@SuppressWarnings("unused")
public void onButtonCancel(View view) {
dismiss();
}

View file

@ -50,7 +50,9 @@ public class EditTriggerDialog extends DialogFragment {
}
// display root trigger
mLayoutTrigger.addView(mTrigger.createView(getContext(), getFragmentManager()));
if (mTrigger != null) {
mTrigger.generateDialog(mLayoutTrigger, getFragmentManager());
}
return view;
}
@ -66,6 +68,7 @@ public class EditTriggerDialog extends DialogFragment {
}
@OnClick(R.id.ok)
@SuppressWarnings("unused")
public void onButtonOk(View view) {
if (mClickListener != null)
mClickListener.onClick(mTrigger);
@ -74,6 +77,7 @@ public class EditTriggerDialog extends DialogFragment {
}
@OnClick(R.id.cancel)
@SuppressWarnings("unused")
public void onButtonCancel(View view) {
dismiss();
}

View file

@ -0,0 +1,122 @@
package info.nightscout.androidaps.plugins.general.automation.elements;
import android.support.annotation.StringRes;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.Spinner;
import java.util.ArrayList;
import java.util.List;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
public class Comparator extends Element {
public enum Compare {
IS_LESSER,
IS_EQUAL_OR_LESSER,
IS_EQUAL,
IS_EQUAL_OR_GREATER,
IS_GREATER,
IS_NOT_AVAILABLE;
public @StringRes
int getStringRes() {
switch (this) {
case IS_LESSER:
return R.string.islesser;
case IS_EQUAL_OR_LESSER:
return R.string.isequalorlesser;
case IS_EQUAL:
return R.string.isequal;
case IS_EQUAL_OR_GREATER:
return R.string.isequalorgreater;
case IS_GREATER:
return R.string.isgreater;
case IS_NOT_AVAILABLE:
return R.string.isnotavailable;
default:
return R.string.unknown;
}
}
public <T extends Comparable> boolean check(T obj1, T obj2) {
if (obj1 == null || obj2 == null)
return this.equals(IS_NOT_AVAILABLE);
int comparison = obj1.compareTo(obj2);
switch (this) {
case IS_LESSER:
return comparison < 0;
case IS_EQUAL_OR_LESSER:
return comparison <= 0;
case IS_EQUAL:
return comparison == 0;
case IS_EQUAL_OR_GREATER:
return comparison >= 0;
case IS_GREATER:
return comparison > 0;
default:
return false;
}
}
public static List<String> labels() {
List<String> list = new ArrayList<>();
for (Compare c : Compare.values()) {
list.add(MainApp.gs(c.getStringRes()));
}
return list;
}
}
private Compare compare = Compare.IS_EQUAL;
public Comparator() {
super();
}
public Comparator(Comparator another) {
super();
compare = another.getValue();
}
@Override
public void addToLayout(LinearLayout root) {
Spinner spinner = new Spinner(root.getContext());
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(root.getContext(), android.R.layout.simple_spinner_item, Compare.labels());
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(spinnerArrayAdapter);
LinearLayout.LayoutParams spinnerParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
spinnerParams.setMargins(0, MainApp.dpToPx(4), 0, MainApp.dpToPx(4));
spinner.setLayoutParams(spinnerParams);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
compare = Compare.values()[position];
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
spinner.setSelection(compare.ordinal());
root.addView(spinner);
}
public Compare getValue() {
return compare;
}
public Comparator setValue(Compare compare) {
this.compare = compare;
return this;
}
}

View file

@ -2,6 +2,6 @@ package info.nightscout.androidaps.plugins.general.automation.elements;
import android.widget.LinearLayout;
public class Element {
public void addToLayout(LinearLayout root) { }
public abstract class Element {
public abstract void addToLayout(LinearLayout root);
}

View file

@ -7,14 +7,21 @@ import android.widget.LinearLayout;
import java.text.DecimalFormat;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
import info.nightscout.androidaps.utils.NumberPicker;
public class InputBg extends Element {
final private TextWatcher textWatcher = new TextWatcher() {
final TextWatcher textWatcher = new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
// TODO: validate inputs
if (units.equals(Constants.MMOL)) {
value = Math.max(value, 4d);
value = Math.min(value, 15d);
} else {
value = Math.max(value, 72d);
value = Math.min(value, 270d);
}
}
@Override
@ -26,37 +33,29 @@ public class InputBg extends Element {
}
};
private String units;
private String units = Constants.MGDL;
private double value;
private final double minValue, maxValue, step;
private final DecimalFormat decimalFormat;
double minValue;
private double maxValue;
private double step;
private DecimalFormat decimalFormat;
public InputBg(String units) {
this.units = units;
public InputBg() {
super();
setUnits(ProfileFunctions.getInstance().getProfileUnits());
}
// set default initial value
if (units.equals(Constants.MMOL)) {
// mmol
value = 5.5;
minValue = 2;
maxValue = 30;
step = 0.1;
decimalFormat = new DecimalFormat("0.0");
} else {
// mg/dL
value = 100;
minValue = 36;
maxValue = 540;
step = 1;
decimalFormat = new DecimalFormat("0");
}
public InputBg(InputBg another) {
super();
value = another.getValue();
setUnits(another.getUnits());
}
@Override
public void addToLayout(LinearLayout root) {
NumberPicker numberPicker = new NumberPicker(root.getContext(), null);
numberPicker.setParams(0d, minValue, maxValue, step, decimalFormat, false, textWatcher);
numberPicker.setValue(value);
numberPicker.setParams(value, minValue, maxValue, step, decimalFormat, true, textWatcher);
numberPicker.setOnValueChangedListener(value -> this.value = value);
root.addView(numberPicker);
}
@ -65,23 +64,33 @@ public class InputBg extends Element {
return units;
}
public void setUnits(String units) {
if (!this.units.equals(units)) {
String previousUnits = this.units;
this.units = units;
value = Profile.toUnits(Profile.toMgdl(value, previousUnits), Profile.toMmol(value, previousUnits), units);
public InputBg setUnits(String units) {
// set default initial value
if (units.equals(Constants.MMOL)) {
// mmol
minValue = 2;
maxValue = 30;
step = 0.1;
decimalFormat = new DecimalFormat("0.0");
} else {
// mg/dL
minValue = 40;
maxValue = 540;
step = 1;
decimalFormat = new DecimalFormat("0");
}
this.units = units;
return this;
}
public InputBg setValue(double value) {
this.value = value;
return this;
}
public double getValue() {
return value;
}
public int getMgdl() {
return (int)Profile.toMgdl(value, units);
}
public void setMgdl(int value) {
this.value = Profile.fromMgdlToUnits(value, units);
}
}

View file

@ -35,7 +35,7 @@ public class InputDuration extends Element {
root.addView(numberPicker);
}
public TimeUnit getUnit() {
TimeUnit getUnit() {
return unit;
}

View file

@ -0,0 +1,57 @@
package info.nightscout.androidaps.plugins.general.automation.elements;
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.LinearLayout;
import java.text.DecimalFormat;
import info.nightscout.androidaps.utils.NumberPicker;
public class InputInsulin extends Element {
final TextWatcher textWatcher = new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
value = Math.max(value, -20d);
value = Math.min(value, 20d);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
};
private double value;
public InputInsulin() {
super();
}
public InputInsulin(InputInsulin another) {
super();
value = another.getValue();
}
@Override
public void addToLayout(LinearLayout root) {
NumberPicker numberPicker = new NumberPicker(root.getContext(), null);
numberPicker.setParams(0d, -20d, 20d, 0.1, new DecimalFormat("0.0"), true, textWatcher);
numberPicker.setValue(value);
numberPicker.setOnValueChangedListener(value -> this.value = value);
root.addView(numberPicker);
}
public double getValue() {
return value;
}
public InputInsulin setValue(double value) {
this.value = value;
return this;
}
}

View file

@ -8,9 +8,9 @@ import android.widget.TextView;
import info.nightscout.androidaps.MainApp;
public class Label extends Element {
private final Element element;
private final String textPre;
private final String textPost;
final Element element;
final String textPre;
final String textPost;
public Label(String textPre, String textPost, Element element) {
this.element = element;

View file

@ -5,7 +5,7 @@ import android.widget.LinearLayout;
import java.util.ArrayList;
public class LayoutBuilder {
private ArrayList<Element> mElements = new ArrayList<>();
ArrayList<Element> mElements = new ArrayList<>();
public LayoutBuilder add(Element element) {
mElements.add(element);
@ -13,7 +13,6 @@ public class LayoutBuilder {
}
public void build(LinearLayout layout) {
layout.removeAllViews();
for (Element e : mElements) {
e.addToLayout(layout);
}

View file

@ -1,10 +1,9 @@
package info.nightscout.androidaps.plugins.general.automation.triggers;
import android.support.v4.app.FragmentManager;
import android.app.Activity;
import android.content.Context;
import android.support.annotation.StringRes;
import android.view.View;
import android.view.ViewGroup;
import android.content.ContextWrapper;
import android.support.v4.app.FragmentManager;
import android.widget.LinearLayout;
import android.widget.TextView;
@ -13,72 +12,12 @@ import com.google.common.base.Optional;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import javax.annotation.Nullable;
public abstract class Trigger {
public enum Comparator {
IS_LESSER,
IS_EQUAL_OR_LESSER,
IS_EQUAL,
IS_EQUAL_OR_GREATER,
IS_GREATER,
IS_NOT_AVAILABLE;
public @StringRes int getStringRes() {
switch (this) {
case IS_LESSER:
return R.string.islesser;
case IS_EQUAL_OR_LESSER:
return R.string.isequalorlesser;
case IS_EQUAL:
return R.string.isequal;
case IS_EQUAL_OR_GREATER:
return R.string.isequalorgreater;
case IS_GREATER:
return R.string.isgreater;
case IS_NOT_AVAILABLE:
return R.string.isnotavailable;
default:
return R.string.unknown;
}
}
public <T extends Comparable> boolean check(T obj1, T obj2) {
if (obj1 == null || obj2 == null)
return this.equals(Comparator.IS_NOT_AVAILABLE);
int comparison = obj1.compareTo(obj2);
switch (this) {
case IS_LESSER:
return comparison < 0;
case IS_EQUAL_OR_LESSER:
return comparison <= 0;
case IS_EQUAL:
return comparison == 0;
case IS_EQUAL_OR_GREATER:
return comparison >= 0;
case IS_GREATER:
return comparison > 0;
default:
return false;
}
}
public static List<String> labels() {
List<String> list = new ArrayList<>();
for(Comparator c : values()) {
list.add(MainApp.gs(c.getStringRes()));
}
return list;
}
}
protected TriggerConnector connector = null;
TriggerConnector connector = null;
long lastRun;
Trigger() {
}
@ -92,7 +31,8 @@ public abstract class Trigger {
public abstract String toJSON();
/*package*/ abstract Trigger fromJSON(String data);
/*package*/
abstract Trigger fromJSON(String data);
public abstract int friendlyName();
@ -100,7 +40,13 @@ public abstract class Trigger {
public abstract Optional<Integer> icon();
public abstract void executed(long time);
public void executed(long time) {
lastRun = time;
}
public long getLastRun() {
return lastRun;
}
public abstract Trigger duplicate();
@ -113,6 +59,7 @@ public abstract class Trigger {
return null;
}
@Nullable
public static Trigger instantiate(JSONObject object) {
try {
String type = object.getString("type");
@ -125,18 +72,21 @@ public abstract class Trigger {
return null;
}
public View createView(Context context, FragmentManager fragmentManager) {
final int padding = MainApp.dpToPx(4);
LinearLayout root = new LinearLayout(context);
root.setPadding(padding, padding, padding, padding);
root.setOrientation(LinearLayout.VERTICAL);
root.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
TextView title = new TextView(context);
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
TextView title = new TextView(root.getContext());
title.setText(friendlyName());
root.addView(title);
}
return root;
@Nullable
Activity scanForActivity(Context cont) {
if (cont == null)
return null;
else if (cont instanceof Activity)
return (Activity) cont;
else if (cont instanceof ContextWrapper)
return scanForActivity(((ContextWrapper) cont).getBaseContext());
return null;
}
}

View file

@ -1,17 +1,7 @@
package info.nightscout.androidaps.plugins.general.automation.triggers;
import android.content.Context;
import android.support.v4.app.FragmentManager;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import com.google.common.base.Optional;
@ -20,64 +10,39 @@ import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.DecimalFormat;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator;
import info.nightscout.androidaps.plugins.general.automation.elements.InputBg;
import info.nightscout.androidaps.plugins.general.automation.elements.Label;
import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.JsonHelper;
import info.nightscout.androidaps.utils.NumberPicker;
import info.nightscout.androidaps.utils.T;
public class TriggerBg extends Trigger {
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
private double threshold;
private Comparator comparator = Comparator.IS_EQUAL;
private String units = ProfileFunctions.getInstance().getProfileUnits();
private long lastRun;
final TextWatcher textWatcher = new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
if (units.equals(Constants.MMOL)) {
threshold = Math.max(threshold, 4d);
threshold = Math.min(threshold, 15d);
} else {
threshold = Math.max(threshold, 72d);
threshold = Math.min(threshold, 270d);
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
};
private InputBg bg = new InputBg();
private Comparator comparator = new Comparator();
public TriggerBg() {
super();
threshold = units.equals(Constants.MGDL) ? 100d : 5.5d;
}
TriggerBg(TriggerBg triggerBg) {
private TriggerBg(TriggerBg triggerBg) {
super();
comparator = triggerBg.comparator;
bg = new InputBg(triggerBg.bg);
comparator = new Comparator(triggerBg.comparator);
lastRun = triggerBg.lastRun;
units = triggerBg.units;
threshold = triggerBg.threshold;
}
public double getThreshold() {
return threshold;
public double getValue() {
return bg.getValue();
}
public Comparator getComparator() {
@ -85,7 +50,7 @@ public class TriggerBg extends Trigger {
}
public String getUnits() {
return units;
return bg.getUnits();
}
public long getLastRun() {
@ -99,7 +64,7 @@ public class TriggerBg extends Trigger {
if (lastRun > DateUtil.now() - T.mins(5).msecs())
return false;
if (glucoseStatus == null && comparator.equals(Comparator.IS_NOT_AVAILABLE)) {
if (glucoseStatus == null && comparator.getValue().equals(Comparator.Compare.IS_NOT_AVAILABLE)) {
if (L.isEnabled(L.AUTOMATION))
log.debug("Ready for execution: " + friendlyDescription());
return true;
@ -107,7 +72,7 @@ public class TriggerBg extends Trigger {
if (glucoseStatus == null)
return false;
boolean doRun = comparator.check(glucoseStatus.glucose, Profile.toMgdl(threshold, units));
boolean doRun = comparator.getValue().check(glucoseStatus.glucose, Profile.toMgdl(bg.getValue(), bg.getUnits()));
if (doRun) {
if (L.isEnabled(L.AUTOMATION))
log.debug("Ready for execution: " + friendlyDescription());
@ -122,10 +87,10 @@ public class TriggerBg extends Trigger {
try {
o.put("type", TriggerBg.class.getName());
JSONObject data = new JSONObject();
data.put("threshold", threshold);
data.put("bg", bg.getValue());
data.put("lastRun", lastRun);
data.put("comparator", comparator.toString());
data.put("units", units);
data.put("comparator", comparator.getValue().toString());
data.put("units", bg.getUnits());
o.put("data", data);
} catch (JSONException e) {
e.printStackTrace();
@ -137,11 +102,11 @@ public class TriggerBg extends Trigger {
Trigger fromJSON(String data) {
try {
JSONObject d = new JSONObject(data);
threshold = JsonHelper.safeGetDouble(d, "threshold");
bg.setValue(JsonHelper.safeGetDouble(d, "bg"));
lastRun = JsonHelper.safeGetLong(d, "lastRun");
comparator = Comparator.valueOf(JsonHelper.safeGetString(d, "comparator"));
units = JsonHelper.safeGetString(d, "units");
} catch (JSONException e) {
comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")));
bg.setUnits(JsonHelper.safeGetString(d, "units"));
} catch (Exception e) {
e.printStackTrace();
}
return this;
@ -154,10 +119,10 @@ public class TriggerBg extends Trigger {
@Override
public String friendlyDescription() {
if (comparator.equals(Comparator.IS_NOT_AVAILABLE))
if (comparator.getValue().equals(Comparator.Compare.IS_NOT_AVAILABLE))
return MainApp.gs(R.string.glucoseisnotavailable);
else {
return MainApp.gs(units.equals(Constants.MGDL) ? R.string.glucosecomparedmgdl : R.string.glucosecomparedmmol, MainApp.gs(comparator.getStringRes()), threshold, units);
return MainApp.gs(bg.getUnits().equals(Constants.MGDL) ? R.string.glucosecomparedmgdl : R.string.glucosecomparedmmol, MainApp.gs(comparator.getValue().getStringRes()), bg.getValue(), bg.getUnits());
}
}
@ -166,18 +131,13 @@ public class TriggerBg extends Trigger {
return Optional.of(R.drawable.icon_cp_bgcheck);
}
@Override
public void executed(long time) {
lastRun = time;
}
@Override
public Trigger duplicate() {
return new TriggerBg(this);
}
TriggerBg threshold(double threshold) {
this.threshold = threshold;
TriggerBg setValue(double value) {
bg.setValue(value);
return this;
}
@ -186,73 +146,21 @@ public class TriggerBg extends Trigger {
return this;
}
TriggerBg comparator(Comparator comparator) {
this.comparator = comparator;
TriggerBg comparator(Comparator.Compare compare) {
this.comparator = new Comparator().setValue(compare);
return this;
}
TriggerBg units(String units) {
this.units = units;
TriggerBg setUnits(String units) {
bg.setUnits(units);
return this;
}
@Override
public View createView(Context context, FragmentManager fragmentManager) {
LinearLayout root = (LinearLayout) super.createView(context, fragmentManager);
// spinner for comparator
Spinner spinner = new Spinner(context);
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(context, android.R.layout.simple_spinner_item, Comparator.labels());
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(spinnerArrayAdapter);
LinearLayout.LayoutParams spinnerParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
spinnerParams.setMargins(0, MainApp.dpToPx(4), 0, MainApp.dpToPx(4));
spinner.setLayoutParams(spinnerParams);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
comparator = Comparator.values()[position];
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
spinner.setSelection(comparator.ordinal());
root.addView(spinner);
// horizontal layout
LinearLayout layout = new LinearLayout(context);
layout.setOrientation(LinearLayout.HORIZONTAL);
layout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
root.addView(layout);
// input field for threshold
NumberPicker numberPicker = new NumberPicker(context, null);
double min = units.equals(Constants.MGDL) ? 3 * Constants.MMOLL_TO_MGDL : 3;
double max = units.equals(Constants.MGDL) ? 20 * Constants.MMOLL_TO_MGDL : 20;
double step = units.equals(Constants.MGDL) ? 1 : 0.1d;
DecimalFormat pattern = units.equals(Constants.MGDL) ? new DecimalFormat("0") : new DecimalFormat("0.0");
numberPicker.setParams(0d, min, max, step, pattern, false, textWatcher);
numberPicker.setValue(threshold);
numberPicker.setOnValueChangedListener(value -> threshold = value);
layout.addView(numberPicker);
// text view for unit
TextView tvUnits = new TextView(context);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.MATCH_PARENT
);
params.setMargins(MainApp.dpToPx(6), 0, 0, 0);
tvUnits.setLayoutParams(params);
tvUnits.setText(units);
tvUnits.setGravity(Gravity.CENTER_VERTICAL);
layout.addView(tvUnits);
return root;
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
new LayoutBuilder()
.add(comparator)
.add(new Label(MainApp.gs(R.string.glucose_u, bg.getUnits()), "", bg))
.build(root);
}
}

View file

@ -1,9 +1,7 @@
package info.nightscout.androidaps.plugins.general.automation.triggers;
import android.content.Context;
import android.support.annotation.StringRes;
import android.support.v4.app.FragmentManager;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
@ -194,7 +192,7 @@ public class TriggerConnector extends Trigger {
int counter = 0;
StringBuilder result = new StringBuilder();
for (Trigger t : list) {
if (counter++ > 0) result.append("\n" + MainApp.gs(friendlyName()) + "\n");
if (counter++ > 0) result.append("\n").append(MainApp.gs(friendlyName())).append("\n");
result.append(t.friendlyDescription());
}
return result.toString();
@ -219,29 +217,24 @@ public class TriggerConnector extends Trigger {
private AutomationFragment.TriggerListAdapter adapter;
public void rebuildView() {
public void rebuildView(FragmentManager fragmentManager) {
if (adapter != null)
adapter.rebuild();
adapter.rebuild(fragmentManager);
}
@Override
public View createView(Context context, FragmentManager fragmentManager) {
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
final int padding = MainApp.dpToPx(5);
LinearLayout root = new LinearLayout(context);
root.setOrientation(LinearLayout.VERTICAL);
root.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
root.setPadding(padding, padding, padding, padding);
root.setBackgroundResource(R.drawable.border_automation_unit);
LinearLayout triggerListLayout = new LinearLayout(context);
LinearLayout triggerListLayout = new LinearLayout(root.getContext());
triggerListLayout.setOrientation(LinearLayout.VERTICAL);
triggerListLayout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
root.addView(triggerListLayout);
adapter = new AutomationFragment.TriggerListAdapter(context, fragmentManager, triggerListLayout, this);
return root;
adapter = new AutomationFragment().new TriggerListAdapter(fragmentManager, root.getContext(), triggerListLayout, this);
}
public TriggerConnector simplify() {

View file

@ -1,15 +1,7 @@
package info.nightscout.androidaps.plugins.general.automation.triggers;
import android.content.Context;
import android.support.v4.app.FragmentManager;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.Spinner;
import com.google.common.base.Optional;
@ -18,66 +10,46 @@ 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.data.IobTotal;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator;
import info.nightscout.androidaps.plugins.general.automation.elements.InputInsulin;
import info.nightscout.androidaps.plugins.general.automation.elements.Label;
import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
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.NumberPicker;
import info.nightscout.androidaps.utils.T;
public class TriggerIob extends Trigger {
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
private double threshold;
private Comparator comparator = Comparator.IS_EQUAL;
private long lastRun;
final TextWatcher textWatcher = new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
threshold = Math.max(threshold, -20d);
threshold = Math.min(threshold, 20d);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
};
private InputInsulin insulin = new InputInsulin();
private Comparator comparator = new Comparator();
public TriggerIob() {
super();
}
TriggerIob(TriggerIob triggerIob) {
private TriggerIob(TriggerIob triggerIob) {
super();
comparator = triggerIob.comparator;
insulin = new InputInsulin(triggerIob.insulin);
comparator = new Comparator(triggerIob.comparator);
lastRun = triggerIob.lastRun;
threshold = triggerIob.threshold;
}
public double getThreshold() {
return threshold;
public double getValue() {
return insulin.getValue();
}
public Comparator getComparator() {
return comparator;
}
public long getLastRun() {
return lastRun;
}
@Override
public synchronized boolean shouldRun() {
Profile profile = ProfileFunctions.getInstance().getProfile();
@ -88,7 +60,7 @@ public class TriggerIob extends Trigger {
if (lastRun > DateUtil.now() - T.mins(5).msecs())
return false;
boolean doRun = comparator.check(iob.iob, threshold);
boolean doRun = comparator.getValue().check(iob.iob, getValue());
if (doRun) {
if (L.isEnabled(L.AUTOMATION))
log.debug("Ready for execution: " + friendlyDescription());
@ -103,9 +75,9 @@ public class TriggerIob extends Trigger {
try {
o.put("type", TriggerIob.class.getName());
JSONObject data = new JSONObject();
data.put("threshold", threshold);
data.put("insulin", getValue());
data.put("lastRun", lastRun);
data.put("comparator", comparator.toString());
data.put("comparator", comparator.getValue().toString());
o.put("data", data);
} catch (JSONException e) {
e.printStackTrace();
@ -117,10 +89,10 @@ public class TriggerIob extends Trigger {
Trigger fromJSON(String data) {
try {
JSONObject d = new JSONObject(data);
threshold = JsonHelper.safeGetDouble(d, "threshold");
insulin.setValue(JsonHelper.safeGetDouble(d, "insulin"));
lastRun = JsonHelper.safeGetLong(d, "lastRun");
comparator = Comparator.valueOf(JsonHelper.safeGetString(d, "comparator"));
} catch (JSONException e) {
comparator.setValue(Comparator.Compare.valueOf(JsonHelper.safeGetString(d, "comparator")));
} catch (Exception e) {
e.printStackTrace();
}
return this;
@ -133,7 +105,7 @@ public class TriggerIob extends Trigger {
@Override
public String friendlyDescription() {
return MainApp.gs(R.string.iobcompared, MainApp.gs(comparator.getStringRes()), threshold);
return MainApp.gs(R.string.iobcompared, MainApp.gs(comparator.getValue().getStringRes()), getValue());
}
@Override
@ -141,18 +113,13 @@ public class TriggerIob extends Trigger {
return Optional.of(R.drawable.remove); // TODO icon
}
@Override
public void executed(long time) {
lastRun = time;
}
@Override
public Trigger duplicate() {
return new TriggerIob(this);
}
TriggerIob threshold(double threshold) {
this.threshold = threshold;
TriggerIob setValue(double threshold) {
insulin.setValue(threshold);
return this;
}
@ -161,52 +128,16 @@ public class TriggerIob extends Trigger {
return this;
}
TriggerIob comparator(Comparator comparator) {
this.comparator = comparator;
TriggerIob comparator(Comparator.Compare compare) {
this.comparator = new Comparator().setValue(compare);
return this;
}
@Override
public View createView(Context context, FragmentManager fragmentManager) {
LinearLayout root = (LinearLayout) super.createView(context, fragmentManager);
// spinner for comparator
Spinner spinner = new Spinner(context);
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(context, android.R.layout.simple_spinner_item, Comparator.labels());
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(spinnerArrayAdapter);
LinearLayout.LayoutParams spinnerParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
spinnerParams.setMargins(0, MainApp.dpToPx(4), 0, MainApp.dpToPx(4));
spinner.setLayoutParams(spinnerParams);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
comparator = Comparator.values()[position];
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
spinner.setSelection(comparator.ordinal());
root.addView(spinner);
// horizontal layout
LinearLayout layout = new LinearLayout(context);
layout.setOrientation(LinearLayout.HORIZONTAL);
layout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
root.addView(layout);
// input field for threshold
NumberPicker numberPicker = new NumberPicker(context, null);
numberPicker.setParams(0d, -20d, 20d, 0.1d, new DecimalFormat("0.0"), true, textWatcher);
numberPicker.setValue(threshold);
numberPicker.setOnValueChangedListener(value -> threshold = value);
layout.addView(numberPicker);
return root;
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
new LayoutBuilder()
.add(comparator)
.add(new Label(MainApp.gs(R.string.iob_u), "", insulin))
.build(root);
}
}

View file

@ -1,11 +1,11 @@
package info.nightscout.androidaps.plugins.general.automation.triggers;
import android.app.Activity;
import android.content.Context;
import android.graphics.Typeface;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.v4.app.FragmentManager;
import android.text.format.DateFormat;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
@ -21,8 +21,9 @@ import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Objects;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
@ -53,16 +54,6 @@ public class TriggerRecurringTime extends Trigger {
Calendar.SUNDAY
};
private static final int[] fullNames = new int[]{
R.string.weekday_monday,
R.string.weekday_tuesday,
R.string.weekday_wednesday,
R.string.weekday_thursday,
R.string.weekday_friday,
R.string.weekday_saturday,
R.string.weekday_sunday
};
private static final int[] shortNames = new int[]{
R.string.weekday_monday_short,
R.string.weekday_tuesday_short,
@ -77,6 +68,7 @@ public class TriggerRecurringTime extends Trigger {
return calendarInts[ordinal()];
}
@Nullable
public static DayOfWeek fromCalendarInt(int day) {
for (int i = 0; i < calendarInts.length; ++i) {
if (calendarInts[i] == day)
@ -85,11 +77,6 @@ public class TriggerRecurringTime extends Trigger {
return null;
}
public @StringRes
int getFullName() {
return fullNames[ordinal()];
}
public @StringRes
int getShortName() {
return shortNames[ordinal()];
@ -98,8 +85,6 @@ public class TriggerRecurringTime extends Trigger {
private final boolean[] weekdays = new boolean[DayOfWeek.values().length];
private long lastRun;
// Recurring
private int hour;
private int minute;
@ -118,9 +103,8 @@ public class TriggerRecurringTime extends Trigger {
minute = triggerTime.minute;
validTo = triggerTime.validTo;
for (int i = 0; i < weekdays.length; ++i) {
weekdays[i] = triggerTime.weekdays[i];
}
if (weekdays.length >= 0)
System.arraycopy(triggerTime.weekdays, 0, weekdays, 0, weekdays.length);
}
public void setAll(boolean value) {
@ -134,14 +118,10 @@ public class TriggerRecurringTime extends Trigger {
return this;
}
public boolean isSet(DayOfWeek day) {
private boolean isSet(DayOfWeek day) {
return weekdays[day.ordinal()];
}
public long getLastRun() {
return lastRun;
}
@Override
public boolean shouldRun() {
if (validTo != 0 && DateUtil.now() > validTo)
@ -155,7 +135,7 @@ public class TriggerRecurringTime extends Trigger {
scheduledCal.set(Calendar.SECOND, 0);
long scheduled = scheduledCal.getTimeInMillis();
if (isSet(DayOfWeek.fromCalendarInt(scheduledDayOfWeek))) {
if (isSet(Objects.requireNonNull(DayOfWeek.fromCalendarInt(scheduledDayOfWeek)))) {
if (DateUtil.now() >= scheduled && DateUtil.now() - scheduled < T.mins(5).msecs()) {
if (lastRun < scheduled) {
if (L.isEnabled(L.AUTOMATION))
@ -219,7 +199,7 @@ public class TriggerRecurringTime extends Trigger {
for (Integer i : getSelectedDays()) {
if (counter > 0)
sb.append(",");
sb.append(MainApp.gs(DayOfWeek.fromCalendarInt(i).getShortName()));
sb.append(MainApp.gs(Objects.requireNonNull(DayOfWeek.fromCalendarInt(i)).getShortName()));
counter++;
}
sb.append(" ");
@ -242,11 +222,6 @@ public class TriggerRecurringTime extends Trigger {
return Optional.of(R.drawable.ic_access_alarm_24dp);
}
@Override
public void executed(long time) {
lastRun = time;
}
@Override
public Trigger duplicate() {
return new TriggerRecurringTime(this);
@ -257,6 +232,7 @@ public class TriggerRecurringTime extends Trigger {
return this;
}
@SuppressWarnings("SameParameterValue")
TriggerRecurringTime validTo(long validTo) {
this.validTo = validTo;
return this;
@ -283,11 +259,11 @@ public class TriggerRecurringTime extends Trigger {
}
@Override
public View createView(final Context context, FragmentManager fragmentManager) {
LinearLayout root = (LinearLayout) super.createView(context, fragmentManager);
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
TextView label = new TextView(root.getContext());
// TODO: Replace external tool WeekdaysPicker with a self-made GUI element
WeekdaysPicker weekdaysPicker = new WeekdaysPicker(context);
WeekdaysPicker weekdaysPicker = new WeekdaysPicker(root.getContext());
weekdaysPicker.setEditable(true);
weekdaysPicker.setSelectedDays(getSelectedDays());
weekdaysPicker.setOnWeekdaysChangeListener((view, i, list) -> set(DayOfWeek.fromCalendarInt(i), list.contains(i)));
@ -295,36 +271,46 @@ public class TriggerRecurringTime extends Trigger {
root.addView(weekdaysPicker);
TextView dateButton = new TextView(context);
TextView timeButton = new TextView(context);
TextView timeButton = new TextView(root.getContext());
Date runAt = new Date();
runAt.setHours(hour);
runAt.setMinutes(minute);
timeButton.setText(DateUtil.timeString(runAt));
GregorianCalendar runAt = new GregorianCalendar();
//Date runAt = new Date();
runAt.set(Calendar.HOUR_OF_DAY, hour);
runAt.set(Calendar.MINUTE, minute);
timeButton.setText(DateUtil.timeString(runAt.getTimeInMillis()));
timeButton.setOnClickListener(view -> {
Calendar calendar = Calendar.getInstance();
calendar.setTime(runAt);
TimePickerDialog tpd = TimePickerDialog.newInstance(
(view12, hourOfDay, minute, second) -> {
this.hour = hourOfDay;
this.minute = minute;
runAt.setHours(this.hour);
runAt.setMinutes(this.minute);
timeButton.setText(DateUtil.timeString(runAt));
hour(hourOfDay);
minute(minute);
runAt.set(Calendar.HOUR_OF_DAY, hour);
runAt.set(Calendar.MINUTE, minute);
timeButton.setText(DateUtil.timeString(runAt.getTimeInMillis()));
},
calendar.get(Calendar.HOUR_OF_DAY),
calendar.get(Calendar.MINUTE),
DateFormat.is24HourFormat(context)
runAt.get(Calendar.HOUR_OF_DAY),
runAt.get(Calendar.MINUTE),
DateFormat.is24HourFormat(root.getContext())
);
tpd.setThemeDark(true);
tpd.dismissOnPause(true);
android.app.FragmentManager fm = ((Activity) context).getFragmentManager();
tpd.show(fm, "Timepickerdialog");
Activity a = scanForActivity(root.getContext());
if (a != null)
tpd.show(a.getFragmentManager(), "TimePickerDialog");
});
root.addView(dateButton);
root.addView(timeButton);
return root;
int px = MainApp.dpToPx(10);
label.setText(MainApp.gs(R.string.atspecifiedtime, ""));
label.setTypeface(label.getTypeface(), Typeface.BOLD);
label.setPadding(px, px, px, px);
timeButton.setPadding(px, px, px, px);
LinearLayout l = new LinearLayout(root.getContext());
l.setOrientation(LinearLayout.HORIZONTAL);
l.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
l.addView(label);
l.addView(timeButton);
root.addView(l);
}
}

View file

@ -1,10 +1,10 @@
package info.nightscout.androidaps.plugins.general.automation.triggers;
import android.app.Activity;
import android.content.Context;
import android.graphics.Typeface;
import android.support.v4.app.FragmentManager;
import android.text.format.DateFormat;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
@ -18,7 +18,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
@ -31,7 +31,6 @@ public class TriggerTime extends Trigger {
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
private long runAt;
private long lastRun;
public TriggerTime() {
runAt = DateUtil.now();
@ -98,11 +97,6 @@ public class TriggerTime extends Trigger {
return Optional.of(R.drawable.ic_access_alarm_24dp);
}
@Override
public void executed(long time) {
lastRun = time;
}
TriggerTime runAt(long runAt) {
this.runAt = runAt;
return this;
@ -123,25 +117,22 @@ public class TriggerTime extends Trigger {
}
@Override
public View createView(final Context context, FragmentManager fragmentManager) {
LinearLayout root = (LinearLayout) super.createView(context, fragmentManager);
//root.setOrientation(LinearLayout.HORIZONTAL);
TextView dateButton = new TextView(context);
TextView timeButton = new TextView(context);
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
TextView label = new TextView(root.getContext());
TextView dateButton = new TextView(root.getContext());
TextView timeButton = new TextView(root.getContext());
dateButton.setText(DateUtil.dateString(runAt));
timeButton.setText(DateUtil.timeString(runAt));
dateButton.setOnClickListener(view -> {
Calendar calendar = Calendar.getInstance();
GregorianCalendar calendar = new GregorianCalendar();
calendar.setTimeInMillis(runAt);
DatePickerDialog dpd = DatePickerDialog.newInstance(
(view1, year, monthOfYear, dayOfMonth) -> {
Date eventTime = new Date(runAt);
eventTime.setYear(year - 1900);
eventTime.setMonth(monthOfYear);
eventTime.setDate(dayOfMonth);
runAt = eventTime.getTime();
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, monthOfYear);
calendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);
runAt = calendar.getTimeInMillis();
dateButton.setText(DateUtil.dateString(runAt));
},
calendar.get(Calendar.YEAR),
@ -150,32 +141,45 @@ public class TriggerTime extends Trigger {
);
dpd.setThemeDark(true);
dpd.dismissOnPause(true);
android.app.FragmentManager fm = ((Activity) context).getFragmentManager();
dpd.show(fm, "Datepickerdialog");
Activity a = scanForActivity(root.getContext());
if (a != null)
dpd.show(a.getFragmentManager(), "DatePickerDialog");
});
timeButton.setOnClickListener(view -> {
Calendar calendar = Calendar.getInstance();
GregorianCalendar calendar = new GregorianCalendar();
calendar.setTimeInMillis(runAt);
TimePickerDialog tpd = TimePickerDialog.newInstance(
(view12, hourOfDay, minute, second) -> {
Date eventTime = new Date(runAt);
eventTime.setHours(hourOfDay);
eventTime.setMinutes(minute);
runAt = eventTime.getTime();
timeButton.setText(DateUtil.timeString(eventTime));
calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
calendar.set(Calendar.MINUTE, minute);
runAt = calendar.getTimeInMillis();
timeButton.setText(DateUtil.timeString(runAt));
},
calendar.get(Calendar.HOUR_OF_DAY),
calendar.get(Calendar.MINUTE),
DateFormat.is24HourFormat(context)
DateFormat.is24HourFormat(root.getContext())
);
tpd.setThemeDark(true);
tpd.dismissOnPause(true);
android.app.FragmentManager fm = ((Activity) context).getFragmentManager();
tpd.show(fm, "Timepickerdialog");
Activity a = scanForActivity(root.getContext());
if (a != null)
tpd.show(a.getFragmentManager(), "TimePickerDialog");
});
root.addView(dateButton);
root.addView(timeButton);
return root;
int px = MainApp.dpToPx(10);
label.setText(MainApp.gs(R.string.atspecifiedtime, ""));
label.setTypeface(label.getTypeface(), Typeface.BOLD);
label.setPadding(px, px, px, px);
dateButton.setPadding(px, px, px, px);
timeButton.setPadding(px, px, px, px);
LinearLayout l = new LinearLayout(root.getContext());
l.setOrientation(LinearLayout.HORIZONTAL);
l.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
l.addView(label);
l.addView(dateButton);
l.addView(timeButton);
root.addView(l);
}
}

View file

@ -1314,13 +1314,6 @@
<string name="weekday_wednesday_short">Wed</string>
<string name="weekday_tuesday_short">Tue</string>
<string name="weekday_monday_short">Mon</string>
<string name="weekday_sunday">Sunday</string>
<string name="weekday_saturday">Saturday</string>
<string name="weekday_friday">Friday</string>
<string name="weekday_thursday">Thursday</string>
<string name="weekday_wednesday">Wednesday</string>
<string name="weekday_tuesday">Tuesday</string>
<string name="weekday_monday">Monday</string>
<string name="automation_description">User defined automation tasks</string>
<string name="automation_missing_task_name">Please enter a task name.</string>
<string name="automation_missing_trigger">Please specify at least one trigger.</string>
@ -1381,6 +1374,12 @@
<string name="mins">%1$dmins</string>
<string name="condition">Condition:</string>
<string name="action">Action:</string>
<string name="iob_u">IOB [U]:</string>
<string name="glucose_u">Glucose [%1$s]:</string>
<string name="delete_short">DEL</string>
<string name="add_short">ADD</string>
<string name="copy_short">COPY</string>
<string name="addnew">Add new</string>
<plurals name="objective_days">
<item quantity="one">%1$d day</item>
<item quantity="other">%1$d days</item>

View file

@ -52,7 +52,7 @@ public class ComposeTriggerTest {
// change connector of t1,t2 from "and" to "or"
Assert.assertEquals(root, t[2].getConnector());
AutomationFragment.TriggerListAdapter.changeConnector(t[2], t[2].getConnector(), TriggerConnector.Type.OR);
AutomationFragment.changeConnector(null, t[2], t[2].getConnector(), TriggerConnector.Type.OR);
Assert.assertEquals(3, root.size());
Assert.assertEquals(t[0], root.get(0));
@ -66,7 +66,7 @@ public class ComposeTriggerTest {
// undo
Assert.assertEquals(newConnector, t[2].getConnector());
AutomationFragment.TriggerListAdapter.changeConnector(t[2], t[2].getConnector(), TriggerConnector.Type.AND);
AutomationFragment.changeConnector(null, t[2], t[2].getConnector(), TriggerConnector.Type.AND);
Assert.assertEquals(4, root.size());
for(int i = 0; i < 4; ++i) {
Assert.assertEquals(t[i], root.get(i));

View file

@ -69,6 +69,12 @@ public class ActionLoopSuspendTest {
Assert.assertEquals(20, b.minutes.getMinutes());
}
@Test
public void hasDialogTest() {
ActionLoopSuspend a = new ActionLoopSuspend();
Assert.assertTrue(a.hasDialog());
}
@Before
public void prepareTest() {
AAPSMocker.mockMainApp();

View file

@ -27,9 +27,9 @@ import static org.mockito.ArgumentMatchers.any;
@RunWith(PowerMockRunner.class)
@PrepareForTest({MainApp.class, SP.class, TreatmentsPlugin.class, ProfileFunctions.class})
public class ActionStartTempTargetTest {
ActionStartTempTarget actionStartTempTarget;
TreatmentsPlugin treatmentsPlugin;
TempTarget tempTargetAdded;
private ActionStartTempTarget actionStartTempTarget;
private TreatmentsPlugin treatmentsPlugin;
private TempTarget tempTargetAdded;
@Test
public void friendlyNameTest() {
@ -38,7 +38,11 @@ public class ActionStartTempTargetTest {
@Test
public void shortDescriptionTest() {
Assert.assertEquals("Start temp target: 100mg/dl@null", actionStartTempTarget.shortDescription());
actionStartTempTarget = new ActionStartTempTarget();
actionStartTempTarget.reason = "Test";
actionStartTempTarget.value = new InputBg().setValue(100).setUnits(Constants.MGDL);
actionStartTempTarget.duration = new InputDuration(30, InputDuration.TimeUnit.MINUTES);
Assert.assertEquals("Start temp target: 100mg/dl@null(Test)", actionStartTempTarget.shortDescription());
}
@Test
@ -66,16 +70,15 @@ public class ActionStartTempTargetTest {
public void toJSONTest() {
actionStartTempTarget = new ActionStartTempTarget();
actionStartTempTarget.reason = "Test";
actionStartTempTarget.value = new InputBg(Constants.MGDL);
actionStartTempTarget.value.setMgdl(100);
actionStartTempTarget.value = new InputBg().setValue(100).setUnits(Constants.MGDL);
actionStartTempTarget.duration = new InputDuration(30, InputDuration.TimeUnit.MINUTES);
Assert.assertEquals("{\"data\":{\"reason\":\"Test\",\"valueInMg\":100,\"durationInMinutes\":30,\"units\":\"mg/dl\"},\"type\":\"info.nightscout.androidaps.plugins.general.automation.actions.ActionStartTempTarget\"}", actionStartTempTarget.toJSON());
Assert.assertEquals("{\"data\":{\"reason\":\"Test\",\"durationInMinutes\":30,\"units\":\"mg/dl\",\"value\":100},\"type\":\"info.nightscout.androidaps.plugins.general.automation.actions.ActionStartTempTarget\"}", actionStartTempTarget.toJSON());
}
@Test
public void fromJSONTest() {
actionStartTempTarget = new ActionStartTempTarget();
actionStartTempTarget.fromJSON("{\"reason\":\"Test\",\"valueInMg\":100,\"durationInMinutes\":30,\"units\":\"mg/dl\"}");
actionStartTempTarget.fromJSON("{\"reason\":\"Test\",\"value\":100,\"durationInMinutes\":30,\"units\":\"mg/dl\"}");
Assert.assertEquals(Constants.MGDL, actionStartTempTarget.value.getUnits());
Assert.assertEquals(100, actionStartTempTarget.value.getValue(), 0.001d);
Assert.assertEquals(30, actionStartTempTarget.duration.getMinutes(), 0.001);

View file

@ -0,0 +1,52 @@
package info.nightscout.androidaps.plugins.general.automation.elements;
import junit.framework.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import info.AAPSMocker;
import info.nightscout.androidaps.MainApp;
@RunWith(PowerMockRunner.class)
@PrepareForTest({MainApp.class})
public class ComparatorTest {
@Test
public void checkTest() {
Assert.assertTrue(Comparator.Compare.IS_EQUAL.check(1, 1));
Assert.assertTrue(Comparator.Compare.IS_LESSER.check(1, 2));
Assert.assertTrue(Comparator.Compare.IS_EQUAL_OR_LESSER.check(1, 2));
Assert.assertTrue(Comparator.Compare.IS_EQUAL_OR_LESSER.check(2, 2));
Assert.assertTrue(Comparator.Compare.IS_GREATER.check(2, 1));
Assert.assertTrue(Comparator.Compare.IS_EQUAL_OR_GREATER.check(2, 1));
Assert.assertTrue(Comparator.Compare.IS_EQUAL_OR_GREATER.check(2, 2));
Assert.assertFalse(Comparator.Compare.IS_LESSER.check(2, 1));
Assert.assertFalse(Comparator.Compare.IS_EQUAL_OR_LESSER.check(2, 1));
Assert.assertFalse(Comparator.Compare.IS_GREATER.check(1, 2));
Assert.assertFalse(Comparator.Compare.IS_EQUAL_OR_GREATER.check(1, 2));
Assert.assertTrue(Comparator.Compare.IS_NOT_AVAILABLE.check(1, null));
}
@Test
public void labelsTest() {
Assert.assertEquals(6, Comparator.Compare.labels().size());
}
@Test
public void getSetValueTest() {
Comparator c = new Comparator().setValue(Comparator.Compare.IS_EQUAL_OR_GREATER);
Assert.assertEquals(Comparator.Compare.IS_EQUAL_OR_GREATER, c.getValue());
}
@Before
public void prepare() {
AAPSMocker.mockMainApp();
AAPSMocker.mockStrings();
}
}

View file

@ -0,0 +1,51 @@
package info.nightscout.androidaps.plugins.general.automation.elements;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import info.AAPSMocker;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
@RunWith(PowerMockRunner.class)
@PrepareForTest({MainApp.class, ProfileFunctions.class})
public class InputBgTest {
@Test
public void textWatcherTest() {
InputBg t = new InputBg().setValue(1d).setUnits(Constants.MMOL);
t.textWatcher.beforeTextChanged(null, 0, 0, 0);
t.textWatcher.onTextChanged(null, 0, 0, 0);
t.textWatcher.afterTextChanged(null);
Assert.assertEquals(4d, t.getValue(), 0.01d);
t = new InputBg().setValue(300d).setUnits(Constants.MGDL);
t.textWatcher.afterTextChanged(null);
Assert.assertEquals(270d, t.getValue(), 0.01d);
}
@Test
public void getSetValueTest() {
InputBg i = new InputBg().setValue(5d).setUnits(Constants.MMOL);
Assert.assertEquals(5d, i.getValue(), 0.01d);
Assert.assertEquals(2, i.minValue, 0.01d);
i = new InputBg().setValue(100d).setUnits(Constants.MGDL);
Assert.assertEquals(100d, i.getValue(), 0.01d);
Assert.assertEquals(40, i.minValue, 0.01d);
Assert.assertEquals(Constants.MGDL, i.getUnits());
}
@Before
public void prepare() {
AAPSMocker.mockMainApp();
AAPSMocker.mockBus();
AAPSMocker.mockStrings();
AAPSMocker.mockProfileFunctions();
}
}

View file

@ -0,0 +1,30 @@
package info.nightscout.androidaps.plugins.general.automation.elements;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import info.AAPSMocker;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
@RunWith(PowerMockRunner.class)
@PrepareForTest({MainApp.class})
public class InputDurationTest {
@Test
public void getSetValueTest() {
InputDuration i = new InputDuration(5, InputDuration.TimeUnit.MINUTES);
Assert.assertEquals(5, i.getValue(), 0.01d);
Assert.assertEquals(InputDuration.TimeUnit.MINUTES, i.getUnit());
i = i = new InputDuration(5, InputDuration.TimeUnit.HOURS);
Assert.assertEquals(5d, i.getValue(), 0.01d);
Assert.assertEquals(InputDuration.TimeUnit.HOURS, i.getUnit());
Assert.assertEquals(5 * 60, i.getMinutes());
i.setMinutes(60);
Assert.assertEquals(1, i.getValue(), 0.01d);
}
}

View file

@ -0,0 +1,29 @@
package info.nightscout.androidaps.plugins.general.automation.elements;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import info.nightscout.androidaps.MainApp;
@RunWith(PowerMockRunner.class)
@PrepareForTest({MainApp.class})
public class InputInsulinTest {
@Test
public void textWatcherTest() {
InputInsulin t = new InputInsulin().setValue(30d);
t.textWatcher.beforeTextChanged(null, 0, 0, 0);
t.textWatcher.onTextChanged(null, 0, 0, 0);
t.textWatcher.afterTextChanged(null);
Assert.assertEquals(20d, t.getValue(), 0.01d);
}
@Test
public void getSetValueTest() {
InputInsulin i = new InputInsulin().setValue(5d);
Assert.assertEquals(5d, i.getValue(), 0.01d);
}
}

View file

@ -0,0 +1,21 @@
package info.nightscout.androidaps.plugins.general.automation.elements;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.junit.Assert.*;
@RunWith(PowerMockRunner.class)
public class LabelTest {
@Test
public void constructorTest() {
Label l = new Label("A", "B", new InputInsulin());
Assert.assertEquals("A", l.textPre);
Assert.assertEquals("B", l.textPost);
Assert.assertEquals(InputInsulin.class, l.element.getClass());
}
}

View file

@ -0,0 +1,23 @@
package info.nightscout.androidaps.plugins.general.automation.elements;
import junit.framework.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import info.nightscout.androidaps.MainApp;
@RunWith(PowerMockRunner.class)
@PrepareForTest({MainApp.class})
public class LayoutBuilderTest {
LayoutBuilder layoutBuilder = new LayoutBuilder();
@Test
public void addTest() {
InputInsulin inputInsulin = new InputInsulin();
layoutBuilder.add(inputInsulin);
Assert.assertEquals(1, layoutBuilder.mElements.size());
}
}

View file

@ -22,6 +22,7 @@ import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator;
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSgv;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.utils.DateUtil;
@ -38,80 +39,67 @@ public class TriggerBgTest {
public void shouldRunTest() {
when(IobCobCalculatorPlugin.getPlugin().getBgReadings()).thenReturn(generateOneCurrentRecordBgData());
TriggerBg t = new TriggerBg().units(Constants.MMOL).threshold(4.1d).comparator(Trigger.Comparator.IS_EQUAL);
TriggerBg t = new TriggerBg().setUnits(Constants.MMOL).setValue(4.1d).comparator(Comparator.Compare.IS_EQUAL);
Assert.assertFalse(t.shouldRun());
t = new TriggerBg().units(Constants.MGDL).threshold(214).comparator(Trigger.Comparator.IS_EQUAL);
t = new TriggerBg().setUnits(Constants.MGDL).setValue(214).comparator(Comparator.Compare.IS_EQUAL);
Assert.assertTrue(t.shouldRun());
t = new TriggerBg().units(Constants.MGDL).threshold(214).comparator(Trigger.Comparator.IS_EQUAL_OR_GREATER);
t = new TriggerBg().setUnits(Constants.MGDL).setValue(214).comparator(Comparator.Compare.IS_EQUAL_OR_GREATER);
Assert.assertTrue(t.shouldRun());
t = new TriggerBg().units(Constants.MGDL).threshold(214).comparator(Trigger.Comparator.IS_EQUAL_OR_LESSER);
t = new TriggerBg().setUnits(Constants.MGDL).setValue(214).comparator(Comparator.Compare.IS_EQUAL_OR_LESSER);
Assert.assertTrue(t.shouldRun());
t = new TriggerBg().units(Constants.MGDL).threshold(215).comparator(Trigger.Comparator.IS_EQUAL);
t = new TriggerBg().setUnits(Constants.MGDL).setValue(215).comparator(Comparator.Compare.IS_EQUAL);
Assert.assertFalse(t.shouldRun());
t = new TriggerBg().units(Constants.MGDL).threshold(215).comparator(Trigger.Comparator.IS_EQUAL_OR_LESSER);
t = new TriggerBg().setUnits(Constants.MGDL).setValue(215).comparator(Comparator.Compare.IS_EQUAL_OR_LESSER);
Assert.assertTrue(t.shouldRun());
t = new TriggerBg().units(Constants.MGDL).threshold(215).comparator(Trigger.Comparator.IS_EQUAL_OR_GREATER);
t = new TriggerBg().setUnits(Constants.MGDL).setValue(215).comparator(Comparator.Compare.IS_EQUAL_OR_GREATER);
Assert.assertFalse(t.shouldRun());
t = new TriggerBg().units(Constants.MGDL).threshold(213).comparator(Trigger.Comparator.IS_EQUAL_OR_GREATER);
t = new TriggerBg().setUnits(Constants.MGDL).setValue(213).comparator(Comparator.Compare.IS_EQUAL_OR_GREATER);
Assert.assertTrue(t.shouldRun());
t = new TriggerBg().units(Constants.MGDL).threshold(213).comparator(Trigger.Comparator.IS_EQUAL_OR_LESSER);
t = new TriggerBg().setUnits(Constants.MGDL).setValue(213).comparator(Comparator.Compare.IS_EQUAL_OR_LESSER);
Assert.assertFalse(t.shouldRun());
when(IobCobCalculatorPlugin.getPlugin().getBgReadings()).thenReturn(new ArrayList<>());
t = new TriggerBg().units(Constants.MGDL).threshold(213).comparator(Trigger.Comparator.IS_EQUAL_OR_LESSER);
t = new TriggerBg().setUnits(Constants.MGDL).setValue(213).comparator(Comparator.Compare.IS_EQUAL_OR_LESSER);
Assert.assertFalse(t.shouldRun());
t = new TriggerBg().comparator(Trigger.Comparator.IS_NOT_AVAILABLE);
t = new TriggerBg().comparator(Comparator.Compare.IS_NOT_AVAILABLE);
Assert.assertTrue(t.shouldRun());
t = new TriggerBg().units(Constants.MGDL).threshold(214).comparator(Trigger.Comparator.IS_EQUAL).lastRun(now - 1);
t = new TriggerBg().setUnits(Constants.MGDL).setValue(214).comparator(Comparator.Compare.IS_EQUAL).lastRun(now - 1);
Assert.assertFalse(t.shouldRun());
}
@Test
public void textWatcherTest() {
TriggerBg t = new TriggerBg().threshold(1d).units(Constants.MMOL);
t.textWatcher.beforeTextChanged(null, 0,0,0);
t.textWatcher.onTextChanged(null, 0,0,0);
t.textWatcher.afterTextChanged(null);
Assert.assertEquals(4d, t.getThreshold(), 0.01d);
t = new TriggerBg().threshold(300d).units(Constants.MGDL);
t.textWatcher.afterTextChanged(null);
Assert.assertEquals(270d, t.getThreshold(), 0.01d);
}
@Test
public void copyConstructorTest() {
TriggerBg t = new TriggerBg().units(Constants.MGDL).threshold(213).comparator(Trigger.Comparator.IS_EQUAL_OR_LESSER);
TriggerBg t = new TriggerBg().setUnits(Constants.MGDL).setValue(213).comparator(Comparator.Compare.IS_EQUAL_OR_LESSER);
TriggerBg t1 = (TriggerBg) t.duplicate();
Assert.assertEquals(213d, t.getThreshold(), 0.01d);
Assert.assertEquals(Constants.MGDL, t.getUnits());
Assert.assertEquals(Trigger.Comparator.IS_EQUAL_OR_LESSER, t.getComparator());
Assert.assertEquals(213d, t1.getValue(), 0.01d);
Assert.assertEquals(Constants.MGDL, t1.getUnits());
Assert.assertEquals(Comparator.Compare.IS_EQUAL_OR_LESSER, t.getComparator().getValue());
}
@Test
public void executeTest() {
TriggerBg t = new TriggerBg().units(Constants.MGDL).threshold(213).comparator(Trigger.Comparator.IS_EQUAL_OR_LESSER);
TriggerBg t = new TriggerBg().setUnits(Constants.MGDL).setValue(213).comparator(Comparator.Compare.IS_EQUAL_OR_LESSER);
t.executed(1);
Assert.assertEquals(1l, t.getLastRun());
}
String bgJson = "{\"data\":{\"comparator\":\"IS_EQUAL\",\"lastRun\":0,\"threshold\":4.1,\"units\":\"mmol\"},\"type\":\"info.nightscout.androidaps.plugins.general.automation.triggers.TriggerBg\"}";
String bgJson = "{\"data\":{\"comparator\":\"IS_EQUAL\",\"lastRun\":0,\"bg\":4.1,\"units\":\"mmol\"},\"type\":\"info.nightscout.androidaps.plugins.general.automation.triggers.TriggerBg\"}";
@Test
public void toJSONTest() {
TriggerBg t = new TriggerBg().units(Constants.MMOL).threshold(4.1d).comparator(Trigger.Comparator.IS_EQUAL);
TriggerBg t = new TriggerBg().setUnits(Constants.MMOL).setValue(4.1d).comparator(Comparator.Compare.IS_EQUAL);
Assert.assertEquals(bgJson, t.toJSON());
}
@Test
public void fromJSONTest() throws JSONException {
TriggerBg t = new TriggerBg().units(Constants.MMOL).threshold(4.1d).comparator(Trigger.Comparator.IS_EQUAL);
TriggerBg t = new TriggerBg().setUnits(Constants.MMOL).setValue(4.1d).comparator(Comparator.Compare.IS_EQUAL);
TriggerBg t2 = (TriggerBg) Trigger.instantiate(new JSONObject(t.toJSON()));
Assert.assertEquals(Trigger.Comparator.IS_EQUAL, t2.getComparator());
Assert.assertEquals(4.1d, t2.getThreshold(), 0.01d);
Assert.assertEquals(Comparator.Compare.IS_EQUAL, t2.getComparator().getValue());
Assert.assertEquals(4.1d, t2.getValue(), 0.01d);
Assert.assertEquals(Constants.MMOL, t2.getUnits());
}

View file

@ -19,6 +19,7 @@ import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
import info.nightscout.androidaps.plugins.general.automation.elements.Comparator;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.utils.DateUtil;
@ -37,73 +38,60 @@ public class TriggerIobTest {
public void shouldRunTest() {
PowerMockito.when(iobCobCalculatorPlugin.calculateFromTreatmentsAndTempsSynchronized(anyLong(), any(Profile.class))).thenReturn(generateIobRecordData());
TriggerIob t = new TriggerIob().threshold(1.1d).comparator(Trigger.Comparator.IS_EQUAL);
TriggerIob t = new TriggerIob().setValue(1.1d).comparator(Comparator.Compare.IS_EQUAL);
Assert.assertFalse(t.shouldRun());
t = new TriggerIob().threshold(1d).comparator(Trigger.Comparator.IS_EQUAL);
t = new TriggerIob().setValue(1d).comparator(Comparator.Compare.IS_EQUAL);
Assert.assertTrue(t.shouldRun());
t = new TriggerIob().threshold(0.8d).comparator(Trigger.Comparator.IS_GREATER);
t = new TriggerIob().setValue(0.8d).comparator(Comparator.Compare.IS_GREATER);
Assert.assertTrue(t.shouldRun());
t = new TriggerIob().threshold(0.8d).comparator(Trigger.Comparator.IS_EQUAL_OR_GREATER);
t = new TriggerIob().setValue(0.8d).comparator(Comparator.Compare.IS_EQUAL_OR_GREATER);
Assert.assertTrue(t.shouldRun());
t = new TriggerIob().threshold(0.9d).comparator(Trigger.Comparator.IS_EQUAL_OR_GREATER);
t = new TriggerIob().setValue(0.9d).comparator(Comparator.Compare.IS_EQUAL_OR_GREATER);
Assert.assertTrue(t.shouldRun());
t = new TriggerIob().threshold(1.2d).comparator(Trigger.Comparator.IS_EQUAL_OR_LESSER);
t = new TriggerIob().setValue(1.2d).comparator(Comparator.Compare.IS_EQUAL_OR_LESSER);
Assert.assertTrue(t.shouldRun());
t = new TriggerIob().threshold(1.1d).comparator(Trigger.Comparator.IS_EQUAL);
t = new TriggerIob().setValue(1.1d).comparator(Comparator.Compare.IS_EQUAL);
Assert.assertFalse(t.shouldRun());
t = new TriggerIob().threshold(1d).comparator(Trigger.Comparator.IS_EQUAL_OR_LESSER);
t = new TriggerIob().setValue(1d).comparator(Comparator.Compare.IS_EQUAL_OR_LESSER);
Assert.assertTrue(t.shouldRun());
t = new TriggerIob().threshold(0.9d).comparator(Trigger.Comparator.IS_EQUAL_OR_LESSER);
t = new TriggerIob().setValue(0.9d).comparator(Comparator.Compare.IS_EQUAL_OR_LESSER);
Assert.assertFalse(t.shouldRun());
t = new TriggerIob().threshold(1d).comparator(Trigger.Comparator.IS_EQUAL).lastRun(now - 1);
t = new TriggerIob().setValue(1d).comparator(Comparator.Compare.IS_EQUAL).lastRun(now - 1);
Assert.assertFalse(t.shouldRun());
}
@Test
public void textWatcherTest() {
TriggerIob t = new TriggerIob().threshold(-30d);
t.textWatcher.beforeTextChanged(null, 0, 0, 0);
t.textWatcher.onTextChanged(null, 0, 0, 0);
t.textWatcher.afterTextChanged(null);
Assert.assertEquals(-20d, t.getThreshold(), 0.01d);
t = new TriggerIob().threshold(300d);
t.textWatcher.afterTextChanged(null);
Assert.assertEquals(20d, t.getThreshold(), 0.01d);
}
@Test
public void copyConstructorTest() {
TriggerIob t = new TriggerIob().threshold(213).comparator(Trigger.Comparator.IS_EQUAL_OR_LESSER);
TriggerIob t = new TriggerIob().setValue(213).comparator(Comparator.Compare.IS_EQUAL_OR_LESSER);
TriggerIob t1 = (TriggerIob) t.duplicate();
Assert.assertEquals(213d, t.getThreshold(), 0.01d);
Assert.assertEquals(Trigger.Comparator.IS_EQUAL_OR_LESSER, t.getComparator());
Assert.assertEquals(213d, t.getValue(), 0.01d);
Assert.assertEquals(Comparator.Compare.IS_EQUAL_OR_LESSER, t.getComparator().getValue());
}
@Test
public void executeTest() {
TriggerIob t = new TriggerIob().threshold(213).comparator(Trigger.Comparator.IS_EQUAL_OR_LESSER);
TriggerIob t = new TriggerIob().setValue(213).comparator(Comparator.Compare.IS_EQUAL_OR_LESSER);
t.executed(1);
Assert.assertEquals(1l, t.getLastRun());
}
String bgJson = "{\"data\":{\"comparator\":\"IS_EQUAL\",\"lastRun\":0,\"threshold\":4.1},\"type\":\"info.nightscout.androidaps.plugins.general.automation.triggers.TriggerIob\"}";
String bgJson = "{\"data\":{\"comparator\":\"IS_EQUAL\",\"insulin\":4.1,\"lastRun\":0},\"type\":\"info.nightscout.androidaps.plugins.general.automation.triggers.TriggerIob\"}";
@Test
public void toJSONTest() {
TriggerIob t = new TriggerIob().threshold(4.1d).comparator(Trigger.Comparator.IS_EQUAL);
TriggerIob t = new TriggerIob().setValue(4.1d).comparator(Comparator.Compare.IS_EQUAL);
Assert.assertEquals(bgJson, t.toJSON());
}
@Test
public void fromJSONTest() throws JSONException {
TriggerIob t = new TriggerIob().threshold(4.1d).comparator(Trigger.Comparator.IS_EQUAL);
TriggerIob t = new TriggerIob().setValue(4.1d).comparator(Comparator.Compare.IS_EQUAL);
TriggerIob t2 = (TriggerIob) Trigger.instantiate(new JSONObject(t.toJSON()));
Assert.assertEquals(Trigger.Comparator.IS_EQUAL, t2.getComparator());
Assert.assertEquals(4.1d, t2.getThreshold(), 0.01d);
Assert.assertEquals(Comparator.Compare.IS_EQUAL, t2.getComparator().getValue());
Assert.assertEquals(4.1d, t2.getValue(), 0.01d);
}
@Test