mirror of
https://github.com/oliexdev/openScale.git
synced 2025-08-15 05:04:22 +02:00
Libra like Trendline (#625)
implemented the Hacker's Diet Libra like trendline based on an exponentially smoothed moving average calculation, see issue #436
This commit is contained in:
@@ -120,12 +120,17 @@ android {
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
coreLibraryDesugaringEnabled true
|
||||
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.9'
|
||||
|
||||
implementation 'com.google.android.material:material:1.3.0-alpha02'
|
||||
implementation 'com.google.android.material:material:1.3.0-alpha02'
|
||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||
|
@@ -16,18 +16,19 @@
|
||||
|
||||
package com.health.openscale.core.datatypes;
|
||||
|
||||
import com.health.openscale.core.utils.CsvHelper;
|
||||
import com.j256.simplecsv.common.CsvColumn;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Date;
|
||||
|
||||
import androidx.room.ColumnInfo;
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.ForeignKey;
|
||||
import androidx.room.Ignore;
|
||||
import androidx.room.Index;
|
||||
import androidx.room.PrimaryKey;
|
||||
|
||||
import com.health.openscale.core.utils.CsvHelper;
|
||||
import com.j256.simplecsv.common.CsvColumn;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Date;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
@Entity(tableName = "scaleMeasurements",
|
||||
@@ -163,6 +164,59 @@ public class ScaleMeasurement implements Cloneable {
|
||||
}
|
||||
}
|
||||
|
||||
public void add(final float summand) {
|
||||
try {
|
||||
Field[] fields = getClass().getDeclaredFields();
|
||||
|
||||
for (Field field : fields) {
|
||||
field.setAccessible(true);
|
||||
Object value = field.get(this);
|
||||
|
||||
if (value != null && Float.class.isAssignableFrom(value.getClass())) {
|
||||
field.set(this, (float)value + summand);
|
||||
}
|
||||
field.setAccessible(false);
|
||||
}
|
||||
|
||||
} catch (IllegalAccessException e) {
|
||||
Timber.e(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void subtract(final ScaleMeasurement minuend) {
|
||||
try {
|
||||
Field[] fields = getClass().getDeclaredFields();
|
||||
|
||||
for (Field field : fields) {
|
||||
field.setAccessible(true);
|
||||
Object value = field.get(this);
|
||||
if (value != null && Float.class.isAssignableFrom(value.getClass())) {
|
||||
field.set(this, (float)value - (float)field.get(minuend));
|
||||
}
|
||||
field.setAccessible(false);
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
Timber.e(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void multiply(final float factor) {
|
||||
try {
|
||||
Field[] fields = getClass().getDeclaredFields();
|
||||
|
||||
for (Field field : fields) {
|
||||
field.setAccessible(true);
|
||||
Object value = field.get(this);
|
||||
if (value != null && Float.class.isAssignableFrom(value.getClass())) {
|
||||
field.set(this, (float)value * factor);
|
||||
}
|
||||
field.setAccessible(false);
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
Timber.e(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void divide(final float divisor) {
|
||||
try {
|
||||
Field[] fields = getClass().getDeclaredFields();
|
||||
|
@@ -59,6 +59,8 @@ import com.health.openscale.gui.measurement.MeasurementEntryFragment;
|
||||
import com.health.openscale.gui.utils.ColorUtil;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZoneId;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
@@ -80,8 +82,8 @@ public class GraphFragment extends Fragment {
|
||||
|
||||
private OpenScale openScale;
|
||||
|
||||
private final Calendar calYears;
|
||||
private Calendar calLastSelected;
|
||||
private LocalDate calYears;
|
||||
private LocalDate calLastSelected;
|
||||
|
||||
private ScaleMeasurement markedMeasurement;
|
||||
|
||||
@@ -89,8 +91,8 @@ public class GraphFragment extends Fragment {
|
||||
private static final String CAL_LAST_SELECTED_KEY = "calLastSelected";
|
||||
|
||||
public GraphFragment() {
|
||||
calYears = Calendar.getInstance();
|
||||
calLastSelected = Calendar.getInstance();
|
||||
calYears = LocalDate.now();
|
||||
calLastSelected = LocalDate.now();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -100,13 +102,13 @@ public class GraphFragment extends Fragment {
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
if (!openScale.isScaleMeasurementListEmpty()) {
|
||||
calYears.setTime(openScale.getLastScaleMeasurement().getDateTime());
|
||||
calLastSelected.setTime(openScale.getLastScaleMeasurement().getDateTime());
|
||||
calYears = openScale.getLastScaleMeasurement().getDateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();;
|
||||
calLastSelected = openScale.getLastScaleMeasurement().getDateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
||||
}
|
||||
}
|
||||
else {
|
||||
calYears.setTimeInMillis(savedInstanceState.getLong(CAL_YEARS_KEY));
|
||||
calLastSelected.setTimeInMillis(savedInstanceState.getLong(CAL_LAST_SELECTED_KEY));
|
||||
calYears = LocalDate.ofEpochDay(savedInstanceState.getLong(CAL_YEARS_KEY));
|
||||
calLastSelected = LocalDate.ofEpochDay(savedInstanceState.getLong(CAL_LAST_SELECTED_KEY));
|
||||
}
|
||||
|
||||
graphView = inflater.inflate(R.layout.fragment_graph, container, false);
|
||||
@@ -143,7 +145,7 @@ public class GraphFragment extends Fragment {
|
||||
});
|
||||
|
||||
txtYear = graphView.findViewById(R.id.txtYear);
|
||||
txtYear.setText(Integer.toString(calYears.get(Calendar.YEAR)));
|
||||
txtYear.setText(Integer.toString(calYears.getYear()));
|
||||
|
||||
chartActionBarView = graphView.findViewById(R.id.chartActionBar);
|
||||
chartActionBarView.setOnActionClickListener(new View.OnClickListener() {
|
||||
@@ -164,14 +166,9 @@ public class GraphFragment extends Fragment {
|
||||
btnLeftYear = graphView.findViewById(R.id.btnLeftYear);
|
||||
btnLeftYear.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View view) {
|
||||
calYears.roll(Calendar.YEAR, false);
|
||||
txtYear.setText(Integer.toString(calYears.get(Calendar.YEAR)));
|
||||
calYears = calYears.minusYears(1);
|
||||
txtYear.setText(Integer.toString(calYears.getYear()));
|
||||
|
||||
List<ScaleMeasurement> scaleMeasurementList =
|
||||
OpenScale.getInstance().getScaleMeasurementOfYear(calYears.get(Calendar.YEAR));
|
||||
if (!scaleMeasurementList.isEmpty()) {
|
||||
calLastSelected.setTime(scaleMeasurementList.get(0).getDateTime());
|
||||
}
|
||||
generateGraphs();
|
||||
}
|
||||
});
|
||||
@@ -179,14 +176,9 @@ public class GraphFragment extends Fragment {
|
||||
btnRightYear = graphView.findViewById(R.id.btnRightYear);
|
||||
btnRightYear.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View view) {
|
||||
calYears.roll(Calendar.YEAR, true);
|
||||
txtYear.setText(Integer.toString(calYears.get(Calendar.YEAR)));
|
||||
calYears = calYears.plusYears(1);
|
||||
txtYear.setText(Integer.toString(calYears.getYear()));
|
||||
|
||||
List<ScaleMeasurement> scaleMeasurementList =
|
||||
OpenScale.getInstance().getScaleMeasurementOfYear(calYears.get(Calendar.YEAR));
|
||||
if (!scaleMeasurementList.isEmpty()) {
|
||||
calLastSelected.setTime(scaleMeasurementList.get(scaleMeasurementList.size() - 1).getDateTime());
|
||||
}
|
||||
generateGraphs();
|
||||
}
|
||||
});
|
||||
@@ -217,6 +209,8 @@ public class GraphFragment extends Fragment {
|
||||
prefs.edit().putBoolean("showMonth", true).apply();
|
||||
}
|
||||
|
||||
getActivity().recreate(); // TODO HACK to refresh graph; graph.invalidate and notfiydatachange is not enough!?
|
||||
|
||||
generateGraphs();
|
||||
return true;
|
||||
case R.id.enableWeek:
|
||||
@@ -228,6 +222,8 @@ public class GraphFragment extends Fragment {
|
||||
prefs.edit().putBoolean("showWeek", true).apply();
|
||||
}
|
||||
|
||||
getActivity().recreate(); // TODO HACK to refresh graph; graph.invalidate and notfiydatachange is not enough!?
|
||||
|
||||
generateGraphs();
|
||||
return true;
|
||||
default:
|
||||
@@ -284,6 +280,7 @@ public class GraphFragment extends Fragment {
|
||||
OpenScale.getInstance().getScaleMeasurementsLiveData().observe(getViewLifecycleOwner(), new Observer<List<ScaleMeasurement>>() {
|
||||
@Override
|
||||
public void onChanged(List<ScaleMeasurement> scaleMeasurements) {
|
||||
chartView.updateMeasurementList(scaleMeasurements);
|
||||
generateGraphs();
|
||||
}
|
||||
});
|
||||
@@ -304,25 +301,24 @@ public class GraphFragment extends Fragment {
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
outState.putLong(CAL_YEARS_KEY, calYears.getTimeInMillis());
|
||||
outState.putLong(CAL_LAST_SELECTED_KEY, calLastSelected.getTimeInMillis());
|
||||
outState.putLong(CAL_YEARS_KEY, calYears.toEpochDay());
|
||||
outState.putLong(CAL_LAST_SELECTED_KEY, calLastSelected.toEpochDay());
|
||||
}
|
||||
|
||||
private void generateColumnData()
|
||||
{
|
||||
int[] numOfMonth = openScale.getCountsOfMonth(calYears.get(Calendar.YEAR));
|
||||
int[] numOfMonth = openScale.getCountsOfMonth(calYears.getYear());
|
||||
|
||||
Calendar calMonths = Calendar.getInstance();
|
||||
calMonths.set(Calendar.MONTH, Calendar.JANUARY);
|
||||
LocalDate calMonths = LocalDate.of(calYears.getYear(), 1, 1);
|
||||
|
||||
List<IBarDataSet> dataSets = new ArrayList<>();
|
||||
|
||||
for (int i=0; i<12; i++) {
|
||||
List<BarEntry> entries = new ArrayList<>();
|
||||
|
||||
entries.add(new BarEntry(calMonths.get(Calendar.MONTH), numOfMonth[i]));
|
||||
entries.add(new BarEntry(calMonths.getMonthValue()-1, numOfMonth[i]));
|
||||
|
||||
calMonths.add(Calendar.MONTH, 1);
|
||||
calMonths = calMonths.plusMonths(1);
|
||||
|
||||
BarDataSet set = new BarDataSet(entries, "month "+i);
|
||||
set.setColor(ColorUtil.COLORS[i % 4]);
|
||||
@@ -339,7 +335,7 @@ public class GraphFragment extends Fragment {
|
||||
}
|
||||
|
||||
private void generateGraphs() {
|
||||
final int selectedYear = calYears.get(Calendar.YEAR);
|
||||
final int selectedYear = calYears.getYear();
|
||||
|
||||
int firstYear = selectedYear;
|
||||
int lastYear = selectedYear;
|
||||
@@ -372,9 +368,9 @@ public class GraphFragment extends Fragment {
|
||||
generateColumnData();
|
||||
|
||||
if (prefs.getBoolean("showWeek", false)) {
|
||||
chartView.setViewRange(selectedYear, calLastSelected.get(Calendar.MONTH), ChartMeasurementView.ViewMode.WEEK_OF_MONTH);
|
||||
chartView.setViewRange(selectedYear, calLastSelected.getMonthValue(), ChartMeasurementView.ViewMode.WEEK_OF_MONTH);
|
||||
} else {
|
||||
chartView.setViewRange(selectedYear, calLastSelected.get(Calendar.MONTH), ChartMeasurementView.ViewMode.DAY_OF_MONTH);
|
||||
chartView.setViewRange(selectedYear, calLastSelected.getMonthValue(), ChartMeasurementView.ViewMode.DAY_OF_MONTH);
|
||||
}
|
||||
} else { // show only yearly diagram and hide monthly diagram
|
||||
chartTop.setVisibility(View.GONE);
|
||||
@@ -386,15 +382,13 @@ public class GraphFragment extends Fragment {
|
||||
chartView.setViewRange(selectedYear, ChartMeasurementView.ViewMode.MONTH_OF_YEAR);
|
||||
}
|
||||
}
|
||||
chartView.refreshMeasurementList();
|
||||
}
|
||||
|
||||
private class chartTopValueTouchListener implements OnChartValueSelectedListener {
|
||||
@Override
|
||||
public void onValueSelected(Entry e, Highlight h) {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.set(Calendar.MONTH, (int)e.getX());
|
||||
|
||||
calLastSelected = cal;
|
||||
calLastSelected = calLastSelected.withMonth((int)e.getX()+1);
|
||||
|
||||
generateGraphs();
|
||||
|
||||
|
@@ -62,7 +62,7 @@ public class ChartMarkerView extends MarkerView {
|
||||
markerText.append("\n");
|
||||
|
||||
if (measurement.isAverageValue()) {
|
||||
markerText.append("Ø ");
|
||||
markerText.append(getContext().getString(R.string.label_trend) + " ");
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -18,14 +18,11 @@ package com.health.openscale.gui.measurement;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.RectF;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.github.mikephil.charting.charts.LineChart;
|
||||
import com.github.mikephil.charting.components.AxisBase;
|
||||
@@ -37,8 +34,6 @@ import com.github.mikephil.charting.data.LineData;
|
||||
import com.github.mikephil.charting.data.LineDataSet;
|
||||
import com.github.mikephil.charting.formatter.ValueFormatter;
|
||||
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
|
||||
import com.github.mikephil.charting.listener.ChartTouchListener;
|
||||
import com.github.mikephil.charting.listener.OnChartGestureListener;
|
||||
import com.github.mikephil.charting.utils.Utils;
|
||||
import com.health.openscale.R;
|
||||
import com.health.openscale.core.OpenScale;
|
||||
@@ -48,15 +43,18 @@ import com.health.openscale.core.utils.Converters;
|
||||
import com.health.openscale.core.utils.PolynomialFitter;
|
||||
import com.health.openscale.gui.utils.ColorUtil;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.FormatStyle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
import static java.time.temporal.ChronoUnit.DAYS;
|
||||
|
||||
public class ChartMeasurementView extends LineChart {
|
||||
public enum ViewMode {
|
||||
DAY_OF_MONTH,
|
||||
@@ -72,18 +70,11 @@ public class ChartMeasurementView extends LineChart {
|
||||
|
||||
private OpenScale openScale;
|
||||
private SharedPreferences prefs;
|
||||
private List<ScaleMeasurement> scaleMeasurementList;
|
||||
private List<MeasurementView> measurementViews;
|
||||
private ScaleMeasurement firstMeasurement;
|
||||
private ScaleMeasurement lastMeasurement;
|
||||
private int maxXValue;
|
||||
private int minXValue;
|
||||
private List<ScaleMeasurement> scaleMeasurementList;
|
||||
private ViewMode viewMode;
|
||||
private boolean isAnimationOn;
|
||||
private boolean isInGraphKey;
|
||||
private int scrollHistoryCount;
|
||||
private ProgressBar progressBar;
|
||||
private boolean isRollingChart;
|
||||
|
||||
public ChartMeasurementView(Context context) {
|
||||
super(context);
|
||||
@@ -100,69 +91,99 @@ public class ChartMeasurementView extends LineChart {
|
||||
initChart();
|
||||
}
|
||||
|
||||
public void setViewRange(final ViewMode mode, boolean rollingChart) {
|
||||
progressBar.setVisibility(VISIBLE);
|
||||
isRollingChart = rollingChart;
|
||||
public void setViewRange(final ViewMode mode) {
|
||||
viewMode = mode;
|
||||
|
||||
if (isRollingChart) {
|
||||
ScaleMeasurement lastMeasurement = openScale.getLastScaleMeasurement();
|
||||
setGranularityAndRange(1980, 1);
|
||||
setXValueFormat(viewMode);
|
||||
|
||||
if (lastMeasurement != null) {
|
||||
Calendar lastMeasurementCalender = Calendar.getInstance();
|
||||
lastMeasurementCalender.setTime(lastMeasurement.getDateTime());
|
||||
|
||||
switch (mode) {
|
||||
case DAY_OF_ALL:
|
||||
lastMeasurementCalender.add(Calendar.DAY_OF_MONTH, -28 * scrollHistoryCount);
|
||||
break;
|
||||
case WEEK_OF_ALL:
|
||||
lastMeasurementCalender.add(Calendar.WEEK_OF_YEAR, -4 * scrollHistoryCount);
|
||||
break;
|
||||
case MONTH_OF_ALL:
|
||||
lastMeasurementCalender.add(Calendar.MONTH, -4 * scrollHistoryCount);
|
||||
break;
|
||||
case YEAR_OF_ALL:
|
||||
lastMeasurementCalender.add(Calendar.YEAR, -4 * scrollHistoryCount);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("view mode not implemented");
|
||||
}
|
||||
|
||||
setMeasurementList(openScale.getScaleMeasurementOfStartDate(lastMeasurementCalender.get(Calendar.YEAR), lastMeasurementCalender.get(Calendar.MONTH), lastMeasurementCalender.get(Calendar.DAY_OF_MONTH)));
|
||||
} else {
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
setMeasurementList(openScale.getScaleMeasurementList());
|
||||
}
|
||||
setViewMode(mode);
|
||||
|
||||
refresh();
|
||||
|
||||
if (isRollingChart) {
|
||||
setRollingChartOn(mode);
|
||||
if (openScale.getLastScaleMeasurement() != null) {
|
||||
moveViewToX(convertDateToInt(openScale.getLastScaleMeasurement().getDateTime()));
|
||||
}
|
||||
}
|
||||
|
||||
public void setViewRange(int year, final ViewMode mode) {
|
||||
progressBar.setVisibility(VISIBLE);
|
||||
setMeasurementList(openScale.getScaleMeasurementOfYear(year));
|
||||
setViewMode(mode);
|
||||
viewMode = mode;
|
||||
|
||||
refresh();
|
||||
setGranularityAndRange(year, 1);
|
||||
setXValueFormat(viewMode);
|
||||
|
||||
LocalDate startDate = LocalDate.of(year, 1, 1);
|
||||
|
||||
moveViewToX(convertDateToInt(startDate));
|
||||
}
|
||||
|
||||
public void setViewRange(int year, int month, final ViewMode mode) {
|
||||
progressBar.setVisibility(VISIBLE);
|
||||
setMeasurementList(openScale.getScaleMeasurementOfMonth(year, month));
|
||||
setViewMode(mode);
|
||||
viewMode = mode;
|
||||
|
||||
refresh();
|
||||
setGranularityAndRange(year, month);
|
||||
setXValueFormat(viewMode);
|
||||
|
||||
LocalDate startDate = LocalDate.of(year, month, 1);
|
||||
|
||||
moveViewToX(convertDateToInt(startDate));
|
||||
}
|
||||
|
||||
public void setAnimationOn(boolean status) {
|
||||
isAnimationOn = status;
|
||||
private void setGranularityAndRange(int year, int month) {
|
||||
LocalDate startDate = LocalDate.of(year, month, 1);
|
||||
LocalDate endDate = LocalDate.of(year, month, 1);
|
||||
|
||||
int range = 0;
|
||||
int granularity = 0;
|
||||
|
||||
switch (viewMode) {
|
||||
case DAY_OF_MONTH:
|
||||
endDate = startDate.plusMonths(1);
|
||||
range = (int)DAYS.between(startDate, endDate);
|
||||
granularity = 1;
|
||||
break;
|
||||
case WEEK_OF_MONTH:
|
||||
endDate = startDate.plusMonths(1);
|
||||
range = (int)DAYS.between(startDate, endDate);
|
||||
granularity = 7;
|
||||
break;
|
||||
case WEEK_OF_YEAR:
|
||||
endDate = startDate.plusYears(1);
|
||||
range = (int)DAYS.between(startDate, endDate);
|
||||
granularity = 7;
|
||||
break;
|
||||
case MONTH_OF_YEAR:
|
||||
endDate = startDate.plusYears(1);
|
||||
range = (int)DAYS.between(startDate, endDate);
|
||||
granularity = 30;
|
||||
break;
|
||||
case DAY_OF_YEAR:
|
||||
endDate = startDate.plusYears(1);
|
||||
range = (int)DAYS.between(startDate, endDate);
|
||||
granularity = 1;
|
||||
break;
|
||||
case DAY_OF_ALL:
|
||||
endDate = startDate.plusMonths(1);
|
||||
range = (int)DAYS.between(startDate, endDate);
|
||||
granularity = 1;
|
||||
break;
|
||||
case WEEK_OF_ALL:
|
||||
endDate = startDate.plusMonths(1);
|
||||
range = (int)DAYS.between(startDate, endDate);
|
||||
granularity = 7;
|
||||
break;
|
||||
case MONTH_OF_ALL:
|
||||
endDate = startDate.plusMonths(3);
|
||||
range = (int)DAYS.between(startDate, endDate);
|
||||
granularity = 30;
|
||||
break;
|
||||
case YEAR_OF_ALL:
|
||||
endDate = startDate.plusYears(1);
|
||||
range = (int)DAYS.between(startDate, endDate);
|
||||
granularity = 365;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("view mode not implemented");
|
||||
}
|
||||
|
||||
getXAxis().setGranularity(granularity);
|
||||
setVisibleXRangeMaximum(range);
|
||||
setCustomViewPortOffsets(); // set custom viewPortOffsets to avoid jitter on translating while auto scale is on
|
||||
}
|
||||
|
||||
public void setIsInGraphKey(boolean status) {
|
||||
@@ -176,18 +197,12 @@ public class ChartMeasurementView extends LineChart {
|
||||
private void initChart() {
|
||||
prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||
openScale = OpenScale.getInstance();
|
||||
scaleMeasurementList = new ArrayList<>();
|
||||
measurementViews = MeasurementView.getMeasurementList(getContext(), MeasurementView.DateTimeOrder.NONE);
|
||||
firstMeasurement = new ScaleMeasurement();
|
||||
lastMeasurement = new ScaleMeasurement();
|
||||
maxXValue = 0;
|
||||
minXValue = 0;
|
||||
isAnimationOn = true;
|
||||
isInGraphKey = true;
|
||||
scrollHistoryCount = 1;
|
||||
progressBar = null;
|
||||
|
||||
setHardwareAccelerationEnabled(true);
|
||||
setAutoScaleMinMaxEnabled(true);
|
||||
setMarker(new ChartMarkerView(getContext(), R.layout.chart_markerview));
|
||||
setDoubleTapToZoomEnabled(false);
|
||||
setHighlightPerTapEnabled(true);
|
||||
@@ -202,136 +217,66 @@ public class ChartMeasurementView extends LineChart {
|
||||
getAxisRight().setTextColor(ColorUtil.getTintColor(getContext()));
|
||||
getXAxis().setPosition(XAxis.XAxisPosition.BOTTOM);
|
||||
getXAxis().setTextColor(ColorUtil.getTintColor(getContext()));
|
||||
getXAxis().setGranularityEnabled(true);
|
||||
}
|
||||
|
||||
setOnChartGestureListener(new OnChartGestureListener() {
|
||||
@Override
|
||||
public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) {
|
||||
private int convertDateToInt(LocalDate date) {
|
||||
return (int)date.toEpochDay();
|
||||
}
|
||||
|
||||
}
|
||||
private int convertDateToInt(Date date) {
|
||||
LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
||||
return (int)localDate.toEpochDay();
|
||||
}
|
||||
|
||||
private LocalDate convertIntToDate(int shortDate) {
|
||||
return LocalDate.ofEpochDay(shortDate);
|
||||
}
|
||||
|
||||
private void setXValueFormat(final ViewMode mode) {
|
||||
getXAxis().setValueFormatter(new ValueFormatter() {
|
||||
|
||||
@Override
|
||||
public void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) {
|
||||
if (isRollingChart) {
|
||||
if (progressBar.getVisibility() == GONE) {
|
||||
if (Math.round(getLowestVisibleX()) == Math.round(getXChartMin())) {
|
||||
scrollHistoryCount++;
|
||||
setViewRange(viewMode, isRollingChart);
|
||||
}
|
||||
}
|
||||
public String getAxisLabel(float value, AxisBase axis) {
|
||||
DateTimeFormatter formatter;
|
||||
|
||||
switch (mode) {
|
||||
case DAY_OF_MONTH:
|
||||
formatter = DateTimeFormatter.ofPattern("dd");
|
||||
break;
|
||||
case WEEK_OF_MONTH:
|
||||
formatter = DateTimeFormatter.ofPattern("'W'W");
|
||||
break;
|
||||
case WEEK_OF_YEAR:
|
||||
formatter = DateTimeFormatter.ofPattern("'W'w");
|
||||
break;
|
||||
case MONTH_OF_YEAR:
|
||||
formatter = DateTimeFormatter.ofPattern("MMM");
|
||||
break;
|
||||
case DAY_OF_YEAR:
|
||||
formatter = DateTimeFormatter.ofPattern("D");
|
||||
break;
|
||||
case DAY_OF_ALL:
|
||||
formatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT);
|
||||
break;
|
||||
case WEEK_OF_ALL:
|
||||
formatter = DateTimeFormatter.ofPattern("'W'w yyyy");
|
||||
break;
|
||||
case MONTH_OF_ALL:
|
||||
formatter = DateTimeFormatter.ofPattern("MMM yyyy");
|
||||
break;
|
||||
case YEAR_OF_ALL:
|
||||
formatter = DateTimeFormatter.ofPattern("yyyy");
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("view mode not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChartLongPressed(MotionEvent me) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChartDoubleTapped(MotionEvent me) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChartSingleTapped(MotionEvent me) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChartScale(MotionEvent me, float scaleX, float scaleY) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChartTranslate(MotionEvent me, float dX, float dY) {
|
||||
|
||||
return formatter.format(convertIntToDate((int)value));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
|
||||
progressBar.setVisibility(GONE);
|
||||
}
|
||||
|
||||
private void setViewMode(final ViewMode mode) {
|
||||
viewMode = mode;
|
||||
Calendar viewModeCalender = Calendar.getInstance();
|
||||
viewModeCalender.setTime(lastMeasurement.getDateTime());
|
||||
|
||||
switch (mode) {
|
||||
case DAY_OF_MONTH:
|
||||
minXValue = viewModeCalender.getMinimum(Calendar.DAY_OF_MONTH);
|
||||
maxXValue = viewModeCalender.getMaximum(Calendar.DAY_OF_MONTH);
|
||||
break;
|
||||
case WEEK_OF_MONTH:
|
||||
minXValue = 1;
|
||||
maxXValue = viewModeCalender.getActualMaximum(Calendar.WEEK_OF_MONTH);
|
||||
break;
|
||||
case WEEK_OF_YEAR:
|
||||
minXValue = viewModeCalender.getActualMinimum(Calendar.WEEK_OF_YEAR);
|
||||
maxXValue = viewModeCalender.getActualMaximum(Calendar.WEEK_OF_YEAR);
|
||||
break;
|
||||
case MONTH_OF_YEAR:
|
||||
minXValue = viewModeCalender.getActualMinimum(Calendar.MONTH);
|
||||
maxXValue = viewModeCalender.getActualMaximum(Calendar.MONTH);
|
||||
break;
|
||||
case DAY_OF_YEAR:
|
||||
minXValue = viewModeCalender.getActualMinimum(Calendar.DAY_OF_YEAR);
|
||||
maxXValue = viewModeCalender.getActualMaximum(Calendar.DAY_OF_YEAR);
|
||||
break;
|
||||
case DAY_OF_ALL:
|
||||
case WEEK_OF_ALL:
|
||||
case MONTH_OF_ALL:
|
||||
case YEAR_OF_ALL:
|
||||
minXValue = convertDateInShort(firstMeasurement.getDateTime());
|
||||
maxXValue = convertDateInShort(lastMeasurement.getDateTime());
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("view mode not implemented");
|
||||
}
|
||||
|
||||
setXValueFormat(mode);
|
||||
}
|
||||
|
||||
private int convertDateInShort(Date date) {
|
||||
Calendar shortDate = Calendar.getInstance();
|
||||
shortDate.setTime(new Date(0));
|
||||
|
||||
Calendar dateCalendar = Calendar.getInstance();
|
||||
dateCalendar.setTime(date);
|
||||
|
||||
switch (viewMode) {
|
||||
case DAY_OF_ALL:
|
||||
shortDate.set(Calendar.DAY_OF_MONTH, dateCalendar.get(Calendar.DAY_OF_MONTH));
|
||||
shortDate.set(Calendar.MONTH, dateCalendar.get(Calendar.MONTH));
|
||||
shortDate.set(Calendar.YEAR, dateCalendar.get(Calendar.YEAR));
|
||||
break;
|
||||
case WEEK_OF_ALL:
|
||||
shortDate.set(Calendar.WEEK_OF_YEAR, dateCalendar.get(Calendar.WEEK_OF_YEAR));
|
||||
shortDate.set(Calendar.YEAR, dateCalendar.get(Calendar.YEAR));
|
||||
break;
|
||||
case MONTH_OF_ALL:
|
||||
shortDate.set(Calendar.MONTH, dateCalendar.get(Calendar.MONTH));
|
||||
shortDate.set(Calendar.YEAR, dateCalendar.get(Calendar.YEAR));
|
||||
break;
|
||||
case YEAR_OF_ALL:
|
||||
shortDate.set(Calendar.YEAR, dateCalendar.get(Calendar.YEAR));
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("view mode not implemented");
|
||||
|
||||
}
|
||||
|
||||
return (int)(shortDate.getTime().getTime() / 1000000L);
|
||||
}
|
||||
|
||||
private void setCustomViewPortOffsets() {
|
||||
float offsetLeft = 0f, offsetRight = 0f, offsetTop = 0f, offsetBottom = 0f;
|
||||
|
||||
@@ -388,231 +333,51 @@ public class ChartMeasurementView extends LineChart {
|
||||
Math.max(minOffset, offsetBottom));
|
||||
}
|
||||
|
||||
private Date convertShortInDate(int shortDate) {
|
||||
return new Date(shortDate * 1000000L);
|
||||
}
|
||||
|
||||
private void setMeasurementList(List<ScaleMeasurement> measurementList) {
|
||||
scaleMeasurementList = measurementList;
|
||||
|
||||
if (!measurementList.isEmpty()) {
|
||||
lastMeasurement = measurementList.get(0);
|
||||
Collections.reverse(measurementList);
|
||||
firstMeasurement = measurementList.get(0);
|
||||
Collections.reverse(measurementList);
|
||||
}
|
||||
}
|
||||
|
||||
private void setRollingChartOn(ViewMode mode) {
|
||||
if (!scaleMeasurementList.isEmpty()) {
|
||||
Calendar zeroCalendar = Calendar.getInstance();
|
||||
zeroCalendar.setTime(new Date(0));
|
||||
|
||||
Calendar lastCalendar = Calendar.getInstance();
|
||||
lastCalendar.setTime(lastMeasurement.getDateTime());
|
||||
|
||||
Calendar deltaCalendar = Calendar.getInstance();
|
||||
|
||||
int range = 0;
|
||||
int granularity = 0;
|
||||
|
||||
switch (mode) {
|
||||
case DAY_OF_ALL:
|
||||
zeroCalendar.set(Calendar.DAY_OF_MONTH, lastCalendar.get(Calendar.DAY_OF_MONTH));
|
||||
zeroCalendar.set(Calendar.MONTH, lastCalendar.get(Calendar.MONTH));
|
||||
zeroCalendar.set(Calendar.YEAR, lastCalendar.get(Calendar.YEAR));
|
||||
deltaCalendar.setTime(zeroCalendar.getTime());
|
||||
deltaCalendar.add(Calendar.DAY_OF_MONTH, -1);
|
||||
granularity = convertDateInShort(zeroCalendar.getTime()) - convertDateInShort(deltaCalendar.getTime());
|
||||
range = granularity * 14;
|
||||
break;
|
||||
case WEEK_OF_ALL:
|
||||
zeroCalendar.set(Calendar.WEEK_OF_YEAR, lastCalendar.get(Calendar.WEEK_OF_YEAR));
|
||||
zeroCalendar.set(Calendar.YEAR, lastCalendar.get(Calendar.YEAR));
|
||||
deltaCalendar.setTime(zeroCalendar.getTime());
|
||||
deltaCalendar.add(Calendar.WEEK_OF_YEAR, -1);
|
||||
granularity = convertDateInShort(zeroCalendar.getTime()) - convertDateInShort(deltaCalendar.getTime());
|
||||
range = granularity * 4;
|
||||
break;
|
||||
case MONTH_OF_ALL:
|
||||
zeroCalendar.set(Calendar.MONTH, lastCalendar.get(Calendar.MONTH));
|
||||
zeroCalendar.set(Calendar.YEAR, lastCalendar.get(Calendar.YEAR));
|
||||
deltaCalendar.setTime(zeroCalendar.getTime());
|
||||
deltaCalendar.add(Calendar.MONTH, -1);
|
||||
granularity = convertDateInShort(zeroCalendar.getTime()) - convertDateInShort(deltaCalendar.getTime());
|
||||
range = granularity * 4;
|
||||
break;
|
||||
case YEAR_OF_ALL:
|
||||
zeroCalendar.set(Calendar.YEAR, lastCalendar.get(Calendar.YEAR));
|
||||
deltaCalendar.add(Calendar.YEAR, -1);
|
||||
granularity = convertDateInShort(zeroCalendar.getTime()) - convertDateInShort(deltaCalendar.getTime());
|
||||
range = granularity * 3;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("view mode not implemented");
|
||||
}
|
||||
|
||||
setAutoScaleMinMaxEnabled(true);
|
||||
setCustomViewPortOffsets(); // set custom viewPortOffsets to avoid jitter on translating while auto scale is on
|
||||
|
||||
getXAxis().setGranularity(granularity);
|
||||
setVisibleXRangeMaximum(range);
|
||||
|
||||
moveViewToX(getBinNr(lastMeasurement));
|
||||
}
|
||||
}
|
||||
|
||||
private void setXValueFormat(final ViewMode mode) {
|
||||
getXAxis().setValueFormatter(new ValueFormatter() {
|
||||
private final SimpleDateFormat xValueFormat = new SimpleDateFormat();
|
||||
private final Calendar calendar = Calendar.getInstance();
|
||||
|
||||
@Override
|
||||
public String getAxisLabel(float value, AxisBase axis) {
|
||||
calendar.setTime(new Date(0));
|
||||
|
||||
switch (mode) {
|
||||
case DAY_OF_MONTH:
|
||||
calendar.set(Calendar.DAY_OF_MONTH, (int)value);
|
||||
xValueFormat.applyLocalizedPattern("dd");
|
||||
break;
|
||||
case WEEK_OF_MONTH:
|
||||
calendar.set(Calendar.WEEK_OF_MONTH, (int)value);
|
||||
xValueFormat.applyLocalizedPattern("'W'W");
|
||||
break;
|
||||
case WEEK_OF_YEAR:
|
||||
calendar.set(Calendar.WEEK_OF_YEAR, (int)value);
|
||||
xValueFormat.applyLocalizedPattern("'W'w");
|
||||
break;
|
||||
case MONTH_OF_YEAR:
|
||||
calendar.set(Calendar.MONTH, (int)value);
|
||||
xValueFormat.applyLocalizedPattern("MMM");
|
||||
break;
|
||||
case DAY_OF_YEAR:
|
||||
calendar.set(Calendar.DAY_OF_YEAR, (int)value);
|
||||
xValueFormat.applyLocalizedPattern("D");
|
||||
break;
|
||||
case DAY_OF_ALL:
|
||||
calendar.setTime(convertShortInDate((int)value));
|
||||
return DateFormat.getDateInstance(DateFormat.SHORT).format(calendar.getTime());
|
||||
case WEEK_OF_ALL:
|
||||
calendar.setTime(convertShortInDate((int)value));
|
||||
xValueFormat.applyLocalizedPattern("'W'w yyyy");
|
||||
return xValueFormat.format(calendar.getTime());
|
||||
case MONTH_OF_ALL:
|
||||
calendar.setTime(convertShortInDate((int)value));
|
||||
xValueFormat.applyLocalizedPattern("MMM yyyy");
|
||||
return xValueFormat.format(calendar.getTime());
|
||||
case YEAR_OF_ALL:
|
||||
calendar.setTime(convertShortInDate((int)value));
|
||||
xValueFormat.applyLocalizedPattern("yyyy");
|
||||
return xValueFormat.format(calendar.getTime());
|
||||
default:
|
||||
throw new IllegalArgumentException("view mode not implemented");
|
||||
}
|
||||
|
||||
return xValueFormat.format(calendar.getTime());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private ScaleMeasurement[] averageScaleMeasurementList(List<ScaleMeasurement> measurementList) {
|
||||
final ScaleMeasurement[] avgMeasurementList = new ScaleMeasurement[ maxXValue + minXValue + 1];
|
||||
|
||||
for (ScaleMeasurement measurement : measurementList) {
|
||||
int binNr = getBinNr(measurement);
|
||||
|
||||
if (avgMeasurementList[binNr] == null) {
|
||||
avgMeasurementList[binNr] = measurement.clone();
|
||||
} else {
|
||||
avgMeasurementList[binNr].add(measurement);
|
||||
}
|
||||
}
|
||||
|
||||
for (ScaleMeasurement avgMeasurement : avgMeasurementList) {
|
||||
if (avgMeasurement == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int binNr = getBinNr(avgMeasurement);
|
||||
avgMeasurement.divide(avgMeasurementList[binNr].count());
|
||||
}
|
||||
|
||||
return avgMeasurementList;
|
||||
}
|
||||
|
||||
private ScaleMeasurement getPreviousMeasurment(ScaleMeasurement[] masurementList, int binNr) {
|
||||
for (int i=binNr-1; i >= 0; i--) {
|
||||
if (masurementList[i] != null) {
|
||||
return masurementList[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private int getBinNr(ScaleMeasurement measurement) {
|
||||
Calendar measurementCalendar = Calendar.getInstance();
|
||||
measurementCalendar.setTime(measurement.getDateTime());
|
||||
|
||||
switch (viewMode) {
|
||||
case DAY_OF_MONTH:
|
||||
return measurementCalendar.get(Calendar.DAY_OF_MONTH);
|
||||
case WEEK_OF_MONTH:
|
||||
return measurementCalendar.get(Calendar.WEEK_OF_MONTH);
|
||||
case WEEK_OF_YEAR:
|
||||
return measurementCalendar.get(Calendar.WEEK_OF_YEAR);
|
||||
case MONTH_OF_YEAR:
|
||||
return measurementCalendar.get(Calendar.MONTH);
|
||||
case DAY_OF_YEAR:
|
||||
return measurementCalendar.get(Calendar.DAY_OF_YEAR);
|
||||
case DAY_OF_ALL:
|
||||
case WEEK_OF_ALL:
|
||||
case MONTH_OF_ALL:
|
||||
case YEAR_OF_ALL:
|
||||
return convertDateInShort(measurement.getDateTime());
|
||||
default:
|
||||
throw new IllegalArgumentException("view mode not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
private void refresh() {
|
||||
public void updateMeasurementList(final List<ScaleMeasurement> scaleMeasurementList) {
|
||||
clear();
|
||||
|
||||
if (scaleMeasurementList.isEmpty()) {
|
||||
progressBar.setVisibility(GONE);
|
||||
return;
|
||||
}
|
||||
|
||||
List<ILineDataSet> lineDataSets = new ArrayList<>();
|
||||
Collections.reverse(scaleMeasurementList);
|
||||
|
||||
ScaleMeasurement[] avgMeasurementList = averageScaleMeasurementList(scaleMeasurementList);
|
||||
this.scaleMeasurementList = scaleMeasurementList;
|
||||
refreshMeasurementList();
|
||||
}
|
||||
|
||||
public void refreshMeasurementList() {
|
||||
if (scaleMeasurementList == null) {
|
||||
progressBar.setVisibility(GONE);
|
||||
return;
|
||||
}
|
||||
|
||||
progressBar.setVisibility(VISIBLE);
|
||||
|
||||
List<ILineDataSet> lineDataSets;
|
||||
lineDataSets = new ArrayList<>();
|
||||
|
||||
for (MeasurementView view : measurementViews) {
|
||||
if (view instanceof FloatMeasurementView) {
|
||||
if (view instanceof FloatMeasurementView && view.isVisible()) {
|
||||
final FloatMeasurementView measurementView = (FloatMeasurementView) view;
|
||||
|
||||
final List<Entry> lineEntries = new ArrayList<>();
|
||||
|
||||
for (ScaleMeasurement avgMeasurement : avgMeasurementList) {
|
||||
if (avgMeasurement == null) {
|
||||
continue;
|
||||
}
|
||||
for (int i=0; i<scaleMeasurementList.size(); i++) {
|
||||
ScaleMeasurement measurement = scaleMeasurementList.get(i);
|
||||
float value = measurementView.getMeasurementValue(measurement);
|
||||
|
||||
int binNr = getBinNr(avgMeasurement);
|
||||
|
||||
ScaleMeasurement prevMeasuremnt = getPreviousMeasurment(avgMeasurementList, binNr);
|
||||
measurementView.loadFrom(avgMeasurement, prevMeasuremnt);
|
||||
|
||||
if (measurementView.getValue() == 0.0f) {
|
||||
if (value == 0.0f) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Entry entry = new Entry();
|
||||
entry.setX(binNr);
|
||||
entry.setY(measurementView.getValue());
|
||||
entry.setX(convertDateToInt(measurement.getDateTime()));
|
||||
entry.setY(value);
|
||||
Object[] extraData = new Object[3];
|
||||
extraData[0] = avgMeasurement;
|
||||
extraData[1] = prevMeasuremnt;
|
||||
extraData[0] = measurement;
|
||||
extraData[1] = (i == 0) ? null : scaleMeasurementList.get(i-1);
|
||||
extraData[2] = measurementView;
|
||||
entry.setData(extraData);
|
||||
|
||||
@@ -623,22 +388,18 @@ public class ChartMeasurementView extends LineChart {
|
||||
}
|
||||
}
|
||||
|
||||
addGoalLine(lineDataSets);
|
||||
|
||||
if (isInGraphKey) {
|
||||
addRegressionLine(lineDataSets);
|
||||
if (prefs.getBoolean("trendLine", true)) {
|
||||
addTrendLine(lineDataSets);
|
||||
}
|
||||
|
||||
LineData data = new LineData(lineDataSets);
|
||||
setData(data);
|
||||
|
||||
getXAxis().setAxisMinimum(minXValue);
|
||||
getXAxis().setAxisMaximum(maxXValue);
|
||||
if (isAnimationOn) {
|
||||
animateY(700);
|
||||
if (prefs.getBoolean("goalLine", false)) {
|
||||
addGoalLine(lineDataSets);
|
||||
}
|
||||
notifyDataSetChanged();
|
||||
invalidate();
|
||||
|
||||
progressBar.setVisibility(GONE);
|
||||
}
|
||||
|
||||
private void addMeasurementLine(List<ILineDataSet> lineDataSets, List<Entry> lineEntries, FloatMeasurementView measurementView) {
|
||||
@@ -648,6 +409,7 @@ public class ChartMeasurementView extends LineChart {
|
||||
measurementLine.setColor(measurementView.getColor());
|
||||
measurementLine.setValueTextColor(ColorUtil.getTintColor(getContext()));
|
||||
measurementLine.setCircleColor(measurementView.getColor());
|
||||
measurementLine.setCircleHoleColor(measurementView.getColor());
|
||||
measurementLine.setAxisDependency(measurementView.getSettings().isOnRightAxis() ? YAxis.AxisDependency.RIGHT : YAxis.AxisDependency.LEFT);
|
||||
measurementLine.setHighlightEnabled(true);
|
||||
measurementLine.setDrawHighlightIndicators(true);
|
||||
@@ -655,26 +417,12 @@ public class ChartMeasurementView extends LineChart {
|
||||
measurementLine.setDrawHorizontalHighlightIndicator(false);
|
||||
measurementLine.setHighLightColor(Color.RED);
|
||||
measurementLine.setDrawCircles(prefs.getBoolean("pointsEnable", true));
|
||||
measurementLine.setDrawValues(prefs.getBoolean("labelsEnable", true));
|
||||
measurementLine.setValueFormatter(new ValueFormatter() {
|
||||
@Override
|
||||
public String getPointLabel(Entry entry) {
|
||||
String prefix = new String();
|
||||
|
||||
Object[] extraData = (Object[])entry.getData();
|
||||
ScaleMeasurement measurement = (ScaleMeasurement)extraData[0];
|
||||
ScaleMeasurement prevMeasurement = (ScaleMeasurement)extraData[1];
|
||||
FloatMeasurementView measurementView = (FloatMeasurementView)extraData[2];
|
||||
|
||||
measurementView.loadFrom(measurement, prevMeasurement);
|
||||
|
||||
if (measurement.isAverageValue()) {
|
||||
prefix = "Ø ";
|
||||
}
|
||||
|
||||
return prefix + measurementView.getValueAsString(true);
|
||||
}
|
||||
});
|
||||
measurementLine.setDrawValues(prefs.getBoolean("labelsEnable", false));
|
||||
measurementLine.setMode(LineDataSet.Mode.HORIZONTAL_BEZIER);
|
||||
if (prefs.getBoolean("trendLine", true)) {
|
||||
// show only data point if trend line is enabled
|
||||
measurementLine.enableDashedLine(0, 1, 0);
|
||||
}
|
||||
|
||||
if (measurementView.isVisible()) {
|
||||
if (isInGraphKey) {
|
||||
@@ -690,73 +438,164 @@ public class ChartMeasurementView extends LineChart {
|
||||
}
|
||||
|
||||
private void addGoalLine(List<ILineDataSet> lineDataSets) {
|
||||
if (prefs.getBoolean("goalLine", true)) {
|
||||
List<Entry> valuesGoalLine = new Stack<>();
|
||||
List<Entry> valuesGoalLine = new Stack<>();
|
||||
|
||||
ScaleUser user = OpenScale.getInstance().getSelectedScaleUser();
|
||||
float goalWeight = Converters.fromKilogram(user.getGoalWeight(), user.getScaleUnit());
|
||||
ScaleUser user = OpenScale.getInstance().getSelectedScaleUser();
|
||||
float goalWeight = Converters.fromKilogram(user.getGoalWeight(), user.getScaleUnit());
|
||||
|
||||
valuesGoalLine.add(new Entry(minXValue, goalWeight));
|
||||
valuesGoalLine.add(new Entry(maxXValue, goalWeight));
|
||||
valuesGoalLine.add(new Entry(getXChartMin(), goalWeight));
|
||||
valuesGoalLine.add(new Entry(getXChartMax(), goalWeight));
|
||||
|
||||
LineDataSet goalLine = new LineDataSet(valuesGoalLine, getContext().getString(R.string.label_goal_line));
|
||||
goalLine.setLineWidth(1.5f);
|
||||
goalLine.setColor(ColorUtil.COLOR_GREEN);
|
||||
goalLine.setAxisDependency(prefs.getBoolean("weightOnRightAxis", true) ? YAxis.AxisDependency.RIGHT : YAxis.AxisDependency.LEFT);
|
||||
goalLine.setDrawValues(false);
|
||||
goalLine.setDrawCircles(false);
|
||||
goalLine.setHighlightEnabled(false);
|
||||
goalLine.enableDashedLine(10, 30, 0);
|
||||
LineDataSet goalLine = new LineDataSet(valuesGoalLine, getContext().getString(R.string.label_goal_line));
|
||||
goalLine.setLineWidth(1.5f);
|
||||
goalLine.setColor(ColorUtil.COLOR_GREEN);
|
||||
goalLine.setAxisDependency(prefs.getBoolean("weightOnRightAxis", true) ? YAxis.AxisDependency.RIGHT : YAxis.AxisDependency.LEFT);
|
||||
goalLine.setDrawValues(false);
|
||||
goalLine.setDrawCircles(false);
|
||||
goalLine.setHighlightEnabled(false);
|
||||
goalLine.enableDashedLine(10, 30, 0);
|
||||
|
||||
lineDataSets.add(goalLine);
|
||||
lineDataSets.add(goalLine);
|
||||
}
|
||||
|
||||
private List<ScaleMeasurement> getScaleMeasurementsAsTrendline(List<ScaleMeasurement> measurementList) {
|
||||
List<ScaleMeasurement> trendlineList = new ArrayList<>();
|
||||
|
||||
// exponentially smoothed moving average with 10% smoothing
|
||||
trendlineList.add(measurementList.get(0));
|
||||
|
||||
for (int i = 1; i < measurementList.size(); i++) {
|
||||
ScaleMeasurement entry = measurementList.get(i).clone();
|
||||
ScaleMeasurement trendPreviousEntry = trendlineList.get(i - 1);
|
||||
|
||||
entry.subtract(trendPreviousEntry);
|
||||
entry.multiply(0.1f);
|
||||
entry.add(trendPreviousEntry);
|
||||
|
||||
trendlineList.add(entry);
|
||||
}
|
||||
|
||||
return trendlineList;
|
||||
}
|
||||
|
||||
private void addTrendLine(List<ILineDataSet> lineDataSets) {
|
||||
|
||||
List<ScaleMeasurement> scaleMeasurementsAsTrendlineList = getScaleMeasurementsAsTrendline(scaleMeasurementList);
|
||||
|
||||
for (MeasurementView view : measurementViews) {
|
||||
if (view instanceof FloatMeasurementView && view.isVisible()) {
|
||||
final FloatMeasurementView measurementView = (FloatMeasurementView) view;
|
||||
|
||||
final List<Entry> lineEntries = new ArrayList<>();
|
||||
|
||||
for (int i=0; i<scaleMeasurementsAsTrendlineList.size(); i++) {
|
||||
ScaleMeasurement measurement = scaleMeasurementsAsTrendlineList.get(i);
|
||||
float value = measurementView.getMeasurementValue(measurement);
|
||||
|
||||
if (value == 0.0f) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Entry entry = new Entry();
|
||||
entry.setX(convertDateToInt(measurement.getDateTime()));
|
||||
entry.setY(value);
|
||||
Object[] extraData = new Object[3];
|
||||
extraData[0] = measurement;
|
||||
extraData[1] = (i == 0) ? null : scaleMeasurementsAsTrendlineList.get(i-1);
|
||||
extraData[2] = measurementView;
|
||||
entry.setData(extraData);
|
||||
|
||||
lineEntries.add(entry);
|
||||
}
|
||||
|
||||
addMeasurementLineTrend(lineDataSets, lineEntries, measurementView);
|
||||
addPredictionLine(lineDataSets, lineEntries, measurementView);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addRegressionLine(List<ILineDataSet> lineDataSets) {
|
||||
if (prefs.getBoolean("regressionLine", false)) {
|
||||
int regressLineOrder = 1;
|
||||
private void addPredictionLine(List<ILineDataSet> lineDataSets, List<Entry> lineEntries, FloatMeasurementView measurementView) {
|
||||
if (lineEntries.size() < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
regressLineOrder = Integer.parseInt(prefs.getString("regressionLineOrder", "1"));
|
||||
} catch (NumberFormatException e) {
|
||||
Toast.makeText(getContext(), getContext().getString(R.string.error_value_required) + ":" + e.getMessage(), Toast.LENGTH_LONG).show();
|
||||
prefs.edit().putString("regressionLineOrder", "1").apply();
|
||||
PolynomialFitter polyFitter = new PolynomialFitter(3);
|
||||
|
||||
// use only the last 30 values for the polynomial fitter
|
||||
for (int i=1; i<30; i++) {
|
||||
int pos = lineEntries.size() - i;
|
||||
|
||||
if (pos >= 0) {
|
||||
Entry entry = lineEntries.get(pos);
|
||||
|
||||
polyFitter.addPoint((double) entry.getX(), (double) entry.getY());
|
||||
}
|
||||
}
|
||||
|
||||
List<ILineDataSet> regressionLineDataSets = new ArrayList<>();
|
||||
PolynomialFitter.Polynomial polynomial = polyFitter.getBestFit();
|
||||
|
||||
for (ILineDataSet dataSet : lineDataSets) {
|
||||
PolynomialFitter polyFitter = new PolynomialFitter(Math.min(regressLineOrder, 100));
|
||||
Entry lastEntry = lineEntries.get(lineEntries.size() - 1);
|
||||
int maxX = (int) lastEntry.getX()+1;
|
||||
List<Entry> predictionValues = new Stack<>();
|
||||
|
||||
for (int i=0; i<dataSet.getEntryCount(); i++) {
|
||||
Entry entry = dataSet.getEntryForIndex(i);
|
||||
polyFitter.addPoint((double) entry.getX(), (double) entry.getY());
|
||||
predictionValues.add(lastEntry);
|
||||
|
||||
// predict 30 days into the future
|
||||
for (int i = maxX; i < maxX + 30; i++) {
|
||||
double yPredictionValue = polynomial.getY(i);
|
||||
predictionValues.add(new Entry((float) i, (float) yPredictionValue));
|
||||
}
|
||||
|
||||
LineDataSet predictionLine = new LineDataSet(predictionValues, measurementView.getName().toString() + "-" + getContext().getString(R.string.label_prediction));
|
||||
predictionLine.setLineWidth(1.5f);
|
||||
predictionLine.setColor(measurementView.getColor());
|
||||
predictionLine.setAxisDependency(measurementView.getSettings().isOnRightAxis() ? YAxis.AxisDependency.RIGHT : YAxis.AxisDependency.LEFT);
|
||||
predictionLine.setDrawValues(false);
|
||||
predictionLine.setDrawCircles(false);
|
||||
predictionLine.setHighlightEnabled(false);
|
||||
predictionLine.enableDashedLine(10, 30, 0);
|
||||
|
||||
if (measurementView.isVisible()) {
|
||||
if (isInGraphKey) {
|
||||
if (measurementView.getSettings().isInGraph()) {
|
||||
lineDataSets.add(predictionLine);
|
||||
}
|
||||
|
||||
PolynomialFitter.Polynomial polynomial = polyFitter.getBestFit();
|
||||
|
||||
List<Entry> valuesLinearRegression = new Stack<>();
|
||||
|
||||
for (int i = minXValue; i < maxXValue + minXValue + 1; i++) {
|
||||
double y_value = polynomial.getY(i);
|
||||
valuesLinearRegression.add(new Entry((float) i, (float) y_value));
|
||||
} else {
|
||||
if (measurementView.getSettings().isInOverviewGraph()) {
|
||||
lineDataSets.add(predictionLine);
|
||||
}
|
||||
|
||||
LineDataSet linearRegressionLine = new LineDataSet(valuesLinearRegression, dataSet.getLabel() + "-" + getContext().getString(R.string.label_regression_line));
|
||||
linearRegressionLine.setLineWidth(1.5f);
|
||||
linearRegressionLine.setColor(dataSet.getColor());
|
||||
linearRegressionLine.setAxisDependency(dataSet.getAxisDependency());
|
||||
linearRegressionLine.setDrawValues(false);
|
||||
linearRegressionLine.setDrawCircles(false);
|
||||
linearRegressionLine.setHighlightEnabled(false);
|
||||
linearRegressionLine.enableDashedLine(10, 30, 0);
|
||||
|
||||
regressionLineDataSets.add(linearRegressionLine);
|
||||
}
|
||||
|
||||
for (ILineDataSet dataSet : regressionLineDataSets) {
|
||||
lineDataSets.add(dataSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addMeasurementLineTrend(List<ILineDataSet> lineDataSets, List<Entry> lineEntries, FloatMeasurementView measurementView) {
|
||||
LineDataSet measurementLine = new LineDataSet(lineEntries, measurementView.getName().toString() + "-" + getContext().getString(R.string.label_trend_line));
|
||||
measurementLine.setLineWidth(1.5f);
|
||||
measurementLine.setValueTextSize(10.0f);
|
||||
measurementLine.setColor(measurementView.getColor());
|
||||
measurementLine.setValueTextColor(ColorUtil.getTintColor(getContext()));
|
||||
measurementLine.setCircleColor(measurementView.getColor());
|
||||
measurementLine.setCircleHoleColor(measurementView.getColor());
|
||||
measurementLine.setAxisDependency(measurementView.getSettings().isOnRightAxis() ? YAxis.AxisDependency.RIGHT : YAxis.AxisDependency.LEFT);
|
||||
measurementLine.setHighlightEnabled(true);
|
||||
measurementLine.setDrawHighlightIndicators(true);
|
||||
measurementLine.setHighlightLineWidth(1.5f);
|
||||
measurementLine.setDrawHorizontalHighlightIndicator(false);
|
||||
measurementLine.setHighLightColor(Color.RED);
|
||||
measurementLine.setDrawCircles(false);//prefs.getBoolean("pointsEnable", true));
|
||||
measurementLine.setDrawValues(prefs.getBoolean("labelsEnable", false));
|
||||
|
||||
if (measurementView.isVisible()) {
|
||||
if (isInGraphKey) {
|
||||
if (measurementView.getSettings().isInGraph()) {
|
||||
lineDataSets.add(measurementLine);
|
||||
}
|
||||
} else {
|
||||
if (measurementView.getSettings().isInOverviewGraph()) {
|
||||
lineDataSets.add(measurementLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -92,7 +92,6 @@ public class OverviewFragment extends Fragment {
|
||||
chartView = overviewView.findViewById(R.id.chartView);
|
||||
chartView.setOnChartValueSelectedListener(new onChartSelectedListener());
|
||||
chartView.setProgressBar(overviewView.findViewById(R.id.progressBar));
|
||||
chartView.setAnimationOn(false);
|
||||
chartView.setIsInGraphKey(false);
|
||||
|
||||
chartActionBarView = overviewView.findViewById(R.id.chartActionBar);
|
||||
@@ -100,6 +99,7 @@ public class OverviewFragment extends Fragment {
|
||||
chartActionBarView.setOnActionClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
chartView.refreshMeasurementList();
|
||||
updateChartView();
|
||||
}
|
||||
});
|
||||
@@ -130,18 +130,6 @@ public class OverviewFragment extends Fragment {
|
||||
prefs.edit().putBoolean("enableOverviewChartActionBar", true).apply();
|
||||
chartActionBarView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
return true;
|
||||
case R.id.enableRollingChart:
|
||||
if (item.isChecked()) {
|
||||
item.setChecked(false);
|
||||
prefs.edit().putBoolean("enableRollingChart", false).apply();
|
||||
} else {
|
||||
item.setChecked(true);
|
||||
prefs.edit().putBoolean("enableRollingChart", true).apply();
|
||||
}
|
||||
|
||||
getActivity().recreate(); // TODO HACK to refresh graph; graph.invalidate and notfiydatachange is not enough!?
|
||||
|
||||
return true;
|
||||
case R.id.menu_range_day:
|
||||
prefs.edit().putInt("selectRangeMode", ChartMeasurementView.ViewMode.DAY_OF_ALL.ordinal()).commit();
|
||||
@@ -156,14 +144,9 @@ public class OverviewFragment extends Fragment {
|
||||
prefs.edit().putInt("selectRangeMode", ChartMeasurementView.ViewMode.YEAR_OF_ALL.ordinal()).commit();
|
||||
}
|
||||
|
||||
|
||||
item.setChecked(true);
|
||||
|
||||
if (prefs.getBoolean("enableRollingChart", true)) {
|
||||
getActivity().recreate(); // TODO HACK to refresh graph; if rolling chart is enabled then graph.invalidate and notfiydatachange is not enough!?
|
||||
} else {
|
||||
updateChartView();
|
||||
}
|
||||
getActivity().recreate(); // TODO HACK to refresh graph; graph.invalidate and notfiydatachange is not enough!?
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -186,8 +169,6 @@ public class OverviewFragment extends Fragment {
|
||||
break;
|
||||
}
|
||||
|
||||
rangePopupMenu.getMenu().findItem(R.id.enableRollingChart).setChecked(prefs.getBoolean("enableRollingChart", true));
|
||||
|
||||
MenuItem enableMeasurementBar = rangePopupMenu.getMenu().findItem(R.id.enableChartActionBar);
|
||||
enableMeasurementBar.setChecked(prefs.getBoolean("enableOverviewChartActionBar", false));
|
||||
|
||||
@@ -280,14 +261,13 @@ public class OverviewFragment extends Fragment {
|
||||
|
||||
updateUserSelection();
|
||||
updateMesurementViews(markedMeasurement);
|
||||
chartView.updateMeasurementList(scaleMeasurementList);
|
||||
updateChartView();
|
||||
}
|
||||
|
||||
private void updateChartView() {
|
||||
boolean enableRollingChart = prefs.getBoolean("enableRollingChart", true);
|
||||
|
||||
ChartMeasurementView.ViewMode selectedRangeMode = ChartMeasurementView.ViewMode.values()[prefs.getInt("selectRangeMode", ChartMeasurementView.ViewMode.DAY_OF_ALL.ordinal())];
|
||||
chartView.setViewRange(selectedRangeMode, enableRollingChart);
|
||||
chartView.setViewRange(selectedRangeMode);
|
||||
}
|
||||
|
||||
private void updateMesurementViews(ScaleMeasurement selectedMeasurement) {
|
||||
|
@@ -24,28 +24,11 @@ import androidx.preference.PreferenceFragmentCompat;
|
||||
import com.health.openscale.R;
|
||||
|
||||
public class GraphPreferences extends PreferenceFragmentCompat {
|
||||
|
||||
private static final String PREFERENCE_KEY_REGRESSION_LINE_ORDER = "regressionLineOrder";
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||
setPreferencesFromResource(R.xml.graph_preferences, rootKey);
|
||||
|
||||
setHasOptionsMenu(true);
|
||||
|
||||
// TODO replaced it with sliding average
|
||||
/*EditTextPreference regressionLineOrder =
|
||||
(EditTextPreference) findPreference(PREFERENCE_KEY_REGRESSION_LINE_ORDER);
|
||||
regressionLineOrder.getEditText().setKeyListener(new DigitsKeyListener());
|
||||
regressionLineOrder.getEditText().setSelectAllOnFocus(true);
|
||||
regressionLineOrder.setSummary(regressionLineOrder.getText());
|
||||
regressionLineOrder.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
preference.setSummary((String) newValue);
|
||||
return true;
|
||||
}
|
||||
});*/
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -8,12 +8,6 @@
|
||||
android:checkable="true"
|
||||
android:checked="false"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/enableRollingChart"
|
||||
android:title="@string/label_rolling_chart"
|
||||
android:checkable="true"
|
||||
android:checked="true"/>
|
||||
|
||||
<group android:id="@+id/rangeGroup"
|
||||
android:checkableBehavior="single">
|
||||
<item android:id="@+id/menu_range_day"
|
||||
|
@@ -136,8 +136,6 @@
|
||||
<string name="label_not_found">غير موجود</string>
|
||||
<string name="label_ignoreOutOfRange">تجاهل خارج نطاق البيانات</string>
|
||||
<string name="label_initial_weight">الوزن البدائي</string>
|
||||
<string name="label_regression_line">خط الوزن الانحداري</string>
|
||||
<string name="label_regression_line_degree">خط انحداري متعدد الحدود</string>
|
||||
<string name="label_goal_line">خط الهدف</string>
|
||||
<string name="label_help">مساعدة</string>
|
||||
<string name="label_feedback_message_enjoying">استمتعت ب openScale؟</string>
|
||||
|
@@ -106,7 +106,6 @@
|
||||
<string name="permission_bluetooth_info">ব্লুটুথ ডিভাইসগুলি অনুসন্ধান করার জন্য অবস্থানের অনুমতি প্রয়োজন। ডিভাইসটি খুঁজে পাওয়ার পরে এটি প্রত্যাহার করা যায়।</string>
|
||||
<string name="permission_not_granted">অনুমতি দেয়া হয়নি</string>
|
||||
<string name="label_measurement_bar">পরিমাপ বার</string>
|
||||
<string name="label_rolling_chart">ঘূর্ণায়মান তালিকা</string>
|
||||
<string name="label_year_view">বছরের চিত্র</string>
|
||||
<string name="label_weeks_view">সপ্তাহের চিত্র</string>
|
||||
<string name="label_month_view">মাসের চিত্র</string>
|
||||
|
@@ -119,8 +119,6 @@
|
||||
<string name="label_not_found">no s\'ha trobat</string>
|
||||
<string name="label_ignoreOutOfRange">Ignora les dades fora del rang</string>
|
||||
<string name="label_initial_weight">Pes inicial</string>
|
||||
<string name="label_regression_line">Línia de regressió</string>
|
||||
<string name="label_regression_line_degree">Grau del polinomi de regressió</string>
|
||||
<string name="label_goal_line">Línia de l\'objectiu</string>
|
||||
<string name="error_max_scale_users">S\'ha assolit el nombre màxim d\'usuaris simultanis de la bàscula</string>
|
||||
<string name="info_step_on_scale_for_reference">Pugeu a la bàscula amb els peus nus per a obtenir les mesures de referència</string>
|
||||
@@ -180,7 +178,6 @@
|
||||
\nCreeu una nova incidència incloent-hi els detalls de l\'error a
|
||||
\nhttps://github.com/oliexdev/openScale/issues</string>
|
||||
<string name="toggle_expand">Expandeix o contrau</string>
|
||||
<string name="label_rolling_chart">Gràfica dinàmica</string>
|
||||
<string name="permission_read_write_data_description">llegir/escriure dades de l\'openScale, incloent-hi informació dels usuaris i totes les mesures desades</string>
|
||||
<string name="permission_read_write_data_label">Llegir/escriure dades de l\'openScale</string>
|
||||
<string name="label_next">Endavant</string>
|
||||
|
@@ -189,8 +189,6 @@
|
||||
<string name="label_enable_legend">Legenda grafu</string>
|
||||
<string name="label_enable_yaxis">Osa Y</string>
|
||||
<string name="label_enable_labels">Popisek dat</string>
|
||||
<string name="label_regression_line">Regresivní křivka</string>
|
||||
<string name="label_regression_line_degree">Stupeň polynomické regrese</string>
|
||||
<string name="label_goal_line">Cílová čára</string>
|
||||
<string name="info_step_on_scale_for_reference">Stoupněte na váhu naboso pro referenční měření</string>
|
||||
<string name="info_step_on_scale">Stoupněte na váhu naboso</string>
|
||||
|
@@ -119,8 +119,6 @@
|
||||
<string name="label_not_found">blev ikke fundet</string>
|
||||
<string name="label_ignoreOutOfRange">Ignorér data udenfor interval</string>
|
||||
<string name="label_initial_weight">Startvægt</string>
|
||||
<string name="label_regression_line">Vægt tilbagegang</string>
|
||||
<string name="label_regression_line_degree">Grad af tilbagegang</string>
|
||||
<string name="label_goal_line">Mållinje</string>
|
||||
<string name="error_max_scale_users">Det maksimale antal brugere er nået</string>
|
||||
<string name="info_step_on_scale_for_reference">Træd op på vægten med bare fødder for at foretagen en referencemåling</string>
|
||||
|
@@ -110,8 +110,6 @@
|
||||
<string name="error_initial_weight_required">Anfangsgewicht ist erforderlich</string>
|
||||
<string name="label_bt_device_no_support">Gerät wird nicht unterstützt</string>
|
||||
<string name="label_goal_line">Ziellinie</string>
|
||||
<string name="label_regression_line">Regressionsgerade</string>
|
||||
<string name="label_regression_line_degree">Polynomischer Regressions-Grad</string>
|
||||
<string name="label_bluetooth_searching">Suche nach Ihrer Bluetooth Waagen</string>
|
||||
<string name="label_bone">Knochenmasse</string>
|
||||
<string name="label_bmr">Grundumsatz (BMR)</string>
|
||||
@@ -230,7 +228,6 @@
|
||||
<string name="label_enable_yaxis">Y-Achse</string>
|
||||
<string name="label_day_view">Tagesansicht</string>
|
||||
<string name="label_year_view">Jahresansicht</string>
|
||||
<string name="label_rolling_chart">Rollendes Diagramm</string>
|
||||
<string name="label_measurement_bar">Messwertanzeige</string>
|
||||
<string name="permission_location_service_info">Gewährleisten Sie den Standortzugriff in den Android-Einstellungen, um nach Bluetooth-Geräten zu suchen. Sie können es anschließend wieder widerrufen.</string>
|
||||
<string name="label_is_on_right_axis">Auf der rechten Achse</string>
|
||||
|
@@ -129,8 +129,6 @@
|
||||
<string name="label_not_found">δεν βρέθηκε</string>
|
||||
<string name="label_ignoreOutOfRange">Αγνόησε δεδομένα εκτός εύρους</string>
|
||||
<string name="label_initial_weight">Αρχικό βάρος</string>
|
||||
<string name="label_regression_line">Γραμμή παλινδρόμησης</string>
|
||||
<string name="label_regression_line_degree">Πολυώνυμος βαθμός οπισθοδρόμησης</string>
|
||||
<string name="label_goal_line">Γραμμή στόχου</string>
|
||||
<string name="label_help">Βοήθεια</string>
|
||||
<string name="label_feedback_message_enjoying">Απολαμβάνετε το ανοιχτόςΖυγός;</string>
|
||||
@@ -230,7 +228,6 @@
|
||||
<string name="info_step_on_scale">Παρακαλώ πατήστε ξυπόλυτοι στην ζυγαριά</string>
|
||||
<string name="label_day_view">Προβολή ημέρας</string>
|
||||
<string name="label_year_view">Προβολή έτους</string>
|
||||
<string name="label_rolling_chart">Κυλιόμενο διάγραμμα</string>
|
||||
<string name="label_measurement_bar">Μπάρα μέτρησης</string>
|
||||
<string name="permission_location_service_info">Χορηγήστε πρόσβαση τοποθεσίας στις ρυθμίσεις του Android για να ψάχνει συσκευές Bluetooth. Προαιρετικά ανακαλέστε το μεταγενέστερα.</string>
|
||||
<string name="label_is_on_right_axis">Είναι στον δεξιό άξονα</string>
|
||||
|
@@ -119,8 +119,6 @@
|
||||
<string name="label_not_found">no encontrado</string>
|
||||
<string name="label_ignoreOutOfRange">Ignorar datos fuera de límites</string>
|
||||
<string name="label_initial_weight">Peso inicial</string>
|
||||
<string name="label_regression_line">Línea de regresión</string>
|
||||
<string name="label_regression_line_degree">Grado de polinomio de regresión</string>
|
||||
<string name="label_goal_line">Línea del objetivo</string>
|
||||
<string name="error_max_scale_users">Máximo número de usuarios concurrentes alcanzado</string>
|
||||
<string name="info_step_on_scale_for_reference">Párese con los pies descalzos en la báscula para tomar medidas de referencia</string>
|
||||
@@ -229,7 +227,6 @@
|
||||
<string name="info_step_on_scale">Súbase con los pies descalzos en la báscula</string>
|
||||
<string name="label_day_view">Vista diaria</string>
|
||||
<string name="label_year_view">Vista anual</string>
|
||||
<string name="label_rolling_chart">Gráfico dinámico</string>
|
||||
<string name="label_measurement_bar">Barra de medición</string>
|
||||
<string name="permission_location_service_info">Otorgue permiso para acceso a la ubicación, en la configuración de Android, para buscar dispositivos Bluetooth. Podrá revocarlo después.</string>
|
||||
<string name="label_is_on_right_axis">Está en el eje de la derecha</string>
|
||||
|
@@ -157,8 +157,6 @@
|
||||
<string name="label_export_dir">Dossier pour l\'exportation</string>
|
||||
<string name="label_not_found">Non trouvé</string>
|
||||
<string name="label_ignoreOutOfRange">Ignorer les valeurs hors de plage valide</string>
|
||||
<string name="label_regression_line">Ligne de régression</string>
|
||||
<string name="label_regression_line_degree">Degré du polynôme pour la ligne</string>
|
||||
<string name="label_goal_line">Ligne pour l\'objectif</string>
|
||||
<string name="label_feedback_message_enjoying">Êtes-vous satisfait d\'openScale ?</string>
|
||||
<string name="label_feedback_message_rate_app">Laisser une évaluation sur Google Play ou GitHub ?</string>
|
||||
@@ -230,7 +228,6 @@
|
||||
<string name="label_enable_yaxis">Ordonnée</string>
|
||||
<string name="label_day_view">Vue journalière</string>
|
||||
<string name="label_year_view">Vue annuelle</string>
|
||||
<string name="label_rolling_chart">Histogramme</string>
|
||||
<string name="label_measurement_bar">Barre des mesures</string>
|
||||
<string name="permission_location_service_info">Autoriser l\'accès à la location pour chercher des dispositifs Bluetooth. Cette permissions peut être révoqué par la suite.</string>
|
||||
<string name="label_is_on_right_axis">Est sur l\'axe de droite</string>
|
||||
|
@@ -126,8 +126,6 @@
|
||||
<string name="label_not_found">non atopado</string>
|
||||
<string name="label_ignoreOutOfRange">Ignorar datos fóra de rango</string>
|
||||
<string name="label_initial_weight">Peso inicial</string>
|
||||
<string name="label_regression_line">Liña de tendencia de peso</string>
|
||||
<string name="label_regression_line_degree">Grao do polinomio de regresión (tendencia)</string>
|
||||
<string name="label_goal_line">Liña do obxectivo</string>
|
||||
<string name="label_help">Axuda</string>
|
||||
<string name="label_feedback_message_enjoying">Gústache openScale?</string>
|
||||
@@ -254,7 +252,6 @@
|
||||
<string name="permission_read_write_data_description">leer/escribir os datos de openScale, incluindo a información de usuarios e todas as medidas gardadas</string>
|
||||
<string name="permission_location_service_info">Outorgue permiso para acceso á ubicuación, na configuración de Android, para buscar dispositivos Bluetooth. Poderá quitalo despois.</string>
|
||||
<string name="label_measurement_bar">Barra de medida</string>
|
||||
<string name="label_rolling_chart">Gráfico dinámico</string>
|
||||
<string name="label_year_view">Vista anual</string>
|
||||
<string name="label_day_view">Vista diaria</string>
|
||||
<string name="toggle_expand">Alternar o expandir</string>
|
||||
|
@@ -131,8 +131,6 @@
|
||||
<string name="label_not_found">nije pronađeno</string>
|
||||
<string name="label_ignoreOutOfRange">Zanemari podatke izvan granica</string>
|
||||
<string name="label_initial_weight">Početna težina</string>
|
||||
<string name="label_regression_line">Linija regresije</string>
|
||||
<string name="label_regression_line_degree">Polinom regresije</string>
|
||||
<string name="label_goal_line">Ciljana linija</string>
|
||||
<string name="label_help">Pomoć</string>
|
||||
<string name="label_feedback_message_enjoying">Sviđa ti se openScale\?</string>
|
||||
@@ -258,7 +256,6 @@
|
||||
<string name="permission_read_write_data_description">čitaj/zapiši openScale podatke, uključujući korisničke podatke i sva spremljena mjerenja</string>
|
||||
<string name="permission_location_service_info">Dozvoli pristup lokaciji u Androidovim postavkama za traženje Bluetooth uređaja. Opcionalno zabrani pristup nakon toga.</string>
|
||||
<string name="label_measurement_bar">Mjerna traka</string>
|
||||
<string name="label_rolling_chart">Dinamički dijagram</string>
|
||||
<string name="label_year_view">Godišnji prikaz</string>
|
||||
<string name="label_day_view">Dnevni prikaz</string>
|
||||
<string name="trisa_scale_pairing_succeeded">Uparivanje je uspjelo!
|
||||
|
@@ -125,8 +125,6 @@
|
||||
<string name="info_on_date">be</string>
|
||||
<string name="label_ignoreOutOfRange">Tartományon kívüli adat elhagyása</string>
|
||||
<string name="label_initial_weight">Kezdő súly</string>
|
||||
<string name="label_regression_line">Regressziós egyenes</string>
|
||||
<string name="label_regression_line_degree">Polinom regresszió foka</string>
|
||||
<string name="label_goal_line">Cél vonal</string>
|
||||
<string name="label_help">Segítség</string>
|
||||
<string name="label_feedback_message_enjoying">Élvezi az openScale-t\?</string>
|
||||
@@ -231,7 +229,6 @@
|
||||
<string name="label_enable_yaxis">Y tengely</string>
|
||||
<string name="label_day_view">Napi nézet</string>
|
||||
<string name="label_year_view">Éves nézet</string>
|
||||
<string name="label_rolling_chart">Mozgó diagram</string>
|
||||
<string name="label_measurement_bar">Mérési sáv</string>
|
||||
<string name="label_is_on_right_axis">a jobb oldali tengelyen</string>
|
||||
<string name="label_upgrade_to_openScale_pro">Kérem frissítsen az openScale Pro-ra a Bluetooth támogatáshoz</string>
|
||||
|
@@ -129,8 +129,6 @@
|
||||
<string name="label_not_found">non trovato</string>
|
||||
<string name="label_ignoreOutOfRange">Ignorare i dati fuori intervallo</string>
|
||||
<string name="label_initial_weight">Peso iniziale</string>
|
||||
<string name="label_regression_line">Retta di regressione</string>
|
||||
<string name="label_regression_line_degree">Grado di regressione polinomiale</string>
|
||||
<string name="label_goal_line">Linea obiettivo</string>
|
||||
<string name="label_help">Aiuto</string>
|
||||
<string name="label_feedback_message_enjoying">Ti piace openScale?</string>
|
||||
@@ -209,7 +207,6 @@
|
||||
<string name="trisa_scale_not_paired">Questa bilancia non è stata associata!
|
||||
\n
|
||||
\nTieni premuto il bottone che si trova sollo la bilancia per metterlà in modalità associazione e poi riconnetiti per ottenere la password del dispositivo.</string>
|
||||
<string name="label_rolling_chart">Grafico a linee</string>
|
||||
<string name="info_step_on_scale">Posizionati sulla bilancia a piedi scalzi</string>
|
||||
<string name="info_bluetooth_no_device_retrying">Impossibile stabilire una connessione, nuovo tentativo in corso…</string>
|
||||
<string name="info_bluetooth_connection_disconnected">Connessione Bluetooth chiusa</string>
|
||||
|
@@ -131,8 +131,6 @@
|
||||
<string name="label_not_found">לא נמצא</string>
|
||||
<string name="label_ignoreOutOfRange">התעלמות מנתונים מחוץ לטווח</string>
|
||||
<string name="label_initial_weight">משקל ראשוני</string>
|
||||
<string name="label_regression_line">קו נסיגתי</string>
|
||||
<string name="label_regression_line_degree">רמה פולינומית של נסיגה</string>
|
||||
<string name="label_goal_line">קו יעד</string>
|
||||
<string name="label_help">עזרה</string>
|
||||
<string name="label_feedback_message_enjoying">השימוש ב־openScale מטיב עמך\?</string>
|
||||
@@ -233,7 +231,6 @@
|
||||
<string name="label_enable_yaxis">ציר Y</string>
|
||||
<string name="label_day_view">תצוגה יומית</string>
|
||||
<string name="label_year_view">תצוגה שנתית</string>
|
||||
<string name="label_rolling_chart">תרשים מתגלגל</string>
|
||||
<string name="label_measurement_bar">סרגל מדידה</string>
|
||||
<string name="label_is_on_right_axis">בציר הימני</string>
|
||||
<string name="label_upgrade_to_openScale_pro">נא לשדרג לגרסה המקצועית של openScale לתמיכה ב־Bluetooth</string>
|
||||
|
@@ -168,8 +168,6 @@
|
||||
<string name="label_category_measurement_database">測定データベース</string>
|
||||
<string name="label_export_dir">エクスポートディレクトリー</string>
|
||||
<string name="label_not_found">見つかりません</string>
|
||||
<string name="label_regression_line">回帰線</string>
|
||||
<string name="label_regression_line_degree">回帰多項式次数</string>
|
||||
<string name="label_goal_line">目標線</string>
|
||||
<string name="error_max_scale_users">最大同時測定のユーザー数に達しました</string>
|
||||
<string name="info_step_on_scale">裸足で体重計に載ってください</string>
|
||||
@@ -231,7 +229,6 @@
|
||||
<string name="label_enable_yaxis">Y 軸</string>
|
||||
<string name="label_day_view">日表示</string>
|
||||
<string name="label_year_view">年表示</string>
|
||||
<string name="label_rolling_chart">ローリングチャート</string>
|
||||
<string name="label_measurement_bar">測定バー</string>
|
||||
<string name="label_is_on_right_axis">右軸上に</string>
|
||||
<string name="label_upgrade_to_openScale_pro">Bluetoothサポートは、openScale proにアップグレードしてください</string>
|
||||
|
@@ -128,8 +128,6 @@
|
||||
<string name="label_not_found">발견되지 않음</string>
|
||||
<string name="label_ignoreOutOfRange">범위를 벗어난 데이터 무시</string>
|
||||
<string name="label_initial_weight">초기 무게</string>
|
||||
<string name="label_regression_line">회귀 무게 선</string>
|
||||
<string name="label_regression_line_degree">회귀 다항식 차수</string>
|
||||
<string name="label_goal_line">목표선</string>
|
||||
<string name="label_help">도움말</string>
|
||||
<string name="label_feedback_message_enjoying">openScale을 잘 사용하고 계신가요\?</string>
|
||||
|
@@ -130,8 +130,6 @@
|
||||
<string name="label_not_found">ikke funnet</string>
|
||||
<string name="label_ignoreOutOfRange">Ignorer data utenfor rekkevidde</string>
|
||||
<string name="label_initial_weight">Startvekt</string>
|
||||
<string name="label_regression_line">Regresjonslinje</string>
|
||||
<string name="label_regression_line_degree">Regresjonspolynom-grunntall</string>
|
||||
<string name="label_goal_line">Mållinje</string>
|
||||
<string name="label_help">Hjelp</string>
|
||||
<string name="label_feedback_message_enjoying">Setter du pris på openScale?</string>
|
||||
@@ -231,7 +229,6 @@
|
||||
<string name="label_enable_yaxis">Y-akse</string>
|
||||
<string name="label_day_view">Dagsvisning</string>
|
||||
<string name="label_year_view">Årsvisning</string>
|
||||
<string name="label_rolling_chart">Rullende diagram</string>
|
||||
<string name="label_measurement_bar">Målestav</string>
|
||||
<string name="label_is_on_right_axis">Er på høyre akse</string>
|
||||
<string name="label_upgrade_to_openScale_pro">Oppgrader til openScare pro for Blåtannsstøtte</string>
|
||||
|
@@ -130,8 +130,6 @@
|
||||
<string name="label_not_found">niet gevonden</string>
|
||||
<string name="label_ignoreOutOfRange">Gegevens buiten bereik negeren</string>
|
||||
<string name="label_initial_weight">Startgewicht</string>
|
||||
<string name="label_regression_line">Regressiegewichtslijn</string>
|
||||
<string name="label_regression_line_degree">Regressiepolynoomgraad</string>
|
||||
<string name="label_goal_line">Doellijn</string>
|
||||
<string name="label_help">Hulp</string>
|
||||
<string name="label_feedback_message_enjoying">Gebruik je openScale graag\?</string>
|
||||
@@ -230,7 +228,6 @@
|
||||
<string name="label_enable_yaxis">Y-as</string>
|
||||
<string name="label_day_view">Dagweergave</string>
|
||||
<string name="label_year_view">Jaarweergave</string>
|
||||
<string name="label_rolling_chart">Voortschrijdende grafiek</string>
|
||||
<string name="label_measurement_bar">Meetlat</string>
|
||||
<string name="permission_location_service_info">Verleen toegang tot je locatie in de Android-instellingen om te zoeken naar Bluetooth-apparaten. Dit kun je achteraf evt. weer intrekken.</string>
|
||||
<string name="label_is_on_right_axis">Staat op de rechteras</string>
|
||||
|
@@ -130,8 +130,6 @@
|
||||
<string name="label_not_found">nie znaleziono</string>
|
||||
<string name="label_ignoreOutOfRange">Ignoruj dane spoza zakresu</string>
|
||||
<string name="label_initial_weight">Waga początkowa</string>
|
||||
<string name="label_regression_line">Krzywa aproksymacji</string>
|
||||
<string name="label_regression_line_degree">Stopień wielomianu aproksymacji</string>
|
||||
<string name="label_goal_line">Linia celu</string>
|
||||
<string name="label_help">Pomoc</string>
|
||||
<string name="label_feedback_message_enjoying">Podoba Ci się openScale?</string>
|
||||
@@ -218,7 +216,6 @@
|
||||
\nPołącz ponownie aby pobrać pomiary.</string>
|
||||
<string name="label_day_view">Widok dnia</string>
|
||||
<string name="label_year_view">Widok roku</string>
|
||||
<string name="label_rolling_chart">Wykres przewijany</string>
|
||||
<string name="label_calories">Kalorie</string>
|
||||
<string name="label_measure_unit">Jednostka pomiaru</string>
|
||||
<string name="label_activity_level">Poziom aktywności</string>
|
||||
|
@@ -83,8 +83,6 @@
|
||||
<string name="label_no">Não</string>
|
||||
<string name="label_ok">OK</string>
|
||||
<string name="label_not_found">não encontrado</string>
|
||||
<string name="label_regression_line">Linha de tendência de peso</string>
|
||||
<string name="label_regression_line_degree">Grau de regressão polinomial (tendência)</string>
|
||||
<string name="label_reminder">Lembrete</string>
|
||||
<string name="label_reminder_notify_text">Título da notificação</string>
|
||||
<string name="label_reminder_time">Hora</string>
|
||||
@@ -190,6 +188,7 @@
|
||||
<string name="label_day_view">Visualização diária</string>
|
||||
<string name="label_year_view">Visualização anual</string>
|
||||
<string name="label_long_press_drag_reorder">Toque firmemente e arraste a medição para reorganiza-la</string>
|
||||
<string name="permission_read_write_data_description">leia/escreva dados no openScale, incluindo informações dos usuários e todas as medidas salvas.</string>
|
||||
<string name="permission_read_write_data_description">leia/escreva dados no openScale, incluindo informações dos utilizadores e todas as medidas salvas.</string>
|
||||
<string name="label_rolling_chart">Gráfico</string>
|
||||
<string name="label_measurement_bar">Barra de medidas</string>
|
||||
|
@@ -140,8 +140,6 @@
|
||||
<string name="label_not_found">negăsit</string>
|
||||
<string name="label_ignoreOutOfRange">Ignorare a valorilor invalide</string>
|
||||
<string name="label_initial_weight">Greutate inițială</string>
|
||||
<string name="label_regression_line">Linie de regresie</string>
|
||||
<string name="label_regression_line_degree">Gradul polinomului</string>
|
||||
<string name="label_goal_line">Linie pentru obiectiv</string>
|
||||
<string name="label_help">Ajutor</string>
|
||||
|
||||
|
@@ -172,8 +172,6 @@
|
||||
<string name="label_enable_labels">Метка данных</string>
|
||||
<string name="default_value_reminder_notify_text">Пора взвеситься</string>
|
||||
<string name="info_on_date">в день</string>
|
||||
<string name="label_regression_line">График снижения веса</string>
|
||||
<string name="label_regression_line_degree">Степень полиномиальной регрессии</string>
|
||||
<string name="label_feedback_message_rate_app">Поставить оценку на Google Play или GitHub\?</string>
|
||||
<string name="trisa_scale_not_paired">Эти весы не были подключены!
|
||||
\n
|
||||
@@ -232,7 +230,6 @@
|
||||
<string name="label_enable_yaxis">ось Y</string>
|
||||
<string name="label_day_view">За день</string>
|
||||
<string name="label_year_view">За год</string>
|
||||
<string name="label_rolling_chart">Относительный масштаб</string>
|
||||
<string name="label_measurement_bar">Отображение измерений</string>
|
||||
<string name="label_is_on_right_axis">на правой оси</string>
|
||||
<string name="label_upgrade_to_openScale_pro">Пожалуйста, обновите до openScale Pro для подддержки Bluetooth</string>
|
||||
|
@@ -113,8 +113,6 @@
|
||||
<string name="label_not_found">nenájdený</string>
|
||||
<string name="label_ignoreOutOfRange">Ignorovať údaje mimo rozsah</string>
|
||||
<string name="label_initial_weight">Počiatočná hmotnosť</string>
|
||||
<string name="label_regression_line">Vývoj úbytku</string>
|
||||
<string name="label_regression_line_degree">Stupeň polynomiálnej regresie</string>
|
||||
<string name="label_goal_line">Cieľová línia</string>
|
||||
<string name="error_max_scale_users">Dosiahli ste maximálny počet používateľov</string>
|
||||
<string name="info_step_on_scale_for_reference">Prosím, postavte sa na váhu pre referenčné meranie</string>
|
||||
@@ -211,7 +209,6 @@
|
||||
<string name="trisa_scale_pairing_succeeded">Spárovanie úspešné!
|
||||
\n
|
||||
\nPripojte sa znovu pre prijatie údajov meraní.</string>
|
||||
<string name="label_rolling_chart">Pohyblivý diagram</string>
|
||||
<string name="label_measurement_bar">Lišta merania</string>
|
||||
<string name="info_scale_low_battery">Nízka úroveň batérie (%d%%), vymeňte alebo nabite prosím batérie vo váhe</string>
|
||||
<string name="info_bluetooth_connection_error_scale_offline">Nepodarilo sa pripojiť k váhe. Overte, či je váha zapnutá.</string>
|
||||
|
@@ -152,8 +152,6 @@
|
||||
<string name="label_not_found">nič ni bilo najdeno</string>
|
||||
<string name="label_ignoreOutOfRange">Ignoriraj vrednosti zunaj meje</string>
|
||||
<string name="label_initial_weight">Začetna teža</string>
|
||||
<string name="label_regression_line">Regresijska krivulja teže</string>
|
||||
<string name="label_regression_line_degree">Regresija polinomske stopnje</string>
|
||||
<string name="label_goal_line">Ciljna krivulja</string>
|
||||
<string name="label_help">Pomoč</string>
|
||||
|
||||
|
@@ -119,8 +119,6 @@
|
||||
<string name="label_not_found">hittades inte</string>
|
||||
<string name="label_ignoreOutOfRange">Ignorera data utanför intervall</string>
|
||||
<string name="label_initial_weight">Startvikt</string>
|
||||
<string name="label_regression_line">Regressionslinje</string>
|
||||
<string name="label_regression_line_degree">Regressions-polynom-gradtal</string>
|
||||
<string name="label_goal_line">Mållinje</string>
|
||||
<string name="error_max_scale_users">Max antal samtidiga våganvändare nått</string>
|
||||
<string name="info_step_on_scale_for_reference">Kliv upp barfota på vågen för referensmätningar</string>
|
||||
|
@@ -119,8 +119,6 @@
|
||||
<string name="label_not_found">Bulunamadı</string>
|
||||
<string name="label_ignoreOutOfRange">Aralığın dışındaki verileri yoksay</string>
|
||||
<string name="label_initial_weight">Başlangıç ağırlığı</string>
|
||||
<string name="label_regression_line">Ağırlık çizgisinde gerileme</string>
|
||||
<string name="label_regression_line_degree">polinom derecesinde gerileme</string>
|
||||
<string name="label_goal_line">Hedef çizgisi</string>
|
||||
<string name="error_max_scale_users">Ençok eşzamanlı tartı kullanıcı sayısına ulaştı</string>
|
||||
<string name="info_step_on_scale_for_reference">Referans ölçümleri için lütfen tartıya çıplak ayakla çıkın</string>
|
||||
@@ -229,7 +227,6 @@
|
||||
<string name="info_step_on_scale">Lütfen tartıya yalınayak çıkın</string>
|
||||
<string name="label_day_view">Gün görünümü</string>
|
||||
<string name="label_year_view">Yıl görünümü</string>
|
||||
<string name="label_rolling_chart">Grafik şema</string>
|
||||
<string name="label_measurement_bar">Ölçü çubuğu</string>
|
||||
<string name="permission_location_service_info">Bluetooth aygıtlarını aramak için Android ayarlarından konum erişim izni verin. İsteğe bağlı olarak daha sonra iptal edebilirsiniz.</string>
|
||||
<string name="label_is_on_right_axis">Sağ eksende</string>
|
||||
|
@@ -135,8 +135,6 @@
|
||||
<string name="label_not_found">не знайдено</string>
|
||||
<string name="label_ignoreOutOfRange">Ігнорувати дані за межами діапазону</string>
|
||||
<string name="label_initial_weight">Початкова вага</string>
|
||||
<string name="label_regression_line">Графік зниження</string>
|
||||
<string name="label_regression_line_degree">Ступінь поліномінальної регресії</string>
|
||||
<string name="label_goal_line">Лінія мети</string>
|
||||
<string name="label_help">Допомога</string>
|
||||
<string name="label_feedback_message_enjoying">До вподоби openScale\?</string>
|
||||
@@ -252,7 +250,6 @@
|
||||
<string name="app_intro_next_button">Далі</string>
|
||||
<string name="app_intro_back_button">Назад</string>
|
||||
<string name="app_intro_done_button">Готово</string>
|
||||
<string name="label_rolling_chart">Біжучий графік</string>
|
||||
<string name="label_slide_user_main_text">openScale не вимагає від вас створення онлайн облікового запису.
|
||||
\n
|
||||
\nПоказники тіла розраховані з вимірювань.</string>
|
||||
|
@@ -149,8 +149,6 @@
|
||||
<string name="label_not_found">không tìm thấy</string>
|
||||
<string name="label_ignoreOutOfRange">Bỏ qua dữ liệu ngoài phạm vi</string>
|
||||
<string name="label_initial_weight">Trọng lượng ban đầu</string>
|
||||
<string name="label_regression_line">Đường trọng lượng hồi quy</string>
|
||||
<string name="label_regression_line_degree">Mức độ hồi quy đa thức</string>
|
||||
<string name="label_goal_line">Đường thẳng mục tiêu</string>
|
||||
<string name="label_help">Trợ giúp</string>
|
||||
|
||||
|
@@ -128,8 +128,6 @@
|
||||
<string name="label_not_found">尋找不到</string>
|
||||
<string name="label_ignoreOutOfRange">忽略超出範圍的資料</string>
|
||||
<string name="label_initial_weight">初始體重</string>
|
||||
<string name="label_regression_line">體重回歸線</string>
|
||||
<string name="label_regression_line_degree">回歸線曲度</string>
|
||||
<string name="label_goal_line">目標線</string>
|
||||
<string name="label_help">協助</string>
|
||||
<string name="label_feedback_message_enjoying">openScale 使用愉快嗎?</string>
|
||||
|
@@ -149,9 +149,10 @@
|
||||
<string name="label_not_found">not found</string>
|
||||
<string name="label_ignoreOutOfRange">Ignore out of range data</string>
|
||||
<string name="label_initial_weight">Initial weight</string>
|
||||
<string name="label_regression_line">Regression line</string>
|
||||
<string name="label_regression_line_degree">Regression polynomial degree</string>
|
||||
<string name="label_goal_line">Goal line</string>
|
||||
<string name="label_trend_line">Trendline</string>
|
||||
<string name="label_prediction">Prediction</string>
|
||||
<string name="label_trend">Trend</string>
|
||||
<string name="label_help">Help</string>
|
||||
<string name="label_feedback_message_enjoying">Enjoying openScale?</string>
|
||||
<string name="label_feedback_message_rate_app">How about a rating on Google Play or GitHub?</string>
|
||||
@@ -182,7 +183,6 @@
|
||||
<string name="label_month_view">Month view</string>
|
||||
<string name="label_weeks_view">Week view</string>
|
||||
<string name="label_year_view">Year view</string>
|
||||
<string name="label_rolling_chart">Rolling chart</string>
|
||||
<string name="label_measurement_bar">Measurement bar</string>
|
||||
<string name="permission_not_granted">Permission not granted</string>
|
||||
<string name="permission_bluetooth_info">Location permission needed to search for Bluetooth devices. It can be revoked after the device is found.</string>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
android:summaryOn="@string/info_is_visible"
|
||||
android:title="@string/label_enable_legend" />
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="true"
|
||||
android:defaultValue="false"
|
||||
android:key="labelsEnable"
|
||||
android:summaryOff="@string/info_is_not_visible"
|
||||
android:summaryOn="@string/info_is_visible"
|
||||
@@ -19,20 +19,15 @@
|
||||
android:summaryOn="@string/info_is_visible"
|
||||
android:title="@string/label_enable_points" />
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="true"
|
||||
android:defaultValue="false"
|
||||
android:key="goalLine"
|
||||
android:summaryOff="@string/info_is_not_visible"
|
||||
android:summaryOn="@string/info_is_visible"
|
||||
android:title="@string/label_goal_line" />
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="false"
|
||||
android:key="regressionLine"
|
||||
android:summaryOff="@string/info_is_not_visible"
|
||||
android:summaryOn="@string/info_is_visible"
|
||||
android:title="@string/label_regression_line" />
|
||||
<EditTextPreference
|
||||
android:defaultValue="1"
|
||||
android:dependency="regressionLine"
|
||||
android:key="regressionLineOrder"
|
||||
android:title="@string/label_regression_line_degree" />
|
||||
android:key="trendLine"
|
||||
android:summaryOff="@string/info_is_not_enable"
|
||||
android:summaryOn="@string/info_is_enable"
|
||||
android:title="@string/label_trend_line" />
|
||||
</PreferenceScreen>
|
||||
|
Reference in New Issue
Block a user