diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.java b/app/src/main/java/info/nightscout/androidaps/MainApp.java index 21e2d666a4..63a2446051 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainApp.java +++ b/app/src/main/java/info/nightscout/androidaps/MainApp.java @@ -1,14 +1,10 @@ package info.nightscout.androidaps; import android.app.Application; -import android.bluetooth.BluetoothAdapter; import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; import android.content.IntentFilter; import android.content.res.Resources; import android.os.SystemClock; -import android.util.Log; import androidx.annotation.Nullable; import androidx.annotation.PluralsRes; @@ -44,7 +40,7 @@ import info.nightscout.androidaps.plugins.constraints.dstHelper.DstHelperPlugin; import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin; import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin; import info.nightscout.androidaps.plugins.constraints.storage.StorageConstraintPlugin; -import info.nightscout.androidaps.plugins.general.actions.ActionsFragment; +import info.nightscout.androidaps.plugins.general.actions.ActionsPlugin; import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin; import info.nightscout.androidaps.plugins.general.careportal.CareportalPlugin; import info.nightscout.androidaps.plugins.general.food.FoodPlugin; @@ -70,8 +66,6 @@ import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin; import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin; import info.nightscout.androidaps.plugins.profile.simple.SimpleProfilePlugin; import info.nightscout.androidaps.plugins.pump.combo.ComboPlugin; -import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst; -import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil; import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin; import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin; import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin; @@ -177,7 +171,7 @@ public class MainApp extends Application { // Register all tabs in app here pluginsList.add(OverviewPlugin.getPlugin()); pluginsList.add(IobCobCalculatorPlugin.getPlugin()); - if (Config.ACTION) pluginsList.add(ActionsFragment.getPlugin()); + if (Config.ACTION) pluginsList.add(ActionsPlugin.INSTANCE); pluginsList.add(InsulinOrefRapidActingPlugin.getPlugin()); pluginsList.add(InsulinOrefUltraRapidActingPlugin.getPlugin()); pluginsList.add(InsulinOrefFreePeakPlugin.getPlugin()); @@ -208,7 +202,7 @@ public class MainApp extends Application { if (Config.SAFETY) pluginsList.add(VersionCheckerPlugin.INSTANCE); if (Config.SAFETY) pluginsList.add(StorageConstraintPlugin.getPlugin()); if (Config.SAFETY) pluginsList.add(SignatureVerifier.getPlugin()); - if (Config.APS) pluginsList.add(ObjectivesPlugin.getPlugin()); + if (Config.APS) pluginsList.add(ObjectivesPlugin.INSTANCE); pluginsList.add(SourceXdripPlugin.getPlugin()); pluginsList.add(SourceNSClientPlugin.getPlugin()); pluginsList.add(SourceMM640gPlugin.getPlugin()); diff --git a/app/src/main/java/info/nightscout/androidaps/data/Profile.java b/app/src/main/java/info/nightscout/androidaps/data/Profile.java index ee3d50aa16..2378e60833 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/Profile.java +++ b/app/src/main/java/info/nightscout/androidaps/data/Profile.java @@ -11,6 +11,7 @@ import org.slf4j.LoggerFactory; import java.text.DecimalFormat; import java.util.TimeZone; +import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; @@ -227,8 +228,10 @@ public class Profile { for (int index = 0; index < basal_v.size(); index++) { long secondsFromMidnight = basal_v.keyAt(index); if (notify && secondsFromMidnight % 3600 != 0) { - Notification notification = new Notification(Notification.BASAL_PROFILE_NOT_ALIGNED_TO_HOURS, String.format(MainApp.gs(R.string.basalprofilenotaligned), from), Notification.NORMAL); - MainApp.bus().post(new EventNewNotification(notification)); + if (Config.APS) { + Notification notification = new Notification(Notification.BASAL_PROFILE_NOT_ALIGNED_TO_HOURS, String.format(MainApp.gs(R.string.basalprofilenotaligned), from), Notification.NORMAL); + MainApp.bus().post(new EventNewNotification(notification)); + } } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopFragment.kt index 2ab594c2a2..b7549fcfed 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopFragment.kt @@ -12,10 +12,7 @@ import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopSetLastRunGui import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopUpdateGui import info.nightscout.androidaps.plugins.bus.RxBus -import info.nightscout.androidaps.utils.DateUtil -import info.nightscout.androidaps.utils.FabricPrivacy -import info.nightscout.androidaps.utils.HtmlHelper -import info.nightscout.androidaps.utils.plusAssign +import info.nightscout.androidaps.utils.* import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.CompositeDisposable import kotlinx.android.synthetic.main.loop_fragment.* @@ -61,6 +58,7 @@ class LoopFragment : Fragment() { }) updateGUI() + SP.putBoolean(R.string.key_objectiveuseloop, true) } @Synchronized diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java index d3f6cc8212..c9444acb33 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java @@ -51,7 +51,6 @@ import info.nightscout.androidaps.plugins.aps.loop.events.EventNewOpenLoopNotifi import info.nightscout.androidaps.plugins.bus.RxBus; import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin; import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; import info.nightscout.androidaps.plugins.general.wear.ActionStringHandler; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished; @@ -471,11 +470,7 @@ public class LoopPlugin extends PluginBase { lastRun.lastEnact = new Date(); lastRun.lastOpenModeAccept = new Date(); NSUpload.uploadDeviceStatus(); - ObjectivesPlugin objectivesPlugin = MainApp.getSpecificPlugin(ObjectivesPlugin.class); - if (objectivesPlugin != null) { - ObjectivesPlugin.getPlugin().manualEnacts++; - ObjectivesPlugin.getPlugin().saveProgress(); - } + SP.incInt(R.string.key_ObjectivesmanualEnacts); } MainApp.bus().post(new EventAcceptOpenLoopChange()); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ProfileFunctions.java b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ProfileFunctions.java index 7c92cd98b3..0e38758e86 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ProfileFunctions.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ProfileFunctions.java @@ -27,6 +27,7 @@ import info.nightscout.androidaps.plugins.general.overview.dialogs.ErrorHelperAc import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; import info.nightscout.androidaps.queue.Callback; import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.SP; public class ProfileFunctions { private static Logger log = LoggerFactory.getLogger(L.PROFILE); @@ -159,6 +160,8 @@ public class ProfileFunctions { public static void doProfileSwitch(final ProfileStore profileStore, final String profileName, final int duration, final int percentage, final int timeshift) { ProfileSwitch profileSwitch = prepareProfileSwitch(profileStore, profileName, duration, percentage, timeshift, System.currentTimeMillis()); TreatmentsPlugin.getPlugin().addToHistoryProfileSwitch(profileSwitch); + if (percentage == 90 && duration == 10) + SP.putBoolean(R.string.key_objectiveuseprofileswitch, true); } public static void doProfileSwitch(final int duration, final int percentage, final int timeshift) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesFragment.java deleted file mode 100644 index 7600c017c2..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesFragment.java +++ /dev/null @@ -1,229 +0,0 @@ -package info.nightscout.androidaps.plugins.constraints.objectives; - -import android.app.Activity; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import androidx.annotation.NonNull; -import androidx.cardview.widget.CardView; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.LinearSmoothScroller; -import androidx.recyclerview.widget.RecyclerView; -import android.text.Html; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.CheckBox; -import android.widget.LinearLayout; -import android.widget.TextView; - -import java.util.Date; - -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.common.SubscriberFragment; -import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective; -import info.nightscout.androidaps.utils.FabricPrivacy; - -public class ObjectivesFragment extends SubscriberFragment { - RecyclerView recyclerView; - CheckBox enableFake; - TextView reset; - ObjectivesAdapter objectivesAdapter = new ObjectivesAdapter(); - Handler handler = new Handler(Looper.getMainLooper()); - - private Runnable objectiveUpdater = new Runnable() { - @Override - public void run() { - handler.postDelayed(this, 60 * 1000); - updateGUI(); - } - }; - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - try { - View view = inflater.inflate(R.layout.objectives_fragment, container, false); - - recyclerView = view.findViewById(R.id.objectives_recyclerview); - recyclerView.setLayoutManager(new LinearLayoutManager(view.getContext())); - recyclerView.setAdapter(objectivesAdapter); - enableFake = view.findViewById(R.id.objectives_fake); - reset = view.findViewById(R.id.objectives_reset); - enableFake.setOnClickListener(v -> updateGUI()); - reset.setOnClickListener(v -> { - ObjectivesPlugin.getPlugin().reset(); - ObjectivesPlugin.getPlugin().saveProgress(); - recyclerView.getAdapter().notifyDataSetChanged(); - scrollToCurrentObjective(); - }); - scrollToCurrentObjective(); - startUpdateTimer(); - return view; - } catch (Exception e) { - FabricPrivacy.logException(e); - } - - return null; - } - - @Override - public synchronized void onDestroyView() { - super.onDestroyView(); - handler.removeCallbacks(objectiveUpdater); - } - - private void startUpdateTimer() { - handler.removeCallbacks(objectiveUpdater); - for (Objective objective : ObjectivesPlugin.getPlugin().getObjectives()) { - if (objective.isStarted() && !objective.isAccomplished()) { - long timeTillNextMinute = (System.currentTimeMillis() - objective.getStartedOn().getTime()) % (60 * 1000); - handler.postDelayed(objectiveUpdater, timeTillNextMinute); - break; - } - } - } - - private void scrollToCurrentObjective() { - for (int i = 0; i < ObjectivesPlugin.getPlugin().getObjectives().size(); i++) { - Objective objective = ObjectivesPlugin.getPlugin().getObjectives().get(i); - if (!objective.isStarted() || !objective.isAccomplished()) { - RecyclerView.SmoothScroller smoothScroller = new LinearSmoothScroller(getContext()) { - @Override - protected int getVerticalSnapPreference() { - return LinearSmoothScroller.SNAP_TO_START; - } - - @Override - protected int calculateTimeForScrolling(int dx) { - return super.calculateTimeForScrolling(dx) * 4; - } - }; - smoothScroller.setTargetPosition(i); - recyclerView.getLayoutManager().startSmoothScroll(smoothScroller); - break; - } - } - } - - private class ObjectivesAdapter extends RecyclerView.Adapter { - - @NonNull - @Override - public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.objectives_item, parent, false)); - } - - @Override - public void onBindViewHolder(@NonNull ViewHolder holder, int position) { - Objective objective = ObjectivesPlugin.getPlugin().getObjectives().get(position); - holder.title.setText(MainApp.gs(R.string.nth_objective, position + 1)); - holder.revert.setVisibility(View.INVISIBLE); - if (objective.getObjective() != 0) { - holder.objective.setVisibility(View.VISIBLE); - holder.objective.setText(MainApp.gs(objective.getObjective())); - } else holder.objective.setVisibility(View.GONE); - if (objective.getGate() != 0) { - holder.gate.setVisibility(View.VISIBLE); - holder.gate.setText(MainApp.gs(objective.getGate())); - } else holder.gate.setVisibility(View.GONE); - if (!objective.isStarted()) { - holder.gate.setTextColor(0xFFFFFFFF); - holder.verify.setVisibility(View.GONE); - holder.progress.setVisibility(View.GONE); - if (position == 0 || ObjectivesPlugin.getPlugin().getObjectives().get(position - 1).isAccomplished()) - holder.start.setVisibility(View.VISIBLE); - else holder.start.setVisibility(View.GONE); - } else if (objective.isAccomplished()) { - holder.gate.setTextColor(0xFF4CAF50); - holder.verify.setVisibility(View.GONE); - holder.progress.setVisibility(View.GONE); - holder.start.setVisibility(View.GONE); - } else if (objective.isStarted()) { - holder.gate.setTextColor(0xFFFFFFFF); - holder.verify.setVisibility(View.VISIBLE); - holder.verify.setEnabled(objective.isCompleted() || enableFake.isChecked()); - holder.start.setVisibility(View.GONE); - if(objective.isRevertable()) { - holder.revert.setVisibility(View.VISIBLE); - } - holder.progress.setVisibility(View.VISIBLE); - holder.progress.removeAllViews(); - for (Objective.Task task : objective.getTasks()) { - if (task.shouldBeIgnored()) continue; - TextView textView = new TextView(holder.progress.getContext()); - textView.setTextColor(0xFFFFFFFF); - String basicHTML = "%2$s: %3$s"; - String formattedHTML = String.format(basicHTML, task.isCompleted() ? "#4CAF50" : "#FF9800", MainApp.gs(task.getTask()), task.getProgress()); - textView.setText(Html.fromHtml(formattedHTML)); - holder.progress.addView(textView, LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); - } - } - holder.verify.setOnClickListener((view) -> { - objective.setAccomplishedOn(new Date()); - notifyDataSetChanged(); - scrollToCurrentObjective(); - startUpdateTimer(); - }); - holder.start.setOnClickListener((view) -> { - objective.setStartedOn(new Date()); - notifyDataSetChanged(); - scrollToCurrentObjective(); - startUpdateTimer(); - }); - holder.revert.setOnClickListener((view) -> { - objective.setAccomplishedOn(null); - objective.setStartedOn(null); - if (position > 0) { - Objective prevObj = ObjectivesPlugin.getPlugin().getObjectives().get(position - 1); - prevObj.setAccomplishedOn(null); - } - notifyDataSetChanged(); - scrollToCurrentObjective(); - }); - } - - - - @Override - public int getItemCount() { - return ObjectivesPlugin.getPlugin().getObjectives().size(); - } - - public class ViewHolder extends RecyclerView.ViewHolder { - - public CardView cardView; - public TextView title; - public TextView objective; - public TextView gate; - public LinearLayout progress; - public Button verify; - public Button start; - public Button revert; - - public ViewHolder(View itemView) { - super(itemView); - cardView = (CardView) itemView; - title = itemView.findViewById(R.id.objective_title); - objective = itemView.findViewById(R.id.objective_objective); - gate = itemView.findViewById(R.id.objective_gate); - progress = itemView.findViewById(R.id.objective_progress); - verify = itemView.findViewById(R.id.objective_verify); - start = itemView.findViewById(R.id.objective_start); - revert = itemView.findViewById(R.id.objective_back); - } - } - } - - @Override - public void updateGUI() { - Activity activity = getActivity(); - if (activity != null) - activity.runOnUiThread(() -> { - objectivesAdapter.notifyDataSetChanged(); - }); - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesFragment.kt new file mode 100644 index 0000000000..63f522da8d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesFragment.kt @@ -0,0 +1,268 @@ +package info.nightscout.androidaps.plugins.constraints.objectives + +import android.graphics.Color +import android.os.Bundle +import android.os.Handler +import android.os.Looper +import android.view.Gravity +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.TextView +import androidx.fragment.app.Fragment +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.LinearSmoothScroller +import androidx.recyclerview.widget.RecyclerView +import info.nightscout.androidaps.MainApp +import info.nightscout.androidaps.R +import info.nightscout.androidaps.plugins.bus.RxBus +import info.nightscout.androidaps.plugins.constraints.objectives.activities.ObjectivesExamDialog +import info.nightscout.androidaps.plugins.constraints.objectives.events.EventObjectivesUpdateGui +import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective.ExamTask +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.FabricPrivacy +import info.nightscout.androidaps.utils.HtmlHelper +import info.nightscout.androidaps.utils.SP +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.disposables.CompositeDisposable +import kotlinx.android.synthetic.main.objectives_fragment.* + +class ObjectivesFragment : Fragment() { + private val objectivesAdapter = ObjectivesAdapter() + private val handler = Handler(Looper.getMainLooper()) + + private var disposable: CompositeDisposable = CompositeDisposable() + + private val objectiveUpdater = object : Runnable { + override fun run() { + handler.postDelayed(this, (60 * 1000).toLong()) + updateGUI() + } + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + return inflater.inflate(R.layout.objectives_fragment, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + objectives_recyclerview.layoutManager = LinearLayoutManager(view.context) + objectives_recyclerview.adapter = objectivesAdapter + objectives_fake.setOnClickListener { updateGUI() } + objectives_reset.setOnClickListener { + ObjectivesPlugin.reset() + objectives_recyclerview.adapter?.notifyDataSetChanged() + scrollToCurrentObjective() + } + scrollToCurrentObjective() + startUpdateTimer() + } + + @Synchronized + override fun onResume() { + super.onResume() + disposable.add(RxBus + .toObservable(EventObjectivesUpdateGui::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ + objectives_recyclerview.adapter?.notifyDataSetChanged() + }, { + FabricPrivacy.logException(it) + }) + ) + } + + @Synchronized + override fun onPause() { + super.onPause() + disposable.clear() + } + + @Synchronized + override fun onDestroyView() { + super.onDestroyView() + handler.removeCallbacks(objectiveUpdater) + } + + private fun startUpdateTimer() { + handler.removeCallbacks(objectiveUpdater) + for (objective in ObjectivesPlugin.objectives) { + if (objective.isStarted && !objective.isAccomplished) { + val timeTillNextMinute = (System.currentTimeMillis() - objective.startedOn) % (60 * 1000) + handler.postDelayed(objectiveUpdater, timeTillNextMinute) + break + } + } + } + + private fun scrollToCurrentObjective() { + for (i in 0 until ObjectivesPlugin.objectives.size) { + val objective = ObjectivesPlugin.objectives[i] + if (!objective.isStarted || !objective.isAccomplished) { + val smoothScroller = object : LinearSmoothScroller(context!!) { + override fun getVerticalSnapPreference(): Int { + return SNAP_TO_START + } + + override fun calculateTimeForScrolling(dx: Int): Int { + return super.calculateTimeForScrolling(dx) * 4 + } + } + smoothScroller.targetPosition = i + objectives_recyclerview.layoutManager?.startSmoothScroll(smoothScroller) + break + } + } + } + + private inner class ObjectivesAdapter : RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + return ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.objectives_item, parent, false)) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + val objective = ObjectivesPlugin.objectives[position] + holder.title.text = MainApp.gs(R.string.nth_objective, position + 1) + holder.revert.visibility = View.GONE + if (objective.objective != 0) { + holder.objective.visibility = View.VISIBLE + holder.objective.text = MainApp.gs(objective.objective) + } else + holder.objective.visibility = View.GONE + if (objective.gate != 0) { + holder.gate.visibility = View.VISIBLE + holder.gate.text = MainApp.gs(objective.gate) + } else + holder.gate.visibility = View.GONE + if (!objective.isStarted) { + holder.gate.setTextColor(-0x1) + holder.verify.visibility = View.GONE + holder.progress.visibility = View.GONE + holder.accomplished.visibility = View.GONE + if (position == 0 || ObjectivesPlugin.objectives[position - 1].isAccomplished) + holder.start.visibility = View.VISIBLE + else + holder.start.visibility = View.GONE + } else if (objective.isAccomplished) { + holder.gate.setTextColor(-0xb350b0) + holder.verify.visibility = View.GONE + holder.progress.visibility = View.GONE + holder.start.visibility = View.GONE + holder.accomplished.visibility = View.VISIBLE + } else if (objective.isStarted) { + holder.gate.setTextColor(-0x1) + holder.verify.visibility = View.VISIBLE + holder.verify.isEnabled = objective.isCompleted || objectives_fake.isChecked + holder.start.visibility = View.GONE + holder.accomplished.visibility = View.GONE + if (objective.isRevertable) { + holder.revert.visibility = View.VISIBLE + } + holder.progress.visibility = View.VISIBLE + holder.progress.removeAllViews() + for (task in objective.tasks) { + if (task.shouldBeIgnored()) continue + val name = TextView(holder.progress.context) + name.text = MainApp.gs(task.task) + ":" + name.setTextColor(-0x1) + holder.progress.addView(name, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT) + val state = TextView(holder.progress.context) + state.setTextColor(-0x1) + val basicHTML = "%2\$s" + val formattedHTML = String.format(basicHTML, if (task.isCompleted) "#4CAF50" else "#FF9800", task.progress) + state.text = HtmlHelper.fromHtml(formattedHTML) + state.gravity = Gravity.END + holder.progress.addView(state, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT) + if (task is ExamTask) { + state.setOnClickListener { + val dialog = ObjectivesExamDialog() + val bundle = Bundle() + val position = objective.tasks.indexOf(task) + bundle.putInt("currentTask", position) + dialog.arguments = bundle + ObjectivesExamDialog.objective = objective + fragmentManager?.let { dialog.show(it, "ObjectivesFragment") } + } + } + val separator = View(holder.progress.context) + separator.setBackgroundColor(Color.DKGRAY) + holder.progress.addView(separator, LinearLayout.LayoutParams.MATCH_PARENT, 2) + } + } + holder.accomplished.text = MainApp.gs(R.string.accomplished, DateUtil.dateAndTimeString(objective.accomplishedOn)) + holder.accomplished.setTextColor(-0x3e3e3f) + holder.verify.setOnClickListener { + objective.accomplishedOn = DateUtil.now() + notifyDataSetChanged() + scrollToCurrentObjective() + startUpdateTimer() + } + holder.start.setOnClickListener { + objective.startedOn = DateUtil.now() + notifyDataSetChanged() + scrollToCurrentObjective() + startUpdateTimer() + } + holder.revert.setOnClickListener { + objective.accomplishedOn = 0 + objective.startedOn = 0 + if (position > 0) { + val prevObj = ObjectivesPlugin.objectives[position - 1] + prevObj.accomplishedOn = 0 + } + notifyDataSetChanged() + scrollToCurrentObjective() + } + if (objective.hasSpecialInput && !objective.isAccomplished && objective.isStarted) { + // generate random request code if none exists + val request = SP.getString(R.string.key_objectives_request_code, String.format("%1$05d", (Math.random() * 99999).toInt())) + SP.putString(R.string.key_objectives_request_code, request) + holder.requestCode.text = MainApp.gs(R.string.requestcode, request) + holder.requestCode.visibility = View.VISIBLE + holder.enterButton.visibility = View.VISIBLE + holder.input.visibility = View.VISIBLE + holder.inputHint.visibility = View.VISIBLE + holder.enterButton.setOnClickListener { + val input = holder.input.text.toString() + objective.specialAction(activity, input) + notifyDataSetChanged() + } + } else { + holder.enterButton.visibility = View.GONE + holder.input.visibility = View.GONE + holder.inputHint.visibility = View.GONE + holder.requestCode.visibility = View.GONE + } + } + + + override fun getItemCount(): Int { + return ObjectivesPlugin.objectives.size + } + + inner class ViewHolder internal constructor(itemView: View) : RecyclerView.ViewHolder(itemView) { + val title: TextView = itemView.findViewById(R.id.objective_title) + val objective: TextView = itemView.findViewById(R.id.objective_objective) + val gate: TextView = itemView.findViewById(R.id.objective_gate) + val accomplished: TextView = itemView.findViewById(R.id.objective_accomplished) + val progress: LinearLayout = itemView.findViewById(R.id.objective_progress) + val verify: Button = itemView.findViewById(R.id.objective_verify) + val start: Button = itemView.findViewById(R.id.objective_start) + val revert: Button = itemView.findViewById(R.id.objective_back) + val inputHint: TextView = itemView.findViewById(R.id.objective_inputhint) + val input: EditText = itemView.findViewById(R.id.objective_input) + val enterButton: Button = itemView.findViewById(R.id.objective_enterbutton) + val requestCode: TextView = itemView.findViewById(R.id.objective_requestcode) + } + } + + fun updateGUI() { + activity?.runOnUiThread { objectivesAdapter.notifyDataSetChanged() } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesPlugin.java deleted file mode 100644 index 1d18cd14b4..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesPlugin.java +++ /dev/null @@ -1,164 +0,0 @@ -package info.nightscout.androidaps.plugins.constraints.objectives; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.List; - -import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.interfaces.Constraint; -import info.nightscout.androidaps.interfaces.ConstraintsInterface; -import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.PluginDescription; -import info.nightscout.androidaps.interfaces.PluginType; -import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.constraints.objectives.events.EventObjectivesSaved; -import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective; -import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective1; -import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective2; -import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective3; -import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective4; -import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective5; -import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective6; -import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective7; -import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective8; -import info.nightscout.androidaps.utils.SP; - -/** - * Created by mike on 05.08.2016. - */ -public class ObjectivesPlugin extends PluginBase implements ConstraintsInterface { - private static Logger log = LoggerFactory.getLogger(L.CONSTRAINTS); - - private static ObjectivesPlugin objectivesPlugin; - - public List objectives = new ArrayList<>(); - public boolean bgIsAvailableInNS = false; - public boolean pumpStatusIsAvailableInNS = false; - public Integer manualEnacts = 0; - - public static ObjectivesPlugin getPlugin() { - if (objectivesPlugin == null) { - objectivesPlugin = new ObjectivesPlugin(); - } - return objectivesPlugin; - } - - private ObjectivesPlugin() { - super(new PluginDescription() - .mainType(PluginType.CONSTRAINTS) - .fragmentClass(ObjectivesFragment.class.getName()) - .alwaysEnabled(!Config.NSCLIENT) - .showInList(!Config.NSCLIENT) - .pluginName(R.string.objectives) - .shortName(R.string.objectives_shortname) - .description(R.string.description_objectives) - ); - setupObjectives(); - loadProgress(); - } - - @Override - public boolean specialEnableCondition() { - PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); - return pump == null || pump.getPumpDescription().isTempBasalCapable; - } - - private void setupObjectives() { - objectives.add(new Objective1()); - objectives.add(new Objective2()); - objectives.add(new Objective3()); - objectives.add(new Objective4()); - objectives.add(new Objective5()); - objectives.add(new Objective6()); - objectives.add(new Objective7()); - objectives.add(new Objective8()); - } - - public void reset() { - for (Objective objective : objectives) { - objective.setStartedOn(null); - objective.setAccomplishedOn(null); - } - bgIsAvailableInNS = false; - pumpStatusIsAvailableInNS = false; - manualEnacts = 0; - saveProgress(); - } - - public void saveProgress() { - SP.putBoolean("Objectives" + "bgIsAvailableInNS", bgIsAvailableInNS); - SP.putBoolean("Objectives" + "pumpStatusIsAvailableInNS", pumpStatusIsAvailableInNS); - SP.putString("Objectives" + "manualEnacts", Integer.toString(manualEnacts)); - if (L.isEnabled(L.CONSTRAINTS)) - log.debug("Objectives stored"); - MainApp.bus().post(new EventObjectivesSaved()); - } - - private void loadProgress() { - bgIsAvailableInNS = SP.getBoolean("Objectives" + "bgIsAvailableInNS", false); - pumpStatusIsAvailableInNS = SP.getBoolean("Objectives" + "pumpStatusIsAvailableInNS", false); - try { - manualEnacts = SP.getInt("Objectives" + "manualEnacts", 0); - } catch (Exception e) { - log.error("Unhandled exception", e); - } - if (L.isEnabled(L.CONSTRAINTS)) - log.debug("Objectives loaded"); - } - - public List getObjectives() { - return objectives; - } - - /** - * Constraints interface - **/ - @Override - public Constraint isLoopInvocationAllowed(Constraint value) { - if (!objectives.get(0).isStarted()) - value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 1), this); - return value; - } - - @Override - public Constraint isClosedLoopAllowed(Constraint value) { - if (!objectives.get(3).isStarted()) - value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 4), this); - return value; - } - - @Override - public Constraint isAutosensModeEnabled(Constraint value) { - if (!objectives.get(5).isStarted()) - value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 6), this); - return value; - } - - @Override - public Constraint isAMAModeEnabled(Constraint value) { - if (!objectives.get(6).isStarted()) - value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 7), this); - return value; - } - - @Override - public Constraint isSMBModeEnabled(Constraint value) { - if (!objectives.get(7).isStarted()) - value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 8), this); - return value; - } - - @Override - public Constraint applyMaxIOBConstraints(Constraint maxIob) { - if (objectives.get(3).isStarted() && !objectives.get(3).isAccomplished()) - maxIob.set(0d, String.format(MainApp.gs(R.string.objectivenotfinished), 4), this); - return maxIob; - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesPlugin.kt new file mode 100644 index 0000000000..dcd9dd31d1 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesPlugin.kt @@ -0,0 +1,170 @@ +package info.nightscout.androidaps.plugins.constraints.objectives + +import android.app.Activity +import com.google.common.base.Charsets +import com.google.common.hash.Hashing +import info.nightscout.androidaps.BuildConfig +import info.nightscout.androidaps.Config +import info.nightscout.androidaps.MainApp +import info.nightscout.androidaps.R +import info.nightscout.androidaps.interfaces.* +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin +import info.nightscout.androidaps.plugins.constraints.objectives.objectives.* +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.OKDialog +import info.nightscout.androidaps.utils.SP +import java.util.* + +/** + * Created by mike on 05.08.2016. + */ +object ObjectivesPlugin : PluginBase(PluginDescription() + .mainType(PluginType.CONSTRAINTS) + .fragmentClass(ObjectivesFragment::class.qualifiedName) + .alwaysEnabled(!Config.NSCLIENT) + .showInList(!Config.NSCLIENT) + .pluginName(R.string.objectives) + .shortName(R.string.objectives_shortname) + .description(R.string.description_objectives)), ConstraintsInterface { + + var objectives: MutableList = ArrayList() + + val FIRST_OBJECTIVE = 0 + val USAGE_OBJECTIVE = 1 + val EXAM_OBJECTIVE = 2 + val OPENLOOP_OBJECTIVE = 3 + val MAXBASAL_OBJECTIVE = 4 + val MAXIOB_ZERO_CL_OBJECTIVE = 5 + val MAXIOB_OBJECTIVE = 6 + val AUTOSENS_OBJECTIVE = 7 + val AMA_OBJECTIVE = 8 + val SMB_OBJECTIVE = 9 + + init { + convertSP() + setupObjectives() + } + + override fun specialEnableCondition(): Boolean { + val pump = ConfigBuilderPlugin.getPlugin().activePump + return pump == null || pump.pumpDescription.isTempBasalCapable + } + + // convert 2.3 SP version + private fun convertSP() { + doConvertSP(0, "config") + doConvertSP(1, "openloop") + doConvertSP(2, "maxbasal") + doConvertSP(3, "maxiobzero") + doConvertSP(4, "maxiob") + doConvertSP(5, "autosens") + doConvertSP(6, "ama") + doConvertSP(7, "smb") + } + + private fun doConvertSP(number: Int, name: String) { + if (!SP.contains("Objectives_" + name + "_started")) { + SP.putLong("Objectives_" + name + "_started", SP.getLong("Objectives" + number + "accomplished", 0L)) + SP.putLong("Objectives_" + name + "_accomplished", SP.getLong("Objectives" + number + "accomplished", 0L)) + } + // TODO: we can remove Objectives1accomplished sometimes later + } + + private fun setupObjectives() { + objectives.clear() + objectives.add(Objective0()) + objectives.add(Objective1()) + objectives.add(Objective2()) + objectives.add(Objective3()) + objectives.add(Objective4()) + objectives.add(Objective5()) + objectives.add(Objective6()) + objectives.add(Objective7()) + objectives.add(Objective8()) + objectives.add(Objective9()) + } + + fun reset() { + for (objective in objectives) { + objective.startedOn = 0 + objective.accomplishedOn = 0 + } + SP.putBoolean(R.string.key_ObjectivesbgIsAvailableInNS, false) + SP.putBoolean(R.string.key_ObjectivespumpStatusIsAvailableInNS, false) + SP.putInt(R.string.key_ObjectivesmanualEnacts, 0) + SP.putBoolean(R.string.key_objectiveuseprofileswitch, false) + SP.putBoolean(R.string.key_objectiveusedisconnect, false) + SP.putBoolean(R.string.key_objectiveusereconnect, false) + SP.putBoolean(R.string.key_objectiveusetemptarget, false) + SP.putBoolean(R.string.key_objectiveuseactions, false) + SP.putBoolean(R.string.key_objectiveuseloop, false) + SP.putBoolean(R.string.key_objectiveusescale, false) + } + + fun completeObjectives(activity: Activity, request: String) { + val requestCode = SP.getString(R.string.key_objectives_request_code, "") + var url = SP.getString(R.string.key_nsclientinternal_url, "").toLowerCase() + if (!url.endsWith("\"")) url = "$url/" + val hashNS = Hashing.sha1().hashString(url + BuildConfig.APPLICATION_ID + "/" + requestCode, Charsets.UTF_8).toString() + if (request.equals(hashNS.substring(0, 10), ignoreCase = true)) { + SP.putLong("Objectives_" + "openloop" + "_started", DateUtil.now()) + SP.putLong("Objectives_" + "openloop" + "_accomplished", DateUtil.now()) + SP.putLong("Objectives_" + "maxbasal" + "_started", DateUtil.now()) + SP.putLong("Objectives_" + "maxbasal" + "_accomplished", DateUtil.now()) + SP.putLong("Objectives_" + "maxiobzero" + "_started", DateUtil.now()) + SP.putLong("Objectives_" + "maxiobzero" + "_accomplished", DateUtil.now()) + SP.putLong("Objectives_" + "maxiob" + "_started", DateUtil.now()) + SP.putLong("Objectives_" + "maxiob" + "_accomplished", DateUtil.now()) + SP.putLong("Objectives_" + "autosens" + "_started", DateUtil.now()) + SP.putLong("Objectives_" + "autosens" + "_accomplished", DateUtil.now()) + SP.putLong("Objectives_" + "ama" + "_started", DateUtil.now()) + SP.putLong("Objectives_" + "ama" + "_accomplished", DateUtil.now()) + SP.putLong("Objectives_" + "smb" + "_started", DateUtil.now()) + SP.putLong("Objectives_" + "smb" + "_accomplished", DateUtil.now()) + setupObjectives() + OKDialog.show(activity, "", MainApp.gs(R.string.codeaccepted), null) + } else { + OKDialog.show(activity, "", MainApp.gs(R.string.codeinvalid), null) + } + } + + /** + * Constraints interface + */ + override fun isLoopInvocationAllowed(value: Constraint): Constraint { + if (!objectives[FIRST_OBJECTIVE].isStarted) + value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), FIRST_OBJECTIVE + 1), this) + return value + } + + override fun isClosedLoopAllowed(value: Constraint): Constraint { + if (!objectives[MAXIOB_ZERO_CL_OBJECTIVE].isStarted) + value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), MAXIOB_ZERO_CL_OBJECTIVE + 1), this) + return value + } + + override fun isAutosensModeEnabled(value: Constraint): Constraint { + if (!objectives[AUTOSENS_OBJECTIVE].isStarted) + value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), AUTOSENS_OBJECTIVE + 1), this) + return value + } + + override fun isAMAModeEnabled(value: Constraint): Constraint { + if (!objectives[AMA_OBJECTIVE].isStarted) + value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), AMA_OBJECTIVE + 1), this) + return value + } + + override fun isSMBModeEnabled(value: Constraint): Constraint { + if (!objectives[SMB_OBJECTIVE].isStarted) + value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), SMB_OBJECTIVE + 1), this) + return value + } + + override fun applyMaxIOBConstraints(maxIob: Constraint): Constraint { + if (objectives[MAXIOB_ZERO_CL_OBJECTIVE].isStarted && !objectives[MAXIOB_ZERO_CL_OBJECTIVE].isAccomplished) + maxIob.set(0.0, String.format(MainApp.gs(R.string.objectivenotfinished), MAXIOB_ZERO_CL_OBJECTIVE + 1), this) + return maxIob + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/activities/ObjectivesExamDialog.kt b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/activities/ObjectivesExamDialog.kt new file mode 100644 index 0000000000..a0d6f6cedf --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/activities/ObjectivesExamDialog.kt @@ -0,0 +1,132 @@ +package info.nightscout.androidaps.plugins.constraints.objectives.activities + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.DialogFragment +import info.nightscout.androidaps.MainApp +import info.nightscout.androidaps.R +import info.nightscout.androidaps.plugins.bus.RxBus +import info.nightscout.androidaps.plugins.constraints.objectives.events.EventObjectivesUpdateGui +import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective +import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective.* +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.OKDialog +import info.nightscout.androidaps.utils.T +import info.nightscout.androidaps.utils.ToastUtils +import kotlinx.android.synthetic.main.objectives_exam_fragment.* + +class ObjectivesExamDialog : DialogFragment() { + companion object { + var objective: Objective? = null + } + + var currentTask = 0 + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + // load data from bundle + (savedInstanceState ?: arguments)?.let { bundle -> + currentTask = bundle.getInt("currentTask", 0) + } + + return inflater.inflate(R.layout.objectives_exam_fragment, container, false) + } + + override fun onStart() { + super.onStart() + dialog.setCanceledOnTouchOutside(false) + dialog.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + } + + override fun onResume() { + super.onResume() + updateGui() + } + + override fun onSaveInstanceState(bundle: Bundle) { + super.onSaveInstanceState(bundle) + bundle.putInt("currentTask", currentTask) + } + + fun updateGui() { + objective?.let { objective -> + val task: ExamTask = objective.tasks[currentTask] as ExamTask + objectives_exam_name.setText(task.task) + objectives_exam_question.setText(task.question) + // Options + objectives_exam_options.removeAllViews() + for (o in task.options) { + val option: Option = o as Option; + val cb = option.generate(context) + if (task.answered) { + cb.isEnabled = false + if (option.isCorrect) + cb.isChecked = true + } + objectives_exam_options.addView(cb) + } + // Hints + objectives_exam_hints.removeAllViews() + for (h in task.hints) { + val hint: Hint = h as Hint; + objectives_exam_hints.addView(hint.generate(context)) + } + // Disabled to + objectives_exam_disabledto.text = MainApp.gs(R.string.answerdisabledto, DateUtil.timeString(task.disabledTo)) + objectives_exam_disabledto.visibility = if (task.isEnabledAnswer) View.GONE else View.VISIBLE + // Buttons + objectives_exam_verify.isEnabled = !task.answered && task.isEnabledAnswer + objectives_exam_verify.setOnClickListener { + var result = true + for (o in task.options) { + val option: Option = o as Option; + result = result && option.evaluate() + } + task.setAnswered(result); + if (!result) { + task.disabledTo = DateUtil.now() + T.hours(1).msecs() + ToastUtils.showToastInUiThread(context, R.string.wronganswer) + } else task.disabledTo = 0 + updateGui() + RxBus.send(EventObjectivesUpdateGui()) + } + close.setOnClickListener { dismiss() } + objectives_exam_reset.setOnClickListener { + task.answered = false + //task.disabledTo = 0 + updateGui() + RxBus.send(EventObjectivesUpdateGui()) + } + objectives_back_button.isEnabled = currentTask != 0 + objectives_back_button.setOnClickListener { + currentTask-- + updateGui() + } + objectives_next_button.isEnabled = currentTask != objective.tasks.size - 1 + objectives_next_button.setOnClickListener { + currentTask++ + updateGui() + } + + objectives_next_unanswered_button.isEnabled = !objective.isCompleted + objectives_next_unanswered_button.setOnClickListener { + for (i in (currentTask + 1)..(objective.tasks.size - 1)) { + if (!objective.tasks[i].isCompleted) { + currentTask = i + updateGui() + return@setOnClickListener + } + } + for (i in 0..currentTask) { + if (!objective.tasks[i].isCompleted) { + currentTask = i + updateGui() + return@setOnClickListener + } + } + } + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/events/EventObjectivesSaved.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/events/EventObjectivesSaved.java deleted file mode 100644 index d4dbb0251d..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/events/EventObjectivesSaved.java +++ /dev/null @@ -1,6 +0,0 @@ -package info.nightscout.androidaps.plugins.constraints.objectives.events; - -import info.nightscout.androidaps.events.Event; - -public class EventObjectivesSaved extends Event { -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/events/EventObjectivesUpdateGui.kt b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/events/EventObjectivesUpdateGui.kt new file mode 100644 index 0000000000..fd59db7d9f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/events/EventObjectivesUpdateGui.kt @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.constraints.objectives.events + +import info.nightscout.androidaps.events.EventUpdateGui + +class EventObjectivesUpdateGui : EventUpdateGui() \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective.java index 55aba1b49f..916cfa10be 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective.java @@ -1,35 +1,41 @@ package info.nightscout.androidaps.plugins.constraints.objectives.objectives; +import android.app.Activity; +import android.content.Context; +import android.graphics.Color; +import android.text.util.Linkify; +import android.widget.CheckBox; +import android.widget.TextView; + import androidx.annotation.StringRes; import java.util.ArrayList; -import java.util.Date; import java.util.List; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.SP; import info.nightscout.androidaps.utils.T; public abstract class Objective { - private int number; + private String spName; @StringRes private int objective; @StringRes private int gate; - private Date startedOn; - private Date accomplishedOn; + private long startedOn; + private long accomplishedOn; private List tasks = new ArrayList<>(); + public boolean hasSpecialInput = false; - public Objective(int number, @StringRes int objective, @StringRes int gate) { - this.number = number; + public Objective(String spName, @StringRes int objective, @StringRes int gate) { + this.spName = spName; this.objective = objective; this.gate = gate; - startedOn = new Date(SP.getLong("Objectives" + number + "started", 0L)); - if (startedOn.getTime() == 0L) startedOn = null; - accomplishedOn = new Date(SP.getLong("Objectives" + number + "accomplished", 0L)); - if (accomplishedOn.getTime() == 0L) accomplishedOn = null; + startedOn = SP.getLong("Objectives_" + spName + "_started", 0L); + accomplishedOn = SP.getLong("Objectives_" + spName + "_accomplished", 0L); setupTasks(tasks); for (Task task : tasks) task.objective = this; } @@ -47,14 +53,14 @@ public abstract class Objective { } public boolean isAccomplished() { - return accomplishedOn != null; + return accomplishedOn != 0; } public boolean isStarted() { - return startedOn != null; + return startedOn != 0; } - public Date getStartedOn() { + public long getStartedOn() { return startedOn; } @@ -66,14 +72,18 @@ public abstract class Objective { return gate; } - public void setStartedOn(Date startedOn) { + public void setStartedOn(long startedOn) { this.startedOn = startedOn; - SP.putLong("Objectives" + number + "started", startedOn == null ? 0 : startedOn.getTime()); + SP.putLong("Objectives_" + spName + "_started", startedOn); } - public void setAccomplishedOn(Date accomplishedOn) { + public void setAccomplishedOn(long accomplishedOn) { this.accomplishedOn = accomplishedOn; - SP.putLong("Objectives" + number + "accomplished", accomplishedOn == null ? 0 : accomplishedOn.getTime()); + SP.putLong("Objectives_" + spName + "_accomplished", accomplishedOn); + } + + public long getAccomplishedOn() { + return accomplishedOn; } protected void setupTasks(List tasks) { @@ -84,6 +94,8 @@ public abstract class Objective { return tasks; } + public void specialAction(Activity activity, String input) {} + public abstract class Task { @StringRes private int task; @@ -93,7 +105,7 @@ public abstract class Objective { this.task = task; } - public int getTask() { + public @StringRes int getTask() { return task; } @@ -116,19 +128,19 @@ public abstract class Objective { private long minimumDuration; - public MinimumDurationTask(long minimumDuration) { + MinimumDurationTask(long minimumDuration) { super(R.string.time_elapsed); this.minimumDuration = minimumDuration; } @Override public boolean isCompleted() { - return getObjective().isStarted() && System.currentTimeMillis() - getObjective().getStartedOn().getTime() >= minimumDuration; + return getObjective().isStarted() && System.currentTimeMillis() - getObjective().getStartedOn() >= minimumDuration; } @Override public String getProgress() { - return getDurationText(System.currentTimeMillis() - getObjective().getStartedOn().getTime()) + return getDurationText(System.currentTimeMillis() - getObjective().getStartedOn()) + " / " + getDurationText(minimumDuration); } @@ -142,4 +154,117 @@ public abstract class Objective { } } + public class ExamTask extends Task { + @StringRes + int question; + List hints = new ArrayList<>(); + List options = new ArrayList<>(); + private String spIdentifier; + private boolean answered; + private long disabledTo; + + ExamTask(@StringRes int task, @StringRes int question, String spIdentifier) { + super(task); + this.question = question; + this.spIdentifier = spIdentifier; + answered = SP.getBoolean("ExamTask_" + spIdentifier, false); + disabledTo = SP.getLong("DisabledTo_" + spIdentifier, 0L); + } + + public void setDisabledTo(long newState) { + disabledTo = newState; + SP.putLong("DisabledTo_" + spIdentifier, disabledTo); + } + + public long getDisabledTo() { + return disabledTo; + } + + public boolean isEnabledAnswer() { + return disabledTo < DateUtil.now(); + } + + public void setAnswered(boolean newState) { + answered = newState; + SP.putBoolean("ExamTask_" + spIdentifier, answered); + } + + public boolean getAnswered() { + return answered; + } + + ExamTask option(Option option) { + options.add(option); + return this; + } + + ExamTask hint(Hint hint) { + hints.add(hint); + return this; + } + + public @StringRes int getQuestion() { + return question; + } + + public List getOptions() { + return options; + } + + public List getHints() { + return hints; + } + + @Override + public boolean isCompleted() { + return answered; + } + } + + public class Option { + @StringRes int option; + boolean isCorrect; + + CheckBox cb; // TODO: change it, this will block releasing memeory + + Option(@StringRes int option, boolean isCorrect) { + this.option = option; + this.isCorrect = isCorrect; + } + + public boolean isCorrect() { + return isCorrect; + } + + public CheckBox generate(Context context) { + cb = new CheckBox(context); + cb.setText(option); + return cb; + } + + public boolean evaluate() { + boolean selection = cb.isChecked(); + if (selection && isCorrect) return true; + if (!selection && !isCorrect) return true; + return false; + } + } + + public class Hint { + @StringRes int hint; + + Hint(@StringRes int hint) { + this.hint = hint; + } + + public TextView generate(Context context) { + TextView textView = new TextView(context); + textView.setText(hint); + textView.setAutoLinkMask(Linkify.WEB_URLS); + textView.setLinksClickable(true); + textView.setLinkTextColor(Color.YELLOW); + Linkify.addLinks(textView, Linkify.WEB_URLS); + return textView; + } + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective0.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective0.java new file mode 100644 index 0000000000..f6f0267a23 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective0.java @@ -0,0 +1,84 @@ +package info.nightscout.androidaps.plugins.constraints.objectives.objectives; + +import java.util.List; + +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.db.DatabaseHelper; +import info.nightscout.androidaps.interfaces.APSInterface; +import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.interfaces.PluginType; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin; +import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin; +import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin; +import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.SP; + +public class Objective0 extends Objective { + + public Objective0() { + super("config", R.string.objectives_0_objective, R.string.objectives_0_gate); + } + + @Override + protected void setupTasks(List tasks) { + tasks.add(new Task(R.string.objectives_bgavailableinns) { + @Override + public boolean isCompleted() { + return SP.getBoolean(R.string.key_ObjectivesbgIsAvailableInNS, false); + } + }); + tasks.add(new Task(R.string.nsclienthaswritepermission) { + @Override + public boolean isCompleted() { + return NSClientPlugin.getPlugin().hasWritePermission(); + } + }); + tasks.add(new Task(R.string.virtualpump_uploadstatus_title) { + @Override + public boolean isCompleted() { + return SP.getBoolean("virtualpump_uploadstatus", false); + } + + @Override + public boolean shouldBeIgnored() { + return !VirtualPumpPlugin.getPlugin().isEnabled(PluginType.PUMP); + } + }); + tasks.add(new Task(R.string.objectives_pumpstatusavailableinns) { + @Override + public boolean isCompleted() { + return SP.getBoolean(R.string.key_ObjectivespumpStatusIsAvailableInNS, false); + } + }); + tasks.add(new Task(R.string.hasbgdata) { + @Override + public boolean isCompleted() { + return DatabaseHelper.lastBg() != null; + } + }); + tasks.add(new Task(R.string.loopenabled) { + @Override + public boolean isCompleted() { + return LoopPlugin.getPlugin().isEnabled(PluginType.LOOP); + } + }); + tasks.add(new Task(R.string.apsselected) { + @Override + public boolean isCompleted() { + APSInterface usedAPS = ConfigBuilderPlugin.getPlugin().getActiveAPS(); + if (usedAPS != null && ((PluginBase) usedAPS).isEnabled(PluginType.APS)) + return true; + return false; + } + }); + tasks.add(new Task(R.string.activate_profile) { + @Override + public boolean isCompleted() { + return TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(DateUtil.now()) != null; + } + }); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective1.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective1.java index 65a716abab..22ff17331e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective1.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective1.java @@ -3,81 +3,60 @@ package info.nightscout.androidaps.plugins.constraints.objectives.objectives; import java.util.List; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.db.DatabaseHelper; -import info.nightscout.androidaps.interfaces.APSInterface; -import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginType; -import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin; -import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin; -import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin; -import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin; -import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; -import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.plugins.general.actions.ActionsPlugin; import info.nightscout.androidaps.utils.SP; public class Objective1 extends Objective { + public Objective1() { - super(0, R.string.objectives_0_objective, R.string.objectives_0_gate); + super("usage", R.string.objectives_usage_objective, R.string.objectives_usage_gate); } @Override protected void setupTasks(List tasks) { - tasks.add(new Task(R.string.objectives_bgavailableinns) { + tasks.add(new Task(R.string.objectives_useprofileswitch) { @Override public boolean isCompleted() { - return ObjectivesPlugin.getPlugin().bgIsAvailableInNS; + return SP.getBoolean(R.string.key_objectiveuseprofileswitch, false); } }); - tasks.add(new Task(R.string.nsclienthaswritepermission) { + tasks.add(new Task(R.string.objectives_usedisconnectpump) { @Override public boolean isCompleted() { - return NSClientPlugin.getPlugin().hasWritePermission(); + return SP.getBoolean(R.string.key_objectiveusedisconnect, false); } }); - tasks.add(new Task(R.string.virtualpump_uploadstatus_title) { + tasks.add(new Task(R.string.objectives_usereconnectpump) { @Override public boolean isCompleted() { - return SP.getBoolean("virtualpump_uploadstatus", false); - } - - @Override - public boolean shouldBeIgnored() { - return !VirtualPumpPlugin.getPlugin().isEnabled(PluginType.PUMP); + return SP.getBoolean(R.string.key_objectiveusereconnect, false); } }); - tasks.add(new Task(R.string.objectives_pumpstatusavailableinns) { + tasks.add(new Task(R.string.objectives_usetemptarget) { @Override public boolean isCompleted() { - return ObjectivesPlugin.getPlugin().pumpStatusIsAvailableInNS; + return SP.getBoolean(R.string.key_objectiveusetemptarget, false); } }); - tasks.add(new Task(R.string.hasbgdata) { + tasks.add(new Task(R.string.objectives_useactions) { @Override public boolean isCompleted() { - return DatabaseHelper.lastBg() != null; + return SP.getBoolean(R.string.key_objectiveuseactions, false) && ActionsPlugin.INSTANCE.isEnabled(PluginType.GENERAL) && ActionsPlugin.INSTANCE.isFragmentVisible(); } }); - tasks.add(new Task(R.string.loopenabled) { + tasks.add(new Task(R.string.objectives_useloop) { @Override public boolean isCompleted() { - return LoopPlugin.getPlugin().isEnabled(PluginType.LOOP); + return SP.getBoolean(R.string.key_objectiveuseloop, false); } }); - tasks.add(new Task(R.string.apsselected) { + tasks.add(new Task(R.string.objectives_usescale) { @Override public boolean isCompleted() { - APSInterface usedAPS = ConfigBuilderPlugin.getPlugin().getActiveAPS(); - if (usedAPS != null && ((PluginBase) usedAPS).isEnabled(PluginType.APS)) - return true; - return false; - } - }); - tasks.add(new Task(R.string.activate_profile) { - @Override - public boolean isCompleted() { - return TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(DateUtil.now()) != null; + return SP.getBoolean(R.string.key_objectiveusescale, false); } }); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective2.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective2.java index 6f97bfdd95..9c23278ca3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective2.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective2.java @@ -1,36 +1,70 @@ package info.nightscout.androidaps.plugins.constraints.objectives.objectives; +import java.util.Collections; import java.util.List; -import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin; -import info.nightscout.androidaps.utils.T; public class Objective2 extends Objective { - public final int MANUAL_ENACTS_NEEDED = 20; public Objective2() { - super(1, R.string.objectives_1_objective, R.string.objectives_1_gate); + super("exam", R.string.objectives_exam_objective, R.string.objectives_exam_gate); } @Override protected void setupTasks(List tasks) { - tasks.add(new MinimumDurationTask(T.days(7).msecs())); - tasks.add(new Task(R.string.objectives_manualenacts) { - @Override - public boolean isCompleted() { - return ObjectivesPlugin.getPlugin().manualEnacts >= MANUAL_ENACTS_NEEDED; - } + tasks.add(new ExamTask(R.string.dia_meaningofdia, R.string.dia_whatmeansdia,"dia") + .option(new Option(R.string.dia_minimumis3h, false)) + .option(new Option(R.string.dia_minimumis5h, true)) + .option(new Option(R.string.dia_meaningisequaltodiapump, false)) + .option(new Option(R.string.dia_valuemustbedetermined, true)) + .hint(new Hint(R.string.dia_hint1)) + ); + tasks.add(new ExamTask(R.string.hypott, R.string.hypott_whenhypott,"hypott") + .option(new Option(R.string.hypott_goinglow, true)) + .option(new Option(R.string.hypott_havinglow, true)) + .option(new Option(R.string.hypott_notlowanymorebutrising, false)) + .option(new Option(R.string.hypott_havehadalowbg, false)) + .hint(new Hint(R.string.hypott_hint1)) + ); + tasks.add(new ExamTask(R.string.offlineprofile, R.string.offlineprofile_whatprofile,"offlineprofile") + .option(new Option(R.string.localprofile, true)) + .option(new Option(R.string.nsprofile, false)) + .option(new Option(R.string.offlineprofile_nsprofile, true)) + .hint(new Hint(R.string.offlineprofile_hint1)) + ); + tasks.add(new ExamTask(R.string.pumpdisconnect, R.string.pumpdisconnect_whattodo,"pumpdisconnect") + .option(new Option(R.string.pumpdisconnect_letknow, true)) + .option(new Option(R.string.pumpdisconnect_dontchnage, false)) + .hint(new Hint(R.string.pumpdisconnect_hint1)) + ); + tasks.add(new ExamTask(R.string.objectives, R.string.objectives_howtosave,"objectives") + .option(new Option(R.string.objectives_writetopaper, false)) + .option(new Option(R.string.objectives_exportsettings, true)) + .option(new Option(R.string.objectives_storeelsewhere, true)) + .option(new Option(R.string.objectives_doexportonstart, false)) + .option(new Option(R.string.objectives_doexportafterchange, true)) + .option(new Option(R.string.objectives_doexportafterfirtssettings, true)) + .hint(new Hint(R.string.objectives_hint1)) + ); + tasks.add(new ExamTask(R.string.noisycgm, R.string.noisycgm_whattodo,"noisycgm") + .option(new Option(R.string.nothing, false)) + .option(new Option(R.string.disconnectpumpfor1h, false)) + .option(new Option(R.string.noisycgm_pause, true)) + .option(new Option(R.string.noisycgm_replacesensor, true)) + .option(new Option(R.string.noisycgm_turnoffcgmreceiver, false)) + .option(new Option(R.string.noisycgm_checksmoothing, true)) + .hint(new Hint(R.string.noisycgm_hint1)) + ); - @Override - public String getProgress() { - if (ObjectivesPlugin.getPlugin().manualEnacts >= MANUAL_ENACTS_NEEDED) - return MainApp.gs(R.string.completed_well_done); - else - return ObjectivesPlugin.getPlugin().manualEnacts + " / " + MANUAL_ENACTS_NEEDED; - } - }); + for (Task task : tasks) + Collections.shuffle(((ExamTask)task).options); } + + @Override + public boolean isRevertable() { + return true; + } + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective3.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective3.java index 4924d9434c..c9ac7d8935 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective3.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective3.java @@ -1,10 +1,45 @@ package info.nightscout.androidaps.plugins.constraints.objectives.objectives; +import android.app.Activity; + +import java.util.List; + +import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin; +import info.nightscout.androidaps.utils.SP; +import info.nightscout.androidaps.utils.T; public class Objective3 extends Objective { + public final int MANUAL_ENACTS_NEEDED = 20; + public Objective3() { - super(2, R.string.objectives_2_objective, R.string.objectives_2_gate); + super("openloop", R.string.objectives_openloop_objective, R.string.objectives_openloop_gate); + hasSpecialInput = true; + } + + @Override + protected void setupTasks(List tasks) { + tasks.add(new MinimumDurationTask(T.days(7).msecs())); + tasks.add(new Task(R.string.objectives_manualenacts) { + @Override + public boolean isCompleted() { + return SP.getInt(R.string.key_ObjectivesmanualEnacts, 0) >= MANUAL_ENACTS_NEEDED; + } + + @Override + public String getProgress() { + if (SP.getInt(R.string.key_ObjectivesmanualEnacts, 0) >= MANUAL_ENACTS_NEEDED) + return MainApp.gs(R.string.completed_well_done); + else + return SP.getInt(R.string.key_ObjectivesmanualEnacts, 0) + " / " + MANUAL_ENACTS_NEEDED; + } + }); + } + + @Override + public void specialAction(Activity activity, String input) { + ObjectivesPlugin.INSTANCE.completeObjectives(activity, input); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective4.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective4.java index 1bbb4ef7c2..bb46d3c338 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective4.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective4.java @@ -1,33 +1,10 @@ package info.nightscout.androidaps.plugins.constraints.objectives.objectives; -import java.util.List; - import info.nightscout.androidaps.R; -import info.nightscout.androidaps.interfaces.Constraint; -import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin; -import info.nightscout.androidaps.utils.T; public class Objective4 extends Objective { public Objective4() { - super(3, R.string.objectives_3_objective, R.string.objectives_3_gate); - } - - @Override - protected void setupTasks(List tasks) { - tasks.add(new MinimumDurationTask(T.days(5).msecs())); - tasks.add(new Task(R.string.closedmodeenabled) { - @Override - public boolean isCompleted() { - Constraint closedLoopEnabled = new Constraint<>(true); - SafetyPlugin.getPlugin().isClosedLoopAllowed(closedLoopEnabled); - return closedLoopEnabled.value(); - } - }); - } - - @Override - public boolean isRevertable() { - return true; + super("maxbasal", R.string.objectives_maxbasal_objective, R.string.objectives_maxbasal_gate); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective5.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective5.java index b04062655a..2407594069 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective5.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective5.java @@ -2,25 +2,32 @@ package info.nightscout.androidaps.plugins.constraints.objectives.objectives; import java.util.List; -import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.interfaces.Constraint; +import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin; import info.nightscout.androidaps.utils.T; public class Objective5 extends Objective { public Objective5() { - super(4, R.string.objectives_4_objective, R.string.objectives_4_gate); + super("maxiobzero", R.string.objectives_maxiobzero_objective, R.string.objectives_maxiobzero_gate); } @Override protected void setupTasks(List tasks) { - tasks.add(new MinimumDurationTask(T.days(1).msecs())); - tasks.add(new Task(R.string.maxiobset) { + tasks.add(new MinimumDurationTask(T.days(5).msecs())); + tasks.add(new Task(R.string.closedmodeenabled) { @Override public boolean isCompleted() { - double maxIOB = MainApp.getConstraintChecker().getMaxIOBAllowed().value(); - return maxIOB > 0; + Constraint closedLoopEnabled = new Constraint<>(true); + SafetyPlugin.getPlugin().isClosedLoopAllowed(closedLoopEnabled); + return closedLoopEnabled.value(); } }); } + + @Override + public boolean isRevertable() { + return true; + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective6.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective6.java index 284dfa3ab0..1b224bd40c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective6.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective6.java @@ -2,17 +2,25 @@ package info.nightscout.androidaps.plugins.constraints.objectives.objectives; import java.util.List; +import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.utils.T; public class Objective6 extends Objective { public Objective6() { - super(5, R.string.objectives_5_objective, R.string.objectives_5_gate); + super("maxiob", R.string.objectives_maxiob_objective, R.string.objectives_maxiob_gate); } @Override protected void setupTasks(List tasks) { - tasks.add(new MinimumDurationTask(T.days(7).msecs())); + tasks.add(new MinimumDurationTask(T.days(1).msecs())); + tasks.add(new Task(R.string.maxiobset) { + @Override + public boolean isCompleted() { + double maxIOB = MainApp.getConstraintChecker().getMaxIOBAllowed().value(); + return maxIOB > 0; + } + }); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective7.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective7.java index f90411ecfb..497eb0a180 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective7.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective7.java @@ -3,16 +3,17 @@ package info.nightscout.androidaps.plugins.constraints.objectives.objectives; import java.util.List; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin; import info.nightscout.androidaps.utils.T; public class Objective7 extends Objective { public Objective7() { - super(6, R.string.objectives_6_objective, 0); + super("autosens", R.string.objectives_autosens_objective, R.string.objectives_autosens_gate); } @Override protected void setupTasks(List tasks) { - tasks.add(new MinimumDurationTask(T.days(28).msecs())); + tasks.add(new MinimumDurationTask(T.days(7).msecs())); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective8.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective8.java index 7148f5e5ad..3f943041b6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective8.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective8.java @@ -3,12 +3,13 @@ package info.nightscout.androidaps.plugins.constraints.objectives.objectives; import java.util.List; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin; import info.nightscout.androidaps.utils.T; public class Objective8 extends Objective { public Objective8() { - super(7, R.string.objectives_7_objective, R.string.objectives_7_gate); + super("ama", R.string.objectives_ama_objective, 0); } @Override diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective9.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective9.java new file mode 100644 index 0000000000..106c25cb79 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective9.java @@ -0,0 +1,18 @@ +package info.nightscout.androidaps.plugins.constraints.objectives.objectives; + +import java.util.List; + +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.utils.T; + +public class Objective9 extends Objective { + + public Objective9() { + super("smb", R.string.objectives_smb_objective, R.string.objectives_smb_gate); + } + + @Override + protected void setupTasks(List tasks) { + tasks.add(new MinimumDurationTask(T.days(28).msecs())); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.java index 7248a49f0f..579700be4c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.java @@ -5,13 +5,13 @@ import android.app.Activity; import android.content.Intent; import android.graphics.drawable.Drawable; import android.os.Bundle; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentManager; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; +import androidx.fragment.app.FragmentManager; + import com.squareup.otto.Subscribe; import java.util.ArrayList; @@ -43,31 +43,21 @@ import info.nightscout.androidaps.plugins.general.careportal.CareportalFragment; import info.nightscout.androidaps.plugins.general.careportal.Dialogs.NewNSTreatmentDialog; import info.nightscout.androidaps.plugins.general.careportal.OptionsToShow; import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; -import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.SP; import info.nightscout.androidaps.utils.SingleClickButton; - -/** - * A simple {@link Fragment} subclass. - */ public class ActionsFragment extends SubscriberFragment implements View.OnClickListener { - static ActionsPlugin actionsPlugin = new ActionsPlugin(); - - static public ActionsPlugin getPlugin() { - return actionsPlugin; - } - - View actionsFragmentView; - SingleClickButton profileSwitch; - SingleClickButton tempTarget; - SingleClickButton extendedBolus; - SingleClickButton extendedBolusCancel; - SingleClickButton tempBasal; - SingleClickButton tempBasalCancel; - SingleClickButton fill; - SingleClickButton tddStats; - SingleClickButton history; + private View actionsFragmentView; + private SingleClickButton profileSwitch; + private SingleClickButton tempTarget; + private SingleClickButton extendedBolus; + private SingleClickButton extendedBolusCancel; + private SingleClickButton tempBasal; + private SingleClickButton tempBasalCancel; + private SingleClickButton fill; + private SingleClickButton tddStats; + private SingleClickButton history; private Map pumpCustomActions = new HashMap<>(); private List pumpCustomButtons = new ArrayList<>(); @@ -80,38 +70,33 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - try { - View view = inflater.inflate(R.layout.actions_fragment, container, false); + View view = inflater.inflate(R.layout.actions_fragment, container, false); - profileSwitch = (SingleClickButton) view.findViewById(R.id.actions_profileswitch); - tempTarget = (SingleClickButton) view.findViewById(R.id.actions_temptarget); - extendedBolus = (SingleClickButton) view.findViewById(R.id.actions_extendedbolus); - extendedBolusCancel = (SingleClickButton) view.findViewById(R.id.actions_extendedbolus_cancel); - tempBasal = (SingleClickButton) view.findViewById(R.id.actions_settempbasal); - tempBasalCancel = (SingleClickButton) view.findViewById(R.id.actions_canceltempbasal); - fill = (SingleClickButton) view.findViewById(R.id.actions_fill); - tddStats = view.findViewById(R.id.actions_tddstats); - history = view.findViewById(R.id.actions_historybrowser); + profileSwitch = view.findViewById(R.id.actions_profileswitch); + tempTarget = view.findViewById(R.id.actions_temptarget); + extendedBolus = view.findViewById(R.id.actions_extendedbolus); + extendedBolusCancel = view.findViewById(R.id.actions_extendedbolus_cancel); + tempBasal = view.findViewById(R.id.actions_settempbasal); + tempBasalCancel = view.findViewById(R.id.actions_canceltempbasal); + fill = view.findViewById(R.id.actions_fill); + tddStats = view.findViewById(R.id.actions_tddstats); + history = view.findViewById(R.id.actions_historybrowser); - profileSwitch.setOnClickListener(this); - tempTarget.setOnClickListener(this); - extendedBolus.setOnClickListener(this); - extendedBolusCancel.setOnClickListener(this); - tempBasal.setOnClickListener(this); - tempBasalCancel.setOnClickListener(this); - fill.setOnClickListener(this); - history.setOnClickListener(this); - tddStats.setOnClickListener(this); + profileSwitch.setOnClickListener(this); + tempTarget.setOnClickListener(this); + extendedBolus.setOnClickListener(this); + extendedBolusCancel.setOnClickListener(this); + tempBasal.setOnClickListener(this); + tempBasalCancel.setOnClickListener(this); + fill.setOnClickListener(this); + history.setOnClickListener(this); + tddStats.setOnClickListener(this); - actionsFragmentView = view; + actionsFragmentView = view; - updateGUI(); - return view; - } catch (Exception e) { - FabricPrivacy.logException(e); - } - - return null; + updateGUI(); + SP.putBoolean(R.string.key_objectiveuseactions, true); + return view; } @Subscribe diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsPlugin.java deleted file mode 100644 index 5d47206e5c..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsPlugin.java +++ /dev/null @@ -1,23 +0,0 @@ -package info.nightscout.androidaps.plugins.general.actions; - -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.PluginDescription; -import info.nightscout.androidaps.interfaces.PluginType; - -/** - * Created by mike on 05.11.2016. - */ - -public class ActionsPlugin extends PluginBase { - - public ActionsPlugin() { - super(new PluginDescription() - .mainType(PluginType.GENERAL) - .fragmentClass(ActionsFragment.class.getName()) - .pluginName(R.string.actions) - .shortName(R.string.actions_shortname) - .description(R.string.description_actions) - ); - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsPlugin.kt new file mode 100644 index 0000000000..086c75a157 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsPlugin.kt @@ -0,0 +1,13 @@ +package info.nightscout.androidaps.plugins.general.actions + +import info.nightscout.androidaps.R +import info.nightscout.androidaps.interfaces.PluginBase +import info.nightscout.androidaps.interfaces.PluginDescription +import info.nightscout.androidaps.interfaces.PluginType + +object ActionsPlugin : PluginBase(PluginDescription() + .mainType(PluginType.GENERAL) + .fragmentClass(ActionsFragment::class.java.name) + .pluginName(R.string.actions) + .shortName(R.string.actions_shortname) + .description(R.string.description_actions)) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/EventListAdapter.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/EventListAdapter.java index b4c6fb1f11..ec1cac23d6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/EventListAdapter.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/EventListAdapter.java @@ -84,14 +84,13 @@ class EventListAdapter extends RecyclerView.Adapter // enabled event holder.enabled.setOnCheckedChangeListener((buttonView, isChecked) -> { event.setEnabled(isChecked); - notifyDataSetChanged(); RxBus.INSTANCE.send(new EventAutomationDataChanged()); }); // remove event holder.iconTrash.setOnClickListener(v -> { mEventList.remove(event); - notifyDataSetChanged(); + RxBus.INSTANCE.send(new EventAutomationDataChanged()); }); // edit event diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionStartTempTarget.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionStartTempTarget.java index 05d06f0b3a..659bb508eb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionStartTempTarget.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionStartTempTarget.java @@ -71,7 +71,7 @@ public class ActionStartTempTarget extends Action { int unitResId = value.getUnits().equals(Constants.MGDL) ? R.string.mgdl : R.string.mmol; new LayoutBuilder() - .add(new LabelWithElement(MainApp.gs(R.string.careportal_temporarytarget), MainApp.gs(unitResId), value)) + .add(new LabelWithElement(MainApp.gs(R.string.careportal_temporarytarget) + " [" + MainApp.gs(unitResId) + "]", "", value)) .add(new LabelWithElement(MainApp.gs(R.string.careportal_newnstreatment_duration_min_label), "", duration)) .build(root); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputDouble.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputDouble.java index f8464e7ee0..518b00f5b4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputDouble.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputDouble.java @@ -25,8 +25,8 @@ public class InputDouble extends Element { }; private double value; - double minValue; - double maxValue; + private double minValue; + private double maxValue; private double step; private DecimalFormat decimalFormat; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputDuration.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputDuration.java index a35fe4a4ad..aa19896471 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputDuration.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputDuration.java @@ -20,6 +20,11 @@ public class InputDuration extends Element { this.value = value; } + public InputDuration(InputDuration another) { + unit = another.unit; + value = another.value; + } + @Override public void addToLayout(LinearLayout root) { NumberPicker numberPicker = new NumberPicker(root.getContext(), null); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputTempTarget.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputTempTarget.java index 8175c496a5..4906e79add 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputTempTarget.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputTempTarget.java @@ -1,5 +1,7 @@ package info.nightscout.androidaps.plugins.general.automation.elements; +import android.text.Editable; +import android.text.TextWatcher; import android.widget.LinearLayout; import java.text.DecimalFormat; @@ -17,6 +19,22 @@ public class InputTempTarget extends Element { private double step; private DecimalFormat decimalFormat; + private final TextWatcher textWatcher = new TextWatcher() { + @Override + public void afterTextChanged(Editable s) { + value = Math.max(minValue, value); + value = Math.min(maxValue, value); + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + }; + public InputTempTarget() { super(); setUnits(ProfileFunctions.getInstance().getProfileUnits()); @@ -36,7 +54,7 @@ public class InputTempTarget extends Element { @Override public void addToLayout(LinearLayout root) { NumberPicker numberPicker = new NumberPicker(root.getContext(), null); - numberPicker.setParams(value, minValue, maxValue, step, decimalFormat, true, null, null); + numberPicker.setParams(value, minValue, maxValue, step, decimalFormat, true, null, textWatcher); numberPicker.setOnValueChangedListener(value -> this.value = value); root.addView(numberPicker); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/LabelWithElement.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/LabelWithElement.java index 2531d56e6c..145d8c2d2c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/LabelWithElement.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/LabelWithElement.java @@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.general.automation.elements; import android.graphics.Typeface; import android.view.ViewGroup; import android.widget.LinearLayout; +import android.widget.TableLayout; import android.widget.TextView; import info.nightscout.androidaps.MainApp; @@ -37,6 +38,10 @@ public class LabelWithElement extends Element { textViewPre.setTypeface(textViewPre.getTypeface(), Typeface.BOLD); layout.addView(textViewPre); + TextView spacer = new TextView(root.getContext()); + spacer.setLayoutParams(new TableLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1f)); + layout.addView(spacer); + // add element to layout element.addToLayout(layout); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerBolusAgo.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerBolusAgo.java index e1792d8bd3..0ad9f75ab2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerBolusAgo.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerBolusAgo.java @@ -11,8 +11,6 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.text.DecimalFormat; - import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.logging.L; @@ -28,9 +26,7 @@ import info.nightscout.androidaps.utils.T; public class TriggerBolusAgo extends Trigger { private static Logger log = LoggerFactory.getLogger(L.AUTOMATION); - private final double step = 1; - private DecimalFormat decimalFormat = new DecimalFormat("1"); - public InputDuration minutesAgo = new InputDuration(0, InputDuration.TimeUnit.MINUTES); + private InputDuration minutesAgo = new InputDuration(0, InputDuration.TimeUnit.MINUTES); private Comparator comparator = new Comparator(); public TriggerBolusAgo() { @@ -39,7 +35,7 @@ public class TriggerBolusAgo extends Trigger { private TriggerBolusAgo(TriggerBolusAgo triggerBolusAgo) { super(); - minutesAgo = new InputDuration(triggerBolusAgo.minutesAgo.getMinutes(), InputDuration.TimeUnit.MINUTES); + minutesAgo = new InputDuration(triggerBolusAgo.minutesAgo); lastRun = triggerBolusAgo.lastRun; comparator = new Comparator(triggerBolusAgo.comparator); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerCOB.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerCOB.java index a794851236..4ddeb4299a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerCOB.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerCOB.java @@ -32,10 +32,8 @@ import info.nightscout.androidaps.utils.T; public class TriggerCOB extends Trigger { private static Logger log = LoggerFactory.getLogger(L.AUTOMATION); private final int minValue = 0; - private final int maxValue = (int) (SP.getInt(R.string.key_treatmentssafety_maxcarbs, 48)); - private final double step = 1; - private DecimalFormat decimalFormat = new DecimalFormat("1"); - private InputDouble value = new InputDouble(0, (double) minValue, (double) maxValue, step, decimalFormat); + private final int maxValue = SP.getInt(R.string.key_treatmentssafety_maxcarbs, 48); + private InputDouble value = new InputDouble(0, (double) minValue, (double) maxValue, 1, new DecimalFormat("1")); private Comparator comparator = new Comparator(); public TriggerCOB() { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerDelta.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerDelta.java index 0b9edf148a..a3939a60b7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerDelta.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerDelta.java @@ -51,10 +51,11 @@ public class TriggerDelta extends Trigger { private TriggerDelta(TriggerDelta triggerDelta) { super(); - this.units = ProfileFunctions.getInstance().getProfileUnits(); - initializer(); - value = triggerDelta.value; lastRun = triggerDelta.lastRun; + this.units = triggerDelta.units; + deltaType = triggerDelta.deltaType; + value = new InputDelta(triggerDelta.value); + comparator = new Comparator(triggerDelta.comparator); } public double getValue() { @@ -68,7 +69,7 @@ public class TriggerDelta extends Trigger { if (units.equals(Constants.MMOL)) value = new InputDelta(0, -MMOL_MAX, MMOL_MAX, 0.1d, new DecimalFormat("0.1"), DeltaType.DELTA); else - value = new InputDelta(0, -MGDL_MAX, MGDL_MAX, 0.1d, new DecimalFormat("1"), DeltaType.DELTA); + value = new InputDelta(0, -MGDL_MAX, MGDL_MAX, 1d, new DecimalFormat("1"), DeltaType.DELTA); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerLocation.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerLocation.java index d2be0ffa1f..4772d29112 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerLocation.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerLocation.java @@ -51,10 +51,11 @@ public class TriggerLocation extends Trigger { private TriggerLocation(TriggerLocation triggerLocation) { super(); - latitude = new InputDouble(triggerLocation.latitude.getValue(), -90d, +90d, 0.00001d, new DecimalFormat("0.00000")); - longitude = new InputDouble(triggerLocation.longitude.getValue(), -180d, +180d, 0.00001d, new DecimalFormat("0.00000")); - distance = new InputDouble(200d, 0, 100000, 10d, new DecimalFormat("0")); + latitude = new InputDouble(triggerLocation.latitude); + longitude = new InputDouble(triggerLocation.longitude); + distance = new InputDouble(triggerLocation.distance); lastRun = triggerLocation.lastRun; + name = triggerLocation.name; } @Override diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/careportal/Dialogs/NewNSTreatmentDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/careportal/Dialogs/NewNSTreatmentDialog.java index 3489180d9d..7c50cdc7e5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/careportal/Dialogs/NewNSTreatmentDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/careportal/Dialogs/NewNSTreatmentDialog.java @@ -741,6 +741,8 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick } TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget); } + if (duration == 10) + SP.putBoolean(R.string.key_objectiveusetemptarget, true); } else { if (JsonHelper.safeGetString(data, "eventType").equals(CareportalEvent.PROFILESWITCH)) { ProfileSwitch profileSwitch = ProfileFunctions.prepareProfileSwitch( diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/data/NSDeviceStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/data/NSDeviceStatus.java index 78830aae0e..ea7a8c34bd 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/data/NSDeviceStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/data/NSDeviceStatus.java @@ -17,10 +17,9 @@ import java.util.Map; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin; -import info.nightscout.androidaps.plugins.aps.loop.APSResult; import info.nightscout.androidaps.logging.BundleLogger; +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.aps.loop.APSResult; import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.Round; import info.nightscout.androidaps.utils.SP; @@ -108,8 +107,7 @@ public class NSDeviceStatus { setData(devicestatusJson); if (devicestatusJson.has("pump")) { // Objectives 0 - ObjectivesPlugin.getPlugin().pumpStatusIsAvailableInNS = true; - ObjectivesPlugin.getPlugin().saveProgress(); + SP.putBoolean(R.string.key_ObjectivespumpStatusIsAvailableInNS, true); } } if (bundle.containsKey("devicestatuses")) { @@ -120,8 +118,7 @@ public class NSDeviceStatus { setData(devicestatusJson); if (devicestatusJson.has("pump")) { // Objectives 0 - ObjectivesPlugin.getPlugin().pumpStatusIsAvailableInNS = true; - ObjectivesPlugin.getPlugin().saveProgress(); + SP.putBoolean(R.string.key_ObjectivespumpStatusIsAvailableInNS, true); } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.java index 41c0611ce4..233e8a3990 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.java @@ -334,6 +334,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, rangeToDisplay = rangeToDisplay > 24 ? 6 : rangeToDisplay; SP.putInt(R.string.key_rangetodisplay, rangeToDisplay); updateGUI("rangeChange"); + SP.putBoolean(R.string.key_objectiveusescale, true); return false; }); @@ -592,6 +593,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, } } }); + SP.putBoolean(R.string.key_objectiveusereconnect, true); NSUpload.uploadOpenAPSOffline(0); return true; } else if (item.getTitle().equals(MainApp.gs(R.string.suspendloopfor1h))) { @@ -620,6 +622,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, return true; } else if (item.getTitle().equals(MainApp.gs(R.string.disconnectpumpfor1h))) { LoopPlugin.getPlugin().disconnectPump(60, profile); + SP.putBoolean(R.string.key_objectiveusedisconnect, true); updateGUI("suspendmenu"); return true; } else if (item.getTitle().equals(MainApp.gs(R.string.disconnectpumpfor2h))) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/SourceNSClientPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/source/SourceNSClientPlugin.java index 328f054aad..dd0a2c5e88 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/SourceNSClientPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/SourceNSClientPlugin.java @@ -16,7 +16,6 @@ import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginDescription; import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin; import info.nightscout.androidaps.plugins.general.nsclient.data.NSSgv; import info.nightscout.androidaps.utils.JsonHelper; import info.nightscout.androidaps.utils.SP; @@ -85,8 +84,7 @@ public class SourceNSClientPlugin extends PluginBase implements BgSourceInterfac } // Objectives 0 - ObjectivesPlugin.getPlugin().bgIsAvailableInNS = true; - ObjectivesPlugin.getPlugin().saveProgress(); + SP.putBoolean(R.string.key_ObjectivesbgIsAvailableInNS, true); } private void storeSgv(JSONObject sgvJson) { diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.java index cbc0af6491..2c6902cb01 100644 --- a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.java +++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.java @@ -425,8 +425,8 @@ public class SWDefinition { .add(new SWBreak()) .add(new SWFragment(this) .add(new ObjectivesFragment())) - .validator(() -> ObjectivesPlugin.getPlugin().objectives.get(0).isStarted()) - .visibility(() -> !ObjectivesPlugin.getPlugin().objectives.get(0).isStarted() && Config.APS); + .validator(() -> ObjectivesPlugin.INSTANCE.getObjectives().get(ObjectivesPlugin.INSTANCE.getFIRST_OBJECTIVE()).isStarted()) + .visibility(() -> !ObjectivesPlugin.INSTANCE.getObjectives().get(ObjectivesPlugin.INSTANCE.getFIRST_OBJECTIVE()).isStarted() && Config.APS); private void SWDefinitionFull() { // List all the screens here diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java index 3064228fd3..1d3b867a6d 100644 --- a/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java @@ -26,7 +26,6 @@ import info.nightscout.androidaps.activities.NoSplashAppCompatActivity; import info.nightscout.androidaps.events.EventProfileNeedsUpdate; import info.nightscout.androidaps.events.EventProfileStoreChanged; import info.nightscout.androidaps.events.EventPumpStatusChanged; -import info.nightscout.androidaps.plugins.constraints.objectives.events.EventObjectivesSaved; import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientStatus; import info.nightscout.androidaps.setupwizard.elements.SWItem; import info.nightscout.androidaps.setupwizard.events.EventSWUpdate; @@ -121,11 +120,6 @@ public class SetupWizardActivity extends NoSplashAppCompatActivity { updateButtons(); } - @Subscribe - public void onEventObjectivesSaved(EventObjectivesSaved ignored) { - updateButtons(); - } - private void generateLayout() { SWScreen currentScreen = screens.get(currentWizardPage); LinearLayout layout = SWItem.generateLayout(this.findViewById(R.id.sw_content_fields)); diff --git a/app/src/main/java/info/nightscout/androidaps/utils/SP.java b/app/src/main/java/info/nightscout/androidaps/utils/SP.java index 84b6b4b70d..1b46642751 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/SP.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/SP.java @@ -126,6 +126,13 @@ public class SP { editor.apply(); } + static public void incInt(int resourceID) { + SharedPreferences.Editor editor = sharedPreferences.edit(); + int value = SP.getInt(resourceID, 0) + 1; + editor.putInt(MainApp.gs(resourceID), value); + editor.apply(); + } + static public void putString(int resourceID, String value) { SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putString(MainApp.gs(resourceID), value); diff --git a/app/src/main/res/layout/objectives_exam_fragment.xml b/app/src/main/res/layout/objectives_exam_fragment.xml new file mode 100644 index 0000000000..df432cc5d2 --- /dev/null +++ b/app/src/main/res/layout/objectives_exam_fragment.xml @@ -0,0 +1,148 @@ + + + + + + + + + + + + + +