From d5ae732d0c59e7a1e567e5916e26420331e14ea5 Mon Sep 17 00:00:00 2001 From: wulf Date: Thu, 2 Jul 2020 16:51:06 +0200 Subject: [PATCH 01/18] fix #61: add macro nutrient tracking --- .../1.json | 137 ++++++++++++ .../database/ConsumedEntrieAndProductDao.java | 31 +++ .../database/Product.java | 12 +- .../database/ProductDao.java | 4 +- .../network/models/NetworkProduct.java | 51 +++++ .../utils/ProductConversionHelper.java | 53 ++++- .../ui/AddFoodFragment.java | 154 +++++++++++++- .../ui/BaseAddFoodActivity.java | 10 + .../ui/MonthStatisticFragment.java | 149 +++++++++++++ .../ui/OverviewActivity.java | 101 ++++++++- .../ui/SearchFoodFragment.java | 28 +++ .../ui/WeekStatisticFragment.java | 122 ++++++++++- .../ui/adapter/DatabaseEntry.java | 12 +- .../ui/adapter/DatabaseFacade.java | 118 ++++++++++- .../ui/adapter/SearchResultAdapter.java | 3 + app/src/main/res/layout-land/content_food.xml | 200 ++++++++++++++---- app/src/main/res/layout/content_food.xml | 114 +++++++++- app/src/main/res/layout/content_overview.xml | 12 +- .../res/layout/fragment_month_statistic.xml | 61 ++++++ .../res/layout/fragment_week_statistic.xml | 60 ++++++ app/src/main/res/layout/search_result.xml | 34 +++ app/src/main/res/values/strings.xml | 12 ++ 22 files changed, 1402 insertions(+), 76 deletions(-) create mode 100644 app/schemas/org.secuso.privacyfriendlyfoodtracker.database.ApplicationDatabase/1.json diff --git a/app/schemas/org.secuso.privacyfriendlyfoodtracker.database.ApplicationDatabase/1.json b/app/schemas/org.secuso.privacyfriendlyfoodtracker.database.ApplicationDatabase/1.json new file mode 100644 index 0000000..da6a5f0 --- /dev/null +++ b/app/schemas/org.secuso.privacyfriendlyfoodtracker.database.ApplicationDatabase/1.json @@ -0,0 +1,137 @@ +{ + "formatVersion": 1, + "database": { + "version": 1, + "identityHash": "b441afa96955c4160952c91b7d440881", + "entities": [ + { + "tableName": "ConsumedEntries", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `productId` INTEGER NOT NULL, `amount` INTEGER NOT NULL, `date` INTEGER, `name` TEXT, FOREIGN KEY(`productId`) REFERENCES `Product`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "productId", + "columnName": "productId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "amount", + "columnName": "amount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [ + { + "table": "Product", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "productId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "Product", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT, `energy` REAL NOT NULL, `carbs` REAL NOT NULL, `sugar` REAL NOT NULL, `protein` REAL NOT NULL, `fat` REAL NOT NULL, `satFat` REAL NOT NULL, `barcode` TEXT)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "energy", + "columnName": "energy", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "carbs", + "columnName": "carbs", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "sugar", + "columnName": "sugar", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "protein", + "columnName": "protein", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "fat", + "columnName": "fat", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "satFat", + "columnName": "satFat", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "barcode", + "columnName": "barcode", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + } + ], + "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, \"b441afa96955c4160952c91b7d440881\")" + ] + } +} \ No newline at end of file diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/ConsumedEntrieAndProductDao.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/ConsumedEntrieAndProductDao.java index 8284ab1..921961b 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/ConsumedEntrieAndProductDao.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/ConsumedEntrieAndProductDao.java @@ -37,6 +37,37 @@ public interface ConsumedEntrieAndProductDao { @Query("SELECT consumedEntries.date AS unique1, sum(product.energy*consumedEntries.amount/100) AS unique2 FROM consumedEntries INNER JOIN product ON consumedEntries.productId = product.id WHERE consumedEntries.date BETWEEN :dayst AND :dayet") List getCaloriesPeriod(final Date dayst, final Date dayet); + @Query("SELECT consumedEntries.date AS unique1, (sum(product.carbs*consumedEntries.amount)) AS unique2 FROM consumedEntries INNER JOIN product ON consumedEntries.productId = product.id WHERE consumedEntries.date BETWEEN :dayst AND :dayet GROUP BY consumedEntries.date ") + List getCarbsPerDayinPeriod(final Date dayst, final Date dayet); + + @Query("SELECT consumedEntries.date AS unique1, sum(product.carbs*consumedEntries.amount/100) AS unique2 FROM consumedEntries INNER JOIN product ON consumedEntries.productId = product.id WHERE consumedEntries.date BETWEEN :dayst AND :dayet") + List getCarbsPeriod(final Date dayst, final Date dayet); + + @Query("SELECT consumedEntries.date AS unique1, (sum(product.sugar*consumedEntries.amount)) AS unique2 FROM consumedEntries INNER JOIN product ON consumedEntries.productId = product.id WHERE consumedEntries.date BETWEEN :dayst AND :dayet GROUP BY consumedEntries.date ") + List getSugarPerDayinPeriod(final Date dayst, final Date dayet); + + @Query("SELECT consumedEntries.date AS unique1, sum(product.sugar*consumedEntries.amount/100) AS unique2 FROM consumedEntries INNER JOIN product ON consumedEntries.productId = product.id WHERE consumedEntries.date BETWEEN :dayst AND :dayet") + List getSugarPeriod(final Date dayst, final Date dayet); + + @Query("SELECT consumedEntries.date AS unique1, (sum(product.protein*consumedEntries.amount)) AS unique2 FROM consumedEntries INNER JOIN product ON consumedEntries.productId = product.id WHERE consumedEntries.date BETWEEN :dayst AND :dayet GROUP BY consumedEntries.date ") + List getProteinPerDayinPeriod(final Date dayst, final Date dayet); + + @Query("SELECT consumedEntries.date AS unique1, sum(product.protein*consumedEntries.amount/100) AS unique2 FROM consumedEntries INNER JOIN product ON consumedEntries.productId = product.id WHERE consumedEntries.date BETWEEN :dayst AND :dayet") + List getProteinPeriod(final Date dayst, final Date dayet); + + @Query("SELECT consumedEntries.date AS unique1, (sum(product.fat*consumedEntries.amount)) AS unique2 FROM consumedEntries INNER JOIN product ON consumedEntries.productId = product.id WHERE consumedEntries.date BETWEEN :dayst AND :dayet GROUP BY consumedEntries.date ") + List getFatPerDayinPeriod(final Date dayst, final Date dayet); + + @Query("SELECT consumedEntries.date AS unique1, sum(product.fat*consumedEntries.amount/100) AS unique2 FROM consumedEntries INNER JOIN product ON consumedEntries.productId = product.id WHERE consumedEntries.date BETWEEN :dayst AND :dayet") + List getFatPeriod(final Date dayst, final Date dayet); + + @Query("SELECT consumedEntries.date AS unique1, (sum(product.satFat*consumedEntries.amount)) AS unique2 FROM consumedEntries INNER JOIN product ON consumedEntries.productId = product.id WHERE consumedEntries.date BETWEEN :dayst AND :dayet GROUP BY consumedEntries.date ") + List getSatFatPerDayinPeriod(final Date dayst, final Date dayet); + + @Query("SELECT consumedEntries.date AS unique1, sum(product.satFat*consumedEntries.amount/100) AS unique2 FROM consumedEntries INNER JOIN product ON consumedEntries.productId = product.id WHERE consumedEntries.date BETWEEN :dayst AND :dayet") + List getSatFatPeriod(final Date dayst, final Date dayet); + + static class DateCalories { public Date unique1; diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/Product.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/Product.java index 4662413..49be0a2 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/Product.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/Product.java @@ -32,12 +32,22 @@ public class Product { public final int id; public final String name; public final float energy; + public final float carbs; + public final float sugar; + public final float protein; + public final float fat; + public final float satFat; public final String barcode; - public Product(final int id, String name, float energy, String barcode) { + public Product(final int id, String name, float energy, float carbs, float sugar, float protein, float fat, float satFat, String barcode) { this.id = id; this.name = name; this.energy = energy; + this.carbs = carbs; + this.sugar = sugar; + this.protein = protein; + this.fat = fat; + this.satFat = satFat; this.barcode = barcode; } } diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/ProductDao.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/ProductDao.java index 3e6b0b1..81854fe 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/ProductDao.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/ProductDao.java @@ -52,8 +52,8 @@ public interface ProductDao { @Query("SELECT * FROM product WHERE id=:id") Product findProductById(final int id); - @Query("SELECT * FROM product WHERE name=:name AND energy=:energy AND barcode=:barcode") - List findExistingProducts(String name, float energy, String barcode); + @Query("SELECT * FROM product WHERE name=:name AND energy=:energy AND carbs=:carbs AND sugar=:sugar AND protein=:protein AND fat=:fat AND satFat=:satFat AND barcode=:barcode") + List findExistingProducts(String name, float energy, float carbs, float sugar, float protein, float fat, float satFat, String barcode); @Query("SELECT * FROM product WHERE name LIKE :name") List findProductsByName(String name); diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/network/models/NetworkProduct.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/network/models/NetworkProduct.java index 1029e16..de43fc3 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/network/models/NetworkProduct.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/network/models/NetworkProduct.java @@ -490,6 +490,57 @@ public String getNutrimentEnergy() { return ""; } + + /** + * @return The carbs per 100g + */ + public String getNutrimentCarbs() { + if(nutriments.containsKey("carbohydrates_100g")){ + return nutriments.get("carbohydrates_100g").toString(); + } + return ""; + } + + /** + * @return The sugar per 100g + */ + public String getNutrimentSugar() { + if(nutriments.containsKey("sugars_100g")){ + return nutriments.get("sugars_100g").toString(); + } + return ""; + } + + /** + * @return The protein per 100g + */ + public String getNutrimentProtein() { + if(nutriments.containsKey("proteins_100g")){ + return nutriments.get("proteins_100g").toString(); + } + return ""; + } + + /** + * @return The fat per 100g + */ + public String getNutrimentFat() { + if(nutriments.containsKey("fat_100g")){ + return nutriments.get("fat_100g").toString(); + } + return ""; + } + + /** + * @return The protein per 100g + */ + public String getNutrimentSatFat() { + if(nutriments.containsKey("saturated-fat_100g")){ + return nutriments.get("saturated-fat_100g").toString(); + } + return ""; + } + /** * @return The Emb_codes */ diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/network/utils/ProductConversionHelper.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/network/utils/ProductConversionHelper.java index a23b959..b204b1d 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/network/utils/ProductConversionHelper.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/network/utils/ProductConversionHelper.java @@ -19,7 +19,58 @@ public static Product conversionProduct(org.secuso.privacyfriendlyfoodtracker.ne } catch (NumberFormatException e){ energy_100g = Float.parseFloat(product.getNutrimentEnergy()) / 4.184f; } + + String carbsS = product.getNutrimentCarbs(); + float carbs = 0; + if(!"".equals(carbsS)){ + try { + carbs = Integer.parseInt(carbsS); + } catch (NumberFormatException e){ + carbs = Float.parseFloat(carbsS); + } + } + + String sugarS = product.getNutrimentSugar(); + float sugar = 0; + if(!"".equals(sugarS)){ + try { + sugar = Integer.parseInt(sugarS); + } catch (NumberFormatException e){ + sugar = Float.parseFloat(sugarS); + } + } + + String proteinS = product.getNutrimentProtein(); + float protein = 0; + if(!"".equals(proteinS)){ + try { + protein = Integer.parseInt(proteinS); + } catch (NumberFormatException e){ + protein = Float.parseFloat(proteinS); + } + } + + String fatS = product.getNutrimentFat(); + float fat = 0; + if(!"".equals(fatS)){ + try { + fat = Integer.parseInt(fatS); + } catch (NumberFormatException e){ + fat = Float.parseFloat(fatS); + } + } + + String satFatS = product.getNutrimentSatFat(); + float satFat = 0; + if(!"".equals(satFatS)){ + try { + satFat = Integer.parseInt(satFatS); + } catch (NumberFormatException e){ + satFat = Float.parseFloat(satFatS); + } + } + // if the id is equals to 0 then the room database creates a new id (primary key) - return new Product(0, product.getProductName(), energy_100g, product.getCode()); + return new Product(0, product.getProductName(), energy_100g, carbs, sugar, protein, fat, satFat, product.getCode()); } } diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/AddFoodFragment.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/AddFoodFragment.java index 2894cd5..d6aafcd 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/AddFoodFragment.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/AddFoodFragment.java @@ -50,6 +50,11 @@ public class AddFoodFragment extends Fragment { DatabaseFacade databaseFacade; EditText amountField; EditText caloriesField; + EditText carbsField; + EditText sugarField; + EditText proteinField; + EditText fatField; + EditText satFatField; /** * The required empty public constructor */ @@ -82,9 +87,23 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, amountField = parentHolder.findViewById(R.id.input_amount); caloriesField = parentHolder.findViewById(R.id.input_calories); + carbsField = parentHolder.findViewById(R.id.input_carbs); + sugarField = parentHolder.findViewById(R.id.input_sugar); + proteinField = parentHolder.findViewById(R.id.input_protein); + fatField = parentHolder.findViewById(R.id.input_fat); + satFatField = parentHolder.findViewById(R.id.input_satFat); + amountField.setFilters(amountFilter); amountField.setInputType(InputType.TYPE_CLASS_NUMBER); + caloriesField.setFilters(caloriesFilter); + carbsField.setFilters(caloriesFilter); + sugarField.setFilters(caloriesFilter); + proteinField.setFilters(caloriesFilter); + fatField.setFilters(caloriesFilter); + satFatField.setFilters(caloriesFilter); + + FloatingActionButton fab = parentHolder.findViewById(R.id.addEntry); fab.setOnClickListener(new View.OnClickListener() { @Override @@ -96,11 +115,38 @@ public void onClick(View view) { String calories = caloriesField.getText().toString(); + String carbs = carbsField.getText().toString(); + + String sugar = sugarField.getText().toString(); + + String protein = proteinField.getText().toString(); + + String fat = fatField.getText().toString(); + + String satFat = satFatField.getText().toString(); + + + //replace empty macro slots with "0" + if("".equals(carbs)){ + carbs="0"; + } + if("".equals(sugar)){ + sugar="0"; + } + if("".equals(protein)){ + protein="0"; + } + if("".equals(fat)){ + fat="0"; + } + if("".equals(satFat)){ + satFat="0"; + } // validation - boolean validated = validateResponses(name, amount, calories, view); + boolean validated = validateResponses(name, amount, calories, carbs, sugar, protein, fat, satFat, view); if(validated) { - boolean entrySuccessful = makeDatabaseEntry(name, amount, calories); + boolean entrySuccessful = makeDatabaseEntry(name, amount, calories, carbs, sugar, protein, fat, satFat); if (!entrySuccessful){ showErrorMessage(view, R.string.error_database); } else { @@ -122,30 +168,102 @@ public void onClick(View view) { @Override public void setUserVisibleHint(boolean isVisible) { super.setUserVisibleHint(isVisible); + if(isVisible && referenceActivity.productSet) { EditText nameField = parentHolder.findViewById(R.id.input_food); EditText caloriesField = parentHolder.findViewById(R.id.input_calories); + EditText carbsField = parentHolder.findViewById(R.id.input_carbs); + EditText sugarField = parentHolder.findViewById(R.id.input_sugar); + EditText proteinField = parentHolder.findViewById(R.id.input_protein); + EditText fatField = parentHolder.findViewById(R.id.input_fat); + EditText satFatField = parentHolder.findViewById(R.id.input_satFat); + + nameField.setText(referenceActivity.name); nameField.setFocusable(false); nameField.setClickable(false); nameField.setTextColor(getResources().getColor(R.color.middlegrey)); + caloriesField.setText(String.format(Locale.ENGLISH, "%.2f", referenceActivity.calories)); caloriesField.setFocusable(false); caloriesField.setClickable(false); caloriesField.setTextColor(getResources().getColor(R.color.middlegrey)); + + carbsField.setText(String.format(Locale.ENGLISH, "%.2f", referenceActivity.carbs)); + carbsField.setFocusable(false); + carbsField.setClickable(false); + carbsField.setTextColor(getResources().getColor(R.color.middlegrey)); + + sugarField.setText(String.format(Locale.ENGLISH, "%.2f", referenceActivity.sugar)); + sugarField.setFocusable(false); + sugarField.setClickable(false); + sugarField.setTextColor(getResources().getColor(R.color.middlegrey)); + + proteinField.setText(String.format(Locale.ENGLISH, "%.2f", referenceActivity.protein)); + proteinField.setFocusable(false); + proteinField.setClickable(false); + proteinField.setTextColor(getResources().getColor(R.color.middlegrey)); + + fatField.setText(String.format(Locale.ENGLISH, "%.2f", referenceActivity.fat)); + fatField.setFocusable(false); + fatField.setClickable(false); + fatField.setTextColor(getResources().getColor(R.color.middlegrey)); + + satFatField.setText(String.format(Locale.ENGLISH, "%.2f", referenceActivity.satFat)); + satFatField.setFocusable(false); + satFatField.setClickable(false); + satFatField.setTextColor(getResources().getColor(R.color.middlegrey)); + } else if (isVisible && !referenceActivity.productSet) { EditText nameField = parentHolder.findViewById(R.id.input_food); EditText caloriesField = parentHolder.findViewById(R.id.input_calories); + EditText carbsField = parentHolder.findViewById(R.id.input_carbs); + EditText sugarField = parentHolder.findViewById(R.id.input_sugar); + EditText proteinField = parentHolder.findViewById(R.id.input_protein); + EditText fatField = parentHolder.findViewById(R.id.input_fat); + EditText satFatField = parentHolder.findViewById(R.id.input_satFat); + nameField.setText(""); nameField.setFocusable(true); nameField.setFocusableInTouchMode(true); nameField.setClickable(true); nameField.setTextColor(getResources().getColor(R.color.black)); + caloriesField.setText(""); caloriesField.setFocusable(true); caloriesField.setFocusableInTouchMode(true); caloriesField.setClickable(true); caloriesField.setTextColor(getResources().getColor(R.color.black)); + + carbsField.setText(""); + carbsField.setFocusable(true); + carbsField.setFocusableInTouchMode(true); + carbsField.setClickable(true); + carbsField.setTextColor(getResources().getColor(R.color.black)); + + sugarField.setText(""); + sugarField.setFocusable(true); + sugarField.setFocusableInTouchMode(true); + sugarField.setClickable(true); + sugarField.setTextColor(getResources().getColor(R.color.black)); + + proteinField.setText(""); + proteinField.setFocusable(true); + proteinField.setFocusableInTouchMode(true); + proteinField.setClickable(true); + proteinField.setTextColor(getResources().getColor(R.color.black)); + + fatField.setText(""); + fatField.setFocusable(true); + fatField.setFocusableInTouchMode(true); + fatField.setClickable(true); + fatField.setTextColor(getResources().getColor(R.color.black)); + + satFatField.setText(""); + satFatField.setFocusable(true); + satFatField.setFocusableInTouchMode(true); + satFatField.setClickable(true); + satFatField.setTextColor(getResources().getColor(R.color.black)); } } @@ -156,12 +274,18 @@ public void setUserVisibleHint(boolean isVisible) { * @param caloriesString calories per 100g * @return true if successful */ - private boolean makeDatabaseEntry(String name, String amountString, String caloriesString) { + private boolean makeDatabaseEntry(String name, String amountString, String caloriesString, String carbsString, String sugarString, String proteinString, String fatString, String satFatString) { try { int amount = Integer.parseInt(amountString); float calories = Float.parseFloat(caloriesString); + float carbs = Float.parseFloat(carbsString); + float sugar = Float.parseFloat(sugarString); + float protein = Float.parseFloat(proteinString); + float fat = Float.parseFloat(fatString); + float satFat = Float.parseFloat(satFatString); + // We haven't explicitly chosen a product so the productId is 0 for unknown - databaseFacade.insertEntry(amount, ((BaseAddFoodActivity) referenceActivity).date, name, calories, 0); + databaseFacade.insertEntry(amount, ((BaseAddFoodActivity) referenceActivity).date, name, calories, carbs, sugar, protein, fat, satFat, 0); } catch (Exception e) { // something went wrong so the entry wasn't successful e.printStackTrace(); @@ -178,7 +302,7 @@ private boolean makeDatabaseEntry(String name, String amountString, String calor * @param view the view * @return returns true is all entries are valid */ - private boolean validateResponses(String name, String amount, String calories, View view) { + private boolean validateResponses(String name, String amount, String calories, String carbs, String sugar, String protein, String fat, String satFat, View view) { if("".equals(name)){ showErrorMessage(referenceActivity.findViewById(R.id.inputFoodName), R.string.error_food_missing); return false; @@ -190,6 +314,8 @@ private boolean validateResponses(String name, String amount, String calories, V return false; } + + try { Integer.parseInt(amount); } catch (NumberFormatException e) { @@ -203,6 +329,24 @@ private boolean validateResponses(String name, String amount, String calories, V showErrorMessage(referenceActivity.findViewById(R.id.inputCalories), R.string.error_calories_nan); return false; } + try { + Float.parseFloat(carbs); + } catch (NumberFormatException e) { + showErrorMessage(referenceActivity.findViewById(R.id.inputCalories), R.string.error_carbs_nan); + return false; + } + try { + Float.parseFloat(protein); + } catch (NumberFormatException e) { + showErrorMessage(referenceActivity.findViewById(R.id.inputCalories), R.string.error_protein_nan); + return false; + } + try { + Float.parseFloat(fat); + } catch (NumberFormatException e) { + showErrorMessage(referenceActivity.findViewById(R.id.inputCalories), R.string.error_fat_nan); + return false; + } return true; } diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/BaseAddFoodActivity.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/BaseAddFoodActivity.java index 1d07cc4..8fe800e 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/BaseAddFoodActivity.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/BaseAddFoodActivity.java @@ -43,6 +43,16 @@ public class BaseAddFoodActivity extends AppCompatActivity { String name; // Calories per 100g float calories; + // carbs per 100g + float carbs; + // sugar per 100g + float sugar; + // protein per 100g + float protein; + // fat per 100g + float fat; + // satFat of the product + float satFat; // ID of the product int id; diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/MonthStatisticFragment.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/MonthStatisticFragment.java index 78e61f2..1583f60 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/MonthStatisticFragment.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/MonthStatisticFragment.java @@ -20,6 +20,7 @@ import android.app.DatePickerDialog; import android.arch.lifecycle.Observer; import android.arch.lifecycle.ViewModelProviders; +import android.graphics.Color; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; @@ -43,6 +44,7 @@ import org.secuso.privacyfriendlyfoodtracker.ui.viewmodels.SharedStatisticViewModel; import java.math.BigDecimal; +import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; @@ -61,6 +63,9 @@ public class MonthStatisticFragment extends Fragment { View parentHolder; TextView textView; DatabaseFacade databaseFacade; + TextView carbsTextView; + TextView proteinTextView; + TextView fatTextView; public MonthStatisticFragment() { // Required empty public constructor @@ -80,6 +85,10 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Log.e("Error", e.getMessage()); } textView = parentHolder.findViewById(R.id.periodCalories1); + carbsTextView = parentHolder.findViewById(R.id.periodCarbs1); + proteinTextView = parentHolder.findViewById(R.id.periodProtein1); + fatTextView = parentHolder.findViewById(R.id.periodFat1); + final TextView editText = (TextView) parentHolder.findViewById(R.id.datepicker); editText.setText(DateHelper.dateToString(sharedStatisticViewModel.getDate())); editText.setOnClickListener(new View.OnClickListener() { @@ -132,16 +141,56 @@ public void onChanged(@Nullable Calendar calendar) { void UpdateGraph() { + try { final Date startDate = getMonthByValue(-1); final Date endDate = getMonthByValue(0); List consumedEntriesList = databaseFacade.getCaloriesPerDayinPeriod(startDate,endDate); List calories = databaseFacade.getPeriodCalories(startDate,endDate); + + DataPoint[] dataPointInterfaces = new DataPoint[consumedEntriesList.size()]; for (int i = 0; i < consumedEntriesList.size(); i++) { dataPointInterfaces[i] = (new DataPoint(consumedEntriesList.get(i).unique1.getTime(), consumedEntriesList.get(i).unique2/100)); } + + List consumedCarbsEntriesList = databaseFacade.getCarbsPerDayinPeriod(startDate, endDate); + List carbs = databaseFacade.getPeriodCarbs(startDate, endDate); + DataPoint[] carbsDataPointInterfaces = new DataPoint[consumedCarbsEntriesList.size()]; + for (int i = 0; i < consumedCarbsEntriesList.size(); i++) { + carbsDataPointInterfaces[i] = (new DataPoint(consumedCarbsEntriesList.get(i).unique1.getTime(), consumedCarbsEntriesList.get(i).unique2/100)); + } + + List consumedSugarEntriesList = databaseFacade.getSugarPerDayinPeriod(startDate, endDate); + List sugar = databaseFacade.getPeriodSugar(startDate, endDate); + DataPoint[] sugarDataPointInterfaces = new DataPoint[consumedSugarEntriesList.size()]; + for (int i = 0; i < consumedSugarEntriesList.size(); i++) { + sugarDataPointInterfaces[i] = (new DataPoint(consumedSugarEntriesList.get(i).unique1.getTime(), consumedSugarEntriesList.get(i).unique2/100)); + } + + List consumedProteinEntriesList = databaseFacade.getProteinPerDayinPeriod(startDate, endDate); + List protein = databaseFacade.getPeriodProtein(startDate, endDate); + DataPoint[] proteinDataPointInterfaces = new DataPoint[consumedProteinEntriesList.size()]; + for (int i = 0; i < consumedProteinEntriesList.size(); i++) { + proteinDataPointInterfaces[i] = (new DataPoint(consumedProteinEntriesList.get(i).unique1.getTime(), consumedProteinEntriesList.get(i).unique2/100)); + } + + List consumedFatEntriesList = databaseFacade.getFatPerDayinPeriod(startDate, endDate); + List fat = databaseFacade.getPeriodFat(startDate, endDate); + DataPoint[] fatDataPointInterfaces = new DataPoint[consumedFatEntriesList.size()]; + for (int i = 0; i < consumedFatEntriesList.size(); i++) { + fatDataPointInterfaces[i] = (new DataPoint(consumedFatEntriesList.get(i).unique1.getTime(), consumedFatEntriesList.get(i).unique2/100)); + } + + List consumedSatFatEntriesList = databaseFacade.getSatFatPerDayinPeriod(startDate, endDate); + List satFat = databaseFacade.getPeriodSatFat(startDate, endDate); + DataPoint[] satFatDataPointInterfaces = new DataPoint[consumedSatFatEntriesList.size()]; + for (int i = 0; i < consumedSatFatEntriesList.size(); i++) { + satFatDataPointInterfaces[i] = (new DataPoint(consumedSatFatEntriesList.get(i).unique1.getTime(), consumedSatFatEntriesList.get(i).unique2/100)); + } + + if (calories.size() != 0) { Calendar startDateCalendar = Calendar.getInstance(); @@ -153,6 +202,57 @@ void UpdateGraph() { float averageCalories = periodCalories/periodDays; BigDecimal averageCaloriesBigDecimal = round(averageCalories,0) ; textView.setText(averageCaloriesBigDecimal.toString()); + + } + + Calendar startDateCalendar = Calendar.getInstance(); + startDateCalendar.setTime(startDate); + Calendar endDateCalendar = Calendar.getInstance(); + endDateCalendar.setTime(endDate); + float periodDays = daysBetween( endDateCalendar,startDateCalendar); + + if (calories.size() != 0) { + + float periodCalories = calories.get(0).unique2; + float averageCalories = periodCalories/periodDays; + BigDecimal averageCaloriesBigDecimal = round(averageCalories,0) ; + textView.setText(averageCaloriesBigDecimal.toString()); + + } + if (carbs.size() != 0 && sugar.size() != 0) { + + float periodCarbs = carbs.get(0).unique2; + float averageCarbs = periodCarbs/periodDays; + BigDecimal averageCarbsBigDecimal = round(averageCarbs,0) ; + + float periodSugar = sugar.get(0).unique2; + float averageSugar = periodSugar/periodDays; + BigDecimal averageSugarBigDecimal = round(averageSugar,0) ; + + carbsTextView.setText(averageCarbsBigDecimal.toString() + "(" + averageSugarBigDecimal + ")"); + + } + if (protein.size() != 0) { + + float periodProtein = protein.get(0).unique2; + float averageProtein = periodProtein/periodDays; + BigDecimal averageProteinBigDecimal = round(averageProtein,0) ; + proteinTextView.setText(averageProteinBigDecimal.toString()); + + } + + if (fat.size() != 0 && satFat.size() != 0) { + + float periodFat = fat.get(0).unique2; + float averageFat = periodFat/periodDays; + BigDecimal averageFatBigDecimal = round(averageFat,0) ; + + float periodSatFat= satFat.get(0).unique2; + float averageSatFat = periodSatFat/periodDays; + BigDecimal averageSatFatBigDecimal = round(averageSatFat,0) ; + + fatTextView.setText(averageFatBigDecimal.toString() + "(" + averageSatFatBigDecimal + ")"); + } GraphView graph = (GraphView) parentHolder.findViewById(R.id.graph); LineGraphSeries series = new LineGraphSeries<>(dataPointInterfaces); @@ -165,6 +265,55 @@ void UpdateGraph() { graph.getGridLabelRenderer().setTextSize(40); graph.getViewport().setScrollable(true); graph.getGridLabelRenderer().setHorizontalLabelsAngle(135); + + + GraphView carbsGraph = (GraphView) parentHolder.findViewById(R.id.graphCarbs); + LineGraphSeries carbsSeries = new LineGraphSeries<>(carbsDataPointInterfaces); + carbsGraph.addSeries(carbsSeries); + LineGraphSeries sugarSeries = new LineGraphSeries<>(sugarDataPointInterfaces); + sugarSeries.setColor(Color.RED); + carbsGraph.addSeries(sugarSeries); + carbsGraph.getGridLabelRenderer().setLabelFormatter(new DateAsXAxisLabelFormatter(referenceActivity)); + carbsGraph.getGridLabelRenderer().setHumanRounding(false, true); + carbsGraph.getViewport().setMinX(startDate.getTime()); + carbsGraph.getViewport().setMaxX(endDate.getTime()); + carbsGraph.getViewport().setXAxisBoundsManual(true); + + carbsGraph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space + carbsGraph.getGridLabelRenderer().setTextSize(40); + carbsGraph.getViewport().setScrollable(true); + carbsGraph.getGridLabelRenderer().setHorizontalLabelsAngle(135); + + GraphView proteinGraph = (GraphView) parentHolder.findViewById(R.id.graphProtein); + LineGraphSeries proteinSeries = new LineGraphSeries<>(proteinDataPointInterfaces); + proteinGraph.addSeries(proteinSeries); + proteinGraph.getGridLabelRenderer().setLabelFormatter(new DateAsXAxisLabelFormatter(referenceActivity)); + proteinGraph.getGridLabelRenderer().setHumanRounding(false, true); + proteinGraph.getViewport().setMinX(startDate.getTime()); + proteinGraph.getViewport().setMaxX(endDate.getTime()); + proteinGraph.getViewport().setXAxisBoundsManual(true); + + proteinGraph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space + proteinGraph.getGridLabelRenderer().setTextSize(40); + proteinGraph.getViewport().setScrollable(true); + proteinGraph.getGridLabelRenderer().setHorizontalLabelsAngle(135); + + GraphView fatGraph = (GraphView) parentHolder.findViewById(R.id.graphFat); + LineGraphSeries fatSeries = new LineGraphSeries<>(fatDataPointInterfaces); + fatGraph.addSeries(fatSeries); + LineGraphSeries satFatSeries = new LineGraphSeries<>(satFatDataPointInterfaces); + satFatSeries.setColor(Color.RED); + fatGraph.addSeries(satFatSeries); + fatGraph.getGridLabelRenderer().setLabelFormatter(new DateAsXAxisLabelFormatter(referenceActivity)); + fatGraph.getGridLabelRenderer().setHumanRounding(false, true); + fatGraph.getViewport().setMinX(startDate.getTime()); + fatGraph.getViewport().setMaxX(endDate.getTime()); + fatGraph.getViewport().setXAxisBoundsManual(true); + + fatGraph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space + fatGraph.getGridLabelRenderer().setTextSize(40); + fatGraph.getViewport().setScrollable(true); + fatGraph.getGridLabelRenderer().setHorizontalLabelsAngle(135); } catch (Exception e) { Log.e("Error", e.getMessage()); } diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/OverviewActivity.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/OverviewActivity.java index 60159bb..3c60d59 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/OverviewActivity.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/OverviewActivity.java @@ -29,6 +29,7 @@ import android.content.DialogInterface; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.constraint.Barrier; import android.support.v7.app.ActionBar; import android.support.v7.widget.CardView; import android.text.InputFilter; @@ -267,22 +268,36 @@ private ViewGroup getEntryList() { } /** - * Refreshes the calorie counter at the top of the activity. + * Refreshes the calorie and macroCounter counter at the top of the activity. * Recounts calories for all Entries of the day. */ private void refreshTotalCalorieCounter(@Nullable List entries) { BigDecimal totalCalories = new BigDecimal("0"); + BigDecimal totalCarbs = new BigDecimal("0"); + BigDecimal totalSugar = new BigDecimal("0"); + BigDecimal totalProtein = new BigDecimal("0"); + BigDecimal totalFat = new BigDecimal("0"); + BigDecimal totalSatFat = new BigDecimal("0"); TextView heading = this.findViewById(R.id.overviewHeading); + TextView macrosOverview = this.findViewById(R.id.overviewMacros); + String cal = getString(R.string.total_calories); Date d = getDateForActivity(); String formattedDate = getFormattedDate(d); if(entries != null) { for (DatabaseEntry e : entries) { totalCalories = totalCalories.add(BigDecimal.valueOf(e.energy * e.amount / 100)); + totalCarbs = totalCarbs.add(BigDecimal.valueOf(e.carbs * e.amount / 100)); + totalSugar = totalSugar.add(BigDecimal.valueOf(e.sugar * e.amount / 100)); + totalProtein = totalProtein.add(BigDecimal.valueOf(e.protein * e.amount / 100)); + totalFat = totalFat.add(BigDecimal.valueOf(e.fat * e.amount / 100)); + totalSatFat = totalSatFat.add(BigDecimal.valueOf(e.satFat * e.amount / 100)); + // totalCalories += (e.energy * e.amount) / 100; } } heading.setText(String.format(Locale.ENGLISH, " %s: %.2f %s", formattedDate, totalCalories, cal)); + macrosOverview.setText(String.format(Locale.ENGLISH, "Carbs(sugar): %.2f (%.2f) - Protein: %.2f - Fat (sat.): %.2f (%.2f)", totalCarbs, totalSugar, totalProtein, totalFat, totalSatFat)); } /** @@ -363,6 +378,56 @@ private float getConsumedCaloriesForEntry(DatabaseEntry e) { return (e.amount * e.energy) / 100; } + /** + * The consumed carbs per entry + * + * @param e a DatabaseEntry + * @return the calculated consumed carbs + */ + private float getConsumedCarbsForEntry(DatabaseEntry e) { + return (e.amount * e.carbs) / 100; + } + + /** + * The consumed sugar per entry + * + * @param e a DatabaseEntry + * @return the calculated consumed sugar + */ + private float getConsumedSugarForEntry(DatabaseEntry e) { + return (e.amount * e.sugar) / 100; + } + + /** + * The consumed protein per entry + * + * @param e a DatabaseEntry + * @return the calculated consumed protein + */ + private float getConsumedProteinForEntry(DatabaseEntry e) { + return (e.amount * e.protein) / 100; + } + + /** + * The consumed fat per entry + * + * @param e a DatabaseEntry + * @return the calculated consumed fat + */ + private float getConsumedFatForEntry(DatabaseEntry e) { + return (e.amount * e.fat) / 100; + } + + /** + * The consumed saturated fat per entry + * + * @param e a DatabaseEntry + * @return the calculated consumed fat + */ + private float getConsumedSatFatForEntry(DatabaseEntry e) { + return (e.amount * e.satFat) / 100; + } + /** * Creates a CheckedCardView from the entry * @@ -390,6 +455,7 @@ private CardView createCardViewForEntry(DatabaseEntry e) { getResources().getDimension(R.dimen.slide_actions)); TextView id = new TextView(this); + // Each CardView needs an ID to reference in the ConstraintText name.setId(View.generateViewId()); amount.setId(View.generateViewId()); @@ -397,13 +463,38 @@ private CardView createCardViewForEntry(DatabaseEntry e) { calories.setId(View.generateViewId()); id.setText(e.id); + name.setText(e.name); amount.setText(Integer.toString(e.amount) + "g"); energy.setText(String.format(Locale.ENGLISH, " %.2f kCal/100g", e.energy)); - calories.setText(String.format(Locale.ENGLISH, "%.2f kCal", getConsumedCaloriesForEntry(e))); + + //only print out macros with mass > 0 + String calorieAndMacrosText = String.format(Locale.ENGLISH, "%.2f kCal",getConsumedCaloriesForEntry(e)); + float consumedCarbs = getConsumedCarbsForEntry(e); + if(consumedCarbs > 0.01){ + calorieAndMacrosText += String.format(Locale.ENGLISH, "\n%.2fg Carbs",consumedCarbs); + } + float consumedSugar = getConsumedSugarForEntry(e); + if(consumedSugar > 0.01){ + calorieAndMacrosText += String.format(Locale.ENGLISH, "\n%.2fg Sugar",consumedSugar); + } + float consumedProtein = getConsumedProteinForEntry(e); + if(consumedProtein > 0.01){ + calorieAndMacrosText += String.format(Locale.ENGLISH, "\n%.2fg Protein",consumedProtein); + } + float consumedFat = getConsumedFatForEntry(e); + if(consumedFat > 0.01){ + calorieAndMacrosText += String.format(Locale.ENGLISH, "\n%.2fg Fat",consumedFat); + } + float consumedSatFat = getConsumedSatFatForEntry(e); + if(consumedSatFat > 0.01){ + calorieAndMacrosText += String.format(Locale.ENGLISH, "\n%.2fg sat. Fat",consumedSatFat); + } + calories.setText(calorieAndMacrosText); // id is just an invisible attribute on each card id.setVisibility(View.INVISIBLE); + set.constrainWidth(amount.getId(), ConstraintSet.WRAP_CONTENT); set.constrainHeight(amount.getId(), ConstraintSet.WRAP_CONTENT); set.constrainWidth(energy.getId(), ConstraintSet.WRAP_CONTENT); @@ -429,12 +520,14 @@ private CardView createCardViewForEntry(DatabaseEntry e) { set.constrainDefaultHeight(calories.getId(), ConstraintSet.MATCH_CONSTRAINT_WRAP); set.constrainDefaultWidth(calories.getId(), ConstraintSet.MATCH_CONSTRAINT_WRAP); + int barrierId = View.generateViewId(); + set.createBarrier(barrierId,ConstraintSet.TOP,name.getId(),calories.getId()); - set.connect(amount.getId(), ConstraintSet.TOP, name.getId(), ConstraintSet.BOTTOM, 20); + set.connect(amount.getId(), ConstraintSet.TOP, barrierId, ConstraintSet.BOTTOM, 20); set.connect(amount.getId(), ConstraintSet.RIGHT, ConstraintSet.PARENT_ID, ConstraintSet.RIGHT, 20); set.connect(amount.getId(), ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM, 20); - set.connect(energy.getId(), ConstraintSet.TOP, name.getId(), ConstraintSet.BOTTOM, 20); + set.connect(energy.getId(), ConstraintSet.TOP, barrierId, ConstraintSet.BOTTOM, 20); set.connect(energy.getId(), ConstraintSet.LEFT, ConstraintSet.PARENT_ID, ConstraintSet.LEFT, 20); set.connect(energy.getId(), ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM, 20); diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/SearchFoodFragment.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/SearchFoodFragment.java index 9fbc43f..4df792d 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/SearchFoodFragment.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/SearchFoodFragment.java @@ -192,9 +192,37 @@ public boolean onInterceptTouchEvent(@NonNull RecyclerView recyclerView, @NonNul cal = cal.split(" ")[0]; float calories = Float.parseFloat(cal); + TextView carbView = childView.findViewById(R.id.resultCarbs); + String carbsString = carbView.getText().toString(); + carbsString = carbsString.split(" ")[0]; + float carbs = Float.parseFloat(carbsString); + + String sugarString = carbView.getText().toString(); + sugarString = sugarString.split("\\(")[1].split("\\)")[0]; + float sugar = Float.parseFloat(sugarString); + + TextView protView = childView.findViewById(R.id.resultProtein); + String prot = protView.getText().toString(); + prot = prot.split(" ")[0]; + float protein = Float.parseFloat(prot); + + TextView fatView = childView.findViewById(R.id.resultFat); + String fatS = fatView.getText().toString(); + fatS = fatS.split(" ")[0]; + float fat = Float.parseFloat(fatS); + + String satFatS = fatView.getText().toString(); + satFatS = satFatS.split("\\(")[1].split("\\)")[0]; + float satFat = Float.parseFloat(satFatS); + ((BaseAddFoodActivity) referenceActivity).id = id; ((BaseAddFoodActivity) referenceActivity).name = name; ((BaseAddFoodActivity) referenceActivity).calories = calories; + ((BaseAddFoodActivity) referenceActivity).carbs = carbs; + ((BaseAddFoodActivity) referenceActivity).sugar = sugar; + ((BaseAddFoodActivity) referenceActivity).protein = protein; + ((BaseAddFoodActivity) referenceActivity).fat = fat; + ((BaseAddFoodActivity) referenceActivity).satFat = satFat; ((BaseAddFoodActivity) referenceActivity).productSet = true; ViewPager pager = referenceActivity.findViewById(R.id.pager_food); System.out.println("Setting page"); diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/WeekStatisticFragment.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/WeekStatisticFragment.java index e421d33..a7de00d 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/WeekStatisticFragment.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/WeekStatisticFragment.java @@ -21,6 +21,7 @@ import android.app.DatePickerDialog; import android.arch.lifecycle.Observer; import android.arch.lifecycle.ViewModelProviders; +import android.graphics.Color; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; @@ -31,6 +32,7 @@ import android.widget.Button; import android.widget.DatePicker; import android.widget.TextView; +import android.widget.Toast; import com.jjoe64.graphview.GraphView; import com.jjoe64.graphview.helper.DateAsXAxisLabelFormatter; @@ -48,6 +50,7 @@ import java.util.Calendar; import java.util.Date; import java.util.List; +import java.util.Locale; import static org.secuso.privacyfriendlyfoodtracker.ui.helper.MathHelper.round; @@ -63,6 +66,10 @@ public class WeekStatisticFragment extends Fragment { View parentHolder; TextView textView; DatabaseFacade databaseFacade; + TextView carbsTextView; + TextView proteinTextView; + TextView fatTextView; + public WeekStatisticFragment() { // Required empty public constructor } @@ -81,6 +88,10 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Log.e("Error", e.getMessage()); } textView = parentHolder.findViewById(R.id.periodCalories1); + carbsTextView = parentHolder.findViewById(R.id.periodCarbs1); + proteinTextView = parentHolder.findViewById(R.id.periodProtein1); + fatTextView = parentHolder.findViewById(R.id.periodFat1); + final TextView editText = (TextView) parentHolder.findViewById(R.id.datepicker); editText.setText(DateHelper.dateToString(sharedStatisticViewModel.getDate())); editText.setOnClickListener(new View.OnClickListener() { @@ -130,27 +141,82 @@ public void onChanged(@Nullable Calendar calendar) { } void UpdateGraph() { - List consumedEntriesList = new ArrayList<>(); - List calories = new ArrayList<>(); + try { Date startDate = getWeekByValue(-1); Date endDate = getWeekByValue(0); - consumedEntriesList = databaseFacade.getCaloriesPerDayinPeriod(startDate,endDate); - calories = databaseFacade.getPeriodCalories(startDate,endDate); + + List consumedEntriesList = databaseFacade.getCaloriesPerDayinPeriod(startDate, endDate); + List calories = databaseFacade.getPeriodCalories(startDate, endDate); DataPoint[] dataPointInterfaces = new DataPoint[consumedEntriesList.size()]; for (int i = 0; i < consumedEntriesList.size(); i++) { dataPointInterfaces[i] = (new DataPoint(consumedEntriesList.get(i).unique1.getTime(), consumedEntriesList.get(i).unique2/100)); } + + List consumedCarbsEntriesList = databaseFacade.getCarbsPerDayinPeriod(startDate, endDate); + List carbs = databaseFacade.getPeriodCarbs(startDate, endDate); + DataPoint[] carbsDataPointInterfaces = new DataPoint[consumedCarbsEntriesList.size()]; + for (int i = 0; i < consumedCarbsEntriesList.size(); i++) { + carbsDataPointInterfaces[i] = (new DataPoint(consumedCarbsEntriesList.get(i).unique1.getTime(), consumedCarbsEntriesList.get(i).unique2/100)); + } + + List consumedSugarEntriesList = databaseFacade.getSugarPerDayinPeriod(startDate, endDate); + List sugar = databaseFacade.getPeriodSugar(startDate, endDate); + DataPoint[] sugarDataPointInterfaces = new DataPoint[consumedSugarEntriesList.size()]; + for (int i = 0; i < consumedSugarEntriesList.size(); i++) { + sugarDataPointInterfaces[i] = (new DataPoint(consumedSugarEntriesList.get(i).unique1.getTime(), consumedSugarEntriesList.get(i).unique2/100)); + } + + List consumedProteinEntriesList = databaseFacade.getProteinPerDayinPeriod(startDate, endDate); + List protein = databaseFacade.getPeriodProtein(startDate, endDate); + DataPoint[] proteinDataPointInterfaces = new DataPoint[consumedProteinEntriesList.size()]; + for (int i = 0; i < consumedProteinEntriesList.size(); i++) { + proteinDataPointInterfaces[i] = (new DataPoint(consumedProteinEntriesList.get(i).unique1.getTime(), consumedProteinEntriesList.get(i).unique2/100)); + } + + List consumedFatEntriesList = databaseFacade.getFatPerDayinPeriod(startDate, endDate); + List fat = databaseFacade.getPeriodFat(startDate, endDate); + DataPoint[] fatDataPointInterfaces = new DataPoint[consumedFatEntriesList.size()]; + for (int i = 0; i < consumedFatEntriesList.size(); i++) { + fatDataPointInterfaces[i] = (new DataPoint(consumedFatEntriesList.get(i).unique1.getTime(), consumedFatEntriesList.get(i).unique2/100)); + } + + List consumedSatFatEntriesList = databaseFacade.getSatFatPerDayinPeriod(startDate, endDate); + List satFat = databaseFacade.getPeriodSatFat(startDate, endDate); + DataPoint[] satFatDataPointInterfaces = new DataPoint[consumedSatFatEntriesList.size()]; + for (int i = 0; i < consumedSatFatEntriesList.size(); i++) { + satFatDataPointInterfaces[i] = (new DataPoint(consumedSatFatEntriesList.get(i).unique1.getTime(), consumedSatFatEntriesList.get(i).unique2/100)); + } + int weekdays = 8; float averageCalories = calories.get(0).unique2 / weekdays; + float averageCarbs = carbs.get(0).unique2 / weekdays; + float averageSugar = sugar.get(0).unique2 / weekdays; + float averageProtein = protein.get(0).unique2 / weekdays; + float averageFat = fat.get(0).unique2 / weekdays; + float averageSatFat = satFat.get(0).unique2 / weekdays; BigDecimal averageCaloriesBigDecimal = round(averageCalories,0) ; + BigDecimal averageCarbsBigDecimal = round(averageCarbs,0) ; + BigDecimal averageSugarBigDecimal = round(averageSugar,0) ; + BigDecimal averageProteinBigDecimal = round(averageProtein,0) ; + BigDecimal averageFatBigDecimal = round(averageFat,0) ; + BigDecimal averageSatFatBigDecimal = round(averageSatFat,0) ; if (calories.size() != 0) { textView.setText(averageCaloriesBigDecimal.toString()); } + if (carbs.size() != 0 && sugar.size() != 0) { + carbsTextView.setText(averageCarbsBigDecimal.toString() + " (" + averageSugarBigDecimal.toString() +")"); + } + if (protein.size() != 0) { + proteinTextView.setText(averageProteinBigDecimal.toString()); + } + if (fat.size() != 0 && satFat.size() != 0) { + fatTextView.setText(averageFatBigDecimal.toString() + " (" + averageSatFatBigDecimal.toString() +")"); + } GraphView graph = (GraphView) parentHolder.findViewById(R.id.graph); LineGraphSeries series = new LineGraphSeries<>(dataPointInterfaces); graph.addSeries(series); @@ -164,6 +230,54 @@ void UpdateGraph() { graph.getGridLabelRenderer().setTextSize(40); graph.getViewport().setScrollable(true); graph.getGridLabelRenderer().setHorizontalLabelsAngle(135); + + GraphView carbsGraph = (GraphView) parentHolder.findViewById(R.id.graphCarbs); + LineGraphSeries carbsSeries = new LineGraphSeries<>(carbsDataPointInterfaces); + carbsGraph.addSeries(carbsSeries); + LineGraphSeries sugarSeries = new LineGraphSeries<>(sugarDataPointInterfaces); + sugarSeries.setColor(Color.RED); + carbsGraph.addSeries(sugarSeries); + carbsGraph.getGridLabelRenderer().setLabelFormatter(new DateAsXAxisLabelFormatter(referenceActivity)); + carbsGraph.getGridLabelRenderer().setHumanRounding(false, true); + carbsGraph.getViewport().setMinX(startDate.getTime()); + carbsGraph.getViewport().setMaxX(endDate.getTime()); + carbsGraph.getViewport().setXAxisBoundsManual(true); + + carbsGraph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space + carbsGraph.getGridLabelRenderer().setTextSize(40); + carbsGraph.getViewport().setScrollable(true); + carbsGraph.getGridLabelRenderer().setHorizontalLabelsAngle(135); + + GraphView proteinGraph = (GraphView) parentHolder.findViewById(R.id.graphProtein); + LineGraphSeries proteinSeries = new LineGraphSeries<>(proteinDataPointInterfaces); + proteinGraph.addSeries(proteinSeries); + proteinGraph.getGridLabelRenderer().setLabelFormatter(new DateAsXAxisLabelFormatter(referenceActivity)); + proteinGraph.getGridLabelRenderer().setHumanRounding(false, true); + proteinGraph.getViewport().setMinX(startDate.getTime()); + proteinGraph.getViewport().setMaxX(endDate.getTime()); + proteinGraph.getViewport().setXAxisBoundsManual(true); + + proteinGraph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space + proteinGraph.getGridLabelRenderer().setTextSize(40); + proteinGraph.getViewport().setScrollable(true); + proteinGraph.getGridLabelRenderer().setHorizontalLabelsAngle(135); + + GraphView fatGraph = (GraphView) parentHolder.findViewById(R.id.graphFat); + LineGraphSeries fatSeries = new LineGraphSeries<>(fatDataPointInterfaces); + fatGraph.addSeries(fatSeries); + LineGraphSeries satFatSeries = new LineGraphSeries<>(satFatDataPointInterfaces); + satFatSeries.setColor(Color.RED); + fatGraph.addSeries(satFatSeries); + fatGraph.getGridLabelRenderer().setLabelFormatter(new DateAsXAxisLabelFormatter(referenceActivity)); + fatGraph.getGridLabelRenderer().setHumanRounding(false, true); + fatGraph.getViewport().setMinX(startDate.getTime()); + fatGraph.getViewport().setMaxX(endDate.getTime()); + fatGraph.getViewport().setXAxisBoundsManual(true); + + fatGraph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space + fatGraph.getGridLabelRenderer().setTextSize(40); + fatGraph.getViewport().setScrollable(true); + fatGraph.getGridLabelRenderer().setHorizontalLabelsAngle(135); } catch (Exception e) { Log.e("Error", e.getMessage()); } diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/adapter/DatabaseEntry.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/adapter/DatabaseEntry.java index 5661b48..0a90ac2 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/adapter/DatabaseEntry.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/adapter/DatabaseEntry.java @@ -22,13 +22,23 @@ */ public class DatabaseEntry { public float energy; + public float carbs; + public float sugar; + public float protein; + public float fat; + public float satFat; public int amount; public String name; public String id; - public DatabaseEntry(String id, String name, int amount, float energy){ + public DatabaseEntry(String id, String name, int amount, float energy, float carbs, float sugar, float protein, float fat, float satFat){ this.id = id; this.amount = amount; this.energy = energy; + this.carbs = carbs; + this.sugar = sugar; + this.protein = protein; + this.fat = fat; + this.satFat = satFat; this.name = name; } } \ No newline at end of file diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/adapter/DatabaseFacade.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/adapter/DatabaseFacade.java index 36510c4..4395715 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/adapter/DatabaseFacade.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/adapter/DatabaseFacade.java @@ -55,16 +55,16 @@ public DatabaseFacade(Context context) throws Exception { * @param name the name * @param productId the consumed product id */ - public void insertEntry(final int amount, final java.util.Date date, final String name, final float energy, final int productId){ + public void insertEntry(final int amount, final java.util.Date date, final String name, final float energy, final float carbs, final float sugar, final float protein, final float fat, final float satFat, final int productId){ Executors.newSingleThreadExecutor().execute(new Runnable() { @Override public void run() { int existingProductId = 0; //If the productId is 0 we need to create a new product in the database if (0 == productId) { - insertProductPrivate(name, energy, ""); + insertProductPrivate(name, energy, carbs, sugar, protein, fat, satFat, ""); // retrieve ProductId of newly created Product from database - List existingProducts = productDao.findExistingProducts(name, energy, ""); + List existingProducts = productDao.findExistingProducts(name, energy, carbs, sugar, protein, fat, satFat, ""); // There is only one existing product so we take the first one from the List Product p = existingProducts.get(0); existingProductId = p.id; @@ -120,21 +120,21 @@ public void run() { * @param energy the energy * @param barcode the barcode */ - public void insertProduct(final String name, final float energy, final String barcode){ + public void insertProduct(final String name, final float energy, final float carbs, final float sugar, final float protein, final float fat, final float satFat, final String barcode){ Executors.newSingleThreadExecutor().execute(new Runnable() { @Override public void run() { - insertProductPrivate(name, energy, barcode); + insertProductPrivate(name, energy, carbs,sugar, protein, fat, satFat, barcode); } }); } - private void insertProductPrivate(String name, float energy, String barcode) { - List res = productDao.findExistingProducts(name, energy, barcode); + private void insertProductPrivate(String name, float energy, float carbs, float sugar, float protein, float fat, float satFat, String barcode) { + List res = productDao.findExistingProducts(name, energy, carbs, sugar, protein, fat, satFat, barcode); if (res.size() != 0) { return; } - productDao.insert(new Product(0, name, energy, barcode)); + productDao.insert(new Product(0, name, energy, carbs, sugar, protein, fat, satFat, barcode)); } /** @@ -165,7 +165,7 @@ public List getEntriesForDay(java.util.Date date) { List res = consumedEntriesDao.findConsumedEntriesForDate(new java.sql.Date(date.getTime())); for(ConsumedEntries consumedEntry : res) { Product product = productDao.findProductById(consumedEntry.productId); - databaseEntries.add(new DatabaseEntry(String.valueOf(consumedEntry.id),consumedEntry.name, consumedEntry.amount, product.energy)); + databaseEntries.add(new DatabaseEntry(String.valueOf(consumedEntry.id),consumedEntry.name, consumedEntry.amount, product.energy, product.carbs, product.sugar, product.protein, product.fat, product.satFat)); } } catch (Exception e) { @@ -194,6 +194,106 @@ public List getCaloriesPerDayinPeriod( return consumedEntrieAndProductDao.getCaloriesPerDayinPeriod(new java.sql.Date(startDate.getTime()), new java.sql.Date(endDate.getTime())); } + /** + * Returns the sum of carbs per day for a time period. + * @param startDate the start date + * @param endDate the end date + * @return the carbs sum per day and the associated date + */ + public List getPeriodCarbs(java.util.Date startDate, java.util.Date endDate){ + return consumedEntrieAndProductDao.getCarbsPeriod(new java.sql.Date(startDate.getTime()), new java.sql.Date(endDate.getTime())); + } + + /** + * Returns the sum of carbs between two dates. + * @param startDate the start date + * @param endDate the end date + * @return the carbs sum (list position 0) + */ + public List getCarbsPerDayinPeriod(java.util.Date startDate, java.util.Date endDate){ + return consumedEntrieAndProductDao.getCarbsPerDayinPeriod(new java.sql.Date(startDate.getTime()), new java.sql.Date(endDate.getTime())); + } + + /** + * Returns the sum of sugar per day for a time period. + * @param startDate the start date + * @param endDate the end date + * @return the sugar sum per day and the associated date + */ + public List getPeriodSugar(java.util.Date startDate, java.util.Date endDate){ + return consumedEntrieAndProductDao.getSugarPeriod(new java.sql.Date(startDate.getTime()), new java.sql.Date(endDate.getTime())); + } + + /** + * Returns the sum of sugar between two dates. + * @param startDate the start date + * @param endDate the end date + * @return the sugar sum (list position 0) + */ + public List getSugarPerDayinPeriod(java.util.Date startDate, java.util.Date endDate){ + return consumedEntrieAndProductDao.getSugarPerDayinPeriod(new java.sql.Date(startDate.getTime()), new java.sql.Date(endDate.getTime())); + } + + /** + * Returns the sum of protein per day for a time period. + * @param startDate the start date + * @param endDate the end date + * @return the protein sum per day and the associated date + */ + public List getPeriodProtein(java.util.Date startDate, java.util.Date endDate){ + return consumedEntrieAndProductDao.getProteinPeriod(new java.sql.Date(startDate.getTime()), new java.sql.Date(endDate.getTime())); + } + + /** + * Returns the sum of protein between two dates. + * @param startDate the start date + * @param endDate the end date + * @return the protein sum (list position 0) + */ + public List getProteinPerDayinPeriod(java.util.Date startDate, java.util.Date endDate){ + return consumedEntrieAndProductDao.getProteinPerDayinPeriod(new java.sql.Date(startDate.getTime()), new java.sql.Date(endDate.getTime())); + } + + /** + * Returns the sum of fat per day for a time period. + * @param startDate the start date + * @param endDate the end date + * @return the fat sum per day and the associated date + */ + public List getPeriodFat(java.util.Date startDate, java.util.Date endDate){ + return consumedEntrieAndProductDao.getFatPeriod(new java.sql.Date(startDate.getTime()), new java.sql.Date(endDate.getTime())); + } + + /** + * Returns the sum of fat between two dates. + * @param startDate the start date + * @param endDate the end date + * @return the fat sum (list position 0) + */ + public List getFatPerDayinPeriod(java.util.Date startDate, java.util.Date endDate){ + return consumedEntrieAndProductDao.getFatPerDayinPeriod(new java.sql.Date(startDate.getTime()), new java.sql.Date(endDate.getTime())); + } + + /** + * Returns the sum of saturated fat per day for a time period. + * @param startDate the start date + * @param endDate the end date + * @return the fat sum per day and the associated date + */ + public List getPeriodSatFat(java.util.Date startDate, java.util.Date endDate){ + return consumedEntrieAndProductDao.getSatFatPeriod(new java.sql.Date(startDate.getTime()), new java.sql.Date(endDate.getTime())); + } + + /** + * Returns the sum of saturated fat between two dates. + * @param startDate the start date + * @param endDate the end date + * @return the fat sum (list position 0) + */ + public List getSatFatPerDayinPeriod(java.util.Date startDate, java.util.Date endDate){ + return consumedEntrieAndProductDao.getSatFatPerDayinPeriod(new java.sql.Date(startDate.getTime()), new java.sql.Date(endDate.getTime())); + } + /** * Returns a list of products containing the input string * @param name the search term diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/adapter/SearchResultAdapter.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/adapter/SearchResultAdapter.java index 7bc4e6b..0e7b2b7 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/adapter/SearchResultAdapter.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/adapter/SearchResultAdapter.java @@ -93,6 +93,9 @@ public void onBindViewHolder(SearchViewHolder holder, int position) { // - replace the contents of the view with that element ((TextView) holder.mCardView.findViewById(R.id.resultName)).setText(mDataset.get(position).name); ((TextView) holder.mCardView.findViewById(R.id.resultCalories)).setText(String.format(Locale.ENGLISH,"%.2f kCal", mDataset.get(position).energy)); + ((TextView) holder.mCardView.findViewById(R.id.resultCarbs)).setText(String.format(Locale.ENGLISH,"%.2f (%.2f) g Carbs(sugar)", mDataset.get(position).carbs, mDataset.get(position).sugar)); + ((TextView) holder.mCardView.findViewById(R.id.resultProtein)).setText(String.format(Locale.ENGLISH,"%.2f g Protein", mDataset.get(position).protein)); + ((TextView) holder.mCardView.findViewById(R.id.resultFat)).setText(String.format(Locale.ENGLISH,"%.2f (%.2f) g Fat(sat. fat)", mDataset.get(position).fat, mDataset.get(position).satFat)); ((TextView) holder.mCardView.findViewById(R.id.resultId)).setText(String.format(Locale.ENGLISH, "%d", mDataset.get(position).id)); } diff --git a/app/src/main/res/layout-land/content_food.xml b/app/src/main/res/layout-land/content_food.xml index 454523f..b716d68 100644 --- a/app/src/main/res/layout-land/content_food.xml +++ b/app/src/main/res/layout-land/content_food.xml @@ -6,69 +6,175 @@ android:layout_height="match_parent" tools:context=".ui.BaseAddFoodActivity" android:fitsSystemWindows="true"> - - - + android:layout_height="match_parent" + android:orientation="vertical"> + - + app:errorEnabled="true" + app:layout_constraintTop_toTopOf="parent" + tools:layout_editor_absoluteX="16dp"> - + - + - + app:errorEnabled="true" + app:layout_constraintTop_toBottomOf="@+id/inputFoodName"> - - + + + + + + + + + + + + + + + + - + app:errorEnabled="true" + app:layout_constraintTop_toBottomOf="@+id/inputCarbs"> + + + + + + + + + + + + + + + + + + + + + + + + - + - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + app:layout_constraintTop_toBottomOf="@+id/overviewMacros"> + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_week_statistic.xml b/app/src/main/res/layout/fragment_week_statistic.xml index dc9b9c6..291805f 100644 --- a/app/src/main/res/layout/fragment_week_statistic.xml +++ b/app/src/main/res/layout/fragment_week_statistic.xml @@ -109,6 +109,66 @@ android:id="@+id/graph" android:layout_width="match_parent" android:layout_height="200dip" /> + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/search_result.xml b/app/src/main/res/layout/search_result.xml index ea177eb..2aa2386 100644 --- a/app/src/main/res/layout/search_result.xml +++ b/app/src/main/res/layout/search_result.xml @@ -28,6 +28,40 @@ android:id="@+id/resultCalories" app:layout_constraintRight_toRightOf="parent" app:layout_constraintLeft_toRightOf="@id/resultName" + android:text="test" + app:layout_constraintHorizontal_chainStyle="spread" + /> + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7ea2a02..8e5b484 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -110,4 +110,16 @@ Save Search for a product + Only numbers are allowed for carbs + Only numbers are allowed for protein + Only numbers are allowed for fat + g/100g + Carbs in g/100g + Protein in g/100g + Fat in g/100g + Average carbs (sugar) per day + Average protein per day + Average fat (saturated fat) per day + Sugar in g/100g + Saturated Fat in g/100g From 00f3399171d8eacbd6ec517c175cc41f124e5460 Mon Sep 17 00:00:00 2001 From: conrad69 Date: Sun, 16 May 2021 20:29:14 +0200 Subject: [PATCH 02/18] fix findConsumedEntriesForDate; and added database migration path --- .../database/ApplicationDatabase.java | 23 +++++++++++++++++-- .../database/ConsumedEntrieAndProductDao.java | 2 +- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/ApplicationDatabase.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/ApplicationDatabase.java index 7d62ea8..eaac058 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/ApplicationDatabase.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/ApplicationDatabase.java @@ -23,6 +23,7 @@ import android.arch.persistence.room.Room; import android.arch.persistence.room.RoomDatabase; import android.arch.persistence.room.TypeConverters; +import android.arch.persistence.room.migration.Migration; import android.content.Context; import android.support.annotation.NonNull; import android.util.Log; @@ -37,7 +38,7 @@ * * @author Andre Lutz */ -@Database(entities = {ConsumedEntries.class, Product.class}, version = 1, exportSchema = true) +@Database(entities = {ConsumedEntries.class, Product.class}, version = 2, exportSchema = true) @TypeConverters({DateConverter.class}) public abstract class ApplicationDatabase extends RoomDatabase { @@ -72,7 +73,8 @@ public void onCreate(@NonNull SupportSQLiteDatabase db) { Log.e("ApplicationDatabase", e.getMessage()); } } - }).build(); + }) + .addMigrations(MIGRATION_1_2).build(); } } @@ -80,6 +82,23 @@ public void onCreate(@NonNull SupportSQLiteDatabase db) { return sInstance; } + /* + Migrate the database so it contains columns with carbs,fat,satfat etc. + */ + static final Migration MIGRATION_1_2 = new Migration(1, 2) { + @Override + public void migrate(SupportSQLiteDatabase database) { + String[] newFields = new String[]{"carbs","sugar", "protein", "fat","satFat"}; + for(String field : newFields) { + database.execSQL("ALTER TABLE Product " + + " ADD COLUMN "+ field +" REAL NOT NULL default 0"); + } + } + }; + + + + private void setDatabaseCreated() { mIsDatabaseCreated.postValue(true); } diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/ConsumedEntrieAndProductDao.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/ConsumedEntrieAndProductDao.java index 6ff921e..ecb0236 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/ConsumedEntrieAndProductDao.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/ConsumedEntrieAndProductDao.java @@ -70,7 +70,7 @@ public interface ConsumedEntrieAndProductDao { @Query("SELECT consumedEntries.date AS unique1, sum(product.satFat*consumedEntries.amount/100) AS unique2 FROM consumedEntries INNER JOIN product ON consumedEntries.productId = product.id WHERE consumedEntries.date BETWEEN :dayst AND :dayet") List getSatFatPeriod(final Date dayst, final Date dayet); - @Query("SELECT consumedEntries.amount AS amount, consumedEntries.id AS id,consumedEntries.name as name, product.energy as energy FROM consumedEntries INNER JOIN product ON consumedEntries.productId = product.id WHERE consumedEntries.date=:day") + @Query("SELECT consumedEntries.amount AS amount, consumedEntries.id AS id,consumedEntries.name as name, product.energy as energy, product.carbs as carbs, product.sugar as sugar, product.protein as protein, product.fat as fat, product.satFat as satFat FROM consumedEntries INNER JOIN product ON consumedEntries.productId = product.id WHERE consumedEntries.date=:day") LiveData> findConsumedEntriesForDate(final Date day); static class DateCalories From b211a484d76c0a36c2e73c886bd79679c87d48f0 Mon Sep 17 00:00:00 2001 From: conrad69 Date: Sun, 16 May 2021 22:31:24 +0200 Subject: [PATCH 03/18] refactoring Month/WeekStatisticFragment --- .../ui/MonthStatisticFragment.java | 183 +------------ .../ui/WeekStatisticFragment.java | 248 ++++++++---------- 2 files changed, 127 insertions(+), 304 deletions(-) diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/MonthStatisticFragment.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/MonthStatisticFragment.java index 22959d2..0a2ab1a 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/MonthStatisticFragment.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/MonthStatisticFragment.java @@ -32,24 +32,16 @@ import android.widget.DatePicker; import android.widget.TextView; -import com.jjoe64.graphview.GraphView; -import com.jjoe64.graphview.helper.DateAsXAxisLabelFormatter; -import com.jjoe64.graphview.series.DataPoint; -import com.jjoe64.graphview.series.LineGraphSeries; import org.secuso.privacyfriendlyfoodtracker.R; import org.secuso.privacyfriendlyfoodtracker.ui.adapter.DatabaseFacade; import org.secuso.privacyfriendlyfoodtracker.ui.helper.DateHelper; -import org.secuso.privacyfriendlyfoodtracker.database.ConsumedEntrieAndProductDao; import org.secuso.privacyfriendlyfoodtracker.ui.viewmodels.SharedStatisticViewModel; -import java.math.BigDecimal; -import java.util.ArrayList; import java.util.Calendar; import java.util.Date; -import java.util.List; -import static org.secuso.privacyfriendlyfoodtracker.ui.helper.MathHelper.round; +import static org.secuso.privacyfriendlyfoodtracker.ui.WeekStatisticFragment.updateGraphUsingNdayPeriod; /** @@ -140,169 +132,16 @@ public void onChanged(@Nullable Calendar calendar) { } void UpdateGraph() { - - - try { - - final Date startDate = DateHelper.changeDateTimeToMidnight(getMonthByValue(-1)); - final Date endDate = DateHelper.changeDateTimeToMidnight(getMonthByValue(0)); - List consumedEntriesList = databaseFacade.getCaloriesPerDayinPeriod(startDate,endDate); - List calories = databaseFacade.getPeriodCalories(startDate,endDate); - - - DataPoint[] dataPointInterfaces = new DataPoint[consumedEntriesList.size()]; - for (int i = 0; i < consumedEntriesList.size(); i++) { - dataPointInterfaces[i] = (new DataPoint(consumedEntriesList.get(i).unique1.getTime(), consumedEntriesList.get(i).unique2/100)); - } - - List consumedCarbsEntriesList = databaseFacade.getCarbsPerDayinPeriod(startDate, endDate); - List carbs = databaseFacade.getPeriodCarbs(startDate, endDate); - DataPoint[] carbsDataPointInterfaces = new DataPoint[consumedCarbsEntriesList.size()]; - for (int i = 0; i < consumedCarbsEntriesList.size(); i++) { - carbsDataPointInterfaces[i] = (new DataPoint(consumedCarbsEntriesList.get(i).unique1.getTime(), consumedCarbsEntriesList.get(i).unique2/100)); - } - - List consumedSugarEntriesList = databaseFacade.getSugarPerDayinPeriod(startDate, endDate); - List sugar = databaseFacade.getPeriodSugar(startDate, endDate); - DataPoint[] sugarDataPointInterfaces = new DataPoint[consumedSugarEntriesList.size()]; - for (int i = 0; i < consumedSugarEntriesList.size(); i++) { - sugarDataPointInterfaces[i] = (new DataPoint(consumedSugarEntriesList.get(i).unique1.getTime(), consumedSugarEntriesList.get(i).unique2/100)); - } - - List consumedProteinEntriesList = databaseFacade.getProteinPerDayinPeriod(startDate, endDate); - List protein = databaseFacade.getPeriodProtein(startDate, endDate); - DataPoint[] proteinDataPointInterfaces = new DataPoint[consumedProteinEntriesList.size()]; - for (int i = 0; i < consumedProteinEntriesList.size(); i++) { - proteinDataPointInterfaces[i] = (new DataPoint(consumedProteinEntriesList.get(i).unique1.getTime(), consumedProteinEntriesList.get(i).unique2/100)); - } - - List consumedFatEntriesList = databaseFacade.getFatPerDayinPeriod(startDate, endDate); - List fat = databaseFacade.getPeriodFat(startDate, endDate); - DataPoint[] fatDataPointInterfaces = new DataPoint[consumedFatEntriesList.size()]; - for (int i = 0; i < consumedFatEntriesList.size(); i++) { - fatDataPointInterfaces[i] = (new DataPoint(consumedFatEntriesList.get(i).unique1.getTime(), consumedFatEntriesList.get(i).unique2/100)); - } - - List consumedSatFatEntriesList = databaseFacade.getSatFatPerDayinPeriod(startDate, endDate); - List satFat = databaseFacade.getPeriodSatFat(startDate, endDate); - DataPoint[] satFatDataPointInterfaces = new DataPoint[consumedSatFatEntriesList.size()]; - for (int i = 0; i < consumedSatFatEntriesList.size(); i++) { - satFatDataPointInterfaces[i] = (new DataPoint(consumedSatFatEntriesList.get(i).unique1.getTime(), consumedSatFatEntriesList.get(i).unique2/100)); - } - - - Calendar startDateCalendar = Calendar.getInstance(); - startDateCalendar.setTime(startDate); - Calendar endDateCalendar = Calendar.getInstance(); - endDateCalendar.setTime(endDate); - float periodDays = daysBetween( endDateCalendar,startDateCalendar); - - if (calories.size() != 0) { - - float periodCalories = calories.get(0).unique2; - float averageCalories = periodCalories/periodDays; - BigDecimal averageCaloriesBigDecimal = round(averageCalories,0) ; - textView.setText(averageCaloriesBigDecimal.toString()); - - } - if (carbs.size() != 0 && sugar.size() != 0) { - - float periodCarbs = carbs.get(0).unique2; - float averageCarbs = periodCarbs/periodDays; - BigDecimal averageCarbsBigDecimal = round(averageCarbs,0) ; - - float periodSugar = sugar.get(0).unique2; - float averageSugar = periodSugar/periodDays; - BigDecimal averageSugarBigDecimal = round(averageSugar,0) ; - - carbsTextView.setText(averageCarbsBigDecimal.toString() + "(" + averageSugarBigDecimal + ")"); - - } - if (protein.size() != 0) { - - float periodProtein = protein.get(0).unique2; - float averageProtein = periodProtein/periodDays; - BigDecimal averageProteinBigDecimal = round(averageProtein,0) ; - proteinTextView.setText(averageProteinBigDecimal.toString()); - - } - - if (fat.size() != 0 && satFat.size() != 0) { - - float periodFat = fat.get(0).unique2; - float averageFat = periodFat/periodDays; - BigDecimal averageFatBigDecimal = round(averageFat,0) ; - - float periodSatFat= satFat.get(0).unique2; - float averageSatFat = periodSatFat/periodDays; - BigDecimal averageSatFatBigDecimal = round(averageSatFat,0) ; - - fatTextView.setText(averageFatBigDecimal.toString() + "(" + averageSatFatBigDecimal + ")"); - - } - GraphView graph = (GraphView) parentHolder.findViewById(R.id.graph); - LineGraphSeries series = new LineGraphSeries<>(dataPointInterfaces); - graph.addSeries(series); - graph.getGridLabelRenderer().setLabelFormatter(new DateAsXAxisLabelFormatter(referenceActivity)); - graph.getGridLabelRenderer().setHumanRounding(false, true); - graph.getViewport().setMinX(startDate.getTime()); - graph.getViewport().setMaxX(endDate.getTime()); - graph.getViewport().setXAxisBoundsManual(true); - graph.getGridLabelRenderer().setTextSize(40); - graph.getViewport().setScrollable(true); - graph.getGridLabelRenderer().setHorizontalLabelsAngle(135); - - - GraphView carbsGraph = (GraphView) parentHolder.findViewById(R.id.graphCarbs); - LineGraphSeries carbsSeries = new LineGraphSeries<>(carbsDataPointInterfaces); - carbsGraph.addSeries(carbsSeries); - LineGraphSeries sugarSeries = new LineGraphSeries<>(sugarDataPointInterfaces); - sugarSeries.setColor(Color.RED); - carbsGraph.addSeries(sugarSeries); - carbsGraph.getGridLabelRenderer().setLabelFormatter(new DateAsXAxisLabelFormatter(referenceActivity)); - carbsGraph.getGridLabelRenderer().setHumanRounding(false, true); - carbsGraph.getViewport().setMinX(startDate.getTime()); - carbsGraph.getViewport().setMaxX(endDate.getTime()); - carbsGraph.getViewport().setXAxisBoundsManual(true); - - carbsGraph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space - carbsGraph.getGridLabelRenderer().setTextSize(40); - carbsGraph.getViewport().setScrollable(true); - carbsGraph.getGridLabelRenderer().setHorizontalLabelsAngle(135); - - GraphView proteinGraph = (GraphView) parentHolder.findViewById(R.id.graphProtein); - LineGraphSeries proteinSeries = new LineGraphSeries<>(proteinDataPointInterfaces); - proteinGraph.addSeries(proteinSeries); - proteinGraph.getGridLabelRenderer().setLabelFormatter(new DateAsXAxisLabelFormatter(referenceActivity)); - proteinGraph.getGridLabelRenderer().setHumanRounding(false, true); - proteinGraph.getViewport().setMinX(startDate.getTime()); - proteinGraph.getViewport().setMaxX(endDate.getTime()); - proteinGraph.getViewport().setXAxisBoundsManual(true); - - proteinGraph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space - proteinGraph.getGridLabelRenderer().setTextSize(40); - proteinGraph.getViewport().setScrollable(true); - proteinGraph.getGridLabelRenderer().setHorizontalLabelsAngle(135); - - GraphView fatGraph = (GraphView) parentHolder.findViewById(R.id.graphFat); - LineGraphSeries fatSeries = new LineGraphSeries<>(fatDataPointInterfaces); - fatGraph.addSeries(fatSeries); - LineGraphSeries satFatSeries = new LineGraphSeries<>(satFatDataPointInterfaces); - satFatSeries.setColor(Color.RED); - fatGraph.addSeries(satFatSeries); - fatGraph.getGridLabelRenderer().setLabelFormatter(new DateAsXAxisLabelFormatter(referenceActivity)); - fatGraph.getGridLabelRenderer().setHumanRounding(false, true); - fatGraph.getViewport().setMinX(startDate.getTime()); - fatGraph.getViewport().setMaxX(endDate.getTime()); - fatGraph.getViewport().setXAxisBoundsManual(true); - - fatGraph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space - fatGraph.getGridLabelRenderer().setTextSize(40); - fatGraph.getViewport().setScrollable(true); - fatGraph.getGridLabelRenderer().setHorizontalLabelsAngle(135); - } catch (Exception e) { - Log.e("Error", e.getMessage()); - } + Log.i("Month...UpdateGraph","UpdateGraph called"); + final Date startDate = DateHelper.changeDateTimeToMidnight(getMonthByValue(-1)); + final Date endDate = DateHelper.changeDateTimeToMidnight(getMonthByValue(0)); + Calendar startDateCalendar = Calendar.getInstance(); + startDateCalendar.setTime(startDate); + Calendar endDateCalendar = Calendar.getInstance(); + endDateCalendar.setTime(endDate); + int monthDays = (int) daysBetween( endDateCalendar,startDateCalendar); + updateGraphUsingNdayPeriod(parentHolder,referenceActivity,databaseFacade,textView, + carbsTextView,proteinTextView, fatTextView,startDate,endDate, monthDays); } /** diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/WeekStatisticFragment.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/WeekStatisticFragment.java index 2cc6dae..1b20686 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/WeekStatisticFragment.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/WeekStatisticFragment.java @@ -139,152 +139,136 @@ public void onChanged(@Nullable Calendar calendar) { }); return parentHolder; } + static DataPoint[] dataPointsForNutriment(List consumedXYEntries){ + DataPoint[] datapointsToReturn = new DataPoint[consumedXYEntries.size()]; + for (int i = 0; i < consumedXYEntries.size(); i++) { + datapointsToReturn[i] = (new DataPoint(consumedXYEntries.get(i).unique1.getTime(), consumedXYEntries.get(i).unique2/100)); + } + return datapointsToReturn; + } + static void addSeriesToGraphById(View parentHolder, Activity referenceActivity, Date startDate, Date endDate, int graphViewId, LineGraphSeries ... lineGraphSeries){ + GraphView graph = (GraphView) parentHolder.findViewById(graphViewId); + for(LineGraphSeries series : lineGraphSeries){ + graph.addSeries(series); + } + graph.getGridLabelRenderer().setLabelFormatter(new DateAsXAxisLabelFormatter(referenceActivity)); + graph.getGridLabelRenderer().setHumanRounding(false, true); + graph.getViewport().setMinX(startDate.getTime()); + graph.getViewport().setMaxX(endDate.getTime()); + graph.getViewport().setXAxisBoundsManual(true); + + graph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space + graph.getGridLabelRenderer().setTextSize(40); + graph.getViewport().setScrollable(true); + graph.getGridLabelRenderer().setHorizontalLabelsAngle(135); + } - void UpdateGraph() { - + /*** + * Updates the graphs with the calories/carbs/... eaten during that period and also updates the + * average consumed calories/... during that period. Works for weeks and months, depending on the + * given start/end date and n days in period. + * It is static and part of the WekkStatisticFragment class, because I could not think of a + * better place for it. I tried making MonthStatisticFragment inheriting from Week... but this + * resulted in strange bugs. + * @param startDate + * @param endDate + * @param periodLengthInDays Number of days in period, 7 for week, something else for e.g. month. + */ + static void updateGraphUsingNdayPeriod(View parentHolder, Activity referenceActivity, + DatabaseFacade databaseFacade, TextView textView, + TextView carbsTextView, TextView proteinTextView, + TextView fatTextView, + Date startDate, Date endDate, int periodLengthInDays){ + if(databaseFacade == null){ //I replaced the try catch block covering all code of the method with this null-check, hoping the try catch did not catch other things a lot + Log.e("ateGraphUsingNdayPeriod","DatabaseFacade is null! Not adding graph stuff to statistics view."); + return; //TODO: why is databaseFacade null at the beginning? + } List consumedEntriesList = new ArrayList<>(); List calories = new ArrayList<>(); - try { - Date startDate = getWeekByValue(-1); - startDate = DateHelper.changeDateTimeToMidnight(startDate); //set time to midnight so the period does not depend on the time of day - Date endDate = getWeekByValue(0); - endDate = DateHelper.changeDateTimeToMidnight(endDate); - consumedEntriesList = databaseFacade.getCaloriesPerDayinPeriod(startDate,endDate); - calories = databaseFacade.getPeriodCalories(startDate,endDate); - - DataPoint[] dataPointInterfaces = new DataPoint[consumedEntriesList.size()]; - for (int i = 0; i < consumedEntriesList.size(); i++) { - dataPointInterfaces[i] = (new DataPoint(consumedEntriesList.get(i).unique1.getTime(), consumedEntriesList.get(i).unique2/100)); - } - List consumedCarbsEntriesList = databaseFacade.getCarbsPerDayinPeriod(startDate, endDate); - List carbs = databaseFacade.getPeriodCarbs(startDate, endDate); - DataPoint[] carbsDataPointInterfaces = new DataPoint[consumedCarbsEntriesList.size()]; - for (int i = 0; i < consumedCarbsEntriesList.size(); i++) { - carbsDataPointInterfaces[i] = (new DataPoint(consumedCarbsEntriesList.get(i).unique1.getTime(), consumedCarbsEntriesList.get(i).unique2/100)); - } + consumedEntriesList = databaseFacade.getCaloriesPerDayinPeriod(startDate,endDate); + calories = databaseFacade.getPeriodCalories(startDate,endDate); - List consumedSugarEntriesList = databaseFacade.getSugarPerDayinPeriod(startDate, endDate); - List sugar = databaseFacade.getPeriodSugar(startDate, endDate); - DataPoint[] sugarDataPointInterfaces = new DataPoint[consumedSugarEntriesList.size()]; - for (int i = 0; i < consumedSugarEntriesList.size(); i++) { - sugarDataPointInterfaces[i] = (new DataPoint(consumedSugarEntriesList.get(i).unique1.getTime(), consumedSugarEntriesList.get(i).unique2/100)); - } + DataPoint[] dataPointInterfaces = dataPointsForNutriment(consumedEntriesList); - List consumedProteinEntriesList = databaseFacade.getProteinPerDayinPeriod(startDate, endDate); - List protein = databaseFacade.getPeriodProtein(startDate, endDate); - DataPoint[] proteinDataPointInterfaces = new DataPoint[consumedProteinEntriesList.size()]; - for (int i = 0; i < consumedProteinEntriesList.size(); i++) { - proteinDataPointInterfaces[i] = (new DataPoint(consumedProteinEntriesList.get(i).unique1.getTime(), consumedProteinEntriesList.get(i).unique2/100)); - } + List consumedCarbsEntriesList = databaseFacade.getCarbsPerDayinPeriod(startDate, endDate); + List carbs = databaseFacade.getPeriodCarbs(startDate, endDate); + DataPoint[] carbsDataPointInterfaces = dataPointsForNutriment(consumedCarbsEntriesList); - List consumedFatEntriesList = databaseFacade.getFatPerDayinPeriod(startDate, endDate); - List fat = databaseFacade.getPeriodFat(startDate, endDate); - DataPoint[] fatDataPointInterfaces = new DataPoint[consumedFatEntriesList.size()]; - for (int i = 0; i < consumedFatEntriesList.size(); i++) { - fatDataPointInterfaces[i] = (new DataPoint(consumedFatEntriesList.get(i).unique1.getTime(), consumedFatEntriesList.get(i).unique2/100)); - } + List consumedSugarEntriesList = databaseFacade.getSugarPerDayinPeriod(startDate, endDate); + List sugar = databaseFacade.getPeriodSugar(startDate, endDate); + DataPoint[] sugarDataPointInterfaces = dataPointsForNutriment(consumedSugarEntriesList); - List consumedSatFatEntriesList = databaseFacade.getSatFatPerDayinPeriod(startDate, endDate); - List satFat = databaseFacade.getPeriodSatFat(startDate, endDate); - DataPoint[] satFatDataPointInterfaces = new DataPoint[consumedSatFatEntriesList.size()]; - for (int i = 0; i < consumedSatFatEntriesList.size(); i++) { - satFatDataPointInterfaces[i] = (new DataPoint(consumedSatFatEntriesList.get(i).unique1.getTime(), consumedSatFatEntriesList.get(i).unique2/100)); - } + List consumedProteinEntriesList = databaseFacade.getProteinPerDayinPeriod(startDate, endDate); + List protein = databaseFacade.getPeriodProtein(startDate, endDate); + DataPoint[] proteinDataPointInterfaces = dataPointsForNutriment(consumedProteinEntriesList); - int weekdays = 7; + List consumedFatEntriesList = databaseFacade.getFatPerDayinPeriod(startDate, endDate); + List fat = databaseFacade.getPeriodFat(startDate, endDate); + DataPoint[] fatDataPointInterfaces = dataPointsForNutriment(consumedFatEntriesList); + List consumedSatFatEntriesList = databaseFacade.getSatFatPerDayinPeriod(startDate, endDate); + List satFat = databaseFacade.getPeriodSatFat(startDate, endDate); + DataPoint[] satFatDataPointInterfaces = dataPointsForNutriment(consumedSatFatEntriesList); - float averageCalories = calories.get(0).unique2 / weekdays; - float averageCarbs = carbs.get(0).unique2 / weekdays; - float averageSugar = sugar.get(0).unique2 / weekdays; - float averageProtein = protein.get(0).unique2 / weekdays; - float averageFat = fat.get(0).unique2 / weekdays; - float averageSatFat = satFat.get(0).unique2 / weekdays; - BigDecimal averageCaloriesBigDecimal = round(averageCalories,0) ; - BigDecimal averageCarbsBigDecimal = round(averageCarbs,0) ; - BigDecimal averageSugarBigDecimal = round(averageSugar,0) ; - BigDecimal averageProteinBigDecimal = round(averageProtein,0) ; - BigDecimal averageFatBigDecimal = round(averageFat,0) ; - BigDecimal averageSatFatBigDecimal = round(averageSatFat,0) ; - if (calories.size() != 0) { - textView.setText(averageCaloriesBigDecimal.toString()); - } - if (carbs.size() != 0 && sugar.size() != 0) { - carbsTextView.setText(averageCarbsBigDecimal.toString() + " (" + averageSugarBigDecimal.toString() +")"); - } - if (protein.size() != 0) { - proteinTextView.setText(averageProteinBigDecimal.toString()); - } - if (fat.size() != 0 && satFat.size() != 0) { - fatTextView.setText(averageFatBigDecimal.toString() + " (" + averageSatFatBigDecimal.toString() +")"); - } - GraphView graph = (GraphView) parentHolder.findViewById(R.id.graph); - LineGraphSeries series = new LineGraphSeries<>(dataPointInterfaces); - graph.addSeries(series); - graph.getGridLabelRenderer().setLabelFormatter(new DateAsXAxisLabelFormatter(referenceActivity)); - graph.getGridLabelRenderer().setHumanRounding(false, true); - graph.getViewport().setMinX(startDate.getTime()); - graph.getViewport().setMaxX(endDate.getTime()); - graph.getViewport().setXAxisBoundsManual(true); - - graph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space - graph.getGridLabelRenderer().setTextSize(40); - graph.getViewport().setScrollable(true); - graph.getGridLabelRenderer().setHorizontalLabelsAngle(135); - - GraphView carbsGraph = (GraphView) parentHolder.findViewById(R.id.graphCarbs); - LineGraphSeries carbsSeries = new LineGraphSeries<>(carbsDataPointInterfaces); - carbsGraph.addSeries(carbsSeries); - LineGraphSeries sugarSeries = new LineGraphSeries<>(sugarDataPointInterfaces); - sugarSeries.setColor(Color.RED); - carbsGraph.addSeries(sugarSeries); - carbsGraph.getGridLabelRenderer().setLabelFormatter(new DateAsXAxisLabelFormatter(referenceActivity)); - carbsGraph.getGridLabelRenderer().setHumanRounding(false, true); - carbsGraph.getViewport().setMinX(startDate.getTime()); - carbsGraph.getViewport().setMaxX(endDate.getTime()); - carbsGraph.getViewport().setXAxisBoundsManual(true); - - carbsGraph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space - carbsGraph.getGridLabelRenderer().setTextSize(40); - carbsGraph.getViewport().setScrollable(true); - carbsGraph.getGridLabelRenderer().setHorizontalLabelsAngle(135); - - GraphView proteinGraph = (GraphView) parentHolder.findViewById(R.id.graphProtein); - LineGraphSeries proteinSeries = new LineGraphSeries<>(proteinDataPointInterfaces); - proteinGraph.addSeries(proteinSeries); - proteinGraph.getGridLabelRenderer().setLabelFormatter(new DateAsXAxisLabelFormatter(referenceActivity)); - proteinGraph.getGridLabelRenderer().setHumanRounding(false, true); - proteinGraph.getViewport().setMinX(startDate.getTime()); - proteinGraph.getViewport().setMaxX(endDate.getTime()); - proteinGraph.getViewport().setXAxisBoundsManual(true); - - proteinGraph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space - proteinGraph.getGridLabelRenderer().setTextSize(40); - proteinGraph.getViewport().setScrollable(true); - proteinGraph.getGridLabelRenderer().setHorizontalLabelsAngle(135); - - GraphView fatGraph = (GraphView) parentHolder.findViewById(R.id.graphFat); - LineGraphSeries fatSeries = new LineGraphSeries<>(fatDataPointInterfaces); - fatGraph.addSeries(fatSeries); - LineGraphSeries satFatSeries = new LineGraphSeries<>(satFatDataPointInterfaces); - satFatSeries.setColor(Color.RED); - fatGraph.addSeries(satFatSeries); - fatGraph.getGridLabelRenderer().setLabelFormatter(new DateAsXAxisLabelFormatter(referenceActivity)); - fatGraph.getGridLabelRenderer().setHumanRounding(false, true); - fatGraph.getViewport().setMinX(startDate.getTime()); - fatGraph.getViewport().setMaxX(endDate.getTime()); - fatGraph.getViewport().setXAxisBoundsManual(true); - - fatGraph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space - fatGraph.getGridLabelRenderer().setTextSize(40); - fatGraph.getViewport().setScrollable(true); - fatGraph.getGridLabelRenderer().setHorizontalLabelsAngle(135); - } catch (Exception e) { - Log.e("Error", e.getMessage()); + float averageCalories = calories.get(0).unique2 / periodLengthInDays; + float averageCarbs = carbs.get(0).unique2 / periodLengthInDays; + float averageSugar = sugar.get(0).unique2 / periodLengthInDays; + float averageProtein = protein.get(0).unique2 / periodLengthInDays; + float averageFat = fat.get(0).unique2 / periodLengthInDays; + float averageSatFat = satFat.get(0).unique2 / periodLengthInDays; + + BigDecimal averageCaloriesBigDecimal = round(averageCalories,0) ; + BigDecimal averageCarbsBigDecimal = round(averageCarbs,0) ; + BigDecimal averageSugarBigDecimal = round(averageSugar,0) ; + BigDecimal averageProteinBigDecimal = round(averageProtein,0) ; + BigDecimal averageFatBigDecimal = round(averageFat,0) ; + BigDecimal averageSatFatBigDecimal = round(averageSatFat,0) ; + + if (calories.size() != 0) { + textView.setText(averageCaloriesBigDecimal.toString()); + } + if (carbs.size() != 0 && sugar.size() != 0) { + carbsTextView.setText(averageCarbsBigDecimal.toString() + " (" + averageSugarBigDecimal.toString() +")"); + } + if (protein.size() != 0) { + proteinTextView.setText(averageProteinBigDecimal.toString()); + } + if (fat.size() != 0 && satFat.size() != 0) { + fatTextView.setText(averageFatBigDecimal.toString() + " (" + averageSatFatBigDecimal.toString() +")"); } + + LineGraphSeries calSeries = new LineGraphSeries<>(dataPointInterfaces); + addSeriesToGraphById(parentHolder,referenceActivity,startDate,endDate,R.id.graph, calSeries); + + LineGraphSeries carbsSeries = new LineGraphSeries<>(carbsDataPointInterfaces); + LineGraphSeries sugarSeries = new LineGraphSeries<>(sugarDataPointInterfaces); + sugarSeries.setColor(Color.RED); + addSeriesToGraphById(parentHolder,referenceActivity,startDate,endDate,R.id.graphCarbs, + carbsSeries, sugarSeries); + + + LineGraphSeries proteinSeries = new LineGraphSeries<>(proteinDataPointInterfaces); + addSeriesToGraphById(parentHolder,referenceActivity,startDate,endDate,R.id.graphProtein, + proteinSeries); + + + LineGraphSeries fatSeries = new LineGraphSeries<>(fatDataPointInterfaces); + LineGraphSeries satFatSeries = new LineGraphSeries<>(satFatDataPointInterfaces); + satFatSeries.setColor(Color.RED); + addSeriesToGraphById(parentHolder,referenceActivity,startDate,endDate,R.id.graphFat, + fatSeries, satFatSeries); + } + void UpdateGraph() { + int weekdays = 7; + Date startDate = getWeekByValue(-1); + startDate = DateHelper.changeDateTimeToMidnight(startDate); //set time to midnight so the period does not depend on the time of day + Date endDate = getWeekByValue(0); + endDate = DateHelper.changeDateTimeToMidnight(endDate); + updateGraphUsingNdayPeriod(parentHolder,referenceActivity,databaseFacade,textView, + carbsTextView,proteinTextView, fatTextView,startDate,endDate, weekdays); } Date changeWeekByValue(int value) { From d529b530a3c55e1515bb2b77651191fd0de2769d Mon Sep 17 00:00:00 2001 From: conrad69 Date: Wed, 4 Aug 2021 17:04:51 +0200 Subject: [PATCH 04/18] food info in overview and settings is ok --- app/build.gradle | 2 +- .../2.json | 317 ++++++++++++++++++ app/src/main/AndroidManifest.xml | 6 +- .../database/ApplicationDatabase.java | 16 +- .../database/ConsumedEntrieAndProductDao.java | 53 ++- .../database/Product.java | 74 +++- .../database/ProductDao.java | 4 +- .../utils/ProductConversionHelper.java | 3 +- .../ui/AddFoodFragment.java | 244 +++++++------- .../ui/BaseAddFoodActivity.java | 5 + .../ui/FoodInfo.java | 32 ++ .../ui/FoodInfosToShow.java | 281 ++++++++++++++++ .../ui/OverviewActivity.java | 293 +++++++++++----- .../ui/SearchFoodFragment.java | 45 +-- .../ui/SettingsActivity.java | 30 +- .../ui/adapter/DatabaseEntry.java | 71 +++- .../ui/adapter/DatabaseFacade.java | 17 +- .../ui/adapter/SearchResultAdapter.java | 34 +- .../ui/helper/BaseActivity.java | 6 +- app/src/main/res/layout-land/content_food.xml | 198 +++-------- app/src/main/res/layout/content_food.xml | 105 +----- app/src/main/res/layout/content_overview.xml | 50 ++- app/src/main/res/layout/search_result.xml | 34 +- app/src/main/res/menu/main_drawer.xml | 5 + app/src/main/res/values/strings.xml | 31 +- 25 files changed, 1377 insertions(+), 579 deletions(-) create mode 100644 app/schemas/org.secuso.privacyfriendlyfoodtracker.database.ApplicationDatabase/2.json create mode 100644 app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/FoodInfo.java create mode 100644 app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/FoodInfosToShow.java diff --git a/app/build.gradle b/app/build.gradle index f55791c..e8f65d7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -5,7 +5,7 @@ android { buildToolsVersion '28.0.3' defaultConfig { - applicationId "org.secuso.privacyfriendlyfoodtracker" + applicationId "org.secuso.privacyfriendlyfoodtracker3" minSdkVersion 21 targetSdkVersion 27 versionCode 4 diff --git a/app/schemas/org.secuso.privacyfriendlyfoodtracker.database.ApplicationDatabase/2.json b/app/schemas/org.secuso.privacyfriendlyfoodtracker.database.ApplicationDatabase/2.json new file mode 100644 index 0000000..e4b906f --- /dev/null +++ b/app/schemas/org.secuso.privacyfriendlyfoodtracker.database.ApplicationDatabase/2.json @@ -0,0 +1,317 @@ +{ + "formatVersion": 1, + "database": { + "version": 2, + "identityHash": "36282fcf09b983d08eea3aacd9b71510", + "entities": [ + { + "tableName": "ConsumedEntries", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `productId` INTEGER NOT NULL, `amount` INTEGER NOT NULL, `date` INTEGER, `name` TEXT, FOREIGN KEY(`productId`) REFERENCES `Product`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "productId", + "columnName": "productId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "amount", + "columnName": "amount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [ + { + "table": "Product", + "onDelete": "CASCADE", + "onUpdate": "NO ACTION", + "columns": [ + "productId" + ], + "referencedColumns": [ + "id" + ] + } + ] + }, + { + "tableName": "Product", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT, `energy` REAL NOT NULL, `carbs` REAL NOT NULL, `sugar` REAL NOT NULL, `protein` REAL NOT NULL, `fat` REAL NOT NULL, `satFat` REAL NOT NULL, `salt` REAL NOT NULL, `vitaminA_retinol` REAL NOT NULL, `betaCarotin` REAL NOT NULL, `vitaminD` REAL NOT NULL, `vitaminE` REAL NOT NULL, `vitaminK` REAL NOT NULL, `thiamin_B1` REAL NOT NULL, `riboflavin_B2` REAL NOT NULL, `niacin` REAL NOT NULL, `vitaminB6` REAL NOT NULL, `folat` REAL NOT NULL, `pantothenacid` REAL NOT NULL, `biotin` REAL NOT NULL, `cobalamin_B12` REAL NOT NULL, `vitaminC` REAL NOT NULL, `natrium` REAL NOT NULL, `chlorid` REAL NOT NULL, `kalium` REAL NOT NULL, `calcium` REAL NOT NULL, `phosphor` REAL NOT NULL, `magnesium` REAL NOT NULL, `eisen` REAL NOT NULL, `jod` REAL NOT NULL, `fluorid` REAL NOT NULL, `zink` REAL NOT NULL, `selen` REAL NOT NULL, `kupfer` REAL NOT NULL, `mangan` REAL NOT NULL, `chrom` REAL NOT NULL, `molybdaen` REAL NOT NULL, `barcode` TEXT)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "energy", + "columnName": "energy", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "carbs", + "columnName": "carbs", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "sugar", + "columnName": "sugar", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "protein", + "columnName": "protein", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "fat", + "columnName": "fat", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "satFat", + "columnName": "satFat", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "salt", + "columnName": "salt", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "vitaminA_retinol", + "columnName": "vitaminA_retinol", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "betaCarotin", + "columnName": "betaCarotin", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "vitaminD", + "columnName": "vitaminD", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "vitaminE", + "columnName": "vitaminE", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "vitaminK", + "columnName": "vitaminK", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "thiamin_B1", + "columnName": "thiamin_B1", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "riboflavin_B2", + "columnName": "riboflavin_B2", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "niacin", + "columnName": "niacin", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "vitaminB6", + "columnName": "vitaminB6", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "folat", + "columnName": "folat", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "pantothenacid", + "columnName": "pantothenacid", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "biotin", + "columnName": "biotin", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "cobalamin_B12", + "columnName": "cobalamin_B12", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "vitaminC", + "columnName": "vitaminC", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "natrium", + "columnName": "natrium", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "chlorid", + "columnName": "chlorid", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "kalium", + "columnName": "kalium", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "calcium", + "columnName": "calcium", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "phosphor", + "columnName": "phosphor", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "magnesium", + "columnName": "magnesium", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "eisen", + "columnName": "eisen", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "jod", + "columnName": "jod", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "fluorid", + "columnName": "fluorid", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "zink", + "columnName": "zink", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "selen", + "columnName": "selen", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "kupfer", + "columnName": "kupfer", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "mangan", + "columnName": "mangan", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "chrom", + "columnName": "chrom", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "molybdaen", + "columnName": "molybdaen", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "barcode", + "columnName": "barcode", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + } + ], + "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, \"36282fcf09b983d08eea3aacd9b71510\")" + ] + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a403d5a..ae5714d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,8 +15,8 @@ + android:theme="@style/AppTheme.NoActionBar" /> + android:windowSoftInputMode="adjustResize" /> \ No newline at end of file diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/ApplicationDatabase.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/ApplicationDatabase.java index eaac058..c7abd5b 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/ApplicationDatabase.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/ApplicationDatabase.java @@ -74,7 +74,7 @@ public void onCreate(@NonNull SupportSQLiteDatabase db) { } } }) - .addMigrations(MIGRATION_1_2).build(); + .addMigrations(MIGRATION_1_2).addMigrations(MIGRATION_2_3).build(); } } @@ -96,6 +96,20 @@ public void migrate(SupportSQLiteDatabase database) { } }; + /*** + * Migrate database so it also contains micro nutriments. + */ + static final Migration MIGRATION_2_3 = new Migration(2, 3) { + @Override + public void migrate(SupportSQLiteDatabase database) { + String[] newFields = new String[]{"salt", "vitaminA_retinol", "betaCarotin", "vitaminD", "vitaminE", "vitaminK", "thiamin_B1", "riboflavin_B2", "niacin", "vitaminB6", "folat", "pantothenacid", "biotin", "cobalamin_B12", "vitaminC", "natrium", "chlorid", "kalium", "calcium", "phosphor", "magnesium", "eisen", "jod", "fluorid", "zink", "selen", "kupfer", "mangan", "chrom", "molybdaen"}; + for(String field : newFields) { + database.execSQL("ALTER TABLE Product " + + " ADD COLUMN "+ field +" REAL NOT NULL default 0"); + } + } + }; + diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/ConsumedEntrieAndProductDao.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/ConsumedEntrieAndProductDao.java index ecb0236..a834ca0 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/ConsumedEntrieAndProductDao.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/ConsumedEntrieAndProductDao.java @@ -40,6 +40,12 @@ public interface ConsumedEntrieAndProductDao { @Query("SELECT consumedEntries.date AS unique1, sum(product.energy*consumedEntries.amount/100) AS unique2 FROM consumedEntries INNER JOIN product ON consumedEntries.productId = product.id WHERE consumedEntries.date BETWEEN :dayst AND :dayet") List getCaloriesPeriod(final Date dayst, final Date dayet); + @Query("SELECT consumedEntries.date AS dateOfConsumption, (sum(product.energy*consumedEntries.amount)) AS energyConsumed, (sum(product.carbs*consumedEntries.amount)) AS carbsConsumed, (sum(product.sugar*consumedEntries.amount)) AS sugarConsumed, (sum(product.protein*consumedEntries.amount)) AS proteinConsumed, (sum(product.fat*consumedEntries.amount)) AS fatConsumed, (sum(product.satFat*consumedEntries.amount)) AS satFatConsumed, (sum(product.salt*consumedEntries.amount)) AS saltConsumed, (sum(product.vitaminA_retinol*consumedEntries.amount)) AS vitaminA_retinolConsumed, (sum(product.betaCarotin*consumedEntries.amount)) AS betaCarotinConsumed, (sum(product.vitaminD*consumedEntries.amount)) AS vitaminDConsumed, (sum(product.vitaminE*consumedEntries.amount)) AS vitaminEConsumed, (sum(product.vitaminK*consumedEntries.amount)) AS vitaminKConsumed, (sum(product.thiamin_B1*consumedEntries.amount)) AS thiamin_B1Consumed, (sum(product.riboflavin_B2*consumedEntries.amount)) AS riboflavin_B2Consumed, (sum(product.niacin*consumedEntries.amount)) AS niacinConsumed, (sum(product.vitaminB6*consumedEntries.amount)) AS vitaminB6Consumed, (sum(product.folat*consumedEntries.amount)) AS folatConsumed, (sum(product.pantothenacid*consumedEntries.amount)) AS pantothenacidConsumed, (sum(product.biotin*consumedEntries.amount)) AS biotinConsumed, (sum(product.cobalamin_B12*consumedEntries.amount)) AS cobalamin_B12Consumed, (sum(product.vitaminC*consumedEntries.amount)) AS vitaminCConsumed, (sum(product.natrium*consumedEntries.amount)) AS natriumConsumed, (sum(product.chlorid*consumedEntries.amount)) AS chloridConsumed, (sum(product.kalium*consumedEntries.amount)) AS kaliumConsumed, (sum(product.calcium*consumedEntries.amount)) AS calciumConsumed, (sum(product.phosphor*consumedEntries.amount)) AS phosphorConsumed, (sum(product.magnesium*consumedEntries.amount)) AS magnesiumConsumed, (sum(product.eisen*consumedEntries.amount)) AS eisenConsumed, (sum(product.jod*consumedEntries.amount)) AS jodConsumed, (sum(product.fluorid*consumedEntries.amount)) AS fluoridConsumed, (sum(product.zink*consumedEntries.amount)) AS zinkConsumed, (sum(product.selen*consumedEntries.amount)) AS selenConsumed, (sum(product.kupfer*consumedEntries.amount)) AS kupferConsumed, (sum(product.mangan*consumedEntries.amount)) AS manganConsumed, (sum(product.chrom*consumedEntries.amount)) AS chromConsumed, (sum(product.molybdaen*consumedEntries.amount)) AS molybdaenConsumed FROM consumedEntries INNER JOIN product ON consumedEntries.productId = product.id WHERE consumedEntries.date BETWEEN :dayst AND :dayet GROUP BY consumedEntries.date ") + List getNutrimentsPerDayinPeriod(final Date dayst, final Date dayet); + + @Query("SELECT consumedEntries.date AS dateOfConsumption, (sum(product.energy*consumedEntries.amount/100)) AS energyConsumed, (sum(product.carbs*consumedEntries.amount/100)) AS carbsConsumed, (sum(product.sugar*consumedEntries.amount/100)) AS sugarConsumed, (sum(product.protein*consumedEntries.amount/100)) AS proteinConsumed, (sum(product.fat*consumedEntries.amount/100)) AS fatConsumed, (sum(product.satFat*consumedEntries.amount/100)) AS satFatConsumed, (sum(product.salt*consumedEntries.amount/100)) AS saltConsumed, (sum(product.vitaminA_retinol*consumedEntries.amount/100)) AS vitaminA_retinolConsumed, (sum(product.betaCarotin*consumedEntries.amount/100)) AS betaCarotinConsumed, (sum(product.vitaminD*consumedEntries.amount/100)) AS vitaminDConsumed, (sum(product.vitaminE*consumedEntries.amount/100)) AS vitaminEConsumed, (sum(product.vitaminK*consumedEntries.amount/100)) AS vitaminKConsumed, (sum(product.thiamin_B1*consumedEntries.amount/100)) AS thiamin_B1Consumed, (sum(product.riboflavin_B2*consumedEntries.amount/100)) AS riboflavin_B2Consumed, (sum(product.niacin*consumedEntries.amount/100)) AS niacinConsumed, (sum(product.vitaminB6*consumedEntries.amount/100)) AS vitaminB6Consumed, (sum(product.folat*consumedEntries.amount/100)) AS folatConsumed, (sum(product.pantothenacid*consumedEntries.amount/100)) AS pantothenacidConsumed, (sum(product.biotin*consumedEntries.amount/100)) AS biotinConsumed, (sum(product.cobalamin_B12*consumedEntries.amount/100)) AS cobalamin_B12Consumed, (sum(product.vitaminC*consumedEntries.amount/100)) AS vitaminCConsumed, (sum(product.natrium*consumedEntries.amount/100)) AS natriumConsumed, (sum(product.chlorid*consumedEntries.amount/100)) AS chloridConsumed, (sum(product.kalium*consumedEntries.amount/100)) AS kaliumConsumed, (sum(product.calcium*consumedEntries.amount/100)) AS calciumConsumed, (sum(product.phosphor*consumedEntries.amount/100)) AS phosphorConsumed, (sum(product.magnesium*consumedEntries.amount/100)) AS magnesiumConsumed, (sum(product.eisen*consumedEntries.amount/100)) AS eisenConsumed, (sum(product.jod*consumedEntries.amount/100)) AS jodConsumed, (sum(product.fluorid*consumedEntries.amount/100)) AS fluoridConsumed, (sum(product.zink*consumedEntries.amount/100)) AS zinkConsumed, (sum(product.selen*consumedEntries.amount/100)) AS selenConsumed, (sum(product.kupfer*consumedEntries.amount/100)) AS kupferConsumed, (sum(product.mangan*consumedEntries.amount/100)) AS manganConsumed, (sum(product.chrom*consumedEntries.amount/100)) AS chromConsumed, (sum(product.molybdaen*consumedEntries.amount/100)) AS molybdaenConsumed FROM consumedEntries INNER JOIN product ON consumedEntries.productId = product.id WHERE consumedEntries.date BETWEEN :dayst AND :dayet") + List getNutrimentsPeriod(final Date dayst, final Date dayet); + @Query("SELECT consumedEntries.date AS unique1, (sum(product.carbs*consumedEntries.amount)) AS unique2 FROM consumedEntries INNER JOIN product ON consumedEntries.productId = product.id WHERE consumedEntries.date BETWEEN :dayst AND :dayet GROUP BY consumedEntries.date ") List getCarbsPerDayinPeriod(final Date dayst, final Date dayet); @@ -70,7 +76,7 @@ public interface ConsumedEntrieAndProductDao { @Query("SELECT consumedEntries.date AS unique1, sum(product.satFat*consumedEntries.amount/100) AS unique2 FROM consumedEntries INNER JOIN product ON consumedEntries.productId = product.id WHERE consumedEntries.date BETWEEN :dayst AND :dayet") List getSatFatPeriod(final Date dayst, final Date dayet); - @Query("SELECT consumedEntries.amount AS amount, consumedEntries.id AS id,consumedEntries.name as name, product.energy as energy, product.carbs as carbs, product.sugar as sugar, product.protein as protein, product.fat as fat, product.satFat as satFat FROM consumedEntries INNER JOIN product ON consumedEntries.productId = product.id WHERE consumedEntries.date=:day") + @Query("SELECT consumedEntries.amount AS amount, consumedEntries.id AS id,consumedEntries.name as name, product.energy as energy, product.carbs as carbs, product.sugar as sugar, product.protein as protein, product.fat as fat, product.satFat as satFat, product.salt AS salt, product.vitaminA_retinol AS vitaminA_retinol, product.betaCarotin AS betaCarotin, product.vitaminD AS vitaminD, product.vitaminE AS vitaminE, product.vitaminK AS vitaminK, product.thiamin_B1 AS thiamin_B1, product.riboflavin_B2 AS riboflavin_B2, product.niacin AS niacin, product.vitaminB6 AS vitaminB6, product.folat AS folat, product.pantothenacid AS pantothenacid, product.biotin AS biotin, product.cobalamin_B12 AS cobalamin_B12, product.vitaminC AS vitaminC, product.natrium AS natrium, product.chlorid AS chlorid, product.kalium AS kalium, product.calcium AS calcium, product.phosphor AS phosphor, product.magnesium AS magnesium, product.eisen AS eisen, product.jod AS jod, product.fluorid AS fluorid, product.zink AS zink, product.selen AS selen, product.kupfer AS kupfer, product.mangan AS mangan, product.chrom AS chrom, product.molybdaen AS molybdaen FROM consumedEntries INNER JOIN product ON consumedEntries.productId = product.id WHERE consumedEntries.date=:day") LiveData> findConsumedEntriesForDate(final Date day); static class DateCalories @@ -78,4 +84,49 @@ static class DateCalories public Date unique1; public int unique2; } + class DateNutriments{ + public Date dateOfConsumption; + public float energyConsumed; + public float carbsConsumed; + public float sugarConsumed; + public float proteinConsumed; + public float fatConsumed; + public float satFatConsumed; + public float saltConsumed; + + //vitamins and minerals + //soluable in fat vitamins + public float vitaminA_retinolConsumed; + public float betaCarotinConsumed; + public float vitaminDConsumed; + public float vitaminEConsumed; + public float vitaminKConsumed; + //soluable in water vitamins + public float thiamin_B1Consumed; + public float riboflavin_B2Consumed; + public float niacinConsumed; + public float vitaminB6Consumed; + public float folatConsumed; + public float pantothenacidConsumed; + public float biotinConsumed; + public float cobalamin_B12Consumed; + public float vitaminCConsumed; + //minerals + public float natriumConsumed; + public float chloridConsumed; + public float kaliumConsumed; + public float calciumConsumed; + public float phosphorConsumed; + public float magnesiumConsumed; + //minerals (traces) + public float eisenConsumed; + public float jodConsumed; + public float fluoridConsumed; + public float zinkConsumed; + public float selenConsumed; + public float kupferConsumed; + public float manganConsumed; + public float chromConsumed; + public float molybdaenConsumed; + } } diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/Product.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/Product.java index 49be0a2..8e10709 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/Product.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/Product.java @@ -32,14 +32,53 @@ public class Product { public final int id; public final String name; public final float energy; + + //nutriments public final float carbs; public final float sugar; public final float protein; public final float fat; public final float satFat; + public final float salt; + + //vitamins and minerals + //soluable in fat vitamins + public final float vitaminA_retinol; + public final float betaCarotin; + public final float vitaminD; + public final float vitaminE; + public final float vitaminK; + //soluable in water vitamins + public final float thiamin_B1; + public final float riboflavin_B2; + public final float niacin; + public final float vitaminB6; + public final float folat; + public final float pantothenacid; + public final float biotin; + public final float cobalamin_B12; + public final float vitaminC; + //minerals + public final float natrium; + public final float chlorid; + public final float kalium; + public final float calcium; + public final float phosphor; + public final float magnesium; + //minerals (traces) + public final float eisen; + public final float jod; + public final float fluorid; + public final float zink; + public final float selen; + public final float kupfer; + public final float mangan; + public final float chrom; + public final float molybdaen; + public final String barcode; - public Product(final int id, String name, float energy, float carbs, float sugar, float protein, float fat, float satFat, String barcode) { + public Product(final int id, String name, float energy, float carbs, float sugar, float protein, float fat, float satFat,float salt, float vitaminA_retinol, float betaCarotin, float vitaminD, float vitaminE, float vitaminK, float thiamin_B1, float riboflavin_B2, float niacin, float vitaminB6, float folat, float pantothenacid, float biotin, float cobalamin_B12, float vitaminC, float natrium, float chlorid, float kalium, float calcium, float phosphor, float magnesium, float eisen, float jod, float fluorid, float zink, float selen, float kupfer, float mangan, float chrom, float molybdaen, String barcode) { this.id = id; this.name = name; this.energy = energy; @@ -48,6 +87,39 @@ public Product(final int id, String name, float energy, float carbs, float sugar this.protein = protein; this.fat = fat; this.satFat = satFat; + this.salt=salt; + + + this.vitaminA_retinol=vitaminA_retinol; + this.betaCarotin=betaCarotin; + this.vitaminD=vitaminD; + this.vitaminE=vitaminE; + this.vitaminK=vitaminK; + this.thiamin_B1=thiamin_B1; + this.riboflavin_B2=riboflavin_B2; + this.niacin=niacin; + this.vitaminB6=vitaminB6; + this.folat=folat; + this.pantothenacid=pantothenacid; + this.biotin=biotin; + this.cobalamin_B12=cobalamin_B12; + this.vitaminC=vitaminC; + this.natrium=natrium; + this.chlorid=chlorid; + this.kalium=kalium; + this.calcium=calcium; + this.phosphor=phosphor; + this.magnesium=magnesium; + this.eisen=eisen; + this.jod=jod; + this.fluorid=fluorid; + this.zink=zink; + this.selen=selen; + this.kupfer=kupfer; + this.mangan=mangan; + this.chrom=chrom; + this.molybdaen=molybdaen; + this.barcode = barcode; } } diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/ProductDao.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/ProductDao.java index 81854fe..f6cde14 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/ProductDao.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/database/ProductDao.java @@ -52,8 +52,8 @@ public interface ProductDao { @Query("SELECT * FROM product WHERE id=:id") Product findProductById(final int id); - @Query("SELECT * FROM product WHERE name=:name AND energy=:energy AND carbs=:carbs AND sugar=:sugar AND protein=:protein AND fat=:fat AND satFat=:satFat AND barcode=:barcode") - List findExistingProducts(String name, float energy, float carbs, float sugar, float protein, float fat, float satFat, String barcode); + @Query("SELECT * FROM product WHERE name=:name AND energy=:energy AND carbs=:carbs AND sugar=:sugar AND protein=:protein AND fat=:fat AND satFat=:satFat AND salt=:salt AND vitaminA_retinol=:vitaminA_retinol AND betaCarotin=:betaCarotin AND vitaminD=:vitaminD AND vitaminE=:vitaminE AND vitaminK=:vitaminK AND thiamin_B1=:thiamin_B1 AND riboflavin_B2=:riboflavin_B2 AND niacin=:niacin AND vitaminB6=:vitaminB6 AND folat=:folat AND pantothenacid=:pantothenacid AND biotin=:biotin AND cobalamin_B12=:cobalamin_B12 AND vitaminC=:vitaminC AND natrium=:natrium AND chlorid=:chlorid AND kalium=:kalium AND calcium=:calcium AND phosphor=:phosphor AND magnesium=:magnesium AND eisen=:eisen AND jod=:jod AND fluorid=:fluorid AND zink=:zink AND selen=:selen AND kupfer=:kupfer AND mangan=:mangan AND chrom=:chrom AND molybdaen=:molybdaen AND barcode=:barcode") + List findExistingProducts(String name, float energy, float carbs, float sugar, float protein, float fat, float satFat, float salt, float vitaminA_retinol, float betaCarotin, float vitaminD, float vitaminE, float vitaminK, float thiamin_B1, float riboflavin_B2, float niacin, float vitaminB6, float folat, float pantothenacid, float biotin, float cobalamin_B12, float vitaminC, float natrium, float chlorid, float kalium, float calcium, float phosphor, float magnesium, float eisen, float jod, float fluorid, float zink, float selen, float kupfer, float mangan, float chrom, float molybdaen, String barcode); @Query("SELECT * FROM product WHERE name LIKE :name") List findProductsByName(String name); diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/network/utils/ProductConversionHelper.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/network/utils/ProductConversionHelper.java index b204b1d..e23cd6b 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/network/utils/ProductConversionHelper.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/network/utils/ProductConversionHelper.java @@ -71,6 +71,7 @@ public static Product conversionProduct(org.secuso.privacyfriendlyfoodtracker.ne } // if the id is equals to 0 then the room database creates a new id (primary key) - return new Product(0, product.getProductName(), energy_100g, carbs, sugar, protein, fat, satFat, product.getCode()); + //TODO: fetch the real values instead of just 0s + return new Product(0, product.getProductName(), energy_100g, carbs, sugar, protein, fat, satFat, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, product.getCode()); } } diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/AddFoodFragment.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/AddFoodFragment.java index d6aafcd..746e442 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/AddFoodFragment.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/AddFoodFragment.java @@ -18,6 +18,8 @@ import android.arch.lifecycle.ViewModelProviders; import android.os.Bundle; +import android.support.constraint.ConstraintLayout; +import android.support.constraint.ConstraintSet; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.design.widget.TextInputLayout; @@ -29,12 +31,17 @@ import android.view.View; import android.view.ViewGroup; import android.widget.EditText; +import android.widget.LinearLayout; import android.widget.TextView; import org.secuso.privacyfriendlyfoodtracker.R; import org.secuso.privacyfriendlyfoodtracker.ui.adapter.DatabaseFacade; import org.secuso.privacyfriendlyfoodtracker.ui.viewmodels.SharedStatisticViewModel; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; import java.util.Locale; +import java.util.Map; /** @@ -50,11 +57,9 @@ public class AddFoodFragment extends Fragment { DatabaseFacade databaseFacade; EditText amountField; EditText caloriesField; - EditText carbsField; - EditText sugarField; - EditText proteinField; - EditText fatField; - EditText satFatField; + + Map otherFoodInfoTextInputLayouts = new HashMap<>(); + Map otherFoodInfoEditTexts = new HashMap<>(); /** * The required empty public constructor */ @@ -87,21 +92,47 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, amountField = parentHolder.findViewById(R.id.input_amount); caloriesField = parentHolder.findViewById(R.id.input_calories); - carbsField = parentHolder.findViewById(R.id.input_carbs); - sugarField = parentHolder.findViewById(R.id.input_sugar); - proteinField = parentHolder.findViewById(R.id.input_protein); - fatField = parentHolder.findViewById(R.id.input_fat); - satFatField = parentHolder.findViewById(R.id.input_satFat); + + + ConstraintLayout constraintLayout = parentHolder.findViewById(R.id.addFoodFieldLayout); + + int idOfPredecessor = R.id.inputCalories; + for(Map.Entry foodInfoEntry: FoodInfosToShow.getFoodInfosShownAsMap(getContext()).entrySet()){ + FoodInfo foodInfo = foodInfoEntry.getValue(); + TextInputLayout currentTIL = new TextInputLayout(getContext()); + currentTIL.setId(View.generateViewId()); + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + currentTIL.setLayoutParams(layoutParams); + + EditText currentET = new EditText(getContext()); + + currentET.setLayoutParams(layoutParams); + currentET.setMaxLines(1); + currentET.setFilters(caloriesFilter); + + + currentTIL.setHint(foodInfo.getName() + " in " + foodInfo.getUnit()); + + currentTIL.addView(currentET); + constraintLayout.addView(currentTIL); + ConstraintSet constraintSet = new ConstraintSet(); + constraintSet.clone(constraintLayout); + + constraintSet.connect(currentTIL.getId(), ConstraintSet.TOP, idOfPredecessor, ConstraintSet.BOTTOM, 0); + constraintSet.applyTo(constraintLayout); + + idOfPredecessor = currentTIL.getId(); + + otherFoodInfoEditTexts.put(foodInfoEntry.getKey(),currentET); + otherFoodInfoTextInputLayouts.put(foodInfoEntry.getKey(), currentTIL); + //System.out.println("added" + foodInfo.getName() + " in " + foodInfo.getUnit()); + } + amountField.setFilters(amountFilter); amountField.setInputType(InputType.TYPE_CLASS_NUMBER); caloriesField.setFilters(caloriesFilter); - carbsField.setFilters(caloriesFilter); - sugarField.setFilters(caloriesFilter); - proteinField.setFilters(caloriesFilter); - fatField.setFilters(caloriesFilter); - satFatField.setFilters(caloriesFilter); FloatingActionButton fab = parentHolder.findViewById(R.id.addEntry); @@ -115,38 +146,32 @@ public void onClick(View view) { String calories = caloriesField.getText().toString(); - String carbs = carbsField.getText().toString(); - - String sugar = sugarField.getText().toString(); - String protein = proteinField.getText().toString(); - - String fat = fatField.getText().toString(); + // validation + boolean validated = validateResponses(name, amount, calories); + //now parse the other Infos and validate and put the parsed values into yet another Map + Map fieldValues =new HashMap<>(); + for(Map.Entry editTextEntry : otherFoodInfoEditTexts.entrySet()){ + try { + String etValue = editTextEntry.getValue().getText().toString(); + Float fieldValue; + if ("".equals(etValue)){ + fieldValue = 0.0f; + }else{ + fieldValue = Float.parseFloat(etValue); + } + fieldValues.put(editTextEntry.getKey(),fieldValue); + } catch (NumberFormatException e) { + showErrorMessageString(otherFoodInfoTextInputLayouts.get(editTextEntry.getKey()), getResources().getString(R.string.error_fieldname_nan, FoodInfosToShow.foodInfos.get(editTextEntry.getKey()))); + validated = false; + } + } - String satFat = satFatField.getText().toString(); + if(validated) { - //replace empty macro slots with "0" - if("".equals(carbs)){ - carbs="0"; - } - if("".equals(sugar)){ - sugar="0"; - } - if("".equals(protein)){ - protein="0"; - } - if("".equals(fat)){ - fat="0"; - } - if("".equals(satFat)){ - satFat="0"; - } - // validation - boolean validated = validateResponses(name, amount, calories, carbs, sugar, protein, fat, satFat, view); - if(validated) { - boolean entrySuccessful = makeDatabaseEntry(name, amount, calories, carbs, sugar, protein, fat, satFat); + boolean entrySuccessful = makeDatabaseEntry(name, amount, calories, fieldValues); if (!entrySuccessful){ showErrorMessage(view, R.string.error_database); } else { @@ -172,11 +197,7 @@ public void setUserVisibleHint(boolean isVisible) { if(isVisible && referenceActivity.productSet) { EditText nameField = parentHolder.findViewById(R.id.input_food); EditText caloriesField = parentHolder.findViewById(R.id.input_calories); - EditText carbsField = parentHolder.findViewById(R.id.input_carbs); - EditText sugarField = parentHolder.findViewById(R.id.input_sugar); - EditText proteinField = parentHolder.findViewById(R.id.input_protein); - EditText fatField = parentHolder.findViewById(R.id.input_fat); - EditText satFatField = parentHolder.findViewById(R.id.input_satFat); + nameField.setText(referenceActivity.name); @@ -189,39 +210,18 @@ public void setUserVisibleHint(boolean isVisible) { caloriesField.setClickable(false); caloriesField.setTextColor(getResources().getColor(R.color.middlegrey)); - carbsField.setText(String.format(Locale.ENGLISH, "%.2f", referenceActivity.carbs)); - carbsField.setFocusable(false); - carbsField.setClickable(false); - carbsField.setTextColor(getResources().getColor(R.color.middlegrey)); - - sugarField.setText(String.format(Locale.ENGLISH, "%.2f", referenceActivity.sugar)); - sugarField.setFocusable(false); - sugarField.setClickable(false); - sugarField.setTextColor(getResources().getColor(R.color.middlegrey)); - - proteinField.setText(String.format(Locale.ENGLISH, "%.2f", referenceActivity.protein)); - proteinField.setFocusable(false); - proteinField.setClickable(false); - proteinField.setTextColor(getResources().getColor(R.color.middlegrey)); - - fatField.setText(String.format(Locale.ENGLISH, "%.2f", referenceActivity.fat)); - fatField.setFocusable(false); - fatField.setClickable(false); - fatField.setTextColor(getResources().getColor(R.color.middlegrey)); - - satFatField.setText(String.format(Locale.ENGLISH, "%.2f", referenceActivity.satFat)); - satFatField.setFocusable(false); - satFatField.setClickable(false); - satFatField.setTextColor(getResources().getColor(R.color.middlegrey)); + for(Map.Entry editTextEntry : otherFoodInfoEditTexts.entrySet()){ + EditText currentEt = editTextEntry.getValue(); + //TODO dafür sorgen, dass referenceActivity.otherFoodInfo gefüllt wird + currentEt.setText(String.format(Locale.ENGLISH, "%.2f", FoodInfosToShow.getFoodInfoValueByKey(referenceActivity.selectedProduct,editTextEntry.getKey()))); + currentEt.setFocusable(false); + currentEt.setClickable(false); + currentEt.setTextColor(getResources().getColor(R.color.middlegrey)); + } } else if (isVisible && !referenceActivity.productSet) { EditText nameField = parentHolder.findViewById(R.id.input_food); EditText caloriesField = parentHolder.findViewById(R.id.input_calories); - EditText carbsField = parentHolder.findViewById(R.id.input_carbs); - EditText sugarField = parentHolder.findViewById(R.id.input_sugar); - EditText proteinField = parentHolder.findViewById(R.id.input_protein); - EditText fatField = parentHolder.findViewById(R.id.input_fat); - EditText satFatField = parentHolder.findViewById(R.id.input_satFat); nameField.setText(""); nameField.setFocusable(true); @@ -235,38 +235,32 @@ public void setUserVisibleHint(boolean isVisible) { caloriesField.setClickable(true); caloriesField.setTextColor(getResources().getColor(R.color.black)); - carbsField.setText(""); - carbsField.setFocusable(true); - carbsField.setFocusableInTouchMode(true); - carbsField.setClickable(true); - carbsField.setTextColor(getResources().getColor(R.color.black)); - - sugarField.setText(""); - sugarField.setFocusable(true); - sugarField.setFocusableInTouchMode(true); - sugarField.setClickable(true); - sugarField.setTextColor(getResources().getColor(R.color.black)); - - proteinField.setText(""); - proteinField.setFocusable(true); - proteinField.setFocusableInTouchMode(true); - proteinField.setClickable(true); - proteinField.setTextColor(getResources().getColor(R.color.black)); - - fatField.setText(""); - fatField.setFocusable(true); - fatField.setFocusableInTouchMode(true); - fatField.setClickable(true); - fatField.setTextColor(getResources().getColor(R.color.black)); - - satFatField.setText(""); - satFatField.setFocusable(true); - satFatField.setFocusableInTouchMode(true); - satFatField.setClickable(true); - satFatField.setTextColor(getResources().getColor(R.color.black)); + for(Map.Entry editTextEntry : otherFoodInfoEditTexts.entrySet()){ + EditText currentEt = editTextEntry.getValue(); + currentEt.setText(""); + currentEt.setFocusable(true); + currentEt.setFocusableInTouchMode(true); + currentEt.setClickable(true); + currentEt.setTextColor(getResources().getColor(R.color.black)); + } } } + + /*** + * Map.getOrDefault does not exist in Api<24 :/ + * @param map + * @param key + * @param defaultValue + * @return the mapped value or the default, if no mapping exists + */ + private Float getOrDefault(Map map, String key, float defaultValue){ + Float ret = map.get(key); + if(ret==null){ + ret = defaultValue; + } + return ret; + } /** * Create a new db entry * @param name Name of the food @@ -274,18 +268,15 @@ public void setUserVisibleHint(boolean isVisible) { * @param caloriesString calories per 100g * @return true if successful */ - private boolean makeDatabaseEntry(String name, String amountString, String caloriesString, String carbsString, String sugarString, String proteinString, String fatString, String satFatString) { + private boolean makeDatabaseEntry(String name, String amountString, String caloriesString, Map otherFieldValues) { try { int amount = Integer.parseInt(amountString); float calories = Float.parseFloat(caloriesString); - float carbs = Float.parseFloat(carbsString); - float sugar = Float.parseFloat(sugarString); - float protein = Float.parseFloat(proteinString); - float fat = Float.parseFloat(fatString); - float satFat = Float.parseFloat(satFatString); + // We haven't explicitly chosen a product so the productId is 0 for unknown - databaseFacade.insertEntry(amount, ((BaseAddFoodActivity) referenceActivity).date, name, calories, carbs, sugar, protein, fat, satFat, 0); + databaseFacade.insertEntry(amount, ((BaseAddFoodActivity) referenceActivity).date, name, calories, + getOrDefault(otherFieldValues, "carbs", 0.0f), getOrDefault(otherFieldValues, "sugar", 0.0f), getOrDefault(otherFieldValues, "protein", 0.0f), getOrDefault(otherFieldValues, "fat", 0.0f), getOrDefault(otherFieldValues, "satFat", 0.0f), getOrDefault(otherFieldValues, "salt", 0.0f), getOrDefault(otherFieldValues, "vitaminA_retinol", 0.0f), getOrDefault(otherFieldValues, "betaCarotin", 0.0f), getOrDefault(otherFieldValues, "vitaminD", 0.0f), getOrDefault(otherFieldValues, "vitaminE", 0.0f), getOrDefault(otherFieldValues, "vitaminK", 0.0f), getOrDefault(otherFieldValues, "thiamin_B1", 0.0f), getOrDefault(otherFieldValues, "riboflavin_B2", 0.0f), getOrDefault(otherFieldValues, "niacin", 0.0f), getOrDefault(otherFieldValues, "vitaminB6", 0.0f), getOrDefault(otherFieldValues, "folat", 0.0f), getOrDefault(otherFieldValues, "pantothenacid", 0.0f), getOrDefault(otherFieldValues, "biotin", 0.0f), getOrDefault(otherFieldValues, "cobalamin_B12", 0.0f), getOrDefault(otherFieldValues, "vitaminC", 0.0f), getOrDefault(otherFieldValues, "natrium", 0.0f), getOrDefault(otherFieldValues, "chlorid", 0.0f), getOrDefault(otherFieldValues, "kalium", 0.0f), getOrDefault(otherFieldValues, "calcium", 0.0f), getOrDefault(otherFieldValues, "phosphor", 0.0f), getOrDefault(otherFieldValues, "magnesium", 0.0f), getOrDefault(otherFieldValues, "eisen", 0.0f), getOrDefault(otherFieldValues, "jod", 0.0f), getOrDefault(otherFieldValues, "fluorid", 0.0f), getOrDefault(otherFieldValues, "zink", 0.0f), getOrDefault(otherFieldValues, "selen", 0.0f), getOrDefault(otherFieldValues, "kupfer", 0.0f), getOrDefault(otherFieldValues, "mangan", 0.0f), getOrDefault(otherFieldValues, "chrom", 0.0f), getOrDefault(otherFieldValues, "molybdaen", 0.0f), 0); } catch (Exception e) { // something went wrong so the entry wasn't successful e.printStackTrace(); @@ -299,10 +290,9 @@ private boolean makeDatabaseEntry(String name, String amountString, String calor * @param name name of the product * @param amount amount in g * @param calories calories per 100g - * @param view the view * @return returns true is all entries are valid */ - private boolean validateResponses(String name, String amount, String calories, String carbs, String sugar, String protein, String fat, String satFat, View view) { + private boolean validateResponses(String name, String amount, String calories) { if("".equals(name)){ showErrorMessage(referenceActivity.findViewById(R.id.inputFoodName), R.string.error_food_missing); return false; @@ -329,28 +319,12 @@ private boolean validateResponses(String name, String amount, String calories, S showErrorMessage(referenceActivity.findViewById(R.id.inputCalories), R.string.error_calories_nan); return false; } - try { - Float.parseFloat(carbs); - } catch (NumberFormatException e) { - showErrorMessage(referenceActivity.findViewById(R.id.inputCalories), R.string.error_carbs_nan); - return false; - } - try { - Float.parseFloat(protein); - } catch (NumberFormatException e) { - showErrorMessage(referenceActivity.findViewById(R.id.inputCalories), R.string.error_protein_nan); - return false; - } - try { - Float.parseFloat(fat); - } catch (NumberFormatException e) { - showErrorMessage(referenceActivity.findViewById(R.id.inputCalories), R.string.error_fat_nan); - return false; - } return true; } + + private void showErrorMessage(View view, int errorMessageId){ // reset error messages ((TextInputLayout)referenceActivity.findViewById(R.id.inputFoodName)).setError(""); @@ -367,5 +341,11 @@ private void showErrorMessage(View view, int errorMessageId){ .setAction("Action", null).show(); } } + private void showErrorMessageString(View view, String errorMessage){ + if(view instanceof TextInputLayout){ + TextInputLayout til = (TextInputLayout) view; + til.setError(errorMessage); + } + } } diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/BaseAddFoodActivity.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/BaseAddFoodActivity.java index 8fe800e..1f4f9d9 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/BaseAddFoodActivity.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/BaseAddFoodActivity.java @@ -26,9 +26,12 @@ import android.view.MenuItem; import org.secuso.privacyfriendlyfoodtracker.R; +import org.secuso.privacyfriendlyfoodtracker.database.Product; import org.secuso.privacyfriendlyfoodtracker.ui.adapter.AddFoodPagerAdapter; import java.util.Date; +import java.util.HashMap; +import java.util.Map; /** * Base code for tapped activity. @@ -53,6 +56,8 @@ public class BaseAddFoodActivity extends AppCompatActivity { float fat; // satFat of the product float satFat; + //the product selected + Product selectedProduct; // ID of the product int id; diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/FoodInfo.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/FoodInfo.java new file mode 100644 index 0000000..17dae84 --- /dev/null +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/FoodInfo.java @@ -0,0 +1,32 @@ +package org.secuso.privacyfriendlyfoodtracker.ui; + +/*** + * Contains information about the infos about a food. E.g. there is a FoodInfo("carbs", "g") + * indicating that food can contain "Carbs" which are measured in gramm. + */ +public class FoodInfo { + private String name; + private String unit; + + public FoodInfo(String name, String unit) { + this.name = name; + this.unit = unit; + } + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + + public String getUnit() { + return unit; + } + + public void setUnit(String unit) { + this.unit = unit; + } + +} diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/FoodInfosToShow.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/FoodInfosToShow.java new file mode 100644 index 0000000..d4e85d9 --- /dev/null +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/FoodInfosToShow.java @@ -0,0 +1,281 @@ +package org.secuso.privacyfriendlyfoodtracker.ui; + +import android.content.Context; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import org.secuso.privacyfriendlyfoodtracker.database.Product; +import org.secuso.privacyfriendlyfoodtracker.ui.adapter.DatabaseEntry; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/*** + * This class provides access to all the possible food infos (nutriments, vitamins etc) which the + * user can choose to display in the app. + */ +public class FoodInfosToShow { + + /*** + * Idea for later: If the need arises to allow users to change order of food infos: + * Implement getter method which uses ordered list of food info keys and returns a new + * linkedHashMap, where entries from foodInfo map are inserted according to the ordered list of + * food info keys. + */ + public static Map foodInfos=new LinkedHashMap<>(); // LinkedHashMap so entries are ordered by insertion + static { + //TODO check whether all units are correct, especially vitamins etc. maybe some of them are rather micro than milligram + foodInfos.put("carbs", new FoodInfo("Carbs", "g")); + foodInfos.put("sugar", new FoodInfo("Sugar", "g")); + foodInfos.put("protein", new FoodInfo("Protein", "g")); + foodInfos.put("fat", new FoodInfo("Fat", "g")); + foodInfos.put("satFat", new FoodInfo("SatFat", "g")); + foodInfos.put("salt", new FoodInfo("Salt", "g")); + foodInfos.put("vitaminA_retinol", new FoodInfo("Vitamin A", "mg")); + foodInfos.put("betaCarotin", new FoodInfo("Beta-Carotin", "mg")); + foodInfos.put("vitaminD", new FoodInfo("Vitamin D", "mg")); + foodInfos.put("vitaminE", new FoodInfo("Vitamin E", "mg")); + foodInfos.put("vitaminK", new FoodInfo("Vitamin K", "mg")); + foodInfos.put("thiamin_B1", new FoodInfo("Vitamin B1", "mg")); + foodInfos.put("riboflavin_B2", new FoodInfo("Vitamin B2", "mg")); + foodInfos.put("niacin", new FoodInfo("Niacin", "mg")); + foodInfos.put("vitaminB6", new FoodInfo("Vitamin B6", "mg")); + foodInfos.put("folat", new FoodInfo("Folat", "mg")); + foodInfos.put("pantothenacid", new FoodInfo("Pantothenacid", "mg")); + foodInfos.put("biotin", new FoodInfo("Biotin", "mg")); + foodInfos.put("cobalamin_B12", new FoodInfo("Vitamin B12", "mg")); + foodInfos.put("vitaminC", new FoodInfo("Vitamin C", "mg")); + foodInfos.put("natrium", new FoodInfo("Natrium", "mg")); + foodInfos.put("chlorid", new FoodInfo("Chlorid", "mg")); + foodInfos.put("kalium", new FoodInfo("Kalium", "mg")); + foodInfos.put("calcium", new FoodInfo("Calcium", "mg")); + foodInfos.put("phosphor", new FoodInfo("Phosphor", "mg")); + foodInfos.put("magnesium", new FoodInfo("Magnesium", "mg")); + foodInfos.put("eisen", new FoodInfo("Eisen", "mg")); + foodInfos.put("jod", new FoodInfo("Jod", "mg")); + foodInfos.put("fluorid", new FoodInfo("Fluorid", "mg")); + foodInfos.put("zink", new FoodInfo("Zink", "mg")); + foodInfos.put("selen", new FoodInfo("Selen", "mg")); + foodInfos.put("kupfer", new FoodInfo("Kupfer", "mg")); + foodInfos.put("mangan", new FoodInfo("Mangan", "mg")); + foodInfos.put("chrom", new FoodInfo("Chrom", "mg")); + foodInfos.put("molybdaen", new FoodInfo("Molybdaen", "mg")); + } + + + + public static List getFoodInfosShown(Context context){ + SharedPreferences sharedPreferences = + PreferenceManager.getDefaultSharedPreferences(context); + List foodInfosToShow = new ArrayList<>(); + for(Map.Entry foodInfoEntry : foodInfos.entrySet()){ + if(sharedPreferences.getBoolean(foodInfoEntry.getKey(),false)){ + foodInfosToShow.add(foodInfoEntry.getValue()); + } + } + return foodInfosToShow; + } + + /*** + * Returns a Map containing all FoodInfos that shall be shown in the app. E.g. if the user wished + * to show Carbs and Fat, the returned Map would consist of <"carbs", FoodInfo(...)> and<"fat",FoodInfo>. + * @param context + * @return + */ + public static Map getFoodInfosShownAsMap(Context context){ + SharedPreferences sharedPreferences = + PreferenceManager.getDefaultSharedPreferences(context); + Map foodInfosToShow = new LinkedHashMap<>(); //LinkedHashMap to keep order + for(Map.Entry foodInfoEntry : foodInfos.entrySet()){ + if(sharedPreferences.getBoolean(foodInfoEntry.getKey(),false)){ + foodInfosToShow.put(foodInfoEntry.getKey(),foodInfoEntry.getValue()); + } + } + return foodInfosToShow; + } + + + + /*** + * Given a key identifying a FoodInfo and a DatabaseEntry containing all FoodInfoValues, return + * the specified FoodInfo's value from the DatabaseEntry. Possible keys are those present in + * FoodInfosToShow.foodInfos, e.g. "carbs". + * + * Meta: I also thought about implementing getting a FoodInfo's value from a DatabaseEntry by + * giving each FoodInfo-object a strategy object which offers a method to retrieve the value. That + * way would be a little more object-oriented, but maybe too convoluted, so i stuck with this simple + * key lookup. + * @param databaseEntry + * @param key + * @return + */ + public static float getFoodInfoValueByKey(DatabaseEntry databaseEntry, String key){ + switch(key){ + case "carbs": + return databaseEntry.carbs; + case "sugar": + return databaseEntry.sugar; + case "protein": + return databaseEntry.protein; + case "fat": + return databaseEntry.fat; + case "satFat": + return databaseEntry.satFat; + case "salt": + return databaseEntry.salt; + case "vitaminA_retinol": + return databaseEntry.vitaminA_retinol; + case "betaCarotin": + return databaseEntry.betaCarotin; + case "vitaminD": + return databaseEntry.vitaminD; + case "vitaminE": + return databaseEntry.vitaminE; + case "vitaminK": + return databaseEntry.vitaminK; + case "thiamin_B1": + return databaseEntry.thiamin_B1; + case "riboflavin_B2": + return databaseEntry.riboflavin_B2; + case "niacin": + return databaseEntry.niacin; + case "vitaminB6": + return databaseEntry.vitaminB6; + case "folat": + return databaseEntry.folat; + case "pantothenacid": + return databaseEntry.pantothenacid; + case "biotin": + return databaseEntry.biotin; + case "cobalamin_B12": + return databaseEntry.cobalamin_B12; + case "vitaminC": + return databaseEntry.vitaminC; + case "natrium": + return databaseEntry.natrium; + case "chlorid": + return databaseEntry.chlorid; + case "kalium": + return databaseEntry.kalium; + case "calcium": + return databaseEntry.calcium; + case "phosphor": + return databaseEntry.phosphor; + case "magnesium": + return databaseEntry.magnesium; + case "eisen": + return databaseEntry.eisen; + case "jod": + return databaseEntry.jod; + case "fluorid": + return databaseEntry.fluorid; + case "zink": + return databaseEntry.zink; + case "selen": + return databaseEntry.selen; + case "kupfer": + return databaseEntry.kupfer; + case "mangan": + return databaseEntry.mangan; + case "chrom": + return databaseEntry.chrom; + case "molybdaen": + return databaseEntry.molybdaen; + } + return 0.0f; + } + /*** + * Given a key identifying a FoodInfo and a Product containing all FoodInfoValues, return + * the specified FoodInfo's value from the Product. Possible keys are those present in + * FoodInfosToShow.foodInfos, e.g. "carbs". + * + * Meta: This does exactly the same like getFoodInfoValueByKey(DatabaseEntry,String), just for the + * Product class. It would probably be nicer to just have Product and DatabaseEntry implement an + * interface offering getters for every food info. TODO. + * @param product + * @param key + * @return + */ + public static float getFoodInfoValueByKey(Product product, String key){ + switch(key){ + case "carbs": + return product.carbs; + case "sugar": + return product.sugar; + case "protein": + return product.protein; + case "fat": + return product.fat; + case "satFat": + return product.satFat; + case "salt": + return product.salt; + case "vitaminA_retinol": + return product.vitaminA_retinol; + case "betaCarotin": + return product.betaCarotin; + case "vitaminD": + return product.vitaminD; + case "vitaminE": + return product.vitaminE; + case "vitaminK": + return product.vitaminK; + case "thiamin_B1": + return product.thiamin_B1; + case "riboflavin_B2": + return product.riboflavin_B2; + case "niacin": + return product.niacin; + case "vitaminB6": + return product.vitaminB6; + case "folat": + return product.folat; + case "pantothenacid": + return product.pantothenacid; + case "biotin": + return product.biotin; + case "cobalamin_B12": + return product.cobalamin_B12; + case "vitaminC": + return product.vitaminC; + case "natrium": + return product.natrium; + case "chlorid": + return product.chlorid; + case "kalium": + return product.kalium; + case "calcium": + return product.calcium; + case "phosphor": + return product.phosphor; + case "magnesium": + return product.magnesium; + case "eisen": + return product.eisen; + case "jod": + return product.jod; + case "fluorid": + return product.fluorid; + case "zink": + return product.zink; + case "selen": + return product.selen; + case "kupfer": + return product.kupfer; + case "mangan": + return product.mangan; + case "chrom": + return product.chrom; + case "molybdaen": + return product.molybdaen; + } + return 0.0f; + } +} diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/OverviewActivity.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/OverviewActivity.java index 5d15564..5bfcfa9 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/OverviewActivity.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/OverviewActivity.java @@ -23,12 +23,14 @@ import org.secuso.privacyfriendlyfoodtracker.ui.viewmodels.SharedStatisticViewModel; import org.secuso.privacyfriendlyfoodtracker.ui.views.CheckableCardView; import org.secuso.privacyfriendlyfoodtracker.R; +import org.w3c.dom.Text; import android.app.AlertDialog; import android.arch.lifecycle.Observer; import android.arch.lifecycle.ViewModelProviders; import android.arch.persistence.room.Database; import android.content.DialogInterface; +import android.graphics.drawable.GradientDrawable; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.constraint.Barrier; @@ -37,6 +39,7 @@ import android.text.InputFilter; import android.text.InputType; import android.util.TypedValue; +import android.view.Gravity; import android.view.LayoutInflater; import android.view.Menu; import android.support.v7.widget.Toolbar; @@ -45,6 +48,7 @@ import android.view.ViewGroup; import android.widget.EditText; import android.widget.LinearLayout; +import android.widget.ProgressBar; import android.widget.TextView; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; @@ -58,10 +62,12 @@ import java.math.BigDecimal; import java.text.SimpleDateFormat; +import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Date; import java.util.Locale; +import java.util.Map; /** * The overview for a day @@ -79,6 +85,15 @@ public class OverviewActivity extends AppCompatActivity { private OverviewViewModel viewModel; + /*** + * Maps containing UI elements for the food infos to show. + */ + private Map tvFoodInfoNameMap = new HashMap<>(); + private Map tvFoodInfoAmountMap = new HashMap<>(); + private Map pbFoodInfoProgressMap = new HashMap<>(); + + private ProgressBar progressBarCalories = null; + /** * sets up the activity * @param savedInstanceState the saved instance state @@ -273,13 +288,9 @@ private ViewGroup getEntryList() { */ private void refreshTotalCalorieCounter(@Nullable List entries) { BigDecimal totalCalories = new BigDecimal("0"); - BigDecimal totalCarbs = new BigDecimal("0"); - BigDecimal totalSugar = new BigDecimal("0"); - BigDecimal totalProtein = new BigDecimal("0"); - BigDecimal totalFat = new BigDecimal("0"); - BigDecimal totalSatFat = new BigDecimal("0"); + TextView heading = this.findViewById(R.id.overviewHeading); - TextView macrosOverview = this.findViewById(R.id.overviewMacros); + String cal = getString(R.string.total_calories); Date d = getDateForActivity(); @@ -287,17 +298,188 @@ private void refreshTotalCalorieCounter(@Nullable List entries) { if(entries != null) { for (DatabaseEntry e : entries) { totalCalories = totalCalories.add(BigDecimal.valueOf(e.energy * e.amount / 100)); - totalCarbs = totalCarbs.add(BigDecimal.valueOf(e.carbs * e.amount / 100)); - totalSugar = totalSugar.add(BigDecimal.valueOf(e.sugar * e.amount / 100)); - totalProtein = totalProtein.add(BigDecimal.valueOf(e.protein * e.amount / 100)); - totalFat = totalFat.add(BigDecimal.valueOf(e.fat * e.amount / 100)); - totalSatFat = totalSatFat.add(BigDecimal.valueOf(e.satFat * e.amount / 100)); + } + } + heading.setText(String.format(Locale.ENGLISH, "%s", formattedDate)); + + TextView tvCaloriesAmount = this.findViewById(R.id.caloriesAmountTv); + tvCaloriesAmount.setText(String.format(Locale.ENGLISH, "%.2f %s", totalCalories, cal)); + + boolean rebuildLayout=false; + boolean showDailyGoals = true; + + + Map foodInfosToShow = FoodInfosToShow.getFoodInfosShownAsMap(this); + if(!tvFoodInfoAmountMap.isEmpty()){// if there already is a map with textviews, check if all foodinfos have a view, if not the maps get cleared, so the layout can be created in the next loop without problems + for(Map.Entry foodInfoEntry : foodInfosToShow.entrySet()){ + if(!tvFoodInfoAmountMap.containsKey(foodInfoEntry.getKey())){ + clearLayoutAndMaps(); + rebuildLayout = true; + break; + } + } + for(Map.Entry textViewEntry : tvFoodInfoAmountMap.entrySet()){//do the same as above for textview map entries, to see if maybe food infos have changed to not show, so an empty textview would be dangling around + if(!foodInfosToShow.containsKey(textViewEntry.getKey())){ + clearLayoutAndMaps(); + rebuildLayout = true; + break; + } + } + }else{ + rebuildLayout = true; + } + + + ConstraintLayout constraintLayout = findViewById(R.id.overviewContentConstraintLayout); + + + //add progressBar if daily goal specified + if(showDailyGoals){ + if(progressBarCalories == null){ + clearLayoutAndMaps(); + rebuildLayout = true; + + progressBarCalories = new ProgressBar(this, null, + android.R.attr.progressBarStyleHorizontal); + progressBarCalories.setId(View.generateViewId()); + ConstraintLayout.LayoutParams layoutParams = new ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.MATCH_PARENT, ConstraintLayout.LayoutParams.WRAP_CONTENT); + progressBarCalories.setLayoutParams(layoutParams); + + constraintLayout.addView(progressBarCalories); + + + ConstraintSet constraintSet = new ConstraintSet(); + constraintSet.clone(constraintLayout); + + constraintSet.connect(progressBarCalories.getId(), ConstraintSet.TOP, R.id.caloriesNameTv, ConstraintSet.BOTTOM, 0); + + constraintSet.connect(progressBarCalories.getId(), ConstraintSet.LEFT, constraintLayout.getId(), ConstraintSet.LEFT, 0); + constraintSet.connect(progressBarCalories.getId(), ConstraintSet.RIGHT, constraintLayout.getId(), ConstraintSet.RIGHT, 0); + + + constraintSet.applyTo(constraintLayout); + + } + }else{ + if(progressBarCalories != null){ + constraintLayout.removeView(progressBarCalories); + + clearLayoutAndMaps(); + rebuildLayout = true; + } + } + + int idOfPredecessor = showDailyGoals ? progressBarCalories.getId() : R.id.caloriesNameTv; + for(Map.Entry foodInfoEntry : foodInfosToShow.entrySet()){ + + TextView tvFoodInfoName=null; + TextView tvFoodInfoAmount=null; + ProgressBar progressBar = null; + if(tvFoodInfoAmountMap.containsKey(foodInfoEntry.getKey())){ //this could be also replaced by a check for rebuildLayout + tvFoodInfoAmount = tvFoodInfoAmountMap.get(foodInfoEntry.getKey()); + tvFoodInfoName = tvFoodInfoNameMap.get(foodInfoEntry.getKey()); //tvFoodInfoName should never be needed, when it already exists. But atm I leave it there. + if(showDailyGoals){ + progressBar = pbFoodInfoProgressMap.get(foodInfoEntry.getKey()); + } + }else { + tvFoodInfoAmount = new TextView(this); + tvFoodInfoName = new TextView(this); + + + tvFoodInfoName.setId(View.generateViewId()); + tvFoodInfoAmount.setId(View.generateViewId()); + + if(showDailyGoals) { + progressBar = new ProgressBar(this, null, + android.R.attr.progressBarStyleHorizontal); + progressBar.setId(View.generateViewId()); + } + + tvFoodInfoName.setText(foodInfoEntry.getValue().getName()); + + tvFoodInfoName.setGravity(Gravity.LEFT); + tvFoodInfoAmount.setGravity(Gravity.RIGHT); + + + constraintLayout.addView(tvFoodInfoName); + constraintLayout.addView(tvFoodInfoAmount); + + if(showDailyGoals) { + ConstraintLayout.LayoutParams layoutParams = new ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.MATCH_PARENT, ConstraintLayout.LayoutParams.WRAP_CONTENT); + progressBar.setLayoutParams(layoutParams); + constraintLayout.addView(progressBar); + } + + + ConstraintSet constraintSet = new ConstraintSet(); + constraintSet.clone(constraintLayout); + + constraintSet.connect(tvFoodInfoName.getId(), ConstraintSet.TOP, idOfPredecessor, ConstraintSet.BOTTOM, 0); + constraintSet.connect(tvFoodInfoAmount.getId(), ConstraintSet.TOP, idOfPredecessor, ConstraintSet.BOTTOM, 0); + + constraintSet.connect(tvFoodInfoName.getId(), ConstraintSet.LEFT, constraintLayout.getId(), ConstraintSet.LEFT, 0); + constraintSet.connect(tvFoodInfoAmount.getId(), ConstraintSet.RIGHT, constraintLayout.getId(), ConstraintSet.RIGHT, 0); + + if(showDailyGoals) { + constraintSet.connect(progressBar.getId(), ConstraintSet.TOP, tvFoodInfoAmount.getId(), ConstraintSet.BOTTOM, 0); + constraintSet.connect(progressBar.getId(), ConstraintSet.LEFT, constraintLayout.getId(), ConstraintSet.LEFT, 0); + constraintSet.connect(progressBar.getId(), ConstraintSet.RIGHT, constraintLayout.getId(), ConstraintSet.RIGHT, 0); + } + + constraintSet.applyTo(constraintLayout); + + tvFoodInfoAmountMap.put(foodInfoEntry.getKey(),tvFoodInfoAmount); + tvFoodInfoNameMap.put(foodInfoEntry.getKey(),tvFoodInfoName); + + if(showDailyGoals) { + pbFoodInfoProgressMap.put(foodInfoEntry.getKey(), progressBar); + } + } - // totalCalories += (e.energy * e.amount) / 100; + + + + + BigDecimal totalAmount = new BigDecimal("0"); + + for (DatabaseEntry e : entries) { + totalAmount = totalAmount.add(BigDecimal.valueOf(FoodInfosToShow.getFoodInfoValueByKey(e,foodInfoEntry.getKey()) * e.amount / 100)); } + tvFoodInfoAmount.setText(String.format(Locale.ENGLISH, "%1$.2f%2$s",totalAmount,foodInfoEntry.getValue().getUnit())); + + + + idOfPredecessor = showDailyGoals? progressBar.getId() : tvFoodInfoName.getId(); + } + if(rebuildLayout) { + ConstraintSet constraintSet = new ConstraintSet(); + constraintSet.clone(constraintLayout); + + constraintSet.connect(R.id.DailyList, ConstraintSet.TOP, idOfPredecessor, ConstraintSet.BOTTOM, 0); + + constraintSet.applyTo(constraintLayout); + } + + } + + /*** + * Removes all views that are in maps and then clears the maps. Call if new foodInfos shall be shown + * or something about the daily goals changes + */ + private void clearLayoutAndMaps() { + ConstraintLayout constraintLayout = findViewById(R.id.overviewContentConstraintLayout); + for(Map.Entry tvEntry : tvFoodInfoAmountMap.entrySet()){ + constraintLayout.removeView(tvEntry.getValue()); + } + for(Map.Entry tvEntry : tvFoodInfoNameMap.entrySet()){ + constraintLayout.removeView(tvEntry.getValue()); } - heading.setText(String.format(Locale.ENGLISH, " %s: %.2f %s", formattedDate, totalCalories, cal)); - macrosOverview.setText(String.format(Locale.ENGLISH, "Carbs(sugar): %.2f (%.2f) - Protein: %.2f - Fat (sat.): %.2f (%.2f)", totalCarbs, totalSugar, totalProtein, totalFat, totalSatFat)); + for(Map.Entry pbEntry : pbFoodInfoProgressMap.entrySet()){ + constraintLayout.removeView(pbEntry.getValue()); + } + tvFoodInfoAmountMap.clear(); + tvFoodInfoNameMap.clear(); + pbFoodInfoProgressMap.clear(); } /** @@ -377,56 +559,15 @@ private float getConsumedCaloriesForEntry(DatabaseEntry e) { return (e.amount * e.energy) / 100; } - /** - * The consumed carbs per entry - * - * @param e a DatabaseEntry - * @return the calculated consumed carbs - */ - private float getConsumedCarbsForEntry(DatabaseEntry e) { - return (e.amount * e.carbs) / 100; - } - - /** - * The consumed sugar per entry - * - * @param e a DatabaseEntry - * @return the calculated consumed sugar - */ - private float getConsumedSugarForEntry(DatabaseEntry e) { - return (e.amount * e.sugar) / 100; - } - - /** - * The consumed protein per entry - * - * @param e a DatabaseEntry - * @return the calculated consumed protein - */ - private float getConsumedProteinForEntry(DatabaseEntry e) { - return (e.amount * e.protein) / 100; - } - - /** - * The consumed fat per entry - * - * @param e a DatabaseEntry - * @return the calculated consumed fat - */ - private float getConsumedFatForEntry(DatabaseEntry e) { - return (e.amount * e.fat) / 100; - } - - /** - * The consumed saturated fat per entry - * - * @param e a DatabaseEntry - * @return the calculated consumed fat + /*** + * Given a key identifying a FoodInfo (e.g. "carbs") and a db entry calculate the consumed amount + * of the FoodInfo + * @param key + * @return */ - private float getConsumedSatFatForEntry(DatabaseEntry e) { - return (e.amount * e.satFat) / 100; + private float getConsumedFoodInfoAmountForEntry(DatabaseEntry e,String key) { + return (e.amount * FoodInfosToShow.getFoodInfoValueByKey(e,key)) / 100; } - /** * Creates a CheckedCardView from the entry * @@ -467,27 +608,13 @@ private CardView createCardViewForEntry(DatabaseEntry e) { amount.setText(Integer.toString(e.amount) + "g"); energy.setText(String.format(Locale.ENGLISH, " %.2f kCal/100g", e.energy)); - //only print out macros with mass > 0 String calorieAndMacrosText = String.format(Locale.ENGLISH, "%.2f kCal",getConsumedCaloriesForEntry(e)); - float consumedCarbs = getConsumedCarbsForEntry(e); - if(consumedCarbs > 0.01){ - calorieAndMacrosText += String.format(Locale.ENGLISH, "\n%.2fg Carbs",consumedCarbs); - } - float consumedSugar = getConsumedSugarForEntry(e); - if(consumedSugar > 0.01){ - calorieAndMacrosText += String.format(Locale.ENGLISH, "\n%.2fg Sugar",consumedSugar); - } - float consumedProtein = getConsumedProteinForEntry(e); - if(consumedProtein > 0.01){ - calorieAndMacrosText += String.format(Locale.ENGLISH, "\n%.2fg Protein",consumedProtein); - } - float consumedFat = getConsumedFatForEntry(e); - if(consumedFat > 0.01){ - calorieAndMacrosText += String.format(Locale.ENGLISH, "\n%.2fg Fat",consumedFat); - } - float consumedSatFat = getConsumedSatFatForEntry(e); - if(consumedSatFat > 0.01){ - calorieAndMacrosText += String.format(Locale.ENGLISH, "\n%.2fg sat. Fat",consumedSatFat); + + for(Map.Entry foodInfoEntry : FoodInfosToShow.getFoodInfosShownAsMap(getApplicationContext()).entrySet()){ + float consumedAmount = getConsumedFoodInfoAmountForEntry(e,foodInfoEntry.getKey()); + if(consumedAmount > 0.01){ + calorieAndMacrosText += String.format(Locale.ENGLISH, "\n%1$.2f%2$s %3$s",consumedAmount,foodInfoEntry.getValue().getUnit(), foodInfoEntry.getValue().getName()); + } } calories.setText(calorieAndMacrosText); // id is just an invisible attribute on each card @@ -536,6 +663,8 @@ private CardView createCardViewForEntry(DatabaseEntry e) { return c; } + + /** * Set up listeners for whenever an entry is touched * @param c the cardview diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/SearchFoodFragment.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/SearchFoodFragment.java index 4df792d..63aea87 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/SearchFoodFragment.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/SearchFoodFragment.java @@ -113,7 +113,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, foodList.addItemDecoration(new DividerItemDecoration(referenceActivity.getApplicationContext(), LinearLayoutManager.VERTICAL)); - final SearchResultAdapter adapter = new SearchResultAdapter(databaseFacade.findMostCommonProducts()); + final SearchResultAdapter adapter = new SearchResultAdapter(databaseFacade.findMostCommonProducts(), FoodInfosToShow.getFoodInfosShownAsMap(getContext())); final EditText search = parentHolder.findViewById(R.id.search_term); foodList.setAdapter(adapter); @@ -187,42 +187,22 @@ public boolean onInterceptTouchEvent(@NonNull RecyclerView recyclerView, @NonNul TextView nameView = childView.findViewById(R.id.resultName); String name = nameView.getText().toString(); + /* this used to be the way of getting the selected products calories etc. + I do not understand, why it was done through parsing textViews contents. + I changed it to instead use the product's id and getting the product from the adapter. + TextView calView = childView.findViewById(R.id.resultCalories); String cal = calView.getText().toString(); cal = cal.split(" ")[0]; float calories = Float.parseFloat(cal); - TextView carbView = childView.findViewById(R.id.resultCarbs); - String carbsString = carbView.getText().toString(); - carbsString = carbsString.split(" ")[0]; - float carbs = Float.parseFloat(carbsString); - - String sugarString = carbView.getText().toString(); - sugarString = sugarString.split("\\(")[1].split("\\)")[0]; - float sugar = Float.parseFloat(sugarString); - - TextView protView = childView.findViewById(R.id.resultProtein); - String prot = protView.getText().toString(); - prot = prot.split(" ")[0]; - float protein = Float.parseFloat(prot); - - TextView fatView = childView.findViewById(R.id.resultFat); - String fatS = fatView.getText().toString(); - fatS = fatS.split(" ")[0]; - float fat = Float.parseFloat(fatS); - - String satFatS = fatView.getText().toString(); - satFatS = satFatS.split("\\(")[1].split("\\)")[0]; - float satFat = Float.parseFloat(satFatS); + */ + Product product= adapter.getProductFromId(id); ((BaseAddFoodActivity) referenceActivity).id = id; ((BaseAddFoodActivity) referenceActivity).name = name; - ((BaseAddFoodActivity) referenceActivity).calories = calories; - ((BaseAddFoodActivity) referenceActivity).carbs = carbs; - ((BaseAddFoodActivity) referenceActivity).sugar = sugar; - ((BaseAddFoodActivity) referenceActivity).protein = protein; - ((BaseAddFoodActivity) referenceActivity).fat = fat; - ((BaseAddFoodActivity) referenceActivity).satFat = satFat; + ((BaseAddFoodActivity) referenceActivity).calories = product.energy; + ((BaseAddFoodActivity) referenceActivity).selectedProduct = product; ((BaseAddFoodActivity) referenceActivity).productSet = true; ViewPager pager = referenceActivity.findViewById(R.id.pager_food); System.out.println("Setting page"); @@ -258,7 +238,8 @@ public void onTextChanged(CharSequence s, int start, int before, int count) { // search in the local db first System.out.println(s.toString()); SearchResultAdapter newAdapter = new SearchResultAdapter( - databaseFacade.getProductByName(s.toString()) + databaseFacade.getProductByName(s.toString()), + FoodInfosToShow.getFoodInfosShownAsMap(getContext()) ); foodList.setAdapter(newAdapter); } @@ -290,7 +271,7 @@ public void onResponse(Call call, Response res products.add(convertedProd); } } - SearchResultAdapter newAdapter = new SearchResultAdapter(products); + SearchResultAdapter newAdapter = new SearchResultAdapter(products, FoodInfosToShow.getFoodInfosShownAsMap(getContext())); foodList.setAdapter(newAdapter); foodList.addOnScrollListener(new RecyclerView.OnScrollListener() { @@ -338,7 +319,7 @@ public void onResponse(Call call, Response res products.add(convertedProd); } } - SearchResultAdapter newAdapter = new SearchResultAdapter(products); + SearchResultAdapter newAdapter = new SearchResultAdapter(products, FoodInfosToShow.getFoodInfosShownAsMap(getContext())); foodList.setAdapter(newAdapter); foodList.addOnScrollListener(new RecyclerView.OnScrollListener() { diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/SettingsActivity.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/SettingsActivity.java index cc43531..754998e 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/SettingsActivity.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/SettingsActivity.java @@ -26,13 +26,18 @@ import android.preference.ListPreference; import android.preference.Preference; import android.preference.PreferenceActivity; +import android.preference.PreferenceCategory; import android.preference.PreferenceFragment; import android.preference.PreferenceManager; +import android.preference.PreferenceScreen; +import android.preference.SwitchPreference; import android.view.MenuItem; import org.secuso.privacyfriendlyfoodtracker.R; import org.secuso.privacyfriendlyfoodtracker.ui.helper.BaseActivity; +import java.util.Map; + /** * A {@link PreferenceActivity} that presents a set of application settings. On * handset devices, settings are presented as a single list. On tablets, @@ -118,8 +123,7 @@ protected void onCreate(Bundle savedInstanceState) { @Override protected int getNavigationDrawerID() { - //return R.id.nav_settings; - return 0; + return R.id.nav_settings; } /** @@ -186,10 +190,29 @@ protected boolean isValidFragment(String fragmentName) { */ @TargetApi(Build.VERSION_CODES.HONEYCOMB) public static class GeneralPreferenceFragment extends PreferenceFragment { + public void createFoodInfoPreferences(Context context, PreferenceCategory screen){ + for(Map.Entry foodInfoEntry : FoodInfosToShow.foodInfos.entrySet()){ + SwitchPreference notificationPreference = new SwitchPreference(context); + notificationPreference.setKey(foodInfoEntry.getKey()); + notificationPreference.setTitle(foodInfoEntry.getValue().getName()); + screen.addPreference(notificationPreference); + } + } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - addPreferencesFromResource(R.xml.pref_general); + //addPreferencesFromResource(R.xml.pref_general); + Context context = getActivity();//dont know whther this will work? + PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(context); + + PreferenceCategory whatToShowCategory = new PreferenceCategory(context); + whatToShowCategory.setKey("what_info_to_show_category"); + whatToShowCategory.setTitle("What Food Info To Show"); + screen.addPreference(whatToShowCategory); + + createFoodInfoPreferences(context,whatToShowCategory); + setPreferenceScreen(screen); + //setHasOptionsMenu(true); // Bind the summaries of EditText/List/Dialog/Ringtone preferences @@ -211,4 +234,5 @@ public boolean onOptionsItemSelected(MenuItem item) { return super.onOptionsItemSelected(item); } } + } diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/adapter/DatabaseEntry.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/adapter/DatabaseEntry.java index 0bd70d2..32d734b 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/adapter/DatabaseEntry.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/adapter/DatabaseEntry.java @@ -27,10 +27,47 @@ public class DatabaseEntry { public float protein; public float fat; public float satFat; + public float salt; + + //vitamins and minerals + //soluable in fat vitamins + public float vitaminA_retinol; + public float betaCarotin; + public float vitaminD; + public float vitaminE; + public float vitaminK; + //soluable in water vitamins + public float thiamin_B1; + public float riboflavin_B2; + public float niacin; + public float vitaminB6; + public float folat; + public float pantothenacid; + public float biotin; + public float cobalamin_B12; + public float vitaminC; + //minerals + public float natrium; + public float chlorid; + public float kalium; + public float calcium; + public float phosphor; + public float magnesium; + //minerals (traces) + public float eisen; + public float jod; + public float fluorid; + public float zink; + public float selen; + public float kupfer; + public float mangan; + public float chrom; + public float molybdaen; public int amount; public String name; public int id; - public DatabaseEntry(int id, String name, int amount, float energy, float carbs, float sugar, float protein, float fat, float satFat){ + public DatabaseEntry(int id, String name, int amount, float energy, float carbs, float sugar, float protein, float fat, float satFat, + float salt, float vitaminA_retinol, float betaCarotin, float vitaminD, float vitaminE, float vitaminK, float thiamin_B1, float riboflavin_B2, float niacin, float vitaminB6, float folat, float pantothenacid, float biotin, float cobalamin_B12, float vitaminC, float natrium, float chlorid, float kalium, float calcium, float phosphor, float magnesium, float eisen, float jod, float fluorid, float zink, float selen, float kupfer, float mangan, float chrom, float molybdaen){ this.id = id; this.amount = amount; this.energy = energy; @@ -39,6 +76,38 @@ public DatabaseEntry(int id, String name, int amount, float energy, float carbs, this.protein = protein; this.fat = fat; this.satFat = satFat; + this.salt=salt; + + this.vitaminA_retinol=vitaminA_retinol; + this.betaCarotin=betaCarotin; + this.vitaminD=vitaminD; + this.vitaminE=vitaminE; + this.vitaminK=vitaminK; + this.thiamin_B1=thiamin_B1; + this.riboflavin_B2=riboflavin_B2; + this.niacin=niacin; + this.vitaminB6=vitaminB6; + this.folat=folat; + this.pantothenacid=pantothenacid; + this.biotin=biotin; + this.cobalamin_B12=cobalamin_B12; + this.vitaminC=vitaminC; + this.natrium=natrium; + this.chlorid=chlorid; + this.kalium=kalium; + this.calcium=calcium; + this.phosphor=phosphor; + this.magnesium=magnesium; + this.eisen=eisen; + this.jod=jod; + this.fluorid=fluorid; + this.zink=zink; + this.selen=selen; + this.kupfer=kupfer; + this.mangan=mangan; + this.chrom=chrom; + this.molybdaen=molybdaen; + this.name = name; } } \ No newline at end of file diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/adapter/DatabaseFacade.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/adapter/DatabaseFacade.java index 3feb6b1..ddb58f6 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/adapter/DatabaseFacade.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/adapter/DatabaseFacade.java @@ -55,16 +55,16 @@ public DatabaseFacade(Context context) throws Exception { * @param name the name * @param productId the consumed product id */ - public void insertEntry(final int amount, final java.util.Date date, final String name, final float energy, final float carbs, final float sugar, final float protein, final float fat, final float satFat, final int productId){ + public void insertEntry(final int amount, final java.util.Date date, final String name, final float energy, final float carbs, final float sugar, final float protein, final float fat, final float satFat,final float salt, final float vitaminA_retinol, final float betaCarotin, final float vitaminD, final float vitaminE, final float vitaminK, final float thiamin_B1, final float riboflavin_B2, final float niacin, final float vitaminB6, final float folat, final float pantothenacid, final float biotin, final float cobalamin_B12, final float vitaminC, final float natrium, final float chlorid, final float kalium, final float calcium, final float phosphor, final float magnesium, final float eisen, final float jod, final float fluorid, final float zink, final float selen, final float kupfer, final float mangan, final float chrom, final float molybdaen, final int productId){ Executors.newSingleThreadExecutor().execute(new Runnable() { @Override public void run() { int existingProductId = 0; //If the productId is 0 we need to create a new product in the database if (0 == productId) { - insertProductPrivate(name, energy, carbs, sugar, protein, fat, satFat, ""); + insertProductPrivate(name, energy, carbs, sugar, protein, fat, satFat, salt,vitaminA_retinol, betaCarotin, vitaminD, vitaminE, vitaminK, thiamin_B1, riboflavin_B2, niacin, vitaminB6, folat, pantothenacid, biotin, cobalamin_B12, vitaminC, natrium, chlorid, kalium, calcium, phosphor, magnesium, eisen, jod, fluorid, zink, selen, kupfer, mangan, chrom, molybdaen, ""); // retrieve ProductId of newly created Product from database - List existingProducts = productDao.findExistingProducts(name, energy, carbs, sugar, protein, fat, satFat, ""); + List existingProducts = productDao.findExistingProducts(name, energy, carbs, sugar, protein, fat, satFat,salt, vitaminA_retinol, betaCarotin, vitaminD, vitaminE, vitaminK, thiamin_B1, riboflavin_B2, niacin, vitaminB6, folat, pantothenacid, biotin, cobalamin_B12, vitaminC, natrium, chlorid, kalium, calcium, phosphor, magnesium, eisen, jod, fluorid, zink, selen, kupfer, mangan, chrom, molybdaen, ""); // There is only one existing product so we take the first one from the List Product p = existingProducts.get(0); existingProductId = p.id; @@ -114,12 +114,13 @@ public void run() { }); } + /** * Crate a new Product * @param name the name * @param energy the energy * @param barcode the barcode - */ + * TODO: is this deprecated? public void insertProduct(final String name, final float energy, final float carbs, final float sugar, final float protein, final float fat, final float satFat, final String barcode){ Executors.newSingleThreadExecutor().execute(new Runnable() { @Override @@ -127,14 +128,14 @@ public void run() { insertProductPrivate(name, energy, carbs,sugar, protein, fat, satFat, barcode); } }); - } + } */ - private void insertProductPrivate(String name, float energy, float carbs, float sugar, float protein, float fat, float satFat, String barcode) { - List res = productDao.findExistingProducts(name, energy, carbs, sugar, protein, fat, satFat, barcode); + private void insertProductPrivate(String name, float energy, float carbs, float sugar, float protein, float fat, float satFat, float salt, float vitaminA_retinol, float betaCarotin, float vitaminD, float vitaminE, float vitaminK, float thiamin_B1, float riboflavin_B2, float niacin, float vitaminB6, float folat, float pantothenacid, float biotin, float cobalamin_B12, float vitaminC, float natrium, float chlorid, float kalium, float calcium, float phosphor, float magnesium, float eisen, float jod, float fluorid, float zink, float selen, float kupfer, float mangan, float chrom, float molybdaen, String barcode) { + List res = productDao.findExistingProducts(name, energy, carbs, sugar, protein, fat, satFat, salt, vitaminA_retinol, betaCarotin, vitaminD, vitaminE, vitaminK, thiamin_B1, riboflavin_B2, niacin, vitaminB6, folat, pantothenacid, biotin, cobalamin_B12, vitaminC, natrium, chlorid, kalium, calcium, phosphor, magnesium, eisen, jod, fluorid, zink, selen, kupfer, mangan, chrom, molybdaen, barcode); if (res.size() != 0) { return; } - productDao.insert(new Product(0, name, energy, carbs, sugar, protein, fat, satFat, barcode)); + productDao.insert(new Product(0, name, energy, carbs, sugar, protein, fat, satFat, salt, vitaminA_retinol, betaCarotin, vitaminD, vitaminE, vitaminK, thiamin_B1, riboflavin_B2, niacin, vitaminB6, folat, pantothenacid, biotin, cobalamin_B12, vitaminC, natrium, chlorid, kalium, calcium, phosphor, magnesium, eisen, jod, fluorid, zink, selen, kupfer, mangan, chrom, molybdaen, barcode)); } /** diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/adapter/SearchResultAdapter.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/adapter/SearchResultAdapter.java index 0e7b2b7..32d9c50 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/adapter/SearchResultAdapter.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/adapter/SearchResultAdapter.java @@ -24,9 +24,12 @@ import org.secuso.privacyfriendlyfoodtracker.R; import org.secuso.privacyfriendlyfoodtracker.database.Product; +import org.secuso.privacyfriendlyfoodtracker.ui.FoodInfo; +import org.secuso.privacyfriendlyfoodtracker.ui.FoodInfosToShow; import java.util.List; import java.util.Locale; +import java.util.Map; /** * Implementation of SearchResultAdapter that uses a Fragment to manage each page. This class also handles saving and restoring of fragment's state. @@ -34,9 +37,26 @@ * @author Simon Reinkemeier */ public class SearchResultAdapter extends RecyclerView.Adapter { + private Map mFoodInfosToShow; private List mDataset; + /*** + * Given a product's id, return the product. This method is introduced to no more having to rely + * on parsing a CardViews TextViews to get calories, carbs etc. I do not know, why it was done + * like that in the first place. + * @param id The product id + * @return the product + */ + public Product getProductFromId(int id) { + for(Product product : mDataset){ + if(product.id == id){ + return product; + } + } + return null; + } + /** * Provide a reference to the views for each data item @@ -61,9 +81,11 @@ public SearchViewHolder(CardView v) { /** * Provide a suitable constructor (depends on the kind of dataset) * @param myDataset the dataset that is used for the item creation + * @param foodInfosToShow A map containing all food infos, which shall be shown by the app, according to the user configured settings. */ - public SearchResultAdapter(List myDataset) { + public SearchResultAdapter(List myDataset, Map foodInfosToShow) { mDataset = myDataset; + mFoodInfosToShow = foodInfosToShow; } /** @@ -92,10 +114,12 @@ public void onBindViewHolder(SearchViewHolder holder, int position) { // - get element from your dataset at this position // - replace the contents of the view with that element ((TextView) holder.mCardView.findViewById(R.id.resultName)).setText(mDataset.get(position).name); - ((TextView) holder.mCardView.findViewById(R.id.resultCalories)).setText(String.format(Locale.ENGLISH,"%.2f kCal", mDataset.get(position).energy)); - ((TextView) holder.mCardView.findViewById(R.id.resultCarbs)).setText(String.format(Locale.ENGLISH,"%.2f (%.2f) g Carbs(sugar)", mDataset.get(position).carbs, mDataset.get(position).sugar)); - ((TextView) holder.mCardView.findViewById(R.id.resultProtein)).setText(String.format(Locale.ENGLISH,"%.2f g Protein", mDataset.get(position).protein)); - ((TextView) holder.mCardView.findViewById(R.id.resultFat)).setText(String.format(Locale.ENGLISH,"%.2f (%.2f) g Fat(sat. fat)", mDataset.get(position).fat, mDataset.get(position).satFat)); + //((TextView) holder.mCardView.findViewById(R.id.resultCalories)).setText(String.format(Locale.ENGLISH,"%.2f kCal", mDataset.get(position).energy)); + String calPlusFoodInfoText =String.format(Locale.ENGLISH,"%.2f kCal", mDataset.get(position).energy); + for(Map.Entry foodInfoEntry: mFoodInfosToShow.entrySet()){ + calPlusFoodInfoText += String.format(Locale.ENGLISH,"\n%.2f %s %s", FoodInfosToShow.getFoodInfoValueByKey(mDataset.get(position),foodInfoEntry.getKey()), foodInfoEntry.getValue().getUnit(),foodInfoEntry.getValue().getName()); + } + ((TextView) holder.mCardView.findViewById(R.id.resultCalories)).setText(calPlusFoodInfoText); ((TextView) holder.mCardView.findViewById(R.id.resultId)).setText(String.format(Locale.ENGLISH, "%d", mDataset.get(position).id)); } diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/helper/BaseActivity.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/helper/BaseActivity.java index 58b658a..c4b956e 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/helper/BaseActivity.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/helper/BaseActivity.java @@ -22,6 +22,7 @@ import android.os.Build; import android.os.Bundle; import android.os.Handler; +import android.preference.PreferenceActivity; import android.preference.PreferenceManager; import android.support.design.widget.NavigationView; import android.support.design.widget.NavigationView.OnNavigationItemSelectedListener; @@ -39,6 +40,7 @@ import org.secuso.privacyfriendlyfoodtracker.ui.AboutActivity; import org.secuso.privacyfriendlyfoodtracker.ui.HelpActivity; import org.secuso.privacyfriendlyfoodtracker.ui.MainActivity; +import org.secuso.privacyfriendlyfoodtracker.ui.SettingsActivity; import org.secuso.privacyfriendlyfoodtracker.ui.TutorialActivity; /** @@ -184,12 +186,12 @@ private void callDrawerItem(final int itemId) { intent = new Intent(this, HelpActivity.class); createBackStack(intent); break; - /* case R.id.nav_settings: + case R.id.nav_settings: intent = new Intent(this, SettingsActivity.class); intent.putExtra( PreferenceActivity.EXTRA_SHOW_FRAGMENT, SettingsActivity.GeneralPreferenceFragment.class.getName() ); intent.putExtra( PreferenceActivity.EXTRA_NO_HEADERS, true ); createBackStack(intent); - break;*/ + break; default: } } diff --git a/app/src/main/res/layout-land/content_food.xml b/app/src/main/res/layout-land/content_food.xml index b716d68..b20d9c7 100644 --- a/app/src/main/res/layout-land/content_food.xml +++ b/app/src/main/res/layout-land/content_food.xml @@ -10,171 +10,77 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> - - - - - - - - - - - + + - - - - - - + + + + + + + app:errorEnabled="true" + app:layout_constraintTop_toBottomOf="@+id/inputFoodName"> - - - + + - + app:errorEnabled="true" + app:layout_constraintTop_toBottomOf="@+id/inputFoodAmount"> - + - - + - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/content_overview.xml b/app/src/main/res/layout/content_overview.xml index 805d60d..b6ae38e 100644 --- a/app/src/main/res/layout/content_overview.xml +++ b/app/src/main/res/layout/content_overview.xml @@ -1,4 +1,3 @@ - + + + + + + + android:gravity="right" + app:layout_constraintTop_toBottomOf="@id/overviewHeading" + app:layout_constraintRight_toRightOf="parent"/> - - + android:orientation="vertical" + app:layout_constraintTop_toBottomOf="@id/overviewHeading"/> - + + \ No newline at end of file diff --git a/app/src/main/res/layout/search_result.xml b/app/src/main/res/layout/search_result.xml index 2aa2386..4be597d 100644 --- a/app/src/main/res/layout/search_result.xml +++ b/app/src/main/res/layout/search_result.xml @@ -3,6 +3,7 @@ - - - + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index dc28fa7..de9e872 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -110,9 +110,9 @@ Save Search for a product - Only numbers are allowed for carbs - Only numbers are allowed for protein - Only numbers are allowed for fat + Only numbers are allowed for carbs + Only numbers are allowed for protein + Only numbers are allowed for fat g/100g Carbs in g/100g Protein in g/100g @@ -122,4 +122,29 @@ Average fat (saturated fat) per day Sugar in g/100g Saturated Fat in g/100g + + Messages + Sync + + + Your signature + Default reply action + + + Sync email periodically + Download incoming attachments + Automatically download attachments for incoming emails + + Only download attachments when manually requested + SettingsActivity2 + + First Fragment + Second Fragment + Previous + + Hello first fragment + Hello second fragment. Arg: %1$s + Settings + Only numbers are allowed for %1$s + Calories From a4a75a75d03bf7c1f7a3cdc663d5f071408d36a7 Mon Sep 17 00:00:00 2001 From: conrad69 Date: Wed, 4 Aug 2021 17:32:16 +0200 Subject: [PATCH 05/18] set food info editText to number --- .../secuso/privacyfriendlyfoodtracker/ui/AddFoodFragment.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/AddFoodFragment.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/AddFoodFragment.java index 746e442..3282330 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/AddFoodFragment.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/AddFoodFragment.java @@ -109,6 +109,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, currentET.setLayoutParams(layoutParams); currentET.setMaxLines(1); currentET.setFilters(caloriesFilter); + currentET.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL); currentTIL.setHint(foodInfo.getName() + " in " + foodInfo.getUnit()); From 724cd3f3d1aeaf578b19394d19f45b831084cb64 Mon Sep 17 00:00:00 2001 From: conrad69 Date: Fri, 6 Aug 2021 11:40:25 +0200 Subject: [PATCH 06/18] statistics for every nutriment; cleaned up and refactored, merged month and week stat. fragment --- .../ui/AddFoodFragment.java | 2 +- .../ui/FoodInfosToShow.java | 89 ++++ .../ui/MonthStatisticFragment.java | 190 --------- .../ui/StatisticFragment.java | 381 ++++++++++++++++++ .../ui/WeekStatisticFragment.java | 287 ------------- .../ui/adapter/DatabaseFacade.java | 20 + .../ui/adapter/StatisticPagerAdapter.java | 7 +- ...h_statistic.xml => fragment_statistic.xml} | 63 +-- .../res/layout/fragment_week_statistic.xml | 180 --------- .../main/res/layout/graphview_nutriments.xml | 5 + app/src/main/res/values/strings.xml | 1 + 11 files changed, 502 insertions(+), 723 deletions(-) delete mode 100644 app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/MonthStatisticFragment.java create mode 100644 app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/StatisticFragment.java delete mode 100644 app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/WeekStatisticFragment.java rename app/src/main/res/layout/{fragment_month_statistic.xml => fragment_statistic.xml} (62%) delete mode 100644 app/src/main/res/layout/fragment_week_statistic.xml create mode 100644 app/src/main/res/layout/graphview_nutriments.xml diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/AddFoodFragment.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/AddFoodFragment.java index 3282330..52af2a2 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/AddFoodFragment.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/AddFoodFragment.java @@ -60,6 +60,7 @@ public class AddFoodFragment extends Fragment { Map otherFoodInfoTextInputLayouts = new HashMap<>(); Map otherFoodInfoEditTexts = new HashMap<>(); + /** * The required empty public constructor */ @@ -105,7 +106,6 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, currentTIL.setLayoutParams(layoutParams); EditText currentET = new EditText(getContext()); - currentET.setLayoutParams(layoutParams); currentET.setMaxLines(1); currentET.setFilters(caloriesFilter); diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/FoodInfosToShow.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/FoodInfosToShow.java index d4e85d9..e7fc706 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/FoodInfosToShow.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/FoodInfosToShow.java @@ -6,6 +6,7 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import org.secuso.privacyfriendlyfoodtracker.database.ConsumedEntrieAndProductDao; import org.secuso.privacyfriendlyfoodtracker.database.Product; import org.secuso.privacyfriendlyfoodtracker.ui.adapter.DatabaseEntry; @@ -278,4 +279,92 @@ public static float getFoodInfoValueByKey(Product product, String key){ } return 0.0f; } + + /*** + * Given a key identifying a FoodInfo and a Product containing all FoodInfoValues, return + * the specified FoodInfo's value from the Product. Possible keys are those present in + * FoodInfosToShow.foodInfos, e.g. "carbs". + * + * Meta: This does exactly the same like getFoodInfoValueByKey(DatabaseEntry,String), just for the + * Product class. It would probably be nicer to just have Product and DatabaseEntry implement an + * interface offering getters for every food info. TODO. + * @param product + * @param key + * @return + */ + public static float getFoodInfoValueByKey(ConsumedEntrieAndProductDao.DateNutriments product, String key){ + switch(key){ + case "carbs": + return product.carbsConsumed; + case "sugar": + return product.sugarConsumed; + case "protein": + return product.proteinConsumed; + case "fat": + return product.fatConsumed; + case "satFat": + return product.satFatConsumed; + case "salt": + return product.saltConsumed; + case "vitaminA_retinol": + return product.vitaminA_retinolConsumed; + case "betaCarotin": + return product.betaCarotinConsumed; + case "vitaminD": + return product.vitaminDConsumed; + case "vitaminE": + return product.vitaminEConsumed; + case "vitaminK": + return product.vitaminKConsumed; + case "thiamin_B1": + return product.thiamin_B1Consumed; + case "riboflavin_B2": + return product.riboflavin_B2Consumed; + case "niacin": + return product.niacinConsumed; + case "vitaminB6": + return product.vitaminB6Consumed; + case "folat": + return product.folatConsumed; + case "pantothenacid": + return product.pantothenacidConsumed; + case "biotin": + return product.biotinConsumed; + case "cobalamin_B12": + return product.cobalamin_B12Consumed; + case "vitaminC": + return product.vitaminCConsumed; + case "natrium": + return product.natriumConsumed; + case "chlorid": + return product.chloridConsumed; + case "kalium": + return product.kaliumConsumed; + case "calcium": + return product.calciumConsumed; + case "phosphor": + return product.phosphorConsumed; + case "magnesium": + return product.magnesiumConsumed; + case "eisen": + return product.eisenConsumed; + case "jod": + return product.jodConsumed; + case "fluorid": + return product.fluoridConsumed; + case "zink": + return product.zinkConsumed; + case "selen": + return product.selenConsumed; + case "kupfer": + return product.kupferConsumed; + case "mangan": + return product.manganConsumed; + case "chrom": + return product.chromConsumed; + case "molybdaen": + return product.molybdaenConsumed; + } + return 0.0f; + } } diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/MonthStatisticFragment.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/MonthStatisticFragment.java deleted file mode 100644 index 0a2ab1a..0000000 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/MonthStatisticFragment.java +++ /dev/null @@ -1,190 +0,0 @@ -/* -This file is part of Privacy friendly food tracker. - -Privacy friendly food tracker is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -Privacy friendly food tracker is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Privacy friendly food tracker. If not, see . -*/ -package org.secuso.privacyfriendlyfoodtracker.ui; - -import android.app.Activity; -import android.app.DatePickerDialog; -import android.arch.lifecycle.Observer; -import android.arch.lifecycle.ViewModelProviders; -import android.graphics.Color; -import android.os.Bundle; -import android.support.annotation.Nullable; -import android.support.v4.app.Fragment; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.DatePicker; -import android.widget.TextView; - - -import org.secuso.privacyfriendlyfoodtracker.R; -import org.secuso.privacyfriendlyfoodtracker.ui.adapter.DatabaseFacade; -import org.secuso.privacyfriendlyfoodtracker.ui.helper.DateHelper; -import org.secuso.privacyfriendlyfoodtracker.ui.viewmodels.SharedStatisticViewModel; - -import java.util.Calendar; -import java.util.Date; - -import static org.secuso.privacyfriendlyfoodtracker.ui.WeekStatisticFragment.updateGraphUsingNdayPeriod; - - -/** - * A simple {@link Fragment} subclass. Contains the statistic for a month. - * - * @author Andre Lutz - */ -public class MonthStatisticFragment extends Fragment { - SharedStatisticViewModel sharedStatisticViewModel; - Activity referenceActivity; - View parentHolder; - TextView textView; - DatabaseFacade databaseFacade; - TextView carbsTextView; - TextView proteinTextView; - TextView fatTextView; - - public MonthStatisticFragment() { - // Required empty public constructor - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - // Inflate the layout for this fragment - - referenceActivity = getActivity(); - parentHolder = inflater.inflate(R.layout.fragment_month_statistic, container, false); - sharedStatisticViewModel = ViewModelProviders.of(getActivity()).get(SharedStatisticViewModel.class); - try { - databaseFacade = new DatabaseFacade(referenceActivity.getApplicationContext()); - } catch (Exception e){ - Log.e("Error", e.getMessage()); - } - textView = parentHolder.findViewById(R.id.periodCalories1); - carbsTextView = parentHolder.findViewById(R.id.periodCarbs1); - proteinTextView = parentHolder.findViewById(R.id.periodProtein1); - fatTextView = parentHolder.findViewById(R.id.periodFat1); - - final TextView editText = (TextView) parentHolder.findViewById(R.id.datepicker); - editText.setText(DateHelper.dateToString(sharedStatisticViewModel.getDate())); - editText.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - - DatePickerDialog.OnDateSetListener dpd = new DatePickerDialog.OnDateSetListener() { - @Override - public void onDateSet(DatePicker view, int year, int monthOfYear, - int dayOfMonth) { - sharedStatisticViewModel.setDate(dayOfMonth, monthOfYear, year); - UpdateGraph(); - } - }; - final Calendar currentDate = sharedStatisticViewModel.getCalendar(); - final int mYear = currentDate.get(Calendar.YEAR); - final int mMonth = currentDate.get(Calendar.MONTH); - final int mDay = currentDate.get(Calendar.DAY_OF_MONTH); - DatePickerDialog d = new DatePickerDialog(referenceActivity, dpd, mYear, mMonth, mDay); - d.show(); - - } - }); - final Button left_arrow = parentHolder.findViewById(R.id.left_arrow); - left_arrow.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - changeMonthByValue(-1); - UpdateGraph(); - } - }); - final Button right_arrow = parentHolder.findViewById(R.id.right_arrow); - right_arrow.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - changeMonthByValue(+1); - UpdateGraph(); - } - }); - UpdateGraph(); - sharedStatisticViewModel.getLiveCalendar().observe(this, new Observer() { - @Override - public void onChanged(@Nullable Calendar calendar) { - editText.setText(DateHelper.dateToString(getMonthByValue(-1)) + System.getProperty("line.separator") + " - " + System.getProperty("line.separator") + DateHelper.dateToString(calendar.getTime())); - UpdateGraph(); - } - }); - return parentHolder; - } - - void UpdateGraph() { - Log.i("Month...UpdateGraph","UpdateGraph called"); - final Date startDate = DateHelper.changeDateTimeToMidnight(getMonthByValue(-1)); - final Date endDate = DateHelper.changeDateTimeToMidnight(getMonthByValue(0)); - Calendar startDateCalendar = Calendar.getInstance(); - startDateCalendar.setTime(startDate); - Calendar endDateCalendar = Calendar.getInstance(); - endDateCalendar.setTime(endDate); - int monthDays = (int) daysBetween( endDateCalendar,startDateCalendar); - updateGraphUsingNdayPeriod(parentHolder,referenceActivity,databaseFacade,textView, - carbsTextView,proteinTextView, fatTextView,startDate,endDate, monthDays); - } - - /** - * Source: https://stackoverflow.com/questions/20165564/calculating-days-between-two-dates-with-java - * By Pim Beers - * @param day1 - * @param day2 - * @return - */ - private static int daysBetween(Calendar day1, Calendar day2){ - Calendar dayOne = (Calendar) day1.clone(), - dayTwo = (Calendar) day2.clone(); - - if (dayOne.get(Calendar.YEAR) == dayTwo.get(Calendar.YEAR)) { - return Math.abs(dayOne.get(Calendar.DAY_OF_YEAR) - dayTwo.get(Calendar.DAY_OF_YEAR)); - } else { - if (dayTwo.get(Calendar.YEAR) > dayOne.get(Calendar.YEAR)) { - //swap them - Calendar temp = dayOne; - dayOne = dayTwo; - dayTwo = temp; - } - int extraDays = 0; - - int dayOneOriginalYearDays = dayOne.get(Calendar.DAY_OF_YEAR); - - while (dayOne.get(Calendar.YEAR) > dayTwo.get(Calendar.YEAR)) { - dayOne.add(Calendar.YEAR, -1); - extraDays += dayOne.getActualMaximum(Calendar.DAY_OF_YEAR); - } - - return extraDays - dayTwo.get(Calendar.DAY_OF_YEAR) + dayOneOriginalYearDays ; - } - } - - Date changeMonthByValue(int value) { - Date date = getMonthByValue(value); - sharedStatisticViewModel.setCalendarWithDateObj(date); - return date; - } - - Date getMonthByValue(int value) { - Date date = DateHelper.changeMonth(sharedStatisticViewModel.getDate(), value); - return date; - } -} diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/StatisticFragment.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/StatisticFragment.java new file mode 100644 index 0000000..2babf51 --- /dev/null +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/StatisticFragment.java @@ -0,0 +1,381 @@ +/* +This file is part of Privacy friendly food tracker. + +Privacy friendly food tracker is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Privacy friendly food tracker is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Privacy friendly food tracker. If not, see . +*/ +package org.secuso.privacyfriendlyfoodtracker.ui; + + +import android.app.Activity; +import android.app.DatePickerDialog; +import android.arch.lifecycle.Observer; +import android.arch.lifecycle.ViewModelProviders; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.DatePicker; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.jjoe64.graphview.GraphView; +import com.jjoe64.graphview.helper.DateAsXAxisLabelFormatter; +import com.jjoe64.graphview.series.DataPoint; +import com.jjoe64.graphview.series.LineGraphSeries; + +import org.secuso.privacyfriendlyfoodtracker.R; +import org.secuso.privacyfriendlyfoodtracker.ui.adapter.DatabaseFacade; +import org.secuso.privacyfriendlyfoodtracker.ui.helper.DateHelper; +import org.secuso.privacyfriendlyfoodtracker.database.ConsumedEntrieAndProductDao; +import org.secuso.privacyfriendlyfoodtracker.ui.viewmodels.SharedStatisticViewModel; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.secuso.privacyfriendlyfoodtracker.ui.helper.MathHelper.round; + + +/** + * A simple {@link Fragment} subclass. Contains the statistic for a week or a month, depending on + * the value of isWeek(which can be set via newInstance). + * + * @author Andre Lutz + */ +public class StatisticFragment extends Fragment { + private static final String EXTRA_ISWEEK = "EXTRA_ISWEEK"; + SharedStatisticViewModel sharedStatisticViewModel; + Activity referenceActivity; + View parentHolder; + TextView textView; + DatabaseFacade databaseFacade; + GraphView graphViewCalories; + + /*** + * true, if this fragment shall show weekly statistics, false if this shall show monthly statistics. + */ + boolean isWeek; + + Map graphViewMap = new HashMap<>(); + Map tvNutrimentsAverageMap = new HashMap<>(); + + public StatisticFragment() { + // Required empty public constructor + } + + /*** + * Since fragments need an empty constructor, newInstance is used to create fragments for either + * week or month statistics display + * @param isWeek Whether to show weekly or monthly statistic + * @return + */ + public static final StatisticFragment newInstance(boolean isWeek) { + StatisticFragment f = new StatisticFragment(); + Bundle bdl = new Bundle(2); + bdl.putBoolean(EXTRA_ISWEEK, isWeek); + f.setArguments(bdl); + return f; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + + isWeek = getArguments().getBoolean(EXTRA_ISWEEK,true); + // Inflate the layout for this fragment + referenceActivity = getActivity(); + parentHolder = inflater.inflate(R.layout.fragment_statistic, container, false); + sharedStatisticViewModel = ViewModelProviders.of(getActivity()).get(SharedStatisticViewModel.class); + try { + databaseFacade = new DatabaseFacade(referenceActivity.getApplicationContext()); + } catch (Exception e){ + Log.e("Error", e.getMessage()); + } + textView = parentHolder.findViewById(R.id.periodCalories1); + graphViewCalories = (GraphView) parentHolder.findViewById(R.id.graph); + + + final TextView editText = (TextView) parentHolder.findViewById(R.id.datepicker); + editText.setText(DateHelper.dateToString(sharedStatisticViewModel.getDate())); + editText.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + DatePickerDialog.OnDateSetListener dpd = new DatePickerDialog.OnDateSetListener() { + @Override + public void onDateSet(DatePicker view, int year, int monthOfYear, + int dayOfMonth) { + sharedStatisticViewModel.setDate(dayOfMonth, monthOfYear , year); + UpdateGraph(); + } + }; + final Calendar currentDate = sharedStatisticViewModel.getCalendar(); + final int mYear = currentDate.get(Calendar.YEAR); + final int mMonth = currentDate.get(Calendar.MONTH); + final int mDay = currentDate.get(Calendar.DAY_OF_MONTH); + DatePickerDialog d = new DatePickerDialog(referenceActivity, dpd, mYear, mMonth, mDay); + d.show(); + + } + }); + final Button left_arrow = parentHolder.findViewById(R.id.left_arrow); + final Button right_arrow = parentHolder.findViewById(R.id.right_arrow); + if(isWeek) { + left_arrow.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + changeWeekByValue(-1); + UpdateGraph(); + } + }); + right_arrow.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + changeWeekByValue(+1); + UpdateGraph(); + } + }); + }else{ + left_arrow.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + changeMonthByValue(-1); + UpdateGraph(); + } + }); + right_arrow.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + changeMonthByValue(+1); + UpdateGraph(); + } + }); + } + UpdateGraph(); + Observer observer = null; + if(isWeek){ + observer =new Observer() { + @Override + public void onChanged(@Nullable Calendar calendar) { + editText.setText(DateHelper.dateToString(getWeekByValue(-1)) + System.getProperty("line.separator") + " - " + System.getProperty("line.separator") + DateHelper.dateToString(calendar.getTime())); + UpdateGraph(); + } + }; + }else{ + observer =new Observer() { + @Override + public void onChanged(@Nullable Calendar calendar) { + editText.setText(DateHelper.dateToString(getMonthByValue(-1)) + System.getProperty("line.separator") + " - " + System.getProperty("line.separator") + DateHelper.dateToString(calendar.getTime())); + UpdateGraph(); + } + }; + } + sharedStatisticViewModel.getLiveCalendar().observe(this, observer); + return parentHolder; + } + + /*** + * Adds a LineGraphSeries to a GraphView, setting startDate and endDate as x-axis start/end + * @param graph + * @param startDate + * @param endDate + * @param lineGraphSeries + */ + void addSeriesToGraph(GraphView graph, Date startDate, Date endDate, LineGraphSeries ... lineGraphSeries){ + for(LineGraphSeries series : lineGraphSeries){ + graph.addSeries(series); + } + graph.getGridLabelRenderer().setLabelFormatter(new DateAsXAxisLabelFormatter(referenceActivity)); + graph.getGridLabelRenderer().setHumanRounding(false, true); + graph.getViewport().setMinX(startDate.getTime()); + graph.getViewport().setMaxX(endDate.getTime()); + graph.getViewport().setXAxisBoundsManual(true); + + graph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space + graph.getGridLabelRenderer().setTextSize(40); + graph.getViewport().setScrollable(true); + graph.getGridLabelRenderer().setHorizontalLabelsAngle(135); + } + + /*** + * Updates the graphs with the calories/carbs/... eaten during that period and also updates the + * average consumed calories/... during that period. Works for weeks and months, depending on the + * given start/end date and n days in period. + * It is static and part of the WekkStatisticFragment class, because I could not think of a + * better place for it. I tried making MonthStatisticFragment inheriting from Week... but this + * resulted in strange bugs. + * @param startDate + * @param endDate + * @param periodLengthInDays Number of days in period, 7 for week, something else for e.g. month. + */ + void updateGraphUsingNdayPeriod(Date startDate, Date endDate, int periodLengthInDays){ + if(databaseFacade == null){ //I replaced the try catch block covering all code of the method with this null-check, hoping the try catch did not catch other things a lot + Log.e("ateGraphUsingNdayPeriod","DatabaseFacade is null! Not adding graph stuff to statistics view."); + return; //TODO: why is databaseFacade null at the beginning? + } + List consumedEntriesList = new ArrayList<>(); + List calories = new ArrayList<>(); + + consumedEntriesList = databaseFacade.getCaloriesPerDayinPeriod(startDate,endDate); + calories = databaseFacade.getPeriodCalories(startDate,endDate); + DataPoint[] dataPointInterfaces = new DataPoint[consumedEntriesList.size()]; + for (int i = 0; i < consumedEntriesList.size(); i++) { + dataPointInterfaces[i] = (new DataPoint(consumedEntriesList.get(i).unique1.getTime(), consumedEntriesList.get(i).unique2/100)); + } + LineGraphSeries calSeries = new LineGraphSeries<>(dataPointInterfaces); + addSeriesToGraph(graphViewCalories,startDate,endDate, calSeries); + + float averageCalories = calories.get(0).unique2 / periodLengthInDays; + + BigDecimal averageCaloriesBigDecimal = round(averageCalories,0) ; + + if (calories.size() != 0) { + textView.setText(averageCaloriesBigDecimal.toString()); + } + + List consumedNutrimentsEntriesList = + databaseFacade.getNutrimentsPerDayinPeriod(startDate, endDate); + List consumedNutriments = + databaseFacade.getPeriodNutriments(startDate,endDate); + for(Map.Entry foodInfoEntry : FoodInfosToShow.getFoodInfosShownAsMap(getContext()).entrySet()){ + DataPoint[] nutrimentDataPoints = new DataPoint[consumedNutrimentsEntriesList.size()]; + for (int i = 0; i < consumedNutrimentsEntriesList.size(); i++) { + nutrimentDataPoints[i] = (new DataPoint(consumedNutrimentsEntriesList.get(i).dateOfConsumption.getTime(), FoodInfosToShow.getFoodInfoValueByKey(consumedNutrimentsEntriesList.get(i), foodInfoEntry.getKey())/100)); + } + float averageNutriment = FoodInfosToShow.getFoodInfoValueByKey(consumedNutriments.get(0),foodInfoEntry.getKey()) / periodLengthInDays; + BigDecimal averageNutrimentBigDecimal = round(averageNutriment,0) ; + + TextView tvAverageNutriment = null; + LinearLayout ll = (LinearLayout)parentHolder.findViewById(R.id.statisticLinLayout); + + if(tvNutrimentsAverageMap.containsKey(foodInfoEntry.getKey())){ + tvAverageNutriment = tvNutrimentsAverageMap.get(foodInfoEntry.getKey()); + }else{ + tvAverageNutriment = new TextView(getContext()); + ll.addView(tvAverageNutriment); + tvNutrimentsAverageMap.put(foodInfoEntry.getKey(), tvAverageNutriment); + } + + GraphView graphView = null; + if(graphViewMap.containsKey(foodInfoEntry.getKey())){ + graphView = graphViewMap.get(foodInfoEntry.getKey()); + }else{ + graphView = (GraphView)LayoutInflater.from(getActivity()) + .inflate(R.layout.graphview_nutriments, ll, false); + ll.addView(graphView); + graphViewMap.put(foodInfoEntry.getKey(),graphView); + } + + tvAverageNutriment.setText(getString(R.string.statistics_average_nutriments, + foodInfoEntry.getValue().getName(), + averageNutrimentBigDecimal, + foodInfoEntry.getValue().getUnit())); + + LineGraphSeries nutrimentSeries = new LineGraphSeries<>(nutrimentDataPoints); + addSeriesToGraph(graphView,startDate,endDate, nutrimentSeries); + + + } + + + } + void UpdateGraph() { + Date startDate; + Date endDate; + int days; + if (isWeek) { + startDate = getWeekByValue(-1); + endDate = getWeekByValue(0); + days = 7; + }else{ + startDate = getMonthByValue(-1); + endDate = getMonthByValue(0); + Calendar startDateCalendar = Calendar.getInstance(); + startDateCalendar.setTime(startDate); + Calendar endDateCalendar = Calendar.getInstance(); + endDateCalendar.setTime(endDate); + days = (int) daysBetween( endDateCalendar,startDateCalendar); + } + startDate = DateHelper.changeDateTimeToMidnight(startDate); //set time to midnight so the period does not depend on the time of day + endDate = DateHelper.changeDateTimeToMidnight(endDate); + updateGraphUsingNdayPeriod(startDate,endDate, days); + } + + /** + * Source: https://stackoverflow.com/questions/20165564/calculating-days-between-two-dates-with-java + * By Pim Beers + * @param day1 + * @param day2 + * @return + */ + private static int daysBetween(Calendar day1, Calendar day2){ + Calendar dayOne = (Calendar) day1.clone(), + dayTwo = (Calendar) day2.clone(); + + if (dayOne.get(Calendar.YEAR) == dayTwo.get(Calendar.YEAR)) { + return Math.abs(dayOne.get(Calendar.DAY_OF_YEAR) - dayTwo.get(Calendar.DAY_OF_YEAR)); + } else { + if (dayTwo.get(Calendar.YEAR) > dayOne.get(Calendar.YEAR)) { + //swap them + Calendar temp = dayOne; + dayOne = dayTwo; + dayTwo = temp; + } + int extraDays = 0; + + int dayOneOriginalYearDays = dayOne.get(Calendar.DAY_OF_YEAR); + + while (dayOne.get(Calendar.YEAR) > dayTwo.get(Calendar.YEAR)) { + dayOne.add(Calendar.YEAR, -1); + extraDays += dayOne.getActualMaximum(Calendar.DAY_OF_YEAR); + } + + return extraDays - dayTwo.get(Calendar.DAY_OF_YEAR) + dayOneOriginalYearDays ; + } + } + + Date changeMonthByValue(int value) { + Date date = getMonthByValue(value); + sharedStatisticViewModel.setCalendarWithDateObj(date); + return date; + } + + Date getMonthByValue(int value) { + Date date = DateHelper.changeMonth(sharedStatisticViewModel.getDate(), value); + return date; + } + + + Date changeWeekByValue(int value) { + Date date = getWeekByValue(value); + sharedStatisticViewModel.setCalendarWithDateObj(date); + return date; + } + + + Date getWeekByValue(int value) { + Date date = DateHelper.changeWeek(sharedStatisticViewModel.getDate(), value); + return date; + } + + +} diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/WeekStatisticFragment.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/WeekStatisticFragment.java deleted file mode 100644 index 1b20686..0000000 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/WeekStatisticFragment.java +++ /dev/null @@ -1,287 +0,0 @@ -/* -This file is part of Privacy friendly food tracker. - -Privacy friendly food tracker is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -Privacy friendly food tracker is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Privacy friendly food tracker. If not, see . -*/ -package org.secuso.privacyfriendlyfoodtracker.ui; - - -import android.app.Activity; -import android.app.DatePickerDialog; -import android.arch.lifecycle.Observer; -import android.arch.lifecycle.ViewModelProviders; -import android.graphics.Color; -import android.os.Bundle; -import android.support.annotation.Nullable; -import android.support.v4.app.Fragment; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.DatePicker; -import android.widget.TextView; -import android.widget.Toast; - -import com.jjoe64.graphview.GraphView; -import com.jjoe64.graphview.helper.DateAsXAxisLabelFormatter; -import com.jjoe64.graphview.series.DataPoint; -import com.jjoe64.graphview.series.LineGraphSeries; - -import org.secuso.privacyfriendlyfoodtracker.R; -import org.secuso.privacyfriendlyfoodtracker.ui.adapter.DatabaseFacade; -import org.secuso.privacyfriendlyfoodtracker.ui.helper.DateHelper; -import org.secuso.privacyfriendlyfoodtracker.database.ConsumedEntrieAndProductDao; -import org.secuso.privacyfriendlyfoodtracker.ui.viewmodels.SharedStatisticViewModel; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; -import java.util.List; -import java.util.Locale; - -import static org.secuso.privacyfriendlyfoodtracker.ui.helper.MathHelper.round; - - -/** - * A simple {@link Fragment} subclass. Contains the statistic for a week. - * - * @author Andre Lutz - */ -public class WeekStatisticFragment extends Fragment { - SharedStatisticViewModel sharedStatisticViewModel; - Activity referenceActivity; - View parentHolder; - TextView textView; - DatabaseFacade databaseFacade; - TextView carbsTextView; - TextView proteinTextView; - TextView fatTextView; - - public WeekStatisticFragment() { - // Required empty public constructor - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - - // Inflate the layout for this fragment - referenceActivity = getActivity(); - parentHolder = inflater.inflate(R.layout.fragment_month_statistic, container, false); - sharedStatisticViewModel = ViewModelProviders.of(getActivity()).get(SharedStatisticViewModel.class); - try { - databaseFacade = new DatabaseFacade(referenceActivity.getApplicationContext()); - } catch (Exception e){ - Log.e("Error", e.getMessage()); - } - textView = parentHolder.findViewById(R.id.periodCalories1); - carbsTextView = parentHolder.findViewById(R.id.periodCarbs1); - proteinTextView = parentHolder.findViewById(R.id.periodProtein1); - fatTextView = parentHolder.findViewById(R.id.periodFat1); - - final TextView editText = (TextView) parentHolder.findViewById(R.id.datepicker); - editText.setText(DateHelper.dateToString(sharedStatisticViewModel.getDate())); - editText.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - - DatePickerDialog.OnDateSetListener dpd = new DatePickerDialog.OnDateSetListener() { - @Override - public void onDateSet(DatePicker view, int year, int monthOfYear, - int dayOfMonth) { - sharedStatisticViewModel.setDate(dayOfMonth, monthOfYear , year); - UpdateGraph(); - } - }; - final Calendar currentDate = sharedStatisticViewModel.getCalendar(); - final int mYear = currentDate.get(Calendar.YEAR); - final int mMonth = currentDate.get(Calendar.MONTH); - final int mDay = currentDate.get(Calendar.DAY_OF_MONTH); - DatePickerDialog d = new DatePickerDialog(referenceActivity, dpd, mYear, mMonth, mDay); - d.show(); - - } - }); - final Button left_arrow = parentHolder.findViewById(R.id.left_arrow); - left_arrow.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - changeWeekByValue(-1); - } - }); - final Button right_arrow = parentHolder.findViewById(R.id.right_arrow); - right_arrow.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - changeWeekByValue(+1); - } - }); - UpdateGraph(); - sharedStatisticViewModel.getLiveCalendar().observe(this, new Observer() { - @Override - public void onChanged(@Nullable Calendar calendar) { - editText.setText(DateHelper.dateToString(getWeekByValue(-1)) + System.getProperty("line.separator") + " - " + System.getProperty("line.separator") + DateHelper.dateToString(calendar.getTime())); - UpdateGraph(); - } - }); - return parentHolder; - } - static DataPoint[] dataPointsForNutriment(List consumedXYEntries){ - DataPoint[] datapointsToReturn = new DataPoint[consumedXYEntries.size()]; - for (int i = 0; i < consumedXYEntries.size(); i++) { - datapointsToReturn[i] = (new DataPoint(consumedXYEntries.get(i).unique1.getTime(), consumedXYEntries.get(i).unique2/100)); - } - return datapointsToReturn; - } - static void addSeriesToGraphById(View parentHolder, Activity referenceActivity, Date startDate, Date endDate, int graphViewId, LineGraphSeries ... lineGraphSeries){ - GraphView graph = (GraphView) parentHolder.findViewById(graphViewId); - for(LineGraphSeries series : lineGraphSeries){ - graph.addSeries(series); - } - graph.getGridLabelRenderer().setLabelFormatter(new DateAsXAxisLabelFormatter(referenceActivity)); - graph.getGridLabelRenderer().setHumanRounding(false, true); - graph.getViewport().setMinX(startDate.getTime()); - graph.getViewport().setMaxX(endDate.getTime()); - graph.getViewport().setXAxisBoundsManual(true); - - graph.getGridLabelRenderer().setNumHorizontalLabels(7); // only 7 because of the space - graph.getGridLabelRenderer().setTextSize(40); - graph.getViewport().setScrollable(true); - graph.getGridLabelRenderer().setHorizontalLabelsAngle(135); - } - - /*** - * Updates the graphs with the calories/carbs/... eaten during that period and also updates the - * average consumed calories/... during that period. Works for weeks and months, depending on the - * given start/end date and n days in period. - * It is static and part of the WekkStatisticFragment class, because I could not think of a - * better place for it. I tried making MonthStatisticFragment inheriting from Week... but this - * resulted in strange bugs. - * @param startDate - * @param endDate - * @param periodLengthInDays Number of days in period, 7 for week, something else for e.g. month. - */ - static void updateGraphUsingNdayPeriod(View parentHolder, Activity referenceActivity, - DatabaseFacade databaseFacade, TextView textView, - TextView carbsTextView, TextView proteinTextView, - TextView fatTextView, - Date startDate, Date endDate, int periodLengthInDays){ - if(databaseFacade == null){ //I replaced the try catch block covering all code of the method with this null-check, hoping the try catch did not catch other things a lot - Log.e("ateGraphUsingNdayPeriod","DatabaseFacade is null! Not adding graph stuff to statistics view."); - return; //TODO: why is databaseFacade null at the beginning? - } - List consumedEntriesList = new ArrayList<>(); - List calories = new ArrayList<>(); - - consumedEntriesList = databaseFacade.getCaloriesPerDayinPeriod(startDate,endDate); - calories = databaseFacade.getPeriodCalories(startDate,endDate); - - DataPoint[] dataPointInterfaces = dataPointsForNutriment(consumedEntriesList); - - List consumedCarbsEntriesList = databaseFacade.getCarbsPerDayinPeriod(startDate, endDate); - List carbs = databaseFacade.getPeriodCarbs(startDate, endDate); - DataPoint[] carbsDataPointInterfaces = dataPointsForNutriment(consumedCarbsEntriesList); - - List consumedSugarEntriesList = databaseFacade.getSugarPerDayinPeriod(startDate, endDate); - List sugar = databaseFacade.getPeriodSugar(startDate, endDate); - DataPoint[] sugarDataPointInterfaces = dataPointsForNutriment(consumedSugarEntriesList); - - List consumedProteinEntriesList = databaseFacade.getProteinPerDayinPeriod(startDate, endDate); - List protein = databaseFacade.getPeriodProtein(startDate, endDate); - DataPoint[] proteinDataPointInterfaces = dataPointsForNutriment(consumedProteinEntriesList); - - List consumedFatEntriesList = databaseFacade.getFatPerDayinPeriod(startDate, endDate); - List fat = databaseFacade.getPeriodFat(startDate, endDate); - DataPoint[] fatDataPointInterfaces = dataPointsForNutriment(consumedFatEntriesList); - - List consumedSatFatEntriesList = databaseFacade.getSatFatPerDayinPeriod(startDate, endDate); - List satFat = databaseFacade.getPeriodSatFat(startDate, endDate); - DataPoint[] satFatDataPointInterfaces = dataPointsForNutriment(consumedSatFatEntriesList); - - - - float averageCalories = calories.get(0).unique2 / periodLengthInDays; - float averageCarbs = carbs.get(0).unique2 / periodLengthInDays; - float averageSugar = sugar.get(0).unique2 / periodLengthInDays; - float averageProtein = protein.get(0).unique2 / periodLengthInDays; - float averageFat = fat.get(0).unique2 / periodLengthInDays; - float averageSatFat = satFat.get(0).unique2 / periodLengthInDays; - - BigDecimal averageCaloriesBigDecimal = round(averageCalories,0) ; - BigDecimal averageCarbsBigDecimal = round(averageCarbs,0) ; - BigDecimal averageSugarBigDecimal = round(averageSugar,0) ; - BigDecimal averageProteinBigDecimal = round(averageProtein,0) ; - BigDecimal averageFatBigDecimal = round(averageFat,0) ; - BigDecimal averageSatFatBigDecimal = round(averageSatFat,0) ; - - if (calories.size() != 0) { - textView.setText(averageCaloriesBigDecimal.toString()); - } - if (carbs.size() != 0 && sugar.size() != 0) { - carbsTextView.setText(averageCarbsBigDecimal.toString() + " (" + averageSugarBigDecimal.toString() +")"); - } - if (protein.size() != 0) { - proteinTextView.setText(averageProteinBigDecimal.toString()); - } - if (fat.size() != 0 && satFat.size() != 0) { - fatTextView.setText(averageFatBigDecimal.toString() + " (" + averageSatFatBigDecimal.toString() +")"); - } - - LineGraphSeries calSeries = new LineGraphSeries<>(dataPointInterfaces); - addSeriesToGraphById(parentHolder,referenceActivity,startDate,endDate,R.id.graph, calSeries); - - LineGraphSeries carbsSeries = new LineGraphSeries<>(carbsDataPointInterfaces); - LineGraphSeries sugarSeries = new LineGraphSeries<>(sugarDataPointInterfaces); - sugarSeries.setColor(Color.RED); - addSeriesToGraphById(parentHolder,referenceActivity,startDate,endDate,R.id.graphCarbs, - carbsSeries, sugarSeries); - - - LineGraphSeries proteinSeries = new LineGraphSeries<>(proteinDataPointInterfaces); - addSeriesToGraphById(parentHolder,referenceActivity,startDate,endDate,R.id.graphProtein, - proteinSeries); - - - LineGraphSeries fatSeries = new LineGraphSeries<>(fatDataPointInterfaces); - LineGraphSeries satFatSeries = new LineGraphSeries<>(satFatDataPointInterfaces); - satFatSeries.setColor(Color.RED); - addSeriesToGraphById(parentHolder,referenceActivity,startDate,endDate,R.id.graphFat, - fatSeries, satFatSeries); - } - void UpdateGraph() { - int weekdays = 7; - Date startDate = getWeekByValue(-1); - startDate = DateHelper.changeDateTimeToMidnight(startDate); //set time to midnight so the period does not depend on the time of day - Date endDate = getWeekByValue(0); - endDate = DateHelper.changeDateTimeToMidnight(endDate); - updateGraphUsingNdayPeriod(parentHolder,referenceActivity,databaseFacade,textView, - carbsTextView,proteinTextView, fatTextView,startDate,endDate, weekdays); - } - - Date changeWeekByValue(int value) { - Date date = getWeekByValue(value); - sharedStatisticViewModel.setCalendarWithDateObj(date); - return date; - } - - - Date getWeekByValue(int value) { - Date date = DateHelper.changeWeek(sharedStatisticViewModel.getDate(), value); - return date; - } - - -} diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/adapter/DatabaseFacade.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/adapter/DatabaseFacade.java index ddb58f6..95341f0 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/adapter/DatabaseFacade.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/adapter/DatabaseFacade.java @@ -181,6 +181,26 @@ public List getCaloriesPerDayinPeriod( return consumedEntrieAndProductDao.getCaloriesPerDayinPeriod(new java.sql.Date(startDate.getTime()), new java.sql.Date(endDate.getTime())); } + /** + * Returns the sum of every nutriment per day for a time period. + * @param startDate the start date + * @param endDate the end date + * @return the calories sum per day and the associated date + */ + public List getPeriodNutriments(java.util.Date startDate, java.util.Date endDate){ + return consumedEntrieAndProductDao.getNutrimentsPeriod(new java.sql.Date(startDate.getTime()), new java.sql.Date(endDate.getTime())); + } + + /** + * Returns the sum of every nutriment between two dates. + * @param startDate the start date + * @param endDate the end date + * @return the calories sum (list position 0) + */ + public List getNutrimentsPerDayinPeriod(java.util.Date startDate, java.util.Date endDate){ + return consumedEntrieAndProductDao.getNutrimentsPerDayinPeriod(new java.sql.Date(startDate.getTime()), new java.sql.Date(endDate.getTime())); + } + /** * Returns the sum of carbs per day for a time period. * @param startDate the start date diff --git a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/adapter/StatisticPagerAdapter.java b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/adapter/StatisticPagerAdapter.java index ae4f8f4..005e8c8 100644 --- a/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/adapter/StatisticPagerAdapter.java +++ b/app/src/main/java/org/secuso/privacyfriendlyfoodtracker/ui/adapter/StatisticPagerAdapter.java @@ -22,8 +22,7 @@ import android.support.v4.app.FragmentStatePagerAdapter; import org.secuso.privacyfriendlyfoodtracker.R; -import org.secuso.privacyfriendlyfoodtracker.ui.MonthStatisticFragment; -import org.secuso.privacyfriendlyfoodtracker.ui.WeekStatisticFragment; +import org.secuso.privacyfriendlyfoodtracker.ui.StatisticFragment; /** * Implementation of PagerAdapter that uses a Fragment to manage each page. This class also handles saving and restoring of fragment's state. @@ -54,9 +53,9 @@ public StatisticPagerAdapter(FragmentManager fm, Context context) { public Fragment getItem(int position) { switch (position) { case 0: - return new WeekStatisticFragment(); + return StatisticFragment.newInstance(true); case 1: - return new MonthStatisticFragment(); + return StatisticFragment.newInstance(false); } return null; } diff --git a/app/src/main/res/layout/fragment_month_statistic.xml b/app/src/main/res/layout/fragment_statistic.xml similarity index 62% rename from app/src/main/res/layout/fragment_month_statistic.xml rename to app/src/main/res/layout/fragment_statistic.xml index 960bcea..70647f2 100644 --- a/app/src/main/res/layout/fragment_month_statistic.xml +++ b/app/src/main/res/layout/fragment_statistic.xml @@ -3,7 +3,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".ui.WeekStatisticFragment"> + tools:context=".ui.StatisticFragment"> @@ -109,66 +110,6 @@ android:layout_width="match_parent" android:layout_height="200dip" /> - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/fragment_week_statistic.xml b/app/src/main/res/layout/fragment_week_statistic.xml deleted file mode 100644 index 291805f..0000000 --- a/app/src/main/res/layout/fragment_week_statistic.xml +++ /dev/null @@ -1,180 +0,0 @@ - - - - - - - - - - - - - - - - - - - -