diff --git a/android_app/app/schemas/com.health.openscale.core.database.AppDatabase/5.json b/android_app/app/schemas/com.health.openscale.core.database.AppDatabase/5.json index cd6da352..02e1f958 100644 --- a/android_app/app/schemas/com.health.openscale.core.database.AppDatabase/5.json +++ b/android_app/app/schemas/com.health.openscale.core.database.AppDatabase/5.json @@ -2,7 +2,7 @@ "formatVersion": 1, "database": { "version": 5, - "identityHash": "f0e80a69f9fff0c48f2b7df10de3228f", + "identityHash": "d66fc1fc2752b2d6f41700fa2102492a", "entities": [ { "tableName": "scaleMeasurements", @@ -174,7 +174,7 @@ }, { "tableName": "scaleUsers", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `username` TEXT NOT NULL, `birthday` INTEGER NOT NULL, `bodyHeight` REAL NOT NULL, `scaleUnit` INTEGER NOT NULL, `gender` INTEGER NOT NULL, `initialWeight` REAL NOT NULL, `goalWeight` REAL NOT NULL, `goalDate` INTEGER, `measureUnit` INTEGER NOT NULL, `activityLevel` INTEGER NOT NULL, `assistedWeighing` INTEGER NOT NULL)", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `username` TEXT NOT NULL, `birthday` INTEGER NOT NULL, `bodyHeight` REAL NOT NULL, `scaleUnit` INTEGER NOT NULL, `gender` INTEGER NOT NULL, `initialWeight` REAL NOT NULL, `goalWeight` REAL NOT NULL, `goalDate` INTEGER, `measureUnit` INTEGER NOT NULL, `activityLevel` INTEGER NOT NULL, `assistedWeighing` INTEGER NOT NULL, `leftAmputationLevel` INTEGER NOT NULL, `rightAmputationLevel` INTEGER NOT NULL)", "fields": [ { "fieldPath": "id", @@ -247,6 +247,18 @@ "columnName": "assistedWeighing", "affinity": "INTEGER", "notNull": true + }, + { + "fieldPath": "leftAmputationLevel", + "columnName": "leftAmputationLevel", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "rightAmputationLevel", + "columnName": "rightAmputationLevel", + "affinity": "INTEGER", + "notNull": true } ], "primaryKey": { @@ -262,7 +274,7 @@ "views": [], "setupQueries": [ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", - "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'f0e80a69f9fff0c48f2b7df10de3228f')" + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'd66fc1fc2752b2d6f41700fa2102492a')" ] } } \ No newline at end of file diff --git a/android_app/app/src/main/java/com/health/openscale/core/OpenScale.java b/android_app/app/src/main/java/com/health/openscale/core/OpenScale.java index 525ba382..cc4cae66 100644 --- a/android_app/app/src/main/java/com/health/openscale/core/OpenScale.java +++ b/android_app/app/src/main/java/com/health/openscale/core/OpenScale.java @@ -274,6 +274,7 @@ public class OpenScale { public int addScaleMeasurement(final ScaleMeasurement scaleMeasurement, boolean silent) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + // Check user id and do a smart user assign if option is enabled if (scaleMeasurement.getUserId() == -1) { if (prefs.getBoolean("smartUserAssign", false)) { scaleMeasurement.setUserId(getSmartUserAssignment(scaleMeasurement.getWeight(), 15.0f)); @@ -288,6 +289,7 @@ public class OpenScale { } } + // Assisted weighing if (getScaleUser(scaleMeasurement.getUserId()).isAssistedWeighing()) { int assistedWeighingRefUserId = prefs.getInt("assistedWeighingRefUserId", -1); if (assistedWeighingRefUserId != -1) { @@ -303,6 +305,10 @@ public class OpenScale { } } + // Calculate the amputation correction factor for the weight, if available + scaleMeasurement.setWeight((scaleMeasurement.getWeight() * 100.0f) / getScaleUser(scaleMeasurement.getUserId()).getAmputationCorrectionFactor()); + + // If option is enabled then calculate body measurements from generic formulas MeasurementViewSettings settings = new MeasurementViewSettings(prefs, WaterMeasurementView.KEY); if (settings.isEnabled() && settings.isEstimationEnabled()) { EstimatedWaterMetric waterMetric = EstimatedWaterMetric.getEstimatedMetric( @@ -325,6 +331,7 @@ public class OpenScale { scaleMeasurement.setLbm(lbmMetric.getLBM(getScaleUser(scaleMeasurement.getUserId()), scaleMeasurement)); } + // Insert measurement into the database, check return if it was successful inserted if (measurementDAO.insert(scaleMeasurement) != -1) { Timber.d("Added measurement: %s", scaleMeasurement); if (!silent) { diff --git a/android_app/app/src/main/java/com/health/openscale/core/database/AppDatabase.java b/android_app/app/src/main/java/com/health/openscale/core/database/AppDatabase.java index 1cb7c05a..6a5e1eab 100644 --- a/android_app/app/src/main/java/com/health/openscale/core/database/AppDatabase.java +++ b/android_app/app/src/main/java/com/health/openscale/core/database/AppDatabase.java @@ -182,8 +182,10 @@ public abstract class AppDatabase extends RoomDatabase { public void migrate(SupportSQLiteDatabase database) { database.beginTransaction(); try { - // Add assisted weighing to table + // Add assisted weighing and left/right amputation level to table database.execSQL("ALTER TABLE scaleUsers ADD assistedWeighing INTEGER NOT NULL default 0"); + database.execSQL("ALTER TABLE scaleUsers ADD leftAmputationLevel INTEGER NOT NULL default 0"); + database.execSQL("ALTER TABLE scaleUsers ADD rightAmputationLevel INTEGER NOT NULL default 0"); database.setTransactionSuccessful(); } diff --git a/android_app/app/src/main/java/com/health/openscale/core/datatypes/ScaleUser.java b/android_app/app/src/main/java/com/health/openscale/core/datatypes/ScaleUser.java index ff999cf6..1b781438 100644 --- a/android_app/app/src/main/java/com/health/openscale/core/datatypes/ScaleUser.java +++ b/android_app/app/src/main/java/com/health/openscale/core/datatypes/ScaleUser.java @@ -60,6 +60,12 @@ public class ScaleUser { private Converters.ActivityLevel activityLevel; @ColumnInfo(name = "assistedWeighing") private boolean assistedWeighing; + @NonNull + @ColumnInfo(name = "leftAmputationLevel") + private Converters.AmputationLevel leftAmputationLevel; + @NonNull + @ColumnInfo(name = "rightAmputationLevel") + private Converters.AmputationLevel rightAmputationLevel; public ScaleUser() { userName = ""; @@ -73,6 +79,8 @@ public class ScaleUser { measureUnit = Converters.MeasureUnit.CM; activityLevel = Converters.ActivityLevel.SEDENTARY; assistedWeighing = false; + leftAmputationLevel = Converters.AmputationLevel.NONE; + rightAmputationLevel = Converters.AmputationLevel.NONE; } public int getId() { @@ -187,6 +195,76 @@ public class ScaleUser { this.assistedWeighing = assistedWeighing; } + @NonNull + public Converters.AmputationLevel getLeftAmputationLevel() { + return leftAmputationLevel; + } + + public void setLeftAmputationLevel(@NonNull Converters.AmputationLevel leftAmputationLevel) { + this.leftAmputationLevel = leftAmputationLevel; + } + + @NonNull + public Converters.AmputationLevel getRightAmputationLevel() { + return rightAmputationLevel; + } + + public void setRightAmputationLevel(@NonNull Converters.AmputationLevel rightAmputationLevel) { + this.rightAmputationLevel = rightAmputationLevel; + } + + public float getAmputationCorrectionFactor() { + float correctionFactor = 100.0f; + + switch (rightAmputationLevel) { + case NONE: + break; + case HAND: + correctionFactor -= 0.8f; + break; + case FOREARM_HAND: + correctionFactor -= 3.0f; + break; + case ARM: + correctionFactor -= 11.5f; + break; + case FOOT: + correctionFactor -= 1.8f; + break; + case LOWER_LEG_FOOT: + correctionFactor -= 7.1f; + break; + case LEG: + correctionFactor -= 18.7f; + break; + } + + switch (leftAmputationLevel) { + case NONE: + break; + case HAND: + correctionFactor -= 0.8f; + break; + case FOREARM_HAND: + correctionFactor -= 3.0f; + break; + case ARM: + correctionFactor -= 11.5f; + break; + case FOOT: + correctionFactor -= 1.8f; + break; + case LOWER_LEG_FOOT: + correctionFactor -= 7.1f; + break; + case LEG: + correctionFactor -= 18.7f; + break; + } + + return correctionFactor; + } + public static String getPreferenceKey(int userId, String key) { return String.format("user.%d.%s", userId, key); } diff --git a/android_app/app/src/main/java/com/health/openscale/core/utils/Converters.java b/android_app/app/src/main/java/com/health/openscale/core/utils/Converters.java index d7c109b1..d401e395 100644 --- a/android_app/app/src/main/java/com/health/openscale/core/utils/Converters.java +++ b/android_app/app/src/main/java/com/health/openscale/core/utils/Converters.java @@ -145,6 +145,52 @@ public class Converters { } } + public enum AmputationLevel { + NONE, HAND, FOREARM_HAND, ARM, FOOT, LOWER_LEG_FOOT, LEG; + + public static AmputationLevel fromInt(int unit) { + switch (unit) { + case 0: + return NONE; + case 1: + return HAND; + case 2: + return FOREARM_HAND; + case 3: + return ARM; + case 4: + return FOOT; + case 5: + return LOWER_LEG_FOOT; + case 6: + return LEG; + } + + return NONE; + } + + public int toInt() { + switch (this) { + case NONE: + return 0; + case HAND: + return 1; + case FOREARM_HAND: + return 2; + case ARM: + return 3; + case FOOT: + return 4; + case LOWER_LEG_FOOT: + return 5; + case LEG: + return 6; + } + + return 0; + } + } + private static final float KG_LB = 2.20462f; private static final float KG_ST = 0.157473f; private static final float CM_IN = 0.393701f; @@ -199,6 +245,16 @@ public class Converters { return level.toInt(); } + @TypeConverter + public static AmputationLevel fromAmputationLevelInt(int level) { + return AmputationLevel.fromInt(level); + } + + @TypeConverter + public static int toAmputationLevelInt(AmputationLevel level) { + return level.toInt(); + } + public static float toCentimeter(float value, MeasureUnit unit) { switch (unit) { case INCH: diff --git a/android_app/app/src/main/java/com/health/openscale/gui/preferences/UserSettingsFragment.java b/android_app/app/src/main/java/com/health/openscale/gui/preferences/UserSettingsFragment.java index 0a1f00f1..04f85b01 100644 --- a/android_app/app/src/main/java/com/health/openscale/gui/preferences/UserSettingsFragment.java +++ b/android_app/app/src/main/java/com/health/openscale/gui/preferences/UserSettingsFragment.java @@ -68,6 +68,8 @@ public class UserSettingsFragment extends Fragment { private CheckBox assistedWeighing; private RadioGroup radioMeasurementUnit; private Spinner spinnerActivityLevel; + private Spinner spinnerLeftAmputationLevel; + private Spinner spinnerRightAmputationLevel; private final DateFormat dateFormat = DateFormat.getDateInstance(); @@ -93,6 +95,8 @@ public class UserSettingsFragment extends Fragment { assistedWeighing = root.findViewById(R.id.asisstedWeighing); radioMeasurementUnit = root.findViewById(R.id.groupMeasureUnit); spinnerActivityLevel = root.findViewById(R.id.spinnerActivityLevel); + spinnerLeftAmputationLevel = root.findViewById(R.id.spinnerLeftAmputationLevel); + spinnerRightAmputationLevel = root.findViewById(R.id.spinnerRightAmputationLevel); txtInitialWeight = root.findViewById(R.id.txtInitialWeight); txtGoalWeight = root.findViewById(R.id.txtGoalWeight); @@ -300,6 +304,8 @@ public class UserSettingsFragment extends Fragment { assistedWeighing.setChecked(scaleUser.isAssistedWeighing()); spinnerActivityLevel.setSelection(scaleUser.getActivityLevel().toInt()); + spinnerLeftAmputationLevel.setSelection(scaleUser.getLeftAmputationLevel().toInt()); + spinnerRightAmputationLevel.setSelection(scaleUser.getRightAmputationLevel().toInt()); } private boolean validateInput() @@ -444,8 +450,9 @@ public class UserSettingsFragment extends Fragment { scaleUser.setBodyHeight(Converters.toCentimeter(body_height, measure_unit)); scaleUser.setScaleUnit(scale_unit); scaleUser.setMeasureUnit(measure_unit); - scaleUser.setActivityLevel(Converters.fromActivityLevelInt( - spinnerActivityLevel.getSelectedItemPosition())); + scaleUser.setActivityLevel(Converters.fromActivityLevelInt(spinnerActivityLevel.getSelectedItemPosition())); + scaleUser.setLeftAmputationLevel(Converters.fromAmputationLevelInt(spinnerLeftAmputationLevel.getSelectedItemPosition())); + scaleUser.setRightAmputationLevel(Converters.fromAmputationLevelInt(spinnerRightAmputationLevel.getSelectedItemPosition())); scaleUser.setGender(gender); scaleUser.setAssistedWeighing(assistedWeighing.isChecked()); scaleUser.setInitialWeight(Converters.toKilogram(initial_weight, scale_unit)); diff --git a/android_app/app/src/main/res/layout/fragment_usersettings.xml b/android_app/app/src/main/res/layout/fragment_usersettings.xml index 873f6775..9fad3f01 100644 --- a/android_app/app/src/main/res/layout/fragment_usersettings.xml +++ b/android_app/app/src/main/res/layout/fragment_usersettings.xml @@ -126,6 +126,42 @@ + + + + + + + + + + + + + + @string/activity_level_heavy @string/activity_level_extreme + + + @string/amputation_level_none + @string/amputation_level_hand + @string/amputation_level_forearm_hand + @string/amputation_level_arm + @string/amputation_level_foot + @string/amputation_level_lower_leg_foot + @string/amputation_level_leg + diff --git a/android_app/app/src/main/res/values/strings.xml b/android_app/app/src/main/res/values/strings.xml index 1be988c7..443113a3 100644 --- a/android_app/app/src/main/res/values/strings.xml +++ b/android_app/app/src/main/res/values/strings.xml @@ -57,6 +57,9 @@ Scale unit Gender Assisted weighing + Amputation + Amputation left + Amputation right Male Female Goal weight @@ -238,6 +241,13 @@ Moderate Heavy Extreme + No amputation + Hand + Forearm and leg + Arm + Foot + Lower leg and foot + Leg Please upgrade to openScale pro for Bluetooth support Welcome to\nopenScale Open-source software weight and body metrics tracker, with Bluetooth scale support.