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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +