feat: add weeekly ranking list and average calories
parent
cc1ea62d2d
commit
fcc607043e
|
@ -34,7 +34,6 @@ class StatisticsPercentage extends StatelessWidget {
|
||||||
child: ValueListenableBuilder<List<double>>(
|
child: ValueListenableBuilder<List<double>>(
|
||||||
valueListenable: StatisticsService.instance.ingredients,
|
valueListenable: StatisticsService.instance.ingredients,
|
||||||
builder: (context, value, child) {
|
builder: (context, value, child) {
|
||||||
print(value);
|
|
||||||
return Column(
|
return Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
children: [
|
children: [
|
||||||
|
|
|
@ -6,6 +6,11 @@ String getFoodListStringByFood(String foodName, int count, int calories){
|
||||||
return limitedText;
|
return limitedText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String getWeeklyRankingString(String foodName){
|
||||||
|
int maxWidth = 50;
|
||||||
|
String limitedText = foodName.length > maxWidth ? "${foodName.substring(0, maxWidth - 3)} ... " : foodName;
|
||||||
|
return limitedText;
|
||||||
|
}
|
||||||
|
|
||||||
Map<String,List<int>> getMapOfDistinctElementsWithCounterAndCalories(List<Food> foods){
|
Map<String,List<int>> getMapOfDistinctElementsWithCounterAndCalories(List<Food> foods){
|
||||||
Map<String,List<int>> resultMap = <String,List<int>>{};
|
Map<String,List<int>> resultMap = <String,List<int>>{};
|
||||||
|
@ -18,3 +23,13 @@ Map<String,List<int>> getMapOfDistinctElementsWithCounterAndCalories(List<Food>
|
||||||
}
|
}
|
||||||
return resultMap;
|
return resultMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<Food> getListOfDistinctElements(List<Food> foods){
|
||||||
|
List<Food> result = [];
|
||||||
|
for(int i = 0; i < foods.length;i++){
|
||||||
|
if(!result.any((element) => element.id == foods[i].id)){
|
||||||
|
result.add(foods[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import 'package:ernaehrung/android/config/cast_helper.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import '../models/food.dart';
|
import '../models/food.dart';
|
||||||
|
import 'format_helper.dart';
|
||||||
|
|
||||||
class StatisticsService {
|
class StatisticsService {
|
||||||
|
|
||||||
|
@ -18,60 +19,66 @@ class StatisticsService {
|
||||||
|
|
||||||
final String reducedStatisticsBoxName = 'STATISTICS_REDUCED';
|
final String reducedStatisticsBoxName = 'STATISTICS_REDUCED';
|
||||||
final String mainStatisticsBoxName = 'STATISTICS_MAIN';
|
final String mainStatisticsBoxName = 'STATISTICS_MAIN';
|
||||||
|
final String progressStatisticsBoxName = 'STATISTICS_PROGRESS';
|
||||||
ValueNotifier<int> eatenCalories = ValueNotifier<int>(0);
|
ValueNotifier<int> eatenCalories = ValueNotifier<int>(0);
|
||||||
ValueNotifier<List<double>> ingredients = ValueNotifier<List<double>>([0,0,0]);
|
ValueNotifier<List<double>> ingredients = ValueNotifier<List<double>>([0,0,0]);
|
||||||
|
ValueNotifier<int> dailyAverageForCurrentWeek = ValueNotifier<int>(0);
|
||||||
|
ValueNotifier<List<Food>> weeklyCaloryRanking = ValueNotifier<List<Food>>([]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
initBoxes()async{
|
initBoxes()async{
|
||||||
Box reducedBox = Hive.box(reducedStatisticsBoxName);
|
Box reducedBox = Hive.box(reducedStatisticsBoxName);
|
||||||
putIfKeyNotExists(reducedBox, 'FRÜHSTÜCK', []);
|
Box progressBox = Hive.box(progressStatisticsBoxName);
|
||||||
putIfKeyNotExists(reducedBox, 'MITTAGESSEN', []);
|
|
||||||
putIfKeyNotExists(reducedBox, 'ABENDESSEN', []);
|
putIfKeyNotExists([reducedBox,progressBox], 'FRÜHSTÜCK', []);
|
||||||
|
putIfKeyNotExists([reducedBox,progressBox], 'MITTAGESSEN', []);
|
||||||
|
putIfKeyNotExists([reducedBox,progressBox], 'ABENDESSEN', []);
|
||||||
updateReducedBoxByTimespan(TimeSpan.day);
|
updateReducedBoxByTimespan(TimeSpan.day);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void putIfKeyNotExists(List<Box> boxes, String key, dynamic value) {
|
||||||
void putIfKeyNotExists(Box box, String key, dynamic value) {
|
for(int i = 0; i < boxes.length;i++){
|
||||||
if (!box.containsKey(key)) {
|
if (!boxes[i].containsKey(key)) {
|
||||||
box.put(key, value);
|
boxes[i].put(key, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateReducedBoxByTimespan(TimeSpan timeSpan){
|
updateReducedBoxByTimespan(TimeSpan timeSpan){
|
||||||
clearReducedBoxBeforeUpdate();
|
clearReducedBoxBeforeUpdate();
|
||||||
DateTime now = DateTime.now();
|
int timestamp = getTimestampFromNow();
|
||||||
int timestamp = now.millisecondsSinceEpoch.toInt() ~/ 1000;
|
|
||||||
switch(timeSpan){
|
switch(timeSpan){
|
||||||
case TimeSpan.day:
|
case TimeSpan.day:
|
||||||
getNewFoodAndUpdateReducedBoxByTimestamp(timestamp);
|
getNewFoodAndUpdateBoxByTimestampAndBox(timestamp, Hive.box(reducedStatisticsBoxName));
|
||||||
break;
|
break;
|
||||||
case TimeSpan.week:
|
case TimeSpan.week:
|
||||||
List<int> currentWeek = getTimestampsByTimestampAndTimespan(TimeSpan.week,timestamp);
|
List<int> currentWeek = getTimestampsByTimestampAndTimespan(TimeSpan.week,timestamp);
|
||||||
for(int i = 0;i < currentWeek.length;i++){
|
for(int i = 0;i < currentWeek.length;i++){
|
||||||
getNewFoodAndUpdateReducedBoxByTimestamp(currentWeek[i]);
|
getNewFoodAndUpdateBoxByTimestampAndBox(currentWeek[i],Hive.box(reducedStatisticsBoxName));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TimeSpan.month:
|
case TimeSpan.month:
|
||||||
List<int> currentMonth = getTimestampsByTimestampAndTimespan(TimeSpan.month,timestamp);
|
List<int> currentMonth = getTimestampsByTimestampAndTimespan(TimeSpan.month,timestamp);
|
||||||
for(int i = 0;i < currentMonth.length;i++){
|
for(int i = 0;i < currentMonth.length;i++){
|
||||||
getNewFoodAndUpdateReducedBoxByTimestamp(currentMonth[i]);
|
getNewFoodAndUpdateBoxByTimestampAndBox(currentMonth[i],Hive.box(reducedStatisticsBoxName));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
updateCalculationsAndNotfiyListeners();
|
updateCalculationsAndNotfiyListenersForPorgressStatistics();
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateCalculationsAndNotfiyListeners(){
|
void updateCalculationsAndNotfiyListenersForPorgressStatistics(){
|
||||||
eatenCalories.value = getAllEatenCaloriesForTodayStatistics();
|
eatenCalories.value = getAllEatenCaloriesByBox(Hive.box(reducedStatisticsBoxName));
|
||||||
eatenCalories.notifyListeners();
|
eatenCalories.notifyListeners();
|
||||||
ingredients.value = getAllEatenIngredientsForTodayStatistics();
|
ingredients.value = getAllEatenIngredientsForTodayStatistics();
|
||||||
ingredients.notifyListeners();
|
ingredients.notifyListeners();
|
||||||
}
|
}
|
||||||
void getNewFoodAndUpdateReducedBoxByTimestamp(int timestamp){
|
|
||||||
|
void getNewFoodAndUpdateBoxByTimestampAndBox(int timestamp, Box box){
|
||||||
Map<String,List<Food>> newFood = getFoodMapForGivenTimestampFromMainBox(timestamp);
|
Map<String,List<Food>> newFood = getFoodMapForGivenTimestampFromMainBox(timestamp);
|
||||||
if(newFood.keys.isNotEmpty){
|
if(newFood.keys.isNotEmpty){
|
||||||
setElementsOfReducedBox(newFood);
|
setElementsOfBoxByBox(newFood, box);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,8 +105,7 @@ class StatisticsService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setElementsOfReducedBox(Map<String,List<Food>> newFood){
|
setElementsOfBoxByBox(Map<String,List<Food>> newFood,Box box){
|
||||||
Box box = Hive.box(reducedStatisticsBoxName);
|
|
||||||
Iterable<String> keys = newFood.keys;
|
Iterable<String> keys = newFood.keys;
|
||||||
for(int i = 0; i < keys.length;i++){
|
for(int i = 0; i < keys.length;i++){
|
||||||
List<Food> alreadyExisting = castDynamicToListFood(box.get(keys.elementAt(i)));
|
List<Food> alreadyExisting = castDynamicToListFood(box.get(keys.elementAt(i)));
|
||||||
|
@ -187,8 +193,7 @@ class StatisticsService {
|
||||||
return randomTimestamp;
|
return randomTimestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getAllEatenCaloriesForTodayStatistics(){
|
int getAllEatenCaloriesByBox(Box box){
|
||||||
Box box = Hive.box(reducedStatisticsBoxName);
|
|
||||||
num sum = 0;
|
num sum = 0;
|
||||||
for(int i = 0; i < box.keys.length;i++){
|
for(int i = 0; i < box.keys.length;i++){
|
||||||
for(Food food in box.get(box.keys.elementAt(i))){
|
for(Food food in box.get(box.keys.elementAt(i))){
|
||||||
|
@ -213,33 +218,50 @@ class StatisticsService {
|
||||||
return [fat as double,protein as double,carbs as double];
|
return [fat as double,protein as double,carbs as double];
|
||||||
}
|
}
|
||||||
|
|
||||||
num getAllCaloriesByBoxAndTimestamp(Box box,int timestamp){
|
void updateCalculationsAndNotfiyListenersForTodayStatistics(){
|
||||||
Map<String, List<Food>> valueMap = castDynamicMap(box.get(timestamp));
|
dailyAverageForCurrentWeek.value = getAverageCaloriesForCurrentWeekOnDailyBasis();
|
||||||
num sum = 0;
|
dailyAverageForCurrentWeek.notifyListeners();
|
||||||
for(var mealType in valueMap.keys){
|
weeklyCaloryRanking.value = getWeeklyCaloryRanking();
|
||||||
if(valueMap.containsKey(mealType)){
|
weeklyCaloryRanking.notifyListeners();
|
||||||
List<Food> values = valueMap[mealType]!;
|
|
||||||
for(var value in values){
|
|
||||||
sum += value.calories;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sum;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
num getCaloriesByTimestampAndMealTypeAndBox(Box box,DateTime date, String mealType){
|
void updateProgressBoxValues(){
|
||||||
int timestamp = date.millisecondsSinceEpoch.toInt() ~/ 1000;
|
Box box = Hive.box(progressStatisticsBoxName);
|
||||||
Map<String, List<Food>> valueMap = castDynamicMap(box.get(timestamp));
|
box.clear();
|
||||||
num sum = 0;
|
int timestamp = getTimestampFromNow();
|
||||||
if(valueMap.containsKey(mealType)){
|
List<int> currentWeek = getTimestampsByTimestampAndTimespan(TimeSpan.week,timestamp);
|
||||||
List<Food> values = valueMap[mealType]!;
|
for(int i = 0;i < currentWeek.length;i++){
|
||||||
for(var value in values){
|
getNewFoodAndUpdateBoxByTimestampAndBox(currentWeek[i],box);
|
||||||
sum += value.calories;
|
|
||||||
}
|
}
|
||||||
}
|
updateCalculationsAndNotfiyListenersForTodayStatistics();
|
||||||
return sum;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getAverageCaloriesForCurrentWeekOnDailyBasis(){
|
||||||
|
Box box = Hive.box(progressStatisticsBoxName);
|
||||||
|
return getAllEatenCaloriesByBox(box)~/7;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Food> getWeeklyCaloryRanking(){
|
||||||
|
int timestamp = getTimestampFromNow();
|
||||||
|
List<int> currentWeek = getTimestampsByTimestampAndTimespan(TimeSpan.week,timestamp);
|
||||||
|
List<Food> allFoodsOfWeek = [];
|
||||||
|
for(int i = 0;i < currentWeek.length;i++){
|
||||||
|
Map<String,List<Food>> foodFromMainBox = getFoodMapForGivenTimestampFromMainBox(currentWeek[i]);
|
||||||
|
Iterable<String> keys = foodFromMainBox.keys;
|
||||||
|
if(keys.isNotEmpty){
|
||||||
|
for(int i = 0; i < keys.length;i++ ){
|
||||||
|
allFoodsOfWeek.addAll(foodFromMainBox[keys.elementAt(i)] as Iterable<Food>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
allFoodsOfWeek.sort((a, b) => b.calories - a.calories);
|
||||||
|
return getListOfDistinctElements(allFoodsOfWeek);
|
||||||
|
}
|
||||||
|
|
||||||
|
getTimestampFromNow(){
|
||||||
|
DateTime now = DateTime.now();
|
||||||
|
return now.millisecondsSinceEpoch.toInt() ~/ 1000;
|
||||||
|
}
|
||||||
showItems(){
|
showItems(){
|
||||||
print("Statistics.dart - showItems() - ITEMS");
|
print("Statistics.dart - showItems() - ITEMS");
|
||||||
//Hive.box(boxName).clear();
|
//Hive.box(boxName).clear();
|
||||||
|
|
|
@ -26,6 +26,8 @@ class MainPageState extends State<MainPage> {
|
||||||
currentIndex = index;
|
currentIndex = index;
|
||||||
if(currentIndex == 1){
|
if(currentIndex == 1){
|
||||||
StatisticsService.instance.updateReducedBoxByTimespan(TimeSpan.day);
|
StatisticsService.instance.updateReducedBoxByTimespan(TimeSpan.day);
|
||||||
|
}else if(currentIndex == 2){
|
||||||
|
StatisticsService.instance.updateProgressBoxValues();
|
||||||
}
|
}
|
||||||
pages[currentIndex];
|
pages[currentIndex];
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
import 'package:ernaehrung/android/components/meal_page_text/secondary_big_text_component.dart';
|
import 'package:ernaehrung/android/components/meal_page_text/secondary_big_text_component.dart';
|
||||||
import 'package:ernaehrung/android/components/meal_page_text/secondary_text_component.dart';
|
import 'package:ernaehrung/android/components/meal_page_text/secondary_text_component.dart';
|
||||||
import 'package:ernaehrung/android/components/meal_page_text/title_component.dart';
|
import 'package:ernaehrung/android/components/meal_page_text/title_component.dart';
|
||||||
|
import 'package:ernaehrung/android/config/statistics.dart';
|
||||||
import 'package:fl_chart/fl_chart.dart';
|
import 'package:fl_chart/fl_chart.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../../config/format_helper.dart';
|
||||||
|
|
||||||
class ProgressPage extends StatelessWidget {
|
class ProgressPage extends StatelessWidget {
|
||||||
final String title;
|
final String title;
|
||||||
final Color backgroundColor = const Color(0xff47a44b);
|
final Color backgroundColor = const Color(0xff47a44b);
|
||||||
|
@ -28,7 +31,10 @@ class ProgressPage extends StatelessWidget {
|
||||||
padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 8),
|
padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 8),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Container(
|
ValueListenableBuilder(
|
||||||
|
valueListenable: StatisticsService.instance.dailyAverageForCurrentWeek,
|
||||||
|
builder: (context, value, child) {
|
||||||
|
return Container(
|
||||||
height: 284,
|
height: 284,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
border: Border.all(),
|
border: Border.all(),
|
||||||
|
@ -38,10 +44,10 @@ class ProgressPage extends StatelessWidget {
|
||||||
children: [
|
children: [
|
||||||
const TitleComponent("Kalorien"),
|
const TitleComponent("Kalorien"),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 16,
|
height: 10,
|
||||||
),
|
),
|
||||||
const SecondaryTextComponent("Durchschnittlich"),
|
const SecondaryTextComponent("Durchschnittlich"),
|
||||||
SecondaryBigTextComponent(1235.toString()),
|
SecondaryBigTextComponent(value.toString()),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 200,
|
height: 200,
|
||||||
child: BarChart(
|
child: BarChart(
|
||||||
|
@ -58,79 +64,35 @@ class ProgressPage extends StatelessWidget {
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
Container(
|
ValueListenableBuilder(
|
||||||
margin: const EdgeInsets.symmetric(vertical: 16, horizontal: 0),
|
valueListenable: StatisticsService.instance.weeklyCaloryRanking,
|
||||||
child: Column(
|
builder: (context, value, child) {
|
||||||
//TODO: Aussortieren und mit einer Schleife drüber gehen
|
return Column(
|
||||||
//bzw. die Daten aus der Hivebox ziehen und sortieren
|
//TODO: Loop through the values and display them dynamically
|
||||||
children: [
|
children: [
|
||||||
const TitleComponent(
|
const TitleComponent("Lebensmittel mit dem höchsten Kaloriengehalt"),
|
||||||
"Lebensmittel mit dem höchsten Kaloriengehalt"),
|
|
||||||
const SizedBox(height: 24,),
|
const SizedBox(height: 24,),
|
||||||
|
for (var item in value.toSet())
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: const [
|
children: [
|
||||||
SecondaryTextComponent("Haferflocker"),
|
SecondaryTextComponent(getWeeklyRankingString(item.name)),
|
||||||
SecondaryTextComponent("670 Kalorien"),
|
SecondaryTextComponent(item.calories.toString()),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 24,),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: const [
|
|
||||||
SecondaryTextComponent("Haferflocker"),
|
|
||||||
SecondaryTextComponent("670 Kalorien"),
|
|
||||||
],
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
const SizedBox(height: 24,),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: const [
|
|
||||||
SecondaryTextComponent("Haferflocker"),
|
|
||||||
SecondaryTextComponent("670 Kalorien"),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(height: 24,),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: const [
|
|
||||||
SecondaryTextComponent("Haferflocker"),
|
|
||||||
SecondaryTextComponent("670 Kalorien"),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(height: 24,),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: const [
|
|
||||||
SecondaryTextComponent("Haferflocker"),
|
|
||||||
SecondaryTextComponent("670 Kalorien"),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(height: 24,),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: const [
|
|
||||||
SecondaryTextComponent("Haferflocker"),
|
|
||||||
SecondaryTextComponent("670 Kalorien"),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(height: 24,),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: const [
|
|
||||||
SecondaryTextComponent("Haferflocker"),
|
|
||||||
SecondaryTextComponent("670 Kalorien"),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BarTouchData get barTouchData => BarTouchData(
|
BarTouchData get barTouchData => BarTouchData(
|
||||||
|
|
|
@ -18,6 +18,7 @@ void main() async {
|
||||||
//await Hive.deleteFromDisk();
|
//await Hive.deleteFromDisk();
|
||||||
|
|
||||||
await Hive.openBox('STATISTICS_REDUCED');
|
await Hive.openBox('STATISTICS_REDUCED');
|
||||||
|
await Hive.openBox('STATISTICS_PROGRESS');
|
||||||
await Hive.openBox('STATISTICS_MAIN');
|
await Hive.openBox('STATISTICS_MAIN');
|
||||||
await Hive.openBox('TODAY');
|
await Hive.openBox('TODAY');
|
||||||
setupTodayBox();
|
setupTodayBox();
|
||||||
|
|
Loading…
Reference in New Issue