wt1.1.2 new treeview, bar chart for muscle development
This commit is contained in:
@@ -0,0 +1,292 @@
|
||||
import 'dart:async';
|
||||
import 'dart:collection';
|
||||
|
||||
import 'package:aitrainer_app/localization/app_language.dart';
|
||||
import 'package:aitrainer_app/model/exercise.dart';
|
||||
import 'package:aitrainer_app/model/workout_menu_tree.dart';
|
||||
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
||||
import 'package:aitrainer_app/repository/workout_tree_repository.dart';
|
||||
import 'package:aitrainer_app/util/calculate.dart';
|
||||
import 'package:aitrainer_app/util/common.dart';
|
||||
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:fl_chart/fl_chart.dart';
|
||||
|
||||
part 'development_by_muscle_event.dart';
|
||||
|
||||
part 'development_by_muscle_state.dart';
|
||||
|
||||
class DateRate {
|
||||
static String daily = "daily";
|
||||
static String weekly = "weekly";
|
||||
static String monthly = "monthly";
|
||||
static String yearly = "yearly";
|
||||
}
|
||||
|
||||
class DiagramType {
|
||||
static String sumMass = "sumMass";
|
||||
static String oneRepMax = "oneRepMax";
|
||||
static String percent = "percent";
|
||||
}
|
||||
|
||||
class ChartDataExtended {
|
||||
final List<BarChartGroupData> data;
|
||||
final double interval;
|
||||
final int gridInterval;
|
||||
|
||||
const ChartDataExtended({this.data, this.interval, this.gridInterval});
|
||||
|
||||
Map<String, dynamic> toJson() =>
|
||||
{
|
||||
"data": data.toString(),
|
||||
"interval" : interval.toString(),
|
||||
"gridInterval" : gridInterval,
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
class DevelopmentByMuscleBloc extends Bloc<DevelopmentByMuscleEvent, DevelopmentByMuscleState> with Calculate, Common {
|
||||
final WorkoutTreeRepository workoutTreeRepository;
|
||||
final ExerciseRepository exerciseRepository = ExerciseRepository();
|
||||
LinkedHashMap<int, ChartDataExtended> listChartData = LinkedHashMap();
|
||||
List<BarChartGroupData> chartData;
|
||||
String diagramType = DiagramType.sumMass;
|
||||
String dateRate = DateRate.daily;
|
||||
double basePercent = 0;
|
||||
|
||||
@override
|
||||
DevelopmentByMuscleBloc({
|
||||
this.workoutTreeRepository}) :
|
||||
super(DevelopmentByMuscleStateInitial());
|
||||
|
||||
Future<void> getData() async {
|
||||
|
||||
workoutTreeRepository.sortedTree = null;
|
||||
workoutTreeRepository.sortByMuscleType();
|
||||
|
||||
workoutTreeRepository.sortedTree.forEach((key, value) {
|
||||
List<WorkoutMenuTree> listWorkoutTree = value;
|
||||
listWorkoutTree.forEach((workoutTree) {
|
||||
workoutTree.selected = false;
|
||||
});
|
||||
});
|
||||
|
||||
this.getChartData();
|
||||
|
||||
}
|
||||
|
||||
void getChartData() {
|
||||
List<Exercise> exercises = exerciseRepository.getExerciseList();
|
||||
exercises.sort( (a, b) => a.exerciseTypeId.compareTo(b.exerciseTypeId));
|
||||
exercises = this.groupByDate(exercises);
|
||||
|
||||
int origExerciseTypeId = 0;
|
||||
int x = 0;
|
||||
chartData = List();
|
||||
double maxData = 0;
|
||||
double minData = 9999999999999;
|
||||
exercises.forEach((exercise) {
|
||||
if ( exercise.unitQuantity != null ) {
|
||||
if (origExerciseTypeId != exercise.exerciseTypeId && diagramType == DiagramType.percent) {
|
||||
this.basePercent = getBasePercent(exercise);
|
||||
}
|
||||
double diagramValue = this.getDiagramValue(exercise);
|
||||
|
||||
if (maxData < diagramValue) {
|
||||
maxData = diagramValue;
|
||||
}
|
||||
if (minData > diagramValue) {
|
||||
minData = diagramValue;
|
||||
}
|
||||
//print("exercise " + exercise.exerciseTypeId.toString() + " d " + getDateFormat(exercise.dateAdd) + " mass " + sumMass.toString());
|
||||
//print("date " + exercise.dateAdd.toIso8601String() + " epoch " + exercise.dateAdd.millisecondsSinceEpoch.toString() );
|
||||
BarChartGroupData data = BarChartGroupData(
|
||||
x: exercise.dateAdd.millisecondsSinceEpoch,
|
||||
barRods: [
|
||||
BarChartRodData(y: diagramValue, width: 12, color: Colors.lightBlue)
|
||||
]
|
||||
);
|
||||
if (origExerciseTypeId != exercise.exerciseTypeId) {
|
||||
if (origExerciseTypeId == 0) {
|
||||
origExerciseTypeId = exercise.exerciseTypeId;
|
||||
chartData.add(data);
|
||||
} else {
|
||||
double dInterval = ((maxData + minData) / 8).roundToDouble();
|
||||
int gridInterval = (dInterval / 3).floor();
|
||||
ChartDataExtended extended = ChartDataExtended(
|
||||
data: chartData, interval: dInterval, gridInterval: gridInterval);
|
||||
listChartData[origExerciseTypeId] = extended;
|
||||
maxData = 0;
|
||||
minData = 9999999999999;
|
||||
chartData = List();
|
||||
chartData.add(data);
|
||||
origExerciseTypeId = exercise.exerciseTypeId;
|
||||
}
|
||||
} else {
|
||||
origExerciseTypeId = exercise.exerciseTypeId;
|
||||
chartData.add(data);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
listChartData.forEach((key, value) {
|
||||
print ("typeid " + key.toString() + " chardata " + value.toJson().toString());
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
String getDatePart(DateTime date) {
|
||||
String datePart = DateFormat('MM.dd', AppLanguage().appLocal.toString()).format(date);;
|
||||
if ( this.dateRate == DateRate.weekly ) {
|
||||
datePart = weekNumber(date).toString();
|
||||
} else if ( this.dateRate == DateRate.monthly ) {
|
||||
datePart = DateFormat('MMM', AppLanguage().appLocal.toString()).format(date);
|
||||
} else if ( this.dateRate == DateRate.yearly ) {
|
||||
datePart = DateFormat('y', AppLanguage().appLocal.toString()).format(date);
|
||||
} else if ( this.dateRate == DateRate.daily ) {
|
||||
datePart = DateFormat('MM.dd', AppLanguage().appLocal.toString()).format(date);
|
||||
}
|
||||
return datePart;
|
||||
}
|
||||
|
||||
List<Exercise> groupByDate(List<Exercise> exercises) {
|
||||
List<Exercise> groupedExercises = List();
|
||||
|
||||
String origDatePart;
|
||||
|
||||
int countExercises = 0;
|
||||
double sumQuantity = 0;
|
||||
double maxQuantity = 0;
|
||||
Exercise origExercise;
|
||||
exercises.forEach((exercise) {
|
||||
String exerciseDatePart = getDatePart(exercise.dateAdd);
|
||||
if ( origExercise != null ) {
|
||||
if ( origExercise.exerciseTypeId != exercise.exerciseTypeId || origDatePart != exerciseDatePart ) {
|
||||
Exercise newExercise = origExercise.copy();
|
||||
newExercise.datePart = origDatePart;
|
||||
if (this.diagramType == DiagramType.oneRepMax || this.diagramType == DiagramType.percent) {
|
||||
newExercise.quantity = maxQuantity;
|
||||
} else {
|
||||
newExercise.quantity = sumQuantity / countExercises;
|
||||
}
|
||||
groupedExercises.add(newExercise);
|
||||
countExercises = 0;
|
||||
sumQuantity = 0;
|
||||
maxQuantity = 0;
|
||||
}
|
||||
}
|
||||
origExercise = exercise;
|
||||
origDatePart = exerciseDatePart;
|
||||
|
||||
double newQuantity = getQuantityByDate(exercise);
|
||||
sumQuantity += newQuantity;
|
||||
if (maxQuantity < newQuantity) {
|
||||
maxQuantity = newQuantity;
|
||||
}
|
||||
countExercises++;
|
||||
|
||||
});
|
||||
|
||||
groupedExercises.forEach((element) {
|
||||
print("grouped " + element.toJson().toString());
|
||||
});
|
||||
|
||||
|
||||
return groupedExercises;
|
||||
}
|
||||
|
||||
double getQuantityByDate(Exercise exercise) {
|
||||
double sum = 0;
|
||||
if ( this.diagramType == DiagramType.sumMass ) {
|
||||
if ( exercise.unitQuantity != null ) {
|
||||
sum = exercise.quantity * exercise.unitQuantity;
|
||||
} else {
|
||||
sum = exercise.quantity;
|
||||
}
|
||||
} else if ( this.diagramType == DiagramType.oneRepMax || this.diagramType == DiagramType.percent ) {
|
||||
if ( exercise.unitQuantity != null ) {
|
||||
sum = calculate1RM(exercise.quantity, exercise.unitQuantity);
|
||||
} else {
|
||||
sum = exercise.quantity;
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
double getBasePercent(Exercise exercise) {
|
||||
if ( exercise.unitQuantity != null ) {
|
||||
this.basePercent = calculate1RM(exercise.quantity, exercise.unitQuantity);
|
||||
} else {
|
||||
this.basePercent = exercise.quantity;
|
||||
}
|
||||
//print("Base percent of " + exercise.exerciseTypeId.toString() + ": " + basePercent.toString());
|
||||
return this.basePercent;
|
||||
}
|
||||
|
||||
double getDiagramValue(Exercise exercise) {
|
||||
double value = 0;
|
||||
/*if ( diagramType == DiagramType.sumMass) {
|
||||
value = exercise.quantity;
|
||||
if ( exercise.unitQuantity != null ) {
|
||||
value *= exercise.unitQuantity;
|
||||
}
|
||||
} else if ( diagramType == DiagramType.oneRepMax) {
|
||||
if ( exercise.unitQuantity != null ) {
|
||||
value = calculate1RM(exercise.quantity, exercise.unitQuantity);
|
||||
}
|
||||
} else if ( diagramType == DiagramType.percent) {
|
||||
if ( exercise.unitQuantity != null ) {
|
||||
double oneRepMax = calculate1RM(exercise.quantity, exercise.unitQuantity);
|
||||
value = (oneRepMax / this.basePercent) * 100;
|
||||
//print("Percent of " + exercise.exerciseTypeId.toString() + ": " + value.toString() + " date " + exercise.dateAdd.toIso8601String() + " 1RM " + oneRepMax.toString());
|
||||
} else {
|
||||
value = (exercise.quantity / this.basePercent ) * 100;
|
||||
}*/
|
||||
|
||||
if ( diagramType == DiagramType.percent) {
|
||||
if ( exercise.unitQuantity != null ) {
|
||||
double oneRepMax = calculate1RM(exercise.quantity, exercise.unitQuantity);
|
||||
value = (oneRepMax / this.basePercent) * 100;
|
||||
//print("Percent of " + exercise.exerciseTypeId.toString() + ": " + value.toString() + " date " + exercise.dateAdd.toIso8601String() + " 1RM " + oneRepMax.toString());
|
||||
} else {
|
||||
value = (exercise.quantity / this.basePercent ) * 100;
|
||||
}
|
||||
} else {
|
||||
return exercise.quantity;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
String getDateFormat(DateTime datetime) {
|
||||
return DateFormat('yMd', AppLanguage().appLocal.toString()).format(datetime);
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<DevelopmentByMuscleState> mapEventToState(DevelopmentByMuscleEvent event) async* {
|
||||
try {
|
||||
if (event is DevelopmentByMuscleLoad) {
|
||||
yield DevelopmentByMuscleLoadingState();
|
||||
await getData();
|
||||
yield DevelopmentByMuscleReadyState();
|
||||
} else if ( event is DevelopmentByMuscleDiagramTypeChange ) {
|
||||
yield DevelopmentByMuscleLoadingState();
|
||||
String type = event.diagramType;
|
||||
this.diagramType = type;
|
||||
getChartData();
|
||||
yield DevelopmentByMuscleReadyState();
|
||||
} else if ( event is DevelopmentByMuscleDateRateChange ) {
|
||||
yield DevelopmentByMuscleLoadingState();
|
||||
String dateRate = event.dateRate;
|
||||
this.dateRate = dateRate;
|
||||
getChartData();
|
||||
yield DevelopmentByMuscleReadyState();
|
||||
}
|
||||
} on Exception catch (e) {
|
||||
yield DevelopmentByMuscleErrorState(message: e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
part of 'development_by_muscle_bloc.dart';
|
||||
|
||||
@immutable
|
||||
abstract class DevelopmentByMuscleEvent extends Equatable {
|
||||
const DevelopmentByMuscleEvent();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class DevelopmentByMuscleLoad extends DevelopmentByMuscleEvent {
|
||||
const DevelopmentByMuscleLoad();
|
||||
}
|
||||
|
||||
class DevelopmentByMuscleDateRateChange extends DevelopmentByMuscleEvent {
|
||||
final String dateRate;
|
||||
const DevelopmentByMuscleDateRateChange({this.dateRate});
|
||||
|
||||
@override
|
||||
List<Object> get props => [dateRate];
|
||||
}
|
||||
|
||||
class DevelopmentByMuscleDiagramTypeChange extends DevelopmentByMuscleEvent {
|
||||
final String diagramType;
|
||||
const DevelopmentByMuscleDiagramTypeChange({this.diagramType});
|
||||
|
||||
@override
|
||||
List<Object> get props => [diagramType];
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
part of 'development_by_muscle_bloc.dart';
|
||||
|
||||
@immutable
|
||||
abstract class DevelopmentByMuscleState extends Equatable{
|
||||
const DevelopmentByMuscleState();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class DevelopmentByMuscleStateInitial extends DevelopmentByMuscleState {
|
||||
const DevelopmentByMuscleStateInitial();
|
||||
}
|
||||
|
||||
class DevelopmentByMuscleLoadingState extends DevelopmentByMuscleState {
|
||||
const DevelopmentByMuscleLoadingState();
|
||||
}
|
||||
|
||||
class DevelopmentByMuscleReadyState extends DevelopmentByMuscleState {
|
||||
const DevelopmentByMuscleReadyState();
|
||||
}
|
||||
|
||||
|
||||
class DevelopmentByMuscleErrorState extends DevelopmentByMuscleState {
|
||||
final String message;
|
||||
const DevelopmentByMuscleErrorState({this.message});
|
||||
|
||||
@override
|
||||
List<Object> get props => [message];
|
||||
}
|
||||
Reference in New Issue
Block a user