import 'dart:async'; import 'package:aitrainer_app/bloc/timer/timer_bloc.dart'; import 'package:aitrainer_app/model/exercise.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:meta/meta.dart'; part 'exercise_control_event.dart'; part 'exercise_control_state.dart'; enum ExerciseTypeLocal { oneRepMax, endurance } extension ExerciseTypeLocalExt on ExerciseTypeLocal { String toStr() => this.toString().split(".").last; bool equalsTo(ExerciseTypeLocal type) => this.toString() == type.toString(); bool equalsStringTo(String type) => this.toStr() == type; } class ExerciseControlBloc extends Bloc { final TimerBloc timerBloc; final ExerciseRepository exerciseRepository; final bool readonly; int step = 1; late double initialRM; late double unitQuantity; late double quantity; late double oneRepQuantity; late double oneRepUnitQuantity; double? firstQuantity; // quantity of the first test double? firstUnitQuantity; // unit quantity of the first test double scrollOffset = 0; late ExerciseTypeLocal exerciseTypeLocal; List controlList = []; @override ExerciseControlBloc({required this.exerciseRepository, required this.readonly, required this.timerBloc}) : super(ExerciseControlInitial()) { print("Exercise ${exerciseRepository.exercise!.toJson()}"); exerciseTypeLocal = ExerciseTypeLocal.oneRepMax; oneRepQuantity = exerciseRepository.exercise!.quantity!; if (oneRepQuantity > 25) { exerciseTypeLocal = ExerciseTypeLocal.endurance; } oneRepUnitQuantity = exerciseRepository.exercise!.unitQuantity!; initialRM = this.calculate1RM(percent75: false); unitQuantity = this.calculate1RM(percent75: true).roundToDouble(); quantity = 12; if (oneRepQuantity > 25) { quantity = 35; } exerciseRepository.setUnitQuantity(unitQuantity); exerciseRepository.setQuantity(quantity); for (int i = 0; i < 3; i++) { Exercise exercise = Exercise(); exercise.quantity = quantity; exercise.unitQuantity = unitQuantity; controlList.add(exercise); } timerBloc.add(TimerStart(duration: 300)); } @override Stream mapEventToState(ExerciseControlEvent event) async* { try { if (event is ExerciseControlQuantityChange) { if (event.step == step) { exerciseRepository.setQuantity(event.quantity); quantity = event.quantity; controlList[step - 1].quantity = quantity; } } else if (event is ExerciseControlUnitQuantityChange) { yield ExerciseControlLoading(); print("event step ${event.step} quantity ${event.quantity}"); if (event.step == step) { this.unitQuantity = event.quantity; exerciseRepository.setUnitQuantity(event.quantity); unitQuantity = event.quantity; quantity = calculateQuantityByUnitQuantity().toDouble(); exerciseRepository.setQuantity(quantity); controlList[step - 1].unitQuantity = event.quantity; controlList[step - 1].quantity = quantity; } yield ExerciseControlReady(); } else if (event is ExerciseControlSubmit) { yield ExerciseControlLoading(); if (event.step == step) { step++; scrollOffset = step * 400.0; if (exerciseRepository.exercise!.quantity == null) { exerciseRepository.setQuantity(quantity); } exerciseRepository.end = DateTime.now(); await exerciseRepository.addExercise(); step <= 3 ? timerBloc.add(TimerStart(duration: 300)) : timerBloc.add(TimerEnd(duration: 300)); } yield ExerciseControlReady(); } } on Exception catch (e) { yield ExerciseControlError(message: e.toString()); } } double calculate1RM({bool percent75 = true}) { 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); print("Weight: $weight repeat: $repeat, $rmWendler, Oconner: $rmOconner"); double average = (rmWendler + rmOconner) / 2; double serieQuantity = 0.75; if (exerciseTypeLocal.equalsTo(ExerciseTypeLocal.endurance)) { serieQuantity = 0.5; } return percent75 ? average * serieQuantity : average; } int calculateQuantityByUnitQuantity() { double weight = oneRepUnitQuantity; double repeat = oneRepQuantity; final double rmWendler = weight * repeat * 0.0333 + weight; final double rmOconner = weight * (1 + repeat / 40); print("Weight: $weight oneRepQuantity: $repeat, $rmWendler, Oconner: $rmOconner"); weight = exerciseRepository.exercise!.unitQuantity!; repeat = exerciseRepository.exercise!.quantity!; final double repeatWendler = (rmWendler - weight) / 0.0333 / weight; final double repeatOconner = (rmOconner / weight - 1) * 40; final newRepeat = ((repeatOconner + repeatWendler) / 2).ceil(); print("Initial 1RM: $initialRM Weight: $weight repeatWendler: $repeatWendler repeat Oconner: $repeatOconner. NEW REPEAT: $newRepeat"); return newRepeat; } }