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