WT 1.1.0+39 evaluation, health data
This commit is contained in:
@@ -0,0 +1,225 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:aitrainer_app/model/cache.dart';
|
||||
import 'package:aitrainer_app/model/result.dart';
|
||||
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
||||
import 'package:aitrainer_app/repository/exercise_result_repository.dart';
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
|
||||
import 'package:health/health.dart';
|
||||
|
||||
part 'result_event.dart';
|
||||
part 'result_state.dart';
|
||||
|
||||
class ResultBloc extends Bloc<ResultEvent, ResultState> {
|
||||
final ExerciseResultRepository resultRepository;
|
||||
final ExerciseRepository exerciseRepository;
|
||||
List<HealthDataPoint> _healthDataList = List();
|
||||
DateTime startTime;
|
||||
DateTime endTime;
|
||||
final HealthFactory health = HealthFactory();
|
||||
final List<HealthDataType> types = [
|
||||
HealthDataType.ACTIVE_ENERGY_BURNED,
|
||||
HealthDataType.WATER,
|
||||
HealthDataType.STEPS,
|
||||
HealthDataType.HEART_RATE,
|
||||
HealthDataType.BASAL_ENERGY_BURNED,
|
||||
HealthDataType.BODY_TEMPERATURE,
|
||||
HealthDataType.HIGH_HEART_RATE_EVENT,
|
||||
HealthDataType.LOW_HEART_RATE_EVENT,
|
||||
HealthDataType.RESTING_HEART_RATE
|
||||
];
|
||||
|
||||
ResultBloc({this.resultRepository, this.exerciseRepository}) : super(ResultInitial()) {
|
||||
this.startTime = exerciseRepository.start;
|
||||
this.endTime = exerciseRepository.end;
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<ResultState> mapEventToState(
|
||||
ResultEvent event,
|
||||
) async* {
|
||||
try {
|
||||
if (event is ResultLoad) {
|
||||
yield ResultLoading();
|
||||
|
||||
await _fetchHealthData();
|
||||
_matchExerciseData();
|
||||
yield ResultReady();
|
||||
}
|
||||
} on Exception catch (ex) {
|
||||
yield ResultError(error: ex.toString());
|
||||
}
|
||||
}
|
||||
|
||||
void _matchExerciseData() {
|
||||
resultRepository.getResults().forEach((element) {
|
||||
switch (element.item) {
|
||||
case ResultItem.bpm_avg:
|
||||
element.data = _gethHealthDataPointValueAvg(HealthDataType.HEART_RATE).toStringAsFixed(0);
|
||||
break;
|
||||
case ResultItem.bpm_min:
|
||||
element.data = element.data = _gethHealthDataPointValueMin(HealthDataType.HEART_RATE).toStringAsFixed(0);
|
||||
break;
|
||||
case ResultItem.bpm_max:
|
||||
element.data = element.data = _gethHealthDataPointValueMax(HealthDataType.HEART_RATE).toStringAsFixed(0);
|
||||
break;
|
||||
case ResultItem.calorie:
|
||||
element.data = _gethHealthDataPointValueSum(HealthDataType.ACTIVE_ENERGY_BURNED).toStringAsFixed(0);
|
||||
break;
|
||||
case ResultItem.development_percent_bodypart:
|
||||
// TODO: Handle this case.
|
||||
break;
|
||||
case ResultItem.distance:
|
||||
if (exerciseRepository.exerciseType.unit == "meter") {
|
||||
element.data = exerciseRepository.exercise.quantity.toStringAsFixed(0);
|
||||
}
|
||||
break;
|
||||
case ResultItem.fatburn_percent:
|
||||
DateTime today = DateTime.now();
|
||||
int age = today.year - Cache().userLoggedIn.birthYear;
|
||||
double minBpm = (200 - age) * 0.6;
|
||||
double maxBpm = (200 - age) * 0.7;
|
||||
int counter = 0;
|
||||
int burnCounter = 0;
|
||||
_healthDataList.forEach((dataPoint) {
|
||||
if (dataPoint.type == HealthDataType.ACTIVE_ENERGY_BURNED) {
|
||||
if (dataPoint.value >= minBpm && dataPoint.value <= maxBpm) {
|
||||
burnCounter++;
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
});
|
||||
if (counter > 0) {
|
||||
element.data = (burnCounter / counter * 100).toStringAsFixed(2);
|
||||
} else {
|
||||
element.data = "0";
|
||||
}
|
||||
break;
|
||||
case ResultItem.speed_max:
|
||||
// TODO: Handle this case.
|
||||
break;
|
||||
case ResultItem.reps_volume:
|
||||
if (exerciseRepository.exerciseType.unit == "repeat") {
|
||||
double value = 0;
|
||||
exerciseRepository.actualExerciseList.forEach((element) {
|
||||
value += element.quantity;
|
||||
});
|
||||
element.data = value.toStringAsFixed(0);
|
||||
}
|
||||
break;
|
||||
case ResultItem.steps:
|
||||
element.data = _gethHealthDataPointValueSum(HealthDataType.STEPS).toStringAsFixed(0);
|
||||
break;
|
||||
/* case ResultItem.time:
|
||||
final Duration duration = this.endTime.difference(this.startTime);
|
||||
element.data = _printDuration(duration);
|
||||
break; */
|
||||
case ResultItem.weight_volume:
|
||||
if (exerciseRepository.exerciseType.unitQuantityUnit == "kilogram") {
|
||||
double value = 0;
|
||||
exerciseRepository.actualExerciseList.forEach((element) {
|
||||
value += element.quantity * element.unitQuantity;
|
||||
});
|
||||
element.data = value.toStringAsFixed(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
String _printDuration(Duration duration) {
|
||||
String twoDigits(int n) => n.toString().padLeft(2, "0");
|
||||
String twoDigitMinutes = twoDigits(duration.inMinutes);
|
||||
String twoDigitSeconds = twoDigits(duration.inSeconds.remainder(60));
|
||||
String twoDigitMilliSeconds = duration.inMilliseconds.remainder(1000).toString();
|
||||
return "$twoDigitMinutes:$twoDigitSeconds:$twoDigitMilliSeconds" + '"';
|
||||
}
|
||||
|
||||
double _gethHealthDataPointValueAvg(HealthDataType dataType) {
|
||||
double value = 0;
|
||||
double counter = 0;
|
||||
_healthDataList.forEach((dataPoint) {
|
||||
if (dataPoint.type == dataType) {
|
||||
value += dataPoint.value;
|
||||
counter++;
|
||||
}
|
||||
});
|
||||
double avg = 0;
|
||||
if (counter > 0) {
|
||||
avg = value / counter;
|
||||
}
|
||||
return avg;
|
||||
}
|
||||
|
||||
double _gethHealthDataPointValueSum(HealthDataType dataType) {
|
||||
double value = 0;
|
||||
_healthDataList.forEach((dataPoint) {
|
||||
if (dataPoint.type == dataType) {
|
||||
value += dataPoint.value;
|
||||
}
|
||||
});
|
||||
return value;
|
||||
}
|
||||
|
||||
double _gethHealthDataPointValueMax(HealthDataType dataType) {
|
||||
double max = 0;
|
||||
_healthDataList.forEach((dataPoint) {
|
||||
if (dataPoint.type == dataType) {
|
||||
if (max < dataPoint.value) {
|
||||
max = dataPoint.value;
|
||||
}
|
||||
}
|
||||
});
|
||||
return max;
|
||||
}
|
||||
|
||||
double _gethHealthDataPointValueMin(HealthDataType dataType) {
|
||||
double min = 9999999;
|
||||
_healthDataList.forEach((dataPoint) {
|
||||
if (dataPoint.type == dataType) {
|
||||
if (min > dataPoint.value && dataPoint.value != 0) {
|
||||
min = dataPoint.value;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (min == 9999999) {
|
||||
min = 0;
|
||||
}
|
||||
return min;
|
||||
}
|
||||
|
||||
Future<void> _fetchHealthData() async {
|
||||
if (health == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
print("Get Health data between " + startTime.toString() + " AND " + endTime.toString());
|
||||
_healthDataList = await health.getHealthDataFromTypes(this.startTime, this.endTime, types);
|
||||
_healthDataList.forEach((element) {
|
||||
print(element.toString());
|
||||
});
|
||||
} on Exception catch (e) {
|
||||
print("Caught exception in getHealthDataFromTypes: $e");
|
||||
throw Exception(e);
|
||||
}
|
||||
}
|
||||
|
||||
double calculate1RM({double percent}) {
|
||||
if (exerciseRepository.exercise == null) {
|
||||
exerciseRepository.getLastExercise();
|
||||
}
|
||||
double weight = exerciseRepository.exercise.unitQuantity;
|
||||
double repeat = exerciseRepository.exercise.quantity;
|
||||
if (weight == 0 || repeat == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
double rmWendler = weight * repeat * 0.0333 + weight;
|
||||
double rmOconner = weight * (1 + repeat / 40);
|
||||
double average = (rmWendler + rmOconner) / 2;
|
||||
|
||||
return average * percent;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
part of 'result_bloc.dart';
|
||||
|
||||
abstract class ResultEvent extends Equatable {
|
||||
const ResultEvent();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class ResultLoad extends ResultEvent {
|
||||
const ResultLoad();
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
part of 'result_bloc.dart';
|
||||
|
||||
abstract class ResultState extends Equatable {
|
||||
const ResultState();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class ResultInitial extends ResultState {
|
||||
const ResultInitial();
|
||||
}
|
||||
|
||||
class ResultLoading extends ResultState {
|
||||
const ResultLoading();
|
||||
}
|
||||
|
||||
class ResultReady extends ResultState {
|
||||
const ResultReady();
|
||||
}
|
||||
|
||||
class ResultError extends ResultState {
|
||||
final String error;
|
||||
const ResultError({this.error});
|
||||
|
||||
@override
|
||||
List<Object> get props => [this.error];
|
||||
}
|
||||
Reference in New Issue
Block a user