import 'dart:async'; 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:aitrainer_app/service/logging.dart'; import 'package:aitrainer_app/util/trans.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:health/health.dart'; part 'result_event.dart'; part 'result_state.dart'; class ResultBloc extends Bloc with Logging, Trans { final ExerciseResultRepository resultRepository; final ExerciseRepository exerciseRepository; final BuildContext context; //List _healthDataList = List(); DateTime startTime; DateTime endTime; /* final HealthFactory health = HealthFactory(); final List 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, this.context}) : super(ResultInitial()) { this.startTime = exerciseRepository.start; this.endTime = exerciseRepository.end; if (this.startTime == null) { this.startTime = exerciseRepository.exercise.dateAdd; exerciseRepository.start = exerciseRepository.exercise.dateAdd; } } @override Stream mapEventToState( ResultEvent event, ) async* { try { if (event is ResultLoad) { yield ResultLoading(); //await _fetchHealthData(); _matchExerciseData(); await resultRepository.saveExerciseResults(); yield ResultReady(); } } on Exception catch (ex) { yield ResultError(error: ex.toString()); } } void _matchExerciseData() { resultRepository.getResults().forEach((element) { element.dateFrom = startTime; element.dateTo = endTime; element.exerciseId = exerciseRepository.actualExerciseList[0].exerciseId; switch (element.item) { case ResultItem.bpm_avg: //element.data = _gethHealthDataPointValueAvg(HealthDataType.HEART_RATE); break; case ResultItem.bpm_min: //element.data = element.data = _gethHealthDataPointValueMin(HealthDataType.HEART_RATE); break; case ResultItem.bpm_max: //element.data = element.data = _gethHealthDataPointValueMax(HealthDataType.HEART_RATE); break; case ResultItem.calorie: //element.data = _gethHealthDataPointValueSum(HealthDataType.ACTIVE_ENERGY_BURNED); break; case ResultItem.development_percent_bodypart: // TODO: Handle this case. break; case ResultItem.distance: if (exerciseRepository.exerciseType.unit == "meter") { element.data = exerciseRepository.exercise.quantity; } 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); } 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((actual) { value += actual.quantity; }); element.data = value; } break; case ResultItem.steps: element.data = 0; //_gethHealthDataPointValueSum(HealthDataType.STEPS); 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((actual) { value += actual.quantity * actual.unitQuantity; }); element.data = value; } break; } }); } String printDuration(Duration duration, {isText = false, isDecimal = false}) { 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(); if (isText) { if (isDecimal) { return "$twoDigitMinutes" + t("min") + "$twoDigitSeconds" + t("sec") + ":$twoDigitMilliSeconds" + '"'; } else { return "$twoDigitMinutes" + t("min") + "$twoDigitSeconds" + t("sec"); } } else { return "$twoDigitMinutes:$twoDigitSeconds:$twoDigitMilliSeconds" + '"'; } } String printTime(double duration) { String twoDigits(int n) => n.toString().padLeft(1, "0"); String twoDigitMinutes = twoDigits((duration ~/ 60).toInt()); String twoDigitSeconds = (duration % 60).toStringAsFixed(0); return "$twoDigitMinutes " + t("minutes") + " $twoDigitSeconds"; } /* 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 _fetchHealthData() async { if (health == null) { return; } try { log("Get Health data between " + startTime.toString() + " AND " + endTime.toString()); _healthDataList = await health.getHealthDataFromTypes(this.startTime, this.endTime, types); _healthDataList.forEach((element) { log(element.toString()); }); } on Exception catch (e) { log("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; } }