diff --git a/README.md b/README.md
index c8466fef14..b700f18b7a 100644
--- a/README.md
+++ b/README.md
@@ -4,3 +4,4 @@
* Everyone who’s been looping with AndroidAPS needs to fill out the form after 3 days of looping https://docs.google.com/forms/d/14KcMjlINPMJHVt28MDRupa4sz4DDIooI4SrW0P3HSN8/viewform?c=0&w=1
[![Gitter](https://badges.gitter.im/MilosKozak/AndroidAPS.svg)](https://gitter.im/MilosKozak/AndroidAPS?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+[![Build status](https://travis-ci.org/MilosKozak/AndroidAPS.svg?branch=master)](https://travis-ci.org/MilosKozak/AndroidAPS)
diff --git a/app/build.gradle b/app/build.gradle
index aee236a796..da35bd40a7 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -107,7 +107,7 @@ android {
dependencies {
wearWearApp project(path: ':wear', configuration: 'fullRelease')
- compile fileTree(dir: 'libs', include: ['*.jar'])
+ compile fileTree(include: ['*.jar'], dir: 'libs')
compile('com.crashlytics.sdk.android:crashlytics:2.5.7@aar') {
transitive = true;
}
@@ -127,6 +127,11 @@ dependencies {
compile 'com.jjoe64:graphview:4.0.1'
compile 'com.eclipsesource.j2v8:j2v8:3.1.6@aar'
compile 'com.joanzapata.iconify:android-iconify-fontawesome:2.1.1'
- testCompile 'junit:junit:4.12'
compile 'com.google.android.gms:play-services-wearable:7.5.0'
+ compile 'junit:junit:4.12'
+ testCompile 'org.json:json:20140107'
+ testCompile 'org.mockito:mockito-core:2.+'
+ androidTestCompile 'org.mockito:mockito-core:2.+'
+ androidTestCompile "com.google.dexmaker:dexmaker:1.2"
+ androidTestCompile "com.google.dexmaker:dexmaker-mockito:1.2"
}
diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.java b/app/src/main/java/info/nightscout/androidaps/MainApp.java
index b647e9b6d1..8f9d7606e8 100644
--- a/app/src/main/java/info/nightscout/androidaps/MainApp.java
+++ b/app/src/main/java/info/nightscout/androidaps/MainApp.java
@@ -24,6 +24,7 @@ import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderFragment;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.DanaR.DanaRFragment;
import info.nightscout.androidaps.plugins.DanaRKorean.DanaRKoreanFragment;
+import info.nightscout.androidaps.plugins.LocalProfile.LocalProfileFragment;
import info.nightscout.androidaps.plugins.Loop.LoopFragment;
import info.nightscout.androidaps.plugins.MDI.MDIFragment;
import info.nightscout.androidaps.plugins.NSProfile.NSProfileFragment;
@@ -83,6 +84,7 @@ public class MainApp extends Application {
if (Config.OPENAPSMAENABLED) pluginsList.add(OpenAPSMAFragment.getPlugin());
pluginsList.add(NSProfileFragment.getPlugin());
pluginsList.add(SimpleProfileFragment.getPlugin());
+ pluginsList.add(LocalProfileFragment.getPlugin());
pluginsList.add(CircadianPercentageProfileFragment.getPlugin());
pluginsList.add(TreatmentsFragment.getPlugin());
pluginsList.add(TempBasalsFragment.getPlugin());
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/CircadianPercentageProfile/CircadianPercentageProfileFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/CircadianPercentageProfile/CircadianPercentageProfileFragment.java
index c8a23ccdff..0bf490abb6 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/CircadianPercentageProfile/CircadianPercentageProfileFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/CircadianPercentageProfile/CircadianPercentageProfileFragment.java
@@ -1,6 +1,7 @@
package info.nightscout.androidaps.plugins.CircadianPercentageProfile;
+import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
@@ -19,10 +20,14 @@ import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.TextView;
+import com.squareup.otto.Subscribe;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.events.EventInitializationChanged;
import info.nightscout.androidaps.interfaces.FragmentBase;
import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog;
import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
@@ -60,8 +65,6 @@ public class CircadianPercentageProfileFragment extends Fragment implements Frag
BasalEditDialog basalEditDialog;
-
-
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
@@ -87,7 +90,6 @@ public class CircadianPercentageProfileFragment extends Fragment implements Frag
isfeditIcon = (ImageView) layout.findViewById(R.id.circadianpercentageprofile_isfedit);
-
mgdlView.setChecked(circadianPercentageProfilePlugin.mgdl);
mmolView.setChecked(circadianPercentageProfilePlugin.mmol);
diaView.setText(circadianPercentageProfilePlugin.dia.toString());
@@ -133,7 +135,7 @@ public class CircadianPercentageProfileFragment extends Fragment implements Frag
timeshiftView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean b) {
- if(b)
+ if (b)
ToastUtils.showToastInUiThread(getContext(), getString(R.string.timeshift_hint));
}
@@ -142,7 +144,7 @@ public class CircadianPercentageProfileFragment extends Fragment implements Frag
percentageView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean b) {
- if(b)
+ if (b)
ToastUtils.showToastInUiThread(getContext(), getString(R.string.percentagefactor_hint));
}
});
@@ -210,7 +212,7 @@ public class CircadianPercentageProfileFragment extends Fragment implements Frag
public void onTextChanged(CharSequence s, int start,
int before, int count) {
- if(SafeParse.stringToInt(percentageView.getText().toString()) == 0) {
+ if (SafeParse.stringToInt(percentageView.getText().toString()) == 0) {
circadianPercentageProfilePlugin.percentage = 100;
} else {
circadianPercentageProfilePlugin.percentage = SafeParse.stringToInt(percentageView.getText().toString());
@@ -232,6 +234,8 @@ public class CircadianPercentageProfileFragment extends Fragment implements Frag
percentageView.addTextChangedListener(textWatch);
timeshiftView.addTextChangedListener(textWatch);
+ onStatusEvent(null);
+
return layout;
}
@@ -242,7 +246,7 @@ public class CircadianPercentageProfileFragment extends Fragment implements Frag
sb.append("");
sb.append("
");
sb.append(getString(R.string.nsprofileview_basal_label));
- sb.append( " ( ∑");
+ sb.append(" ( ∑");
sb.append(DecimalFormatter.to2Decimal(circadianPercentageProfilePlugin.percentageBasalSum()));
sb.append("U )");
sb.append("
" + circadianPercentageProfilePlugin.basalString());
@@ -261,21 +265,21 @@ public class CircadianPercentageProfileFragment extends Fragment implements Frag
}
@Override
- public void onStop(){
+ public void onStop() {
super.onStop();
- if(basalEditDialog != null && basalEditDialog.isVisible()){
+ if (basalEditDialog != null && basalEditDialog.isVisible()) {
basalEditDialog.dismiss();
}
basalEditDialog = null;
}
- public static class BasalEditDialog extends DialogFragment{
+ public static class BasalEditDialog extends DialogFragment {
private double[] values;
private String title;
private CircadianPercentageProfileFragment fragment;
- public void setup(double[] values, String title, CircadianPercentageProfileFragment fragment){
+ public void setup(double[] values, String title, CircadianPercentageProfileFragment fragment) {
this.values = values;
this.title = title;
this.fragment = fragment;
@@ -289,23 +293,24 @@ public class CircadianPercentageProfileFragment extends Fragment implements Frag
final EditText[] editTexts = new EditText[24];
for (int i = 0; i < 24; i++) {
View childview = inflater.inflate(R.layout.circadianpercentageprofile_listelement, container, false);
- ((TextView)childview.findViewById(R.id.basal_time_elem)).setText((i<10?"0":"") + i + ":00: ");
+ ((TextView) childview.findViewById(R.id.basal_time_elem)).setText((i < 10 ? "0" : "") + i + ":00: ");
- ImageView copyprevbutton = (ImageView)childview.findViewById(R.id.basal_copyprev_elem);
+ ImageView copyprevbutton = (ImageView) childview.findViewById(R.id.basal_copyprev_elem);
- if(i==0){
- copyprevbutton.setVisibility(View.INVISIBLE);;
+ if (i == 0) {
+ copyprevbutton.setVisibility(View.INVISIBLE);
+ ;
} else {
final int j = i; //needs to be final to be passed to inner class.
copyprevbutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
- editTexts[j].setText(editTexts[j-1].getText());
+ editTexts[j].setText(editTexts[j - 1].getText());
}
});
}
- editTexts[i] = ((EditText) childview.findViewById(R.id.basal_edittext_elem));
+ editTexts[i] = ((EditText) childview.findViewById(R.id.basal_edittext_elem));
editTexts[i].setText(DecimalFormatter.to2Decimal(values[i]));
list.addView(childview);
}
@@ -315,8 +320,8 @@ public class CircadianPercentageProfileFragment extends Fragment implements Frag
@Override
public void onClick(View view) {
for (int i = 0; i < 24; i++) {
- if (editTexts[i].getText().length()!= 0){
- values[i]= SafeParse.stringToDouble(editTexts[i].getText().toString()) ;
+ if (editTexts[i].getText().length() != 0) {
+ values[i] = SafeParse.stringToDouble(editTexts[i].getText().toString());
}
}
fragment.updateProfileInfo();
@@ -334,11 +339,34 @@ public class CircadianPercentageProfileFragment extends Fragment implements Frag
return view;
}
+ }
+ @Override
+ public void onPause() {
+ super.onPause();
+ MainApp.bus().unregister(this);
+ }
+ @Override
+ public void onResume() {
+ super.onResume();
+ MainApp.bus().register(this);
+ onStatusEvent(null);
+ }
-
-
-}
-
+ @Subscribe
+ public void onStatusEvent(final EventInitializationChanged e) {
+ Activity activity = getActivity();
+ if (activity != null)
+ activity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ if (!MainApp.getConfigBuilder().isInitialized() || !MainApp.getConfigBuilder().getPumpDescription().isSetBasalProfileCapable) {
+ profileswitchButton.setVisibility(View.GONE);
+ } else {
+ profileswitchButton.setVisibility(View.VISIBLE);
+ }
+ }
+ });
+ }
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/DanaRFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/DanaRFragment.java
index 4ec54cb37e..63186fc4db 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/DanaRFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/DanaR/DanaRFragment.java
@@ -200,7 +200,7 @@ public class DanaRFragment extends Fragment implements FragmentBase {
if (DanaRPlugin.getDanaRPump().lastConnection.getTime() != 0) {
Long agoMsec = new Date().getTime() - DanaRPlugin.getDanaRPump().lastConnection.getTime();
int agoMin = (int) (agoMsec / 60d / 1000d);
- lastConnectionView.setText(formatTime.format(DanaRPlugin.getDanaRPump().lastConnection) + " (" + agoMin + " " + MainApp.sResources.getString(R.string.minago) + ")");
+ lastConnectionView.setText(formatTime.format(DanaRPlugin.getDanaRPump().lastConnection) + " (" + String.format(MainApp.sResources.getString(R.string.minago), agoMin) + ")");
SetWarnColor.setColor(lastConnectionView, agoMin, 16d, 31d);
}
if (DanaRPlugin.getDanaRPump().lastBolusTime.getTime() != 0) {
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/DanaRKoreanFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/DanaRKoreanFragment.java
index 77e320c3a9..94beeea1f3 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/DanaRKoreanFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/DanaRKorean/DanaRKoreanFragment.java
@@ -197,7 +197,7 @@ public class DanaRKoreanFragment extends Fragment implements FragmentBase {
if (DanaRKoreanPlugin.getDanaRPump().lastConnection.getTime() != 0) {
Long agoMsec = new Date().getTime() - DanaRKoreanPlugin.getDanaRPump().lastConnection.getTime();
int agoMin = (int) (agoMsec / 60d / 1000d);
- lastConnectionView.setText(formatTime.format(DanaRKoreanPlugin.getDanaRPump().lastConnection) + " (" + agoMin + " " + MainApp.sResources.getString(R.string.minago) + ")");
+ lastConnectionView.setText(formatTime.format(DanaRKoreanPlugin.getDanaRPump().lastConnection) + " (" + String.format(MainApp.sResources.getString(R.string.minago), agoMin) + ")");
SetWarnColor.setColor(lastConnectionView, agoMin, 16d, 31d);
}
// if (DanaRKoreanPlugin.getDanaRPump().lastBolusTime.getTime() != 0) {
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/LocalProfile/LocalProfileFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/LocalProfile/LocalProfileFragment.java
new file mode 100644
index 0000000000..401344d4df
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/LocalProfile/LocalProfileFragment.java
@@ -0,0 +1,167 @@
+package info.nightscout.androidaps.plugins.LocalProfile;
+
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.RadioButton;
+
+import com.squareup.otto.Subscribe;
+
+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.events.EventInitializationChanged;
+import info.nightscout.androidaps.interfaces.FragmentBase;
+import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog;
+import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
+import info.nightscout.utils.SafeParse;
+import info.nightscout.utils.TimeListEdit;
+
+public class LocalProfileFragment extends Fragment implements FragmentBase {
+ private static Logger log = LoggerFactory.getLogger(LocalProfileFragment.class);
+
+ private static LocalProfilePlugin localProfilePlugin = new LocalProfilePlugin();
+
+ public static LocalProfilePlugin getPlugin() {
+ return localProfilePlugin;
+ }
+
+ EditText diaView;
+ RadioButton mgdlView;
+ RadioButton mmolView;
+ TimeListEdit icView;
+ TimeListEdit isfView;
+ EditText carView;
+ TimeListEdit basalView;
+ TimeListEdit targetView;
+ Button profileswitchButton;
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ Runnable save = new Runnable() {
+ @Override
+ public void run() {
+ localProfilePlugin.storeSettings();
+ }
+ };
+
+ View layout = inflater.inflate(R.layout.localprofile_fragment, container, false);
+ diaView = (EditText) layout.findViewById(R.id.localprofile_dia);
+ mgdlView = (RadioButton) layout.findViewById(R.id.localprofile_mgdl);
+ mmolView = (RadioButton) layout.findViewById(R.id.localprofile_mmol);
+ icView = new TimeListEdit(getContext(), layout, R.id.localprofile_ic, MainApp.sResources.getString(R.string.nsprofileview_ic_label), getPlugin().ic, null, new DecimalFormat("0.0"), save);
+ isfView = new TimeListEdit(getContext(), layout, R.id.localprofile_isf, MainApp.sResources.getString(R.string.nsprofileview_isf_label), getPlugin().isf, null, new DecimalFormat("0.0"), save);
+ carView = (EditText) layout.findViewById(R.id.localprofile_car);
+ basalView = new TimeListEdit(getContext(), layout, R.id.localprofile_basal, MainApp.sResources.getString(R.string.nsprofileview_basal_label), getPlugin().basal, null, new DecimalFormat("0.00"), save);
+ targetView = new TimeListEdit(getContext(), layout, R.id.localprofile_target, MainApp.sResources.getString(R.string.nsprofileview_target_label), getPlugin().targetLow, getPlugin().targetHigh, new DecimalFormat("0.0"), save);
+ profileswitchButton = (Button) layout.findViewById(R.id.localprofile_profileswitch);
+
+ onStatusEvent(null);
+
+ mgdlView.setChecked(localProfilePlugin.mgdl);
+ mmolView.setChecked(localProfilePlugin.mmol);
+ diaView.setText(localProfilePlugin.dia.toString());
+ carView.setText(localProfilePlugin.car.toString());
+
+ mgdlView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ localProfilePlugin.mgdl = mgdlView.isChecked();
+ localProfilePlugin.mmol = !localProfilePlugin.mgdl;
+ mmolView.setChecked(localProfilePlugin.mmol);
+ localProfilePlugin.storeSettings();
+ }
+ });
+ mmolView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ localProfilePlugin.mmol = mmolView.isChecked();
+ localProfilePlugin.mgdl = !localProfilePlugin.mmol;
+ mgdlView.setChecked(localProfilePlugin.mgdl);
+ localProfilePlugin.storeSettings();
+ }
+ });
+
+ profileswitchButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
+ final OptionsToShow profileswitch = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch, true, false, false, false, false, false, false, true, false);
+ profileswitch.executeProfileSwitch = true;
+ newDialog.setOptions(profileswitch);
+ newDialog.show(getFragmentManager(), "NewNSTreatmentDialog");
+ }
+ });
+
+ TextWatcher textWatch = new TextWatcher() {
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start,
+ int count, int after) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start,
+ int before, int count) {
+ localProfilePlugin.dia = SafeParse.stringToDouble(diaView.getText().toString());
+ localProfilePlugin.car = SafeParse.stringToDouble(carView.getText().toString());
+ localProfilePlugin.storeSettings();
+ }
+ };
+
+ diaView.addTextChangedListener(textWatch);
+ carView.addTextChangedListener(textWatch);
+
+ onStatusEvent(null);
+
+ return layout;
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ MainApp.bus().unregister(this);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ MainApp.bus().register(this);
+ onStatusEvent(null);
+ }
+
+ @Subscribe
+ public void onStatusEvent(final EventInitializationChanged e) {
+ Activity activity = getActivity();
+ if (activity != null)
+ activity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ if (!MainApp.getConfigBuilder().isInitialized() || !MainApp.getConfigBuilder().getPumpDescription().isSetBasalProfileCapable) {
+ profileswitchButton.setVisibility(View.GONE);
+ } else {
+ profileswitchButton.setVisibility(View.VISIBLE);
+ }
+ }
+ });
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/LocalProfile/LocalProfilePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/LocalProfile/LocalProfilePlugin.java
new file mode 100644
index 0000000000..0ead686e5e
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/LocalProfile/LocalProfilePlugin.java
@@ -0,0 +1,300 @@
+package info.nightscout.androidaps.plugins.LocalProfile;
+
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.Config;
+import info.nightscout.androidaps.Constants;
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.interfaces.PluginBase;
+import info.nightscout.androidaps.interfaces.ProfileInterface;
+import info.nightscout.androidaps.plugins.SimpleProfile.SimpleProfileFragment;
+import info.nightscout.client.data.NSProfile;
+import info.nightscout.utils.SafeParse;
+
+/**
+ * Created by mike on 05.08.2016.
+ */
+public class LocalProfilePlugin implements PluginBase, ProfileInterface {
+ private static Logger log = LoggerFactory.getLogger(LocalProfilePlugin.class);
+
+ private static boolean fragmentEnabled = true;
+ private static boolean fragmentVisible = true;
+
+ private static NSProfile convertedProfile = null;
+
+ final private String DEFAULTARRAY = "[{\"timeAsSeconds\":0,\"value\":0}]";
+
+ boolean mgdl;
+ boolean mmol;
+ Double dia;
+ JSONArray ic;
+ JSONArray isf;
+ Double car;
+ JSONArray basal;
+ JSONArray targetLow;
+ JSONArray targetHigh;
+
+ public LocalProfilePlugin() {
+ loadSettings();
+ }
+
+ @Override
+ public String getFragmentClass() {
+ return LocalProfileFragment.class.getName();
+ }
+
+ @Override
+ public int getType() {
+ return PluginBase.PROFILE;
+ }
+
+ @Override
+ public String getName() {
+ return MainApp.instance().getString(R.string.localprofile);
+ }
+
+ @Override
+ public boolean isEnabled(int type) {
+ return type == PROFILE && fragmentEnabled;
+ }
+
+ @Override
+ public boolean isVisibleInTabs(int type) {
+ return type == PROFILE && fragmentVisible;
+ }
+
+ @Override
+ public boolean canBeHidden(int type) {
+ return true;
+ }
+
+ @Override
+ public void setFragmentEnabled(int type, boolean fragmentEnabled) {
+ if (type == PROFILE) this.fragmentEnabled = fragmentEnabled;
+ }
+
+ @Override
+ public void setFragmentVisible(int type, boolean fragmentVisible) {
+ if (type == PROFILE) this.fragmentVisible = fragmentVisible;
+ }
+
+ public void storeSettings() {
+ if (Config.logPrefsChange)
+ log.debug("Storing settings");
+ SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
+ SharedPreferences.Editor editor = settings.edit();
+ editor.putBoolean("LocalProfile" + "mmol", mmol);
+ editor.putBoolean("LocalProfile" + "mgdl", mgdl);
+ editor.putString("LocalProfile" + "dia", dia.toString());
+ editor.putString("LocalProfile" + "ic", ic.toString());
+ editor.putString("LocalProfile" + "isf", isf.toString());
+ editor.putString("LocalProfile" + "car", car.toString());
+ editor.putString("LocalProfile" + "basal", basal.toString());
+ editor.putString("LocalProfile" + "targetlow", targetLow.toString());
+ editor.putString("LocalProfile" + "targethigh", targetHigh.toString());
+
+ editor.commit();
+ createConvertedProfile();
+ }
+
+ private void loadSettings() {
+ if (Config.logPrefsChange)
+ log.debug("Loading stored settings");
+ SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
+
+ if (settings.contains("LocalProfile" + "mgdl"))
+ try {
+ mgdl = settings.getBoolean("LocalProfile" + "mgdl", false);
+ } catch (Exception e) {
+ log.debug(e.getMessage());
+ }
+ else mgdl = false;
+ if (settings.contains("LocalProfile" + "mmol"))
+ try {
+ mmol = settings.getBoolean("LocalProfile" + "mmol", true);
+ } catch (Exception e) {
+ log.debug(e.getMessage());
+ }
+ else mmol = true;
+ if (settings.contains("LocalProfile" + "dia"))
+ try {
+ dia = SafeParse.stringToDouble(settings.getString("LocalProfile" + "dia", "3"));
+ } catch (Exception e) {
+ log.debug(e.getMessage());
+ }
+ else dia = 3d;
+ if (settings.contains("LocalProfile" + "ic"))
+ try {
+ ic = new JSONArray(settings.getString("LocalProfile" + "ic", DEFAULTARRAY));
+ } catch (Exception e) {
+ log.debug(e.getMessage());
+ try {
+ ic = new JSONArray(DEFAULTARRAY);
+ } catch (JSONException e1) {
+ e1.printStackTrace();
+ }
+ }
+ else {
+ try {
+ ic = new JSONArray(DEFAULTARRAY);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+ if (settings.contains("LocalProfile" + "isf"))
+ try {
+ isf = new JSONArray(settings.getString("LocalProfile" + "isf", DEFAULTARRAY));
+ } catch (Exception e) {
+ log.debug(e.getMessage());
+ try {
+ isf = new JSONArray(DEFAULTARRAY);
+ } catch (JSONException e1) {
+ e1.printStackTrace();
+ }
+ }
+ else {
+ try {
+ isf = new JSONArray(DEFAULTARRAY);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+ if (settings.contains("LocalProfile" + "car"))
+ try {
+ car = SafeParse.stringToDouble(settings.getString("LocalProfile" + "car", "20"));
+ } catch (Exception e) {
+ log.debug(e.getMessage());
+ }
+ else car = 20d;
+ if (settings.contains("LocalProfile" + "basal"))
+ try {
+ basal = new JSONArray(settings.getString("LocalProfile" + "basal", DEFAULTARRAY));
+ } catch (Exception e) {
+ log.debug(e.getMessage());
+ try {
+ basal = new JSONArray(DEFAULTARRAY);
+ } catch (JSONException e1) {
+ e1.printStackTrace();
+ }
+ }
+ else {
+ try {
+ basal = new JSONArray(DEFAULTARRAY);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+ if (settings.contains("LocalProfile" + "targetlow"))
+ try {
+ targetLow = new JSONArray(settings.getString("LocalProfile" + "targetlow", DEFAULTARRAY));
+ } catch (Exception e) {
+ log.debug(e.getMessage());
+ try {
+ targetLow = new JSONArray(DEFAULTARRAY);
+ } catch (JSONException e1) {
+ e1.printStackTrace();
+ }
+ }
+ else {
+ try {
+ targetLow = new JSONArray(DEFAULTARRAY);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+ if (settings.contains("LocalProfile" + "targethigh"))
+ try {
+ targetHigh = new JSONArray(settings.getString("LocalProfile" + "targethigh", DEFAULTARRAY));
+ } catch (Exception e) {
+ log.debug(e.getMessage());
+ try {
+ targetHigh = new JSONArray(DEFAULTARRAY);
+ } catch (JSONException e1) {
+ e1.printStackTrace();
+ }
+ }
+ else {
+ try {
+ targetHigh = new JSONArray(DEFAULTARRAY);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+ createConvertedProfile();
+ }
+
+ /*
+ {
+ "_id": "576264a12771b7500d7ad184",
+ "startDate": "2016-06-16T08:35:00.000Z",
+ "defaultProfile": "Default",
+ "store": {
+ "Default": {
+ "dia": "3",
+ "carbratio": [{
+ "time": "00:00",
+ "value": "30"
+ }],
+ "carbs_hr": "20",
+ "delay": "20",
+ "sens": [{
+ "time": "00:00",
+ "value": "100"
+ }],
+ "timezone": "UTC",
+ "basal": [{
+ "time": "00:00",
+ "value": "0.1"
+ }],
+ "target_low": [{
+ "time": "00:00",
+ "value": "0"
+ }],
+ "target_high": [{
+ "time": "00:00",
+ "value": "0"
+ }],
+ "startDate": "1970-01-01T00:00:00.000Z",
+ "units": "mmol"
+ }
+ },
+ "created_at": "2016-06-16T08:34:41.256Z"
+ }
+ */
+ void createConvertedProfile() {
+ JSONObject json = new JSONObject();
+ JSONObject store = new JSONObject();
+ JSONObject profile = new JSONObject();
+
+ try {
+ json.put("defaultProfile", "LocalProfile");
+ json.put("store", store);
+ profile.put("dia", dia);
+ profile.put("carbratio", ic);
+ profile.put("carbs_hr", car);
+ profile.put("sens", isf);
+ profile.put("basal", basal);
+ profile.put("target_low", targetLow);
+ profile.put("target_high", targetHigh);
+ profile.put("units", mgdl ? Constants.MGDL : Constants.MMOL);
+ store.put("LocalProfile", profile);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ convertedProfile = new NSProfile(json, "LocalProfile");
+ }
+
+ @Override
+ public NSProfile getProfile() {
+ return convertedProfile;
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/MDI/MDIPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/MDI/MDIPlugin.java
index 7676086de2..a9b95c25fe 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/MDI/MDIPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/MDI/MDIPlugin.java
@@ -57,7 +57,7 @@ public class MDIPlugin implements PluginBase, PumpInterface {
pumpDescription.highTempPercentDuration = 0;
pumpDescription.highTempAbsoluteDuration = 0;
- pumpDescription.isSetBasalProfileCapable = true;
+ pumpDescription.isSetBasalProfileCapable = false;
pumpDescription.basalStep = 0d;
pumpDescription.basalMinimumRate = 0d;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java
index 2df6dfc6be..c7760d7af7 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java
@@ -82,7 +82,6 @@ import info.nightscout.utils.DateUtil;
import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.Round;
import info.nightscout.utils.SafeParse;
-import info.nightscout.utils.ToastUtils;
public class OverviewFragment extends Fragment {
@@ -590,7 +589,7 @@ public class OverviewFragment extends Fragment {
Long agoMsec = new Date().getTime() - lastBG.timeIndex;
int agoMin = (int) (agoMsec / 60d / 1000d);
- timeAgoView.setText(agoMin + " " + getString(R.string.minago));
+ timeAgoView.setText(String.format(MainApp.sResources.getString(R.string.minago), agoMin));
// iob
MainApp.getConfigBuilder().getActiveTreatments().updateTotalIOB();
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SimpleProfile/SimpleProfileFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/SimpleProfile/SimpleProfileFragment.java
index 107629c97c..1d0381ce3b 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/SimpleProfile/SimpleProfileFragment.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/SimpleProfile/SimpleProfileFragment.java
@@ -11,13 +11,17 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
+import android.widget.LinearLayout;
import android.widget.RadioButton;
import com.squareup.otto.Subscribe;
+import org.json.JSONArray;
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.events.EventInitializationChanged;
@@ -25,7 +29,9 @@ import info.nightscout.androidaps.interfaces.FragmentBase;
import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog;
import info.nightscout.androidaps.plugins.Careportal.OptionsToShow;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
+import info.nightscout.utils.DecimalFormatter;
import info.nightscout.utils.SafeParse;
+import info.nightscout.utils.TimeListEdit;
public class SimpleProfileFragment extends Fragment implements FragmentBase {
private static Logger log = LoggerFactory.getLogger(SimpleProfileFragment.class);
@@ -136,6 +142,9 @@ public class SimpleProfileFragment extends Fragment implements FragmentBase {
basalView.addTextChangedListener(textWatch);
targetlowView.addTextChangedListener(textWatch);
targethighView.addTextChangedListener(textWatch);
+
+ onStatusEvent(null);
+
return layout;
}
@@ -149,6 +158,7 @@ public class SimpleProfileFragment extends Fragment implements FragmentBase {
public void onResume() {
super.onResume();
MainApp.bus().register(this);
+ onStatusEvent(null);
}
@Subscribe
@@ -158,7 +168,7 @@ public class SimpleProfileFragment extends Fragment implements FragmentBase {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
- if (!MainApp.getConfigBuilder().isInitialized()) {
+ if (!MainApp.getConfigBuilder().isInitialized() || !MainApp.getConfigBuilder().getPumpDescription().isSetBasalProfileCapable) {
profileswitchButton.setVisibility(View.GONE);
} else {
profileswitchButton.setVisibility(View.VISIBLE);
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java
index f878b5676f..4f65995948 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/SmsCommunicator/SmsCommunicatorPlugin.java
@@ -16,7 +16,6 @@ import java.text.Normalizer;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
-import java.util.StringTokenizer;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
@@ -210,13 +209,13 @@ public class SmsCommunicatorPlugin implements PluginBase {
int agoMin = (int) (agoMsec / 60d / 1000d);
if (actualBG != null) {
- reply = MainApp.sResources.getString(R.string.actualbg) + " " + actualBG.valueToUnitsToString(units) + ", ";
+ reply = MainApp.sResources.getString(R.string.sms_actualbg) + " " + actualBG.valueToUnitsToString(units) + ", ";
} else if (lastBG != null) {
- reply = MainApp.sResources.getString(R.string.lastbg) + " " + lastBG.valueToUnitsToString(units) + " " + agoMin + MainApp.sResources.getString(R.string.minago) + ", ";
+ reply = MainApp.sResources.getString(R.string.sms_lastbg) + " " + lastBG.valueToUnitsToString(units) + " " + String.format(MainApp.sResources.getString(R.string.sms_minago), agoMin) + ", ";
}
DatabaseHelper.GlucoseStatus glucoseStatus = MainApp.getDbHelper().getGlucoseStatusData();
if (glucoseStatus != null)
- reply += MainApp.sResources.getString(R.string.delta) + ": " + NSProfile.toUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + " " + units + ", ";
+ reply += MainApp.sResources.getString(R.string.sms_delta) + " " + NSProfile.toUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + " " + units + ", ";
MainApp.getConfigBuilder().getActiveTreatments().updateTotalIOB();
IobTotal bolusIob = MainApp.getConfigBuilder().getActiveTreatments().getLastCalculation().round();
@@ -225,9 +224,9 @@ public class SmsCommunicatorPlugin implements PluginBase {
IobTotal basalIob = MainApp.getConfigBuilder().getActiveTempBasals().getLastCalculation().round();
if (basalIob == null) basalIob = new IobTotal();
- reply += MainApp.sResources.getString(R.string.treatments_iob_label_string) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U ("
- + MainApp.sResources.getString(R.string.bolus) + ": " + DecimalFormatter.to2Decimal(bolusIob.iob) + "U "
- + MainApp.sResources.getString(R.string.basal) + ": " + DecimalFormatter.to2Decimal(basalIob.basaliob) + "U)";
+ reply += MainApp.sResources.getString(R.string.sms_iob) + " " + DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U ("
+ + MainApp.sResources.getString(R.string.sms_bolus) + " " + DecimalFormatter.to2Decimal(bolusIob.iob) + "U "
+ + MainApp.sResources.getString(R.string.sms_basal) + " " + DecimalFormatter.to2Decimal(basalIob.basaliob) + "U)";
sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date()));
receivedSms.processed = true;
@@ -315,7 +314,7 @@ public class SmsCommunicatorPlugin implements PluginBase {
resetWaitingMessages();
sendSMS(cancelTempBasalWaitingForConfirmation = new Sms(receivedSms.phoneNumber, reply, new Date(), passCode));
} else {
- reply = MainApp.sResources.getString(R.string.remotebasalnotallowed);
+ reply = MainApp.sResources.getString(R.string.smscommunicator_remotebasalnotallowed);
sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date()));
}
} else {
@@ -329,7 +328,7 @@ public class SmsCommunicatorPlugin implements PluginBase {
sendSMS(tempBasalWaitingForConfirmation = new Sms(receivedSms.phoneNumber, reply, new Date(), passCode));
tempBasalWaitingForConfirmation.tempBasal = tempBasal;
} else {
- reply = MainApp.sResources.getString(R.string.remotebasalnotallowed);
+ reply = MainApp.sResources.getString(R.string.smscommunicator_remotebasalnotallowed);
sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date()));
}
}
@@ -337,7 +336,7 @@ public class SmsCommunicatorPlugin implements PluginBase {
break;
case "BOLUS":
if (new Date().getTime() - lastRemoteBolusTime.getTime() < Constants.remoteBolusMinDistance) {
- reply = MainApp.sResources.getString(R.string.remotebolusnotallowed);
+ reply = MainApp.sResources.getString(R.string.smscommunicator_remotebolusnotallowed);
sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date()));
} else if (splited.length > 1) {
amount = SafeParse.stringToDouble(splited[1]);
@@ -351,7 +350,7 @@ public class SmsCommunicatorPlugin implements PluginBase {
sendSMS(bolusWaitingForConfirmation = new Sms(receivedSms.phoneNumber, reply, new Date(), passCode));
bolusWaitingForConfirmation.bolusRequested = amount;
} else {
- reply = MainApp.sResources.getString(R.string.remotebolusnotallowed);
+ reply = MainApp.sResources.getString(R.string.smscommunicator_remotebolusnotallowed);
sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date()));
}
}
@@ -365,12 +364,12 @@ public class SmsCommunicatorPlugin implements PluginBase {
danaRPlugin = (DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class);
PumpEnactResult result = pumpInterface.deliverTreatment(bolusWaitingForConfirmation.bolusRequested, 0, null);
if (result.success) {
- reply = String.format(MainApp.sResources.getString(R.string.bolusdelivered), result.bolusDelivered);
+ reply = String.format(MainApp.sResources.getString(R.string.smscommunicator_bolusdelivered), result.bolusDelivered);
if (danaRPlugin != null) reply += "\n" + danaRPlugin.shortStatus();
lastRemoteBolusTime = new Date();
sendSMSToAllNumbers(new Sms(receivedSms.phoneNumber, reply, new Date()));
} else {
- reply = MainApp.sResources.getString(R.string.bolusfailed);
+ reply = MainApp.sResources.getString(R.string.smscommunicator_bolusfailed);
if (danaRPlugin != null) reply += "\n" + danaRPlugin.shortStatus();
sendSMS(new Sms(receivedSms.phoneNumber, reply, new Date()));
}
diff --git a/app/src/main/java/info/nightscout/utils/TimeListEdit.java b/app/src/main/java/info/nightscout/utils/TimeListEdit.java
new file mode 100644
index 0000000000..b1abfb6849
--- /dev/null
+++ b/app/src/main/java/info/nightscout/utils/TimeListEdit.java
@@ -0,0 +1,335 @@
+package info.nightscout.utils;
+
+import android.content.Context;
+import android.os.Build;
+import android.text.Editable;
+import android.text.Layout;
+import android.text.TextWatcher;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.Spinner;
+import android.widget.TextView;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.text.DateFormat;
+import java.text.NumberFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+
+/**
+ * Created by mike on 29.12.2016.
+ */
+
+public class TimeListEdit {
+ private static Logger log = LoggerFactory.getLogger(TimeListEdit.class);
+
+ final int ONEHOURINSECONDS = 60 * 60;
+
+ LinearLayout layout;
+
+ Context context;
+ View view;
+ int resLayoutId;
+ String label;
+ JSONArray data1;
+ JSONArray data2;
+ NumberFormat formatter;
+ Runnable save;
+
+ public TimeListEdit(Context context, View view, int resLayoutId, String label, JSONArray data1, JSONArray data2, NumberFormat formatter, Runnable save) {
+ this.context = context;
+ this.view = view;
+ this.resLayoutId = resLayoutId;
+ this.label = label;
+ this.data1 = data1;
+ this.data2 = data2;
+ this.formatter = formatter;
+ this.save = save;
+ buildView();
+ }
+
+ private void buildView() {
+ LayoutInflater inflater = LayoutInflater.from(context);
+ layout = (LinearLayout) view.findViewById(resLayoutId);
+
+ layout.removeAllViews();
+
+ TextView textlabel = new TextView(context);
+ textlabel.setText(label);
+ textlabel.setGravity(Gravity.LEFT);
+ LinearLayout.LayoutParams llp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
+ llp.setMargins(10, 0, 0, 0); // llp.setMargins(left, top, right, bottom);
+ textlabel.setLayoutParams(llp);
+ textlabel.setBackgroundColor(MainApp.sResources.getColor(R.color.linearBlockBackground));
+ if (Build.VERSION.SDK_INT < 23)
+ textlabel.setTextAppearance(context, android.R.style.TextAppearance_Medium);
+ else
+ textlabel.setTextAppearance(android.R.style.TextAppearance_Medium);
+ layout.addView(textlabel);
+
+ for (int i = 0; i < itemsCount(); i++) {
+ View childview = inflater.inflate(R.layout.timelistedit_element, layout, false);
+ final Spinner timeSpinner = (Spinner) childview.findViewById(R.id.timelistedit_time);
+ int previous = i == 0 ? -1 * ONEHOURINSECONDS : secondFromMidnight(i - 1);
+ int next = i == itemsCount() - 1 ? 24 * ONEHOURINSECONDS : secondFromMidnight(i + 1);
+ if (i == 0) next = ONEHOURINSECONDS;
+ fillSpinner(timeSpinner, secondFromMidnight(i), previous, next);
+
+ final EditText editText1 = (EditText) childview.findViewById(R.id.timelistedit_edit1);
+ fillNumber(editText1, value1(i));
+ final EditText editText2 = ((EditText) childview.findViewById(R.id.timelistedit_edit2));
+ fillNumber(editText2, value2(i));
+ if (data2 == null) {
+ editText2.setVisibility(View.GONE);
+ }
+
+
+ ImageView addbutton = (ImageView) childview.findViewById(R.id.timelistedit_add);
+ ImageView removebutton = (ImageView) childview.findViewById(R.id.timelistedit_remove);
+
+ if (itemsCount() == 1 && i == 0) {
+ removebutton.setVisibility(View.GONE);
+ }
+
+ if (itemsCount() >= 24) {
+ addbutton.setVisibility(View.GONE);
+ }
+
+ final int fixedPos = i;
+ addbutton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ int seconds = secondFromMidnight(fixedPos);
+ addItem(fixedPos, seconds, 0, 0);
+ // for here for the rest of values
+ for (int i = fixedPos + 1; i < itemsCount(); i++) {
+ if (secondFromMidnight(i - 1) >= secondFromMidnight(i)) {
+ editItem(i, secondFromMidnight(i - 1) + ONEHOURINSECONDS, value1(i), value2(i));
+ }
+ }
+ while (itemsCount() > 24 || secondFromMidnight(itemsCount() - 1) > 23 * ONEHOURINSECONDS)
+ removeItem(itemsCount() - 1);
+ log();
+ buildView();
+ }
+ });
+
+ removebutton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ removeItem(fixedPos);
+ log();
+ buildView();
+ }
+ });
+
+ timeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView> parent, View view, int position, long id) {
+ int seconds = DateUtil.toSeconds(timeSpinner.getSelectedItem().toString());
+ editItem(fixedPos, seconds, value1(fixedPos), value2(fixedPos));
+ log();
+ buildView();
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView> parent) {
+ editItem(fixedPos, 0, value1(fixedPos), value2(fixedPos));
+ log();
+ buildView();
+ }
+ }
+ );
+
+ editText1.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void afterTextChanged(Editable s) {
+ editItem(fixedPos, secondFromMidnight(fixedPos), SafeParse.stringToDouble(editText1.getText().toString()), value2(fixedPos));
+ log();
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start,
+ int count, int after) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start,
+ int before, int count) {
+ }
+ });
+
+ editText2.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void afterTextChanged(Editable s) {
+ editItem(fixedPos, secondFromMidnight(fixedPos), value1(fixedPos), SafeParse.stringToDouble(editText2.getText().toString()));
+ log();
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start,
+ int count, int after) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start,
+ int before, int count) {
+ }
+ });
+
+ layout.addView(childview);
+ }
+
+ if (!(itemsCount() > 0 && secondFromMidnight(itemsCount() - 1) == 23 * ONEHOURINSECONDS)) {
+ ImageView imageView = new ImageView(context);
+ imageView.setImageResource(R.drawable.add);
+ LinearLayout.LayoutParams illp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
+ illp.setMargins(0, 25, 0, 25); // llp.setMargins(left, top, right, bottom);
+ illp.gravity = Gravity.CENTER;
+ layout.addView(imageView);
+ imageView.setLayoutParams(illp);
+ imageView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ addItem(itemsCount(), itemsCount() > 0 ? secondFromMidnight(itemsCount() - 1) + ONEHOURINSECONDS : 0, 0, 0);
+ log();
+ buildView();
+ }
+ });
+ }
+
+ }
+
+ public void fillSpinner(Spinner spinner, int secondsFromMidnight, int previous, int next) {
+ int posInList = 0;
+ ArrayList timeList = new ArrayList<>();
+ DateFormat df = new SimpleDateFormat("HH:mm");
+ int pos = 0;
+ for (int t = previous + ONEHOURINSECONDS; t < next; t += ONEHOURINSECONDS) {
+ timeList.add(df.format(DateUtil.toDate(t)));
+ if (secondsFromMidnight == t) posInList = pos;
+ pos++;
+ }
+
+ ArrayAdapter adapter = new ArrayAdapter(context,
+ android.R.layout.simple_spinner_item, timeList);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ spinner.setAdapter(adapter);
+ spinner.setSelection(posInList, false);
+ }
+
+ public void fillNumber(EditText edit, Double value) {
+ if (value.equals(0d))
+ edit.setText("");
+ else
+ edit.setText(formatter.format(value));
+ }
+
+ public int itemsCount() {
+ return data1.length();
+ }
+
+ public int secondFromMidnight(int index) {
+ try {
+ JSONObject item = (JSONObject) data1.get(index);
+ if (item.has("timeAsSeconds")) {
+ return item.getInt("timeAsSeconds");
+ }
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return 0;
+ }
+
+ public double value1(int index) {
+ try {
+ JSONObject item = (JSONObject) data1.get(index);
+ if (item.has("value")) {
+ return item.getDouble("value");
+ }
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return 0d;
+ }
+
+ public double value2(int index) {
+ if (data2 != null) {
+ try {
+ JSONObject item = (JSONObject) data2.get(index);
+ if (item.has("value")) {
+ return item.getDouble("value");
+ }
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+ return 0d;
+ }
+
+ public void editItem(int index, int timeAsSeconds, double value1, double value2) {
+ try {
+ JSONObject newObject1 = new JSONObject();
+ newObject1.put("timeAsSeconds", timeAsSeconds);
+ newObject1.put("value", value1);
+ data1.put(index, newObject1);
+ if (data2 != null) {
+ JSONObject newObject2 = new JSONObject();
+ newObject2.put("timeAsSeconds", timeAsSeconds);
+ newObject2.put("value", value2);
+ data2.put(index, newObject2);
+ }
+ if (save != null) save.run();
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ public void addItem(int index, int timeAsSeconds, double value1, double value2) {
+ try {
+ // shift data
+ for (int i = data1.length(); i > index; i--) {
+ data1.put(i, data1.get(i - 1));
+ if (data2 != null)
+ data2.put(i, data2.get(i - 1));
+ }
+ // add new object
+ editItem(index, timeAsSeconds, value1, value2);
+ if (save != null) save.run();
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ public void removeItem(int index) {
+ data1.remove(index);
+ if (data2 != null)
+ data2.remove(index);
+ if (save != null) save.run();
+ }
+
+ void log() {
+ DateFormat df = new SimpleDateFormat("HH:mm");
+ for (int i = 0; i < data1.length(); i++) {
+ int pos = 0;
+ log.debug(i + ": @" + df.format(DateUtil.toDate(secondFromMidnight(i))) + " " + value1(i) + (data2 != null ? " " + value2(i) : ""));
+ }
+ }
+}
diff --git a/app/src/main/res/drawable/add.png b/app/src/main/res/drawable/add.png
new file mode 100644
index 0000000000..b25da64672
Binary files /dev/null and b/app/src/main/res/drawable/add.png differ
diff --git a/app/src/main/res/drawable/clone.png b/app/src/main/res/drawable/clone.png
new file mode 100644
index 0000000000..82fd90cca8
Binary files /dev/null and b/app/src/main/res/drawable/clone.png differ
diff --git a/app/src/main/res/drawable/remove.png b/app/src/main/res/drawable/remove.png
new file mode 100644
index 0000000000..835575cea2
Binary files /dev/null and b/app/src/main/res/drawable/remove.png differ
diff --git a/app/src/main/res/layout/localprofile_fragment.xml b/app/src/main/res/layout/localprofile_fragment.xml
new file mode 100644
index 0000000000..03b459eb9b
--- /dev/null
+++ b/app/src/main/res/layout/localprofile_fragment.xml
@@ -0,0 +1,118 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/overview_fragment.xml b/app/src/main/res/layout/overview_fragment.xml
index c6ba630b63..517eae9577 100644
--- a/app/src/main/res/layout/overview_fragment.xml
+++ b/app/src/main/res/layout/overview_fragment.xml
@@ -20,6 +20,38 @@
+
+
+
+
+
+
+
+ android:textSize="70dp"
+ android:textStyle="bold"
+ android:layout_marginTop="-15dp" />
-
-
-
-
-
-
-
+ android:layout_marginLeft="10dp"
+ android:layout_weight="0.5"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
-
diff --git a/app/src/main/res/layout/simpleprofile_fragment.xml b/app/src/main/res/layout/simpleprofile_fragment.xml
index 0c96593df1..2b5a2390db 100644
--- a/app/src/main/res/layout/simpleprofile_fragment.xml
+++ b/app/src/main/res/layout/simpleprofile_fragment.xml
@@ -4,116 +4,90 @@
android:layout_height="match_parent"
tools:context=".plugins.SimpleProfile.SimpleProfileFragment">
-
+ android:layout_height="match_parent">
-
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
-
+
-
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
@@ -122,50 +96,51 @@
android:id="@+id/simpleprofile_basalrate"
android:layout_width="100dp"
android:layout_height="wrap_content"
- android:layout_column="2"
android:inputType="numberDecimal" />
-
-
-
-
+
-
-
+
-
-
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/timelistedit_element.xml b/app/src/main/res/layout/timelistedit_element.xml
new file mode 100644
index 0000000000..b0588aea45
--- /dev/null
+++ b/app/src/main/res/layout/timelistedit_element.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml
index 9d833e5d01..3ca9fc4008 100644
--- a/app/src/main/res/values-bg/strings.xml
+++ b/app/src/main/res/values-bg/strings.xml
@@ -16,12 +16,12 @@
Известие
Проверка на КЗ
Корекция с въглехидр.
- Замяна сензор
+ Смяна на сензор
Рестарт на сензор
Комбиниран болус
Болус за корекция
Физ. активност
- Замяна резервоар
+ Смяна на резервоар
Болус за осн. хранене
Абсолютна
ВХ
@@ -41,7 +41,7 @@
Бележка
OpenAPS оффлайн
Смяна на профил
- Замяна сет
+ Смяна на сет
Въпрос
Болус за закуска
Край на временен базал
@@ -193,7 +193,6 @@
Макс. лимит на временен базал [Е/ч]
Български
Макс. лимит на не болус IOB подаван от openAPS
- min ago
Свързан
Избраното устройство не съществува
Прекъснат
@@ -214,7 +213,7 @@
MUST NOT BE USED TO MAKE MEDICAL DECISIONS. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+XXXXXXXXXX;+YYYYYYYYYY
Болус %.2fU беше подаден успешно
- Болусът не е доставен
+ Болусът не е доставен
Откажи временен базал
Последно свързване:
Изчаква резултат
@@ -222,7 +221,7 @@
Позволени телефонни номера
Успех
За да доставите болус %.2fU отговорете с код %s
- Отдалечен болус не е разрешен
+ Отдалечен болус не е разрешен
Обнови профила
Процент
Сензор
@@ -308,7 +307,7 @@
Премахни
Бърз болус
Настройки за бърз болус
- Не са позволени отдалечени настройки
+ Не са позволени отдалечени настройки
To start basal %.2fU/h reply with code %s
To stop temp basal reply with code %s
Loop has been disabled
@@ -356,13 +355,13 @@
Базал:
Базалните стойности са под минимума. Не е зададен профил!
Батерията на помпата е изтощена
- КЗ:
+ КЗ:
Забрани EasyUI режим в помпата
Разреши удължен болус в помпата
Промени режима от U/d на U/h в помпата
DanaR за Корея
Горна линия
- Последна КЗ:
+ Последна КЗ:
Долна линия
Изтощена батерия
Отвори Опции на часовника
@@ -376,4 +375,5 @@
Изпрати всички данни отново
Wear
Избран е грешен тип помпа
+ преди %d м.
diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml
index bbb8aaf954..d6c65fb557 100644
--- a/app/src/main/res/values-cs/strings.xml
+++ b/app/src/main/res/values-cs/strings.xml
@@ -73,7 +73,6 @@
Nastaveno pumpou
SMYČKA ZAKÁZÁNA OMEZENÍM
Ručně spuštěno
- m zpět
Minimální trvání
Záloha
Ukončit
@@ -227,8 +226,8 @@
Poslední spojení:
Zrušit dočasný bazál
Bolus %.2fU aplikován úspěšně
- Chyba při aplikování bolusu
- Vzdálený bolus není momentálně povolen
+ Chyba při aplikování bolusu
+ Vzdálený bolus není momentálně povolen
K potvzení bolusu %.2fU odpověz SMS s kódem %s
SMS komunikátor
Povolená tel. čísla
@@ -301,7 +300,7 @@
Spanish
Není vybrán žádný profil
Hodnota %s je mimo přednastavený rozsah
- Vzdálené posílání příkazů není povoleno
+ Vzdálené posílání příkazů není povoleno
Na spuštění bazálu %.2fU/h odpověz SMS s kódem %s
Na ukončení bazálu odpověz SMS s kódem %s
Dočaný bazál zastaven
@@ -374,6 +373,16 @@
Vybrán špatný ovladač pumpy
Hodnota bazálu pod minimem. Nenastaveno!
Pera
- Glykémie:
- Poslední glykémie:
+ Glykémie:
+ Poslední glykémie:
+ před %d min
+ Bazál:
+ Bolus:
+ Rozdíl:
+ IOB:
+ před %d min
+ Bolus %.2fU aplikován úspěšně
+ Průběžné oznámení
+ ZASTARALÉ
+ Místní profil
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index b31207f125..fc536ee468 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -176,7 +176,6 @@
Carbs constraint applied
Reset Datenbanken
Minimale Dauer
- min ago
Erneure treatments von NS
Exit
Fehlend
@@ -198,7 +197,7 @@
Nightscout
+XXXXXXXXXX;+YYYYYYYYYY
Absolut
- Bolus fehlgeschlagen
+ Bolus fehlgeschlagen
Temp Basal abbrechen
Temoräres Ziel
Temoräres Ziel abbrechen
@@ -241,7 +240,7 @@
Nightscout Profil zur Pumpe synchronisieren
auf Pumpenergebnis warten
Kein Bluetoothadapter gefunden
- Remote Bolus nicht erlaubt
+ Remote Bolus nicht erlaubt
Um Bolus %.2fU bitte mit %s antworten
Korean
Limit erreicht
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
index c87ec9529e..ec979b5df3 100644
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -74,7 +74,6 @@
Glucosa
Delta
Avg. delta
- min antes
Config Builder
Objetivos
@@ -240,10 +239,10 @@
Números de teléfono permitidos
XXXXXXXXXX +; + YYYYYYYYYY
Para entregar bolo% .2fU responder con código% s
- bolo falló
+ bolo falló
Bolo% .2fU entregado con éxito
Entregando% .2fU
- Bolo remoto no permitido
+ Bolo remoto no permitido
Dedo
Sensor
Manual
@@ -334,7 +333,7 @@
NS solo subida. No efectivo con SGV salvo que este seleccionada una fuente local como xDrip. No efectivo en perfiles usando perfiles NS
Otros
¡Bomba no iniciada!
- No permitidos ajustes basales remotos
+ No permitidos ajustes basales remotos
¿Realmente quiere resetear la base de datos?
Comando desconocido o respuesta incorrecta
¡Por favor asegurar que la cantidad coincide con la especificación del set de infusión!
diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml
index f4fb743f62..8a950cf344 100644
--- a/app/src/main/res/values-ko/strings.xml
+++ b/app/src/main/res/values-ko/strings.xml
@@ -75,7 +75,6 @@
혈당
Delta
Avg. delta
- 분 전
Config Builder
목표
@@ -238,16 +237,15 @@
Absolute
임시기초주입 취소하기
SMS 전송
- MM 640g
결과 기다리는 중
허가된 전화번호
+XXXXXXXXXX;+YYYYYYYYYY
식사주입 %.2fU 을 실행하려면 %s 를 입력하고 답장하세요
- Bolus failed
+ Bolus failed
Bolus %.2fU delivered successfully
%.2fU 주입중
SMS 원격 명령 사용하기
- 원격 식사주입 허용되지 않음
+ 원격 식사주입 허용되지 않음
Finger
Sensor
Manual
@@ -312,7 +310,7 @@
Loop가 중지중입니다.
Loop가 실행중입니다.
값 %s 은 하드리밋(Hard Limit)를 벗어났습니다
- 원격 기초주입설정이 허가되지 않았습니다
+ 원격 기초주입설정이 허가되지 않았습니다
기초주입 %.2fU/h 을 실행하려면 %s 를 입력하고 답장하세요
Temp basal %.2fU/h for %d min started successfully
Temp basal start failed
@@ -381,7 +379,7 @@
펌프에서 확장식사기능을 활성화 하세요
펌프에서 U/d에서 U/h로 모드를 변경하세요
기초주입값이 최소값 이하입니다. 프로파일이 설정되지 않습니다!
- BG:
- Last BG:
+ BG:
+ Last BG:
MDI
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index ab184438f9..9359821c78 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -31,6 +31,7 @@
Insulin:
Carbs:
IOB:
+ IOB:
Activity:
Toal IOB:
Total IOB activity:
@@ -75,8 +76,8 @@
Reason
Glucose
Delta
+ Delta:
Avg. delta
- m ago
Config Builder
Objectives
@@ -123,7 +124,9 @@
Confirmation
Enter new treatment:
Bolus
+ Bolus:
Basal
+ Basal:
Carbs
Change your input!
Set new extended bolus:
@@ -245,11 +248,12 @@
Allowed phone numbers
+XXXXXXXXXX;+YYYYYYYYYY
To deliver bolus %.2fU reply with code %s
- Bolus failed
+ Bolus failed
Bolus %.2fU delivered successfully
+ Bolus %.2fU delivered successfully
Delivering %.2fU
Allow remote commands via SMS
- Remote bolus not allowed
+ Remote bolus not allowed
Finger
Sensor
Manual
@@ -314,7 +318,7 @@
Loop is disabled
Loop is enabled
Value %s is out of hard limits
- Remote basal setting is not allowed
+ Remote basal setting is not allowed
To start basal %.2fU/h reply with code %s
Temp basal %.2fU/h for %d min started successfully
Temp basal start failed
@@ -384,9 +388,12 @@
Enable extended boluses on pump
Change mode from U/d to U/h on pump
Basal value below minimum. Profile not set!
- BG:
- Last BG:
+ BG:
+ Last BG:
MDI
Ongoing Notification
OLD DATA
+ %dmin ago
+ %dmin ago
+ Local Profile
diff --git a/app/src/test/info/nightscout/utils/RoundTest.java b/app/src/test/java/info/nightscout/utils/RoundTest.java
similarity index 75%
rename from app/src/test/info/nightscout/utils/RoundTest.java
rename to app/src/test/java/info/nightscout/utils/RoundTest.java
index 91bce62014..d95ab2b391 100644
--- a/app/src/test/info/nightscout/utils/RoundTest.java
+++ b/app/src/test/java/info/nightscout/utils/RoundTest.java
@@ -6,20 +6,24 @@ import static org.junit.Assert.*;
public class RoundTest {
+ public RoundTest(){
+ super();
+ }
+
@Test
- public void roundTo() {
+ public void roundToTest() throws Exception {
assertEquals( 0.55d, Round.roundTo(0.54d, 0.05d), 0.00000001d );
assertEquals( 1d, Round.roundTo(1.49d, 1d), 0.00000001d );
}
@Test
- public void floorTo() {
+ public void floorToTest() throws Exception {
assertEquals( 0.5d, Round.floorTo(0.54d, 0.05d), 0.00000001d );
assertEquals( 1d, Round.floorTo(1.59d, 1d), 0.00000001d );
}
@Test
- public void ceilTo() {
+ public void ceilToTest() throws Exception {
assertEquals( 0.6d, Round.ceilTo(0.54d, 0.1d), 0.00000001d );
assertEquals( 2d, Round.ceilTo(1.49999d, 1d), 0.00000001d );
}
diff --git a/app/src/test/java/info/nightscout/utils/TimeListEditTest.java b/app/src/test/java/info/nightscout/utils/TimeListEditTest.java
new file mode 100644
index 0000000000..8fd387eebd
--- /dev/null
+++ b/app/src/test/java/info/nightscout/utils/TimeListEditTest.java
@@ -0,0 +1,57 @@
+package info.nightscout.utils;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+
+import org.json.JSONArray;
+import org.junit.Test;
+import org.mockito.Mock;
+
+import java.lang.reflect.Method;
+import java.text.DecimalFormat;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.when;
+
+/**
+ * Created by mike on 30.12.2016.
+ */
+public class TimeListEditTest {
+
+ /*
+ JSONArray data = new JSONArray();
+ JSONArray data2 = new JSONArray();
+ TimeListEdit tle = new TimeListEdit(null, null, 0, "Test1", data, "ic", null, new DecimalFormat("0.00"));
+ TimeListEdit tle2 = new TimeListEdit(null, null, 0, "Test2", data2, "ic", "ic2", new DecimalFormat("0.00"));
+
+
+ @Test
+ public void doArrayTest() throws Exception {
+ tle.addItem(0, 0, 0.1, 0);
+ tle.addItem(1, 60 * 60, 0.2, 0);
+ assertEquals(2, tle.itemsCount());
+
+ tle.editItem(0, 2 * 60 * 60, 1, 0);
+ assertEquals(2, tle.itemsCount());
+ assertEquals(1d, tle.value1(0), 0.00001d);
+ assertEquals( 2 * 60 * 60, tle.secondFromMidnight(0));
+ tle.removeItem(0);
+ assertEquals(0.2d, tle.value1(0), 0.00001d);
+ assertEquals(0, tle.value2(0), 0.00001d);
+ assertEquals(60 * 60, tle.secondFromMidnight(0));
+
+ //System.out.print(tle2.toString());
+ assertEquals(0, tle2.itemsCount());
+ tle2.addItem(0, 0, 1, 2);
+ assertEquals(1, tle2.itemsCount());
+ assertEquals(0, tle2.secondFromMidnight(0));
+ assertEquals(1d, tle2.value1(0), 0.00001d);
+ assertEquals(2d, tle2.value2(0), 0.00001d);
+ }
+
+ */
+ @Test
+ public void fakeTest() throws Exception {
+ }
+
+}
\ No newline at end of file
diff --git a/wear/wear.iml b/wear/wear.iml
index ce3df746e7..0de50a9087 100644
--- a/wear/wear.iml
+++ b/wear/wear.iml
@@ -43,6 +43,13 @@
+
+
+
+
+
+
+
@@ -51,13 +58,6 @@
-
-
-
-
-
-
-
@@ -66,14 +66,6 @@
-
-
-
-
-
-
-
-
@@ -82,6 +74,14 @@
+
+
+
+
+
+
+
+
@@ -106,14 +106,6 @@
-
-
-
-
-
-
-
-
@@ -122,10 +114,16 @@
+
+
+
+
+
+
+
+
-
-
@@ -134,8 +132,11 @@
+<<<<<<< Updated upstream
+=======
+>>>>>>> Stashed changes
@@ -144,7 +145,6 @@
-