1
0
mirror of https://github.com/oliexdev/openScale.git synced 2025-08-29 19:20:36 +02:00

add an optional goal and linear regression weight line

This commit is contained in:
OliE
2017-09-22 10:52:31 +02:00
parent 210fcea36a
commit 8761ef5f0e
3 changed files with 137 additions and 1 deletions

View File

@@ -20,6 +20,7 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.design.widget.FloatingActionButton;
@@ -332,6 +333,137 @@ public class GraphFragment extends Fragment implements FragmentUpdateListener {
enableMonth.setBackgroundTintList(ColorStateList.valueOf(Color.parseColor("#d3d3d3")));
}
if (prefs.getBoolean("goalLine", true)) {
Stack<PointValue> valuesGoalLine = new Stack<PointValue>();
float goalWeight = openScale.getSelectedScaleUser().goal_weight;
valuesGoalLine.push(new PointValue(0, goalWeight));
valuesGoalLine.push(new PointValue(31, goalWeight));
Line goalLine = new Line(valuesGoalLine)
.setHasPoints(false);
goalLine.setPathEffect(new DashPathEffect(new float[] {10,30}, 0));
lines.add(goalLine);
}
if (prefs.getBoolean("regressionLine", true)) {
/*
// quadratic regression y = ax^2 + bx + c
double x_value = 0.0;
double y_value = 0.0;
double s40 = 0; //sum of x^4
double s30 = 0; //sum of x^3
double s20 = 0; //sum of x^2
double s10 = 0; //sum of x
double s00 = scaleDataList.size();
//sum of x^0 * y^0 ie 1 * number of entries
double s21 = 0; //sum of x^2*y
double s11 = 0; //sum of x*y
double s01 = 0; //sum of y
for(ScaleData scaleEntry: scaleDataList) {
calDB.setTime(scaleEntry.getDateTime());
x_value = calDB.get(field);
y_value = scaleEntry.getConvertedWeight(openScale.getSelectedScaleUser().scale_unit);
s40 += Math.pow(x_value, 4);
s30 += Math.pow(x_value, 3);
s20 += Math.pow(x_value, 2);
s10 += x_value;
s21 += Math.pow(x_value, 2) * y_value;
s11 += x_value * y_value;
s01 += y_value;
}
// solve equations using Cramer's law
double a = (s21*(s20 * s00 - s10 * s10) -
s11*(s30 * s00 - s10 * s20) +
s01*(s30 * s10 - s20 * s20))
/
(s40*(s20 * s00 - s10 * s10) -
s30*(s30 * s00 - s10 * s20) +
s20*(s30 * s10 - s20 * s20));
double b = (s40*(s11 * s00 - s01 * s10) -
s30*(s21 * s00 - s01 * s20) +
s20*(s21 * s10 - s11 * s20))
/
(s40 * (s20 * s00 - s10 * s10) -
s30 * (s30 * s00 - s10 * s20) +
s20 * (s30 * s10 - s20 * s20));
double c = (s40*(s20 * s01 - s10 * s11) -
s30*(s30 * s01 - s10 * s21) +
s20*(s30 * s11 - s20 * s21))
/
(s40 * (s20 * s00 - s10 * s10) -
s30 * (s30 * s00 - s10 * s20) +
s20 * (s30 * s10 - s20 * s20));
*/
// linear regression y = a + x*b
double sumx = 0.0;
double sumy = 0.0;
double x_value = 0.0;
double y_value = 0.0;
for(ScaleData scaleEntry: scaleDataList) {
calDB.setTime(scaleEntry.getDateTime());
x_value = calDB.get(field);
y_value = scaleEntry.getConvertedWeight(openScale.getSelectedScaleUser().scale_unit);
sumx += x_value;
sumy += y_value;
}
double xbar = sumx / scaleDataList.size();
double ybar = sumy / scaleDataList.size();
double xxbar = 0.0;
double xybar = 0.0;
for(ScaleData scaleEntry: scaleDataList) {
calDB.setTime(scaleEntry.getDateTime());
x_value = calDB.get(field);
y_value = scaleEntry.getConvertedWeight(openScale.getSelectedScaleUser().scale_unit);
xxbar += (x_value - xbar) * (x_value - xbar);
xybar += (y_value - xbar) * (y_value - ybar);
}
double b = xybar / xxbar;
double a = ybar - b * xbar;
Stack<PointValue> valuesLinearRegression = new Stack<PointValue>();
for (int i = 0; i < 31; i++) {
y_value = a + b * i; // linear regression
//y_value = a * i*i + b * i + c; // quadratic regression
valuesLinearRegression.push(new PointValue((float) i, (float) y_value));
}
Line linearRegressionLine = new Line(valuesLinearRegression)
.setColor(ChartUtils.COLOR_VIOLET)
.setHasPoints(false);
linearRegressionLine.setPathEffect(new DashPathEffect(new float[] {10,30}, 0));
lines.add(linearRegressionLine);
}
LineChartData lineData = new LineChartData(lines);
lineData.setAxisXBottom(new Axis(axisValues).
setHasLines(true).

View File

@@ -150,6 +150,9 @@
<string name="label_ignoreOutOfRange">Ignore data that are out of range</string>
<string name="label_initial_weight">Initial weight</string>
<string name="label_average_data">Calculate average per day/month</string>
<string name="label_regression_line">Regression weight line</string>
<string name="label_goal_line">Goal line</string>
<string name="error_max_scale_users">Maximum number of concurrent scale users reached.</string>
<string name="info_step_on_scale">Please step barefoot on the scale for reference measurements.</string>

View File

@@ -4,4 +4,5 @@
<CheckBoxPreference android:title="@string/label_enable_points" android:summaryOn="@string/info_is_visible" android:summaryOff="@string/info_is_not_visible" android:key="pointsEnable" android:defaultValue="true"/>
<CheckBoxPreference android:title="@string/label_delete_confirmation" android:summaryOn="@string/info_is_enable" android:summaryOff="@string/info_is_not_enable" android:key="deleteConfirmationEnable" android:defaultValue="true" />
<CheckBoxPreference android:title="@string/label_average_data" android:summaryOn="@string/info_is_enable" android:summaryOff="@string/info_is_not_enable" android:key="averageData" android:defaultValue="true" />
</PreferenceScreen>
<CheckBoxPreference android:title="@string/label_goal_line" android:summaryOn="@string/info_is_visible" android:summaryOff="@string/info_is_not_visible" android:key="goalLine" android:defaultValue="true" />
<CheckBoxPreference android:title="@string/label_regression_line" android:summaryOn="@string/info_is_visible" android:summaryOff="@string/info_is_not_visible" android:key="regressionLine" android:defaultValue="true" /></PreferenceScreen>