AndroidAPS/app/src/main/java/info/nightscout/androidaps/activities/TDDStatsActivity.java
2020-03-21 15:09:14 +01:00

535 lines
22 KiB
Java

package info.nightscout.androidaps.activities;
import android.graphics.Color;
import android.graphics.Rect;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import androidx.recyclerview.widget.LinearLayoutManager;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import javax.inject.Inject;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.TDD;
import info.nightscout.androidaps.events.EventPumpStatusChanged;
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
import info.nightscout.androidaps.interfaces.CommandQueueProvider;
import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction;
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin;
import info.nightscout.androidaps.plugins.pump.danaR.events.EventDanaRSyncStatus;
import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin;
import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin;
import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin;
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.SafeParse;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
import info.nightscout.androidaps.utils.sharedPreferences.SP;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
public class TDDStatsActivity extends NoSplashAppCompatActivity {
@Inject AAPSLogger aapsLogger;
@Inject ResourceHelper resourceHelper;
@Inject RxBusWrapper rxBus;
@Inject SP sp;
@Inject ProfileFunction profileFunction;
@Inject ActivePluginProvider activePlugin;
@Inject DanaRSPlugin danaRSPlugin;
@Inject DanaRPlugin danaRPlugin;
@Inject DanaRv2Plugin danaRv2Plugin;
@Inject DanaRKoreanPlugin danaRKoreanPlugin;
@Inject LocalInsightPlugin localInsightPlugin;
@Inject ConfigBuilderPlugin configBuilderPlugin;
@Inject CommandQueueProvider commandQueue;
@Inject FabricPrivacy fabricPrivacy;
private CompositeDisposable disposable = new CompositeDisposable();
TextView statusView, statsMessage, totalBaseBasal2;
EditText totalBaseBasal;
Button reloadButton;
LinearLayoutManager llm;
TableLayout tl, ctl, etl;
String TBB;
double magicNumber;
DecimalFormat decimalFormat;
List<TDD> historyList = new ArrayList<>();
List<TDD> dummies;
public TDDStatsActivity() {
super();
}
@Override
protected void onResume() {
super.onResume();
disposable.add(rxBus
.toObservable(EventPumpStatusChanged.class)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(event -> statusView.setText(event.getStatus(resourceHelper)), exception -> fabricPrivacy.logException(exception))
);
disposable.add(rxBus
.toObservable(EventDanaRSyncStatus.class)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(event -> {
aapsLogger.debug("EventDanaRSyncStatus: " + event.getMessage());
statusView.setText(event.getMessage());
}, exception -> fabricPrivacy.logException(exception))
);
}
@Override
protected void onPause() {
super.onPause();
disposable.clear();
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
View myView = getCurrentFocus();
if (myView instanceof EditText) {
Rect rect = new Rect();
myView.getGlobalVisibleRect(rect);
if (!rect.contains((int) event.getRawX(), (int) event.getRawY())) {
myView.clearFocus();
}
}
}
return super.dispatchTouchEvent(event);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.danar_statsactivity);
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
statusView = findViewById(R.id.danar_stats_connection_status);
reloadButton = findViewById(R.id.danar_statsreload);
totalBaseBasal = findViewById(R.id.danar_stats_editTotalBaseBasal);
totalBaseBasal2 = findViewById(R.id.danar_stats_editTotalBaseBasal2);
statsMessage = findViewById(R.id.danar_stats_Message);
statusView.setVisibility(View.GONE);
statsMessage.setVisibility(View.GONE);
totalBaseBasal2.setEnabled(false);
totalBaseBasal2.setClickable(false);
totalBaseBasal2.setFocusable(false);
totalBaseBasal2.setInputType(0);
decimalFormat = new DecimalFormat("0.000");
llm = new LinearLayoutManager(this);
TBB = sp.getString("TBB", "10.00");
Profile profile = profileFunction.getProfile();
if (profile != null) {
double cppTBB = profile.baseBasalSum();
TBB = decimalFormat.format(cppTBB);
sp.putString("TBB", TBB);
}
totalBaseBasal.setText(TBB);
if (!activePlugin.getActivePump().getPumpDescription().needsManualTDDLoad)
reloadButton.setVisibility(View.GONE);
// stats table
tl = findViewById(R.id.main_table);
TableRow tr_head = new TableRow(this);
tr_head.setBackgroundColor(Color.DKGRAY);
tr_head.setLayoutParams(new TableLayout.LayoutParams(
TableLayout.LayoutParams.MATCH_PARENT,
TableLayout.LayoutParams.WRAP_CONTENT));
TextView label_date = new TextView(this);
label_date.setText(resourceHelper.gs(R.string.danar_stats_date));
label_date.setTextColor(Color.WHITE);
tr_head.addView(label_date);
TextView label_basalrate = new TextView(this);
label_basalrate.setText(resourceHelper.gs(R.string.danar_stats_basalrate));
label_basalrate.setTextColor(Color.WHITE);
tr_head.addView(label_basalrate);
TextView label_bolus = new TextView(this);
label_bolus.setText(resourceHelper.gs(R.string.danar_stats_bolus));
label_bolus.setTextColor(Color.WHITE);
tr_head.addView(label_bolus);
TextView label_tdd = new TextView(this);
label_tdd.setText(resourceHelper.gs(R.string.danar_stats_tdd));
label_tdd.setTextColor(Color.WHITE);
tr_head.addView(label_tdd);
TextView label_ratio = new TextView(this);
label_ratio.setText(resourceHelper.gs(R.string.danar_stats_ratio));
label_ratio.setTextColor(Color.WHITE);
tr_head.addView(label_ratio);
// add stats headers to tables
tl.addView(tr_head, new TableLayout.LayoutParams(
TableLayout.LayoutParams.MATCH_PARENT,
TableLayout.LayoutParams.WRAP_CONTENT));
// cumulative table
ctl = findViewById(R.id.cumulative_table);
TableRow ctr_head = new TableRow(this);
ctr_head.setBackgroundColor(Color.DKGRAY);
ctr_head.setLayoutParams(new TableLayout.LayoutParams(
TableLayout.LayoutParams.MATCH_PARENT,
TableLayout.LayoutParams.WRAP_CONTENT));
TextView label_cum_amount_days = new TextView(this);
label_cum_amount_days.setText(resourceHelper.gs(R.string.danar_stats_amount_days));
label_cum_amount_days.setTextColor(Color.WHITE);
ctr_head.addView(label_cum_amount_days);
TextView label_cum_tdd = new TextView(this);
label_cum_tdd.setText(resourceHelper.gs(R.string.danar_stats_tdd));
label_cum_tdd.setTextColor(Color.WHITE);
ctr_head.addView(label_cum_tdd);
TextView label_cum_ratio = new TextView(this);
label_cum_ratio.setText(resourceHelper.gs(R.string.danar_stats_ratio));
label_cum_ratio.setTextColor(Color.WHITE);
ctr_head.addView(label_cum_ratio);
// add cummulative headers to tables
ctl.addView(ctr_head, new TableLayout.LayoutParams(
TableLayout.LayoutParams.MATCH_PARENT,
TableLayout.LayoutParams.WRAP_CONTENT));
// expontial table
etl = findViewById(R.id.expweight_table);
TableRow etr_head = new TableRow(this);
etr_head.setBackgroundColor(Color.DKGRAY);
etr_head.setLayoutParams(new TableLayout.LayoutParams(
TableLayout.LayoutParams.MATCH_PARENT,
TableLayout.LayoutParams.WRAP_CONTENT));
TextView label_exp_weight = new TextView(this);
label_exp_weight.setText(resourceHelper.gs(R.string.danar_stats_weight));
label_exp_weight.setTextColor(Color.WHITE);
etr_head.addView(label_exp_weight);
TextView label_exp_tdd = new TextView(this);
label_exp_tdd.setText(resourceHelper.gs(R.string.danar_stats_tdd));
label_exp_tdd.setTextColor(Color.WHITE);
etr_head.addView(label_exp_tdd);
TextView label_exp_ratio = new TextView(this);
label_exp_ratio.setText(resourceHelper.gs(R.string.danar_stats_ratio));
label_exp_ratio.setTextColor(Color.WHITE);
etr_head.addView(label_exp_ratio);
// add expontial headers to tables
etl.addView(etr_head, new TableLayout.LayoutParams(
TableLayout.LayoutParams.MATCH_PARENT,
TableLayout.LayoutParams.WRAP_CONTENT));
reloadButton.setOnClickListener(v -> {
runOnUiThread(() -> {
reloadButton.setVisibility(View.GONE);
statusView.setVisibility(View.VISIBLE);
statsMessage.setVisibility(View.VISIBLE);
statsMessage.setText(resourceHelper.gs(R.string.danar_stats_warning_Message));
});
commandQueue.loadTDDs(new Callback() {
@Override
public void run() {
loadDataFromDB();
runOnUiThread(() -> {
reloadButton.setVisibility(View.VISIBLE);
statusView.setVisibility(View.GONE);
statsMessage.setVisibility(View.GONE);
});
}
});
});
totalBaseBasal.setOnEditorActionListener((v, actionId, event) -> {
if (actionId == EditorInfo.IME_ACTION_DONE) {
totalBaseBasal.clearFocus();
return true;
}
return false;
});
totalBaseBasal.setOnFocusChangeListener((v, hasFocus) -> {
if (hasFocus) {
totalBaseBasal.getText().clear();
} else {
sp.putString("TBB", totalBaseBasal.getText().toString());
TBB = sp.getString("TBB", "");
loadDataFromDB();
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(totalBaseBasal.getWindowToken(), 0);
}
});
loadDataFromDB();
}
private void loadDataFromDB() {
historyList = MainApp.getDbHelper().getTDDs();
//only use newest 10
historyList = historyList.subList(0, Math.min(10, historyList.size()));
//fill single gaps
dummies = new LinkedList();
DateFormat df = new SimpleDateFormat("dd.MM.", Locale.getDefault());
for (int i = 0; i < historyList.size() - 1; i++) {
TDD elem1 = historyList.get(i);
TDD elem2 = historyList.get(i + 1);
if (!df.format(new Date(elem1.date)).equals(df.format(new Date(elem2.date + 25 * 60 * 60 * 1000)))) {
TDD dummy = new TDD();
dummy.date = elem1.date - 24 * 60 * 60 * 1000;
dummy.basal = elem1.basal / 2;
dummy.bolus = elem1.bolus / 2;
dummies.add(dummy);
elem1.basal /= 2;
elem1.bolus /= 2;
}
}
historyList.addAll(dummies);
Collections.sort(historyList, (lhs, rhs) -> (int) (rhs.date - lhs.date));
runOnUiThread(() -> {
cleanTable(tl);
cleanTable(ctl);
cleanTable(etl);
DateFormat df1 = new SimpleDateFormat("dd.MM.", Locale.getDefault());
if (TextUtils.isEmpty(TBB)) {
totalBaseBasal.setError("Please Enter Total Base Basal");
return;
} else {
magicNumber = SafeParse.stringToDouble(TBB);
}
magicNumber *= 2;
totalBaseBasal2.setText(decimalFormat.format(magicNumber));
int i = 0;
double sum = 0d;
double weighted03 = 0d;
double weighted05 = 0d;
double weighted07 = 0d;
//TDD table
for (TDD record : historyList) {
double tdd = record.getTotal();
// Create the table row
TableRow tr = new TableRow(TDDStatsActivity.this);
if (i % 2 != 0) tr.setBackgroundColor(Color.DKGRAY);
if (dummies.contains(record)) {
tr.setBackgroundColor(Color.argb(125, 255, 0, 0));
}
tr.setId(100 + i);
tr.setLayoutParams(new TableLayout.LayoutParams(
TableLayout.LayoutParams.MATCH_PARENT,
TableLayout.LayoutParams.WRAP_CONTENT));
// Here create the TextView dynamically
TextView labelDATE = new TextView(TDDStatsActivity.this);
labelDATE.setId(200 + i);
labelDATE.setText(df1.format(new Date(record.date)));
labelDATE.setTextColor(Color.WHITE);
tr.addView(labelDATE);
TextView labelBASAL = new TextView(TDDStatsActivity.this);
labelBASAL.setId(300 + i);
labelBASAL.setText(resourceHelper.gs(R.string.formatinsulinunits, record.basal));
labelBASAL.setTextColor(Color.WHITE);
tr.addView(labelBASAL);
TextView labelBOLUS = new TextView(TDDStatsActivity.this);
labelBOLUS.setId(400 + i);
labelBOLUS.setText(resourceHelper.gs(R.string.formatinsulinunits, record.bolus));
labelBOLUS.setTextColor(Color.WHITE);
tr.addView(labelBOLUS);
TextView labelTDD = new TextView(TDDStatsActivity.this);
labelTDD.setId(500 + i);
labelTDD.setText(resourceHelper.gs(R.string.formatinsulinunits, tdd));
labelTDD.setTextColor(Color.WHITE);
tr.addView(labelTDD);
TextView labelRATIO = new TextView(TDDStatsActivity.this);
labelRATIO.setId(600 + i);
labelRATIO.setText(Math.round(100 * tdd / magicNumber) + "%");
labelRATIO.setTextColor(Color.WHITE);
tr.addView(labelRATIO);
// add stats rows to tables
tl.addView(tr, new TableLayout.LayoutParams(
TableLayout.LayoutParams.MATCH_PARENT,
TableLayout.LayoutParams.WRAP_CONTENT));
i++;
}
i = 0;
//cumulative TDDs
for (TDD record : historyList) {
if (!historyList.isEmpty() && df1.format(new Date(record.date)).equals(df1.format(new Date()))) {
//Today should not be included
continue;
}
i++;
sum = sum + record.getTotal();
// Create the cumtable row
TableRow ctr = new TableRow(TDDStatsActivity.this);
if (i % 2 == 0) ctr.setBackgroundColor(Color.DKGRAY);
ctr.setId(700 + i);
ctr.setLayoutParams(new TableLayout.LayoutParams(
TableLayout.LayoutParams.MATCH_PARENT,
TableLayout.LayoutParams.WRAP_CONTENT));
// Here create the TextView dynamically
TextView labelDAYS = new TextView(TDDStatsActivity.this);
labelDAYS.setId(800 + i);
labelDAYS.setText("" + i);
labelDAYS.setTextColor(Color.WHITE);
ctr.addView(labelDAYS);
TextView labelCUMTDD = new TextView(TDDStatsActivity.this);
labelCUMTDD.setId(900 + i);
labelCUMTDD.setText(resourceHelper.gs(R.string.formatinsulinunits, sum / i));
labelCUMTDD.setTextColor(Color.WHITE);
ctr.addView(labelCUMTDD);
TextView labelCUMRATIO = new TextView(TDDStatsActivity.this);
labelCUMRATIO.setId(1000 + i);
labelCUMRATIO.setText(Math.round(100 * sum / i / magicNumber) + "%");
labelCUMRATIO.setTextColor(Color.WHITE);
ctr.addView(labelCUMRATIO);
// add cummulative rows to tables
ctl.addView(ctr, new TableLayout.LayoutParams(
TableLayout.LayoutParams.MATCH_PARENT,
TableLayout.LayoutParams.WRAP_CONTENT));
}
if (isOldData(historyList) && activePlugin.getActivePump().getPumpDescription().needsManualTDDLoad) {
statsMessage.setVisibility(View.VISIBLE);
statsMessage.setText(resourceHelper.gs(R.string.danar_stats_olddata_Message));
} else {
tl.setBackgroundColor(Color.TRANSPARENT);
}
if (!historyList.isEmpty() && df1.format(new Date(historyList.get(0).date)).equals(df1.format(new Date()))) {
//Today should not be included
historyList.remove(0);
}
Collections.reverse(historyList);
i = 0;
for (TDD record : historyList) {
double tdd = record.getTotal();
if (i == 0) {
weighted03 = tdd;
weighted05 = tdd;
weighted07 = tdd;
} else {
weighted07 = (weighted07 * 0.3 + tdd * 0.7);
weighted05 = (weighted05 * 0.5 + tdd * 0.5);
weighted03 = (weighted03 * 0.7 + tdd * 0.3);
}
i++;
}
// Create the exptable row
TableRow etr = new TableRow(TDDStatsActivity.this);
if (i % 2 != 0) etr.setBackgroundColor(Color.DKGRAY);
etr.setId(1100 + i);
etr.setLayoutParams(new TableLayout.LayoutParams(
TableLayout.LayoutParams.MATCH_PARENT,
TableLayout.LayoutParams.WRAP_CONTENT));
// Here create the TextView dynamically
TextView labelWEIGHT = new TextView(TDDStatsActivity.this);
labelWEIGHT.setId(1200 + i);
labelWEIGHT.setText("0.3\n" + "0.5\n" + "0.7");
labelWEIGHT.setTextColor(Color.WHITE);
etr.addView(labelWEIGHT);
TextView labelEXPTDD = new TextView(TDDStatsActivity.this);
labelEXPTDD.setId(1300 + i);
labelEXPTDD.setText(resourceHelper.gs(R.string.formatinsulinunits, weighted03) + "\n" +
resourceHelper.gs(R.string.formatinsulinunits, weighted05) + "\n" +
resourceHelper.gs(R.string.formatinsulinunits, weighted07));
labelEXPTDD.setTextColor(Color.WHITE);
etr.addView(labelEXPTDD);
TextView labelEXPRATIO = new TextView(TDDStatsActivity.this);
labelEXPRATIO.setId(1400 + i);
labelEXPRATIO.setText(Math.round(100 * weighted03 / magicNumber) + "%\n"
+ Math.round(100 * weighted05 / magicNumber) + "%\n"
+ Math.round(100 * weighted07 / magicNumber) + "%");
labelEXPRATIO.setTextColor(Color.WHITE);
etr.addView(labelEXPRATIO);
// add exponentail rows to tables
etl.addView(etr, new TableLayout.LayoutParams(
TableLayout.LayoutParams.MATCH_PARENT,
TableLayout.LayoutParams.WRAP_CONTENT));
});
}
private void cleanTable(TableLayout table) {
int childCount = table.getChildCount();
// Remove all rows except the first one
if (childCount > 1) {
table.removeViews(1, childCount - 1);
}
}
public boolean isOldData(List<TDD> historyList) {
boolean startsYesterday = danaRPlugin.isEnabled() || danaRSPlugin.isEnabled() || danaRv2Plugin.isEnabled() || danaRKoreanPlugin.isEnabled() || localInsightPlugin.isEnabled();
DateFormat df = new SimpleDateFormat("dd.MM.", Locale.getDefault());
return (historyList.size() < 3 || !(df.format(new Date(historyList.get(0).date)).equals(df.format(new Date(System.currentTimeMillis() - (startsYesterday ? 1000 * 60 * 60 * 24 : 0))))));
}
}