WT 1.1.25 Training Plan Exercise Alternatives

This commit is contained in:
bossanyit
2021-12-18 18:03:52 +01:00
parent 54a61fa585
commit 05cace39bf
15 changed files with 297 additions and 734 deletions
+192 -143
View File
@@ -1,3 +1,5 @@
import 'dart:collection';
import 'package:aitrainer_app/main.dart';
import 'package:aitrainer_app/bloc/menu/menu_bloc.dart';
import 'package:aitrainer_app/model/cache.dart';
@@ -29,9 +31,12 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
final TrainingPlanRepository trainingPlanRepository;
final MenuBloc menuBloc;
TrainingPlanBloc({required this.trainingPlanRepository, required this.menuBloc}) : super(TrainingPlanInitial()) {
on<TrainingPlanCreateException>(_onCreateException);
on<TrainingPlanActivate>(_onActivate);
on<TrainingPlanWeightChangeRecalculate>(_onWeightChangeRecalculate);
on<TrainingPlanSaveExercise>(_onSaveExercise);
on<TrainingPlanAlternateChange>(_onChangeAlternate);
on<TrainingPlanSkipExercise>(_onSkipExercise);
on<TrainingPlanSkipEntireExercise>(_onSkipEntireExercise);
on<TrainingPlanFinishDropset>(_onFinishDropSet);
@@ -44,6 +49,7 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
on<TrainingPlanSetChange>(_onCustomPlanSetChange);
on<TrainingPlanRepeatsChange>(_onCustomPlanRepeatChange);
on<TrainingPlanAddExerciseType>(_onCustomPlanAddExerciseType);
on<TrainingPlanGoToRestart>(_onRestarting);
// on<TrainingPlanError>(_onTrainingPlanError);
}
@@ -72,6 +78,9 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
CustomerTrainingPlanDetails? getMyDetail() => this._myDetail;
setMyDetail(CustomerTrainingPlanDetails? value) => this._myDetail = value;
HashMap<int, List<CustomerTrainingPlanDetails>> _alternatives = HashMap();
get alternatives => this._alternatives;
/// _onActivate
/// activating the training plan, calculating the weights to the given repeats
/// from previous exercises
@@ -81,6 +90,7 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
emit(TrainingPlanLoading());
_myPlan = trainingPlanRepository.activateTrainingPlan(event.trainingPlanId);
_myPlan!.type = CustomerTrainingPlanType.template;
this.createAlternatives();
menuBloc.menuTreeRepository.sortedTree.forEach((name, list) {
final List<WorkoutMenuTree> menuList = list as List<WorkoutMenuTree>;
@@ -129,82 +139,129 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
/// event: TrainingPlanWeightChange
void _onSaveExercise(TrainingPlanSaveExercise event, Emitter<TrainingPlanState> emit) async {
emit(TrainingPlanLoading());
if (event.detail.repeats == -1) {
emit(TrainingPlanReady());
throw Exception("Please type your repeats!");
}
print("SAVE for ExerciseTypeID: ${event.detail.exerciseTypeId} weight: ${event.detail.weight}");
if (event.detail.weight == -3) {
print("DropSet");
event.detail.state = ExercisePlanDetailState.finished;
emit(TrainingPlanReady());
} else {
final Exercise exercise = Exercise();
exercise.customerId = Cache().userLoggedIn!.customerId!;
exercise.exerciseTypeId = event.detail.exerciseTypeId;
exercise.quantity = event.detail.repeats!.toDouble();
exercise.unit = event.detail.exerciseType!.unit;
exercise.unitQuantity = event.detail.weight;
exercise.dateAdd = DateTime.now();
event.detail.exercises.add(exercise);
if (this.isAllDetailsSameExerciseFinished(event.detail)) {
event.detail.state = ExercisePlanDetailState.finished;
try {
if (event.detail.repeats == -1) {
emit(TrainingPlanReady());
throw Exception("Please type your repeats!");
}
print("SAVE for ExerciseTypeID: ${event.detail.exerciseTypeId} weight: ${event.detail.weight}");
if (event.detail.weight == -3) {
print("DropSet");
event.detail.state = ExercisePlanDetailState.finished;
emit(TrainingPlanReady());
} else {
final Exercise exercise = Exercise();
exercise.customerId = Cache().userLoggedIn!.customerId!;
exercise.exerciseTypeId = event.detail.exerciseTypeId;
exercise.quantity = event.detail.repeats!.toDouble();
exercise.unit = event.detail.exerciseType!.unit;
exercise.unitQuantity = event.detail.weight;
exercise.dateAdd = DateTime.now();
event.detail.exercises.add(exercise);
if (this.isAllDetailsSameExerciseFinished(event.detail)) {
event.detail.state = ExercisePlanDetailState.finished;
}
// recalculate the weight to the original planned repeats for the next details
int id = 0;
if (exercise.unitQuantity != null && exercise.unitQuantity! > 0) {
for (var nextDetail in _myPlan!.details) {
if (nextDetail.exerciseTypeId == event.detail.exerciseTypeId) {
if (id == 0 && nextDetail.customerTrainingPlanDetailsId == event.detail.customerTrainingPlanDetailsId) {
id = nextDetail.customerTrainingPlanDetailsId!;
}
double weightFromPlan = trainingPlanRepository.getOriginalWeight(this.getMyPlan()!.trainingPlanId!, nextDetail);
print("NextDetail detail: $nextDetail *** PlanWeight: $weightFromPlan");
if (nextDetail.weight == -2 && nextDetail.customerTrainingPlanDetailsId != event.detail.customerTrainingPlanDetailsId) {
print("Nr 1. - recalculating -2 ${event.detail.customerTrainingPlanDetailsId}");
trainingPlanRepository.recalculateDetail(_myPlan!.trainingPlanId!, event.detail, nextDetail);
nextDetail.baseOneRepMax = Common.calculate1RM(nextDetail.weight!, nextDetail.repeats!.toDouble());
} else if (weightFromPlan == -1 && nextDetail.set! > 1 && nextDetail.exercises.length == 1) {
print("Nr 2. recalculating -1 ${event.detail.customerTrainingPlanDetailsId}");
nextDetail = trainingPlanRepository.recalculateDetailFixRepeats(_myPlan!.trainingPlanId!, nextDetail);
nextDetail.baseOneRepMax = Common.calculate1RM(nextDetail.weight!, nextDetail.repeats!.toDouble());
} else if (nextDetail.weight == -1 && nextDetail.set! == 1) {
print("Nr 3. recalculating -1, set 1 ${event.detail.customerTrainingPlanDetailsId}");
nextDetail = trainingPlanRepository.recalculateDetailFixRepeatsSet1(_myPlan!.trainingPlanId!, nextDetail, event.detail);
nextDetail.baseOneRepMax = Common.calculate1RM(nextDetail.weight!, nextDetail.repeats!.toDouble());
} else if (event.detail.set! == 1 &&
(weightFromPlan == -2 || weightFromPlan == -1) &&
nextDetail.customerTrainingPlanDetailsId! > id) {
print("Nr 4. recalculating after the first exercise ${event.detail.customerTrainingPlanDetailsId}");
nextDetail = trainingPlanRepository.recalculateDetailFixRepeatsSet1(_myPlan!.trainingPlanId!, nextDetail, event.detail);
nextDetail.baseOneRepMax = Common.calculate1RM(nextDetail.weight!, nextDetail.repeats!.toDouble());
// recalculate the weight to the original planned repeats for the next details
int id = 0;
if (exercise.unitQuantity != null && exercise.unitQuantity! > 0) {
double calculatedWeight = 0;
for (var nextDetail in _myPlan!.details) {
if (nextDetail.exerciseTypeId == event.detail.exerciseTypeId) {
if (id == 0 && nextDetail.customerTrainingPlanDetailsId == event.detail.customerTrainingPlanDetailsId) {
id = nextDetail.customerTrainingPlanDetailsId!;
}
double weightFromPlan = trainingPlanRepository.getOriginalWeight(this.getMyPlan()!.trainingPlanId!, nextDetail);
print("NextDetail detail: $nextDetail *** PlanWeight: $weightFromPlan");
if (nextDetail.weight == -2 && nextDetail.customerTrainingPlanDetailsId != event.detail.customerTrainingPlanDetailsId) {
print("Nr 1. - recalculating -2 ${event.detail.customerTrainingPlanDetailsId}");
trainingPlanRepository.recalculateDetail(_myPlan!.trainingPlanId!, event.detail, nextDetail);
nextDetail.baseOneRepMax = Common.calculate1RM(nextDetail.weight!, nextDetail.repeats!.toDouble());
} else if (weightFromPlan == -1 && nextDetail.set! > 1 && nextDetail.exercises.length == 1) {
print("Nr 2. recalculating -1 ${event.detail.customerTrainingPlanDetailsId}");
nextDetail = trainingPlanRepository.recalculateDetailFixRepeats(_myPlan!.trainingPlanId!, nextDetail);
nextDetail.baseOneRepMax = Common.calculate1RM(nextDetail.weight!, nextDetail.repeats!.toDouble());
} else if (nextDetail.weight == -1 && nextDetail.set! == 1) {
print("Nr 3. recalculating -1, set 1 ${event.detail.customerTrainingPlanDetailsId}");
nextDetail = trainingPlanRepository.recalculateDetailFixRepeatsSet1(_myPlan!.trainingPlanId!, nextDetail, event.detail);
nextDetail.baseOneRepMax = Common.calculate1RM(nextDetail.weight!, nextDetail.repeats!.toDouble());
} else if (event.detail.set! == 1 &&
(weightFromPlan == -2 || weightFromPlan == -1) &&
nextDetail.customerTrainingPlanDetailsId! == id + 1) {
print("Nr 4. recalculating after the first exercise ${event.detail.customerTrainingPlanDetailsId}");
nextDetail = trainingPlanRepository.recalculateDetailFixRepeatsSet1(_myPlan!.trainingPlanId!, nextDetail, event.detail);
nextDetail.baseOneRepMax = Common.calculate1RM(nextDetail.weight!, nextDetail.repeats!.toDouble());
calculatedWeight = nextDetail.weight!;
} else if (event.detail.set! == 1 &&
(weightFromPlan == -2 || weightFromPlan == -1) &&
nextDetail.customerTrainingPlanDetailsId! > id + 1) {
print("Nr 5. recalculating after the second exercise ${event.detail.customerTrainingPlanDetailsId}");
nextDetail.weight = calculatedWeight;
}
}
}
}
exercise.trainingPlanDetailsId = _myPlan!.trainingPlanId;
// save Exercise
Exercise savedExercise = await ExerciseApi().addExercise(exercise);
Cache().addExercise(savedExercise);
Cache().myTrainingPlan = _myPlan;
await Cache().saveMyTrainingPlan();
}
exercise.trainingPlanDetailsId = _myPlan!.trainingPlanId;
if (!isInDebugMode) {
CustomerRepository customerRepository = CustomerRepository();
customerRepository.customer = Cache().userLoggedIn;
MauticRepository mauticRepository = MauticRepository(customerRepository: customerRepository);
await mauticRepository.sendMauticExercise();
}
Track().track(TrackingEvent.training_plan_execute, eventValue: event.detail.exerciseType!.name);
// save Exercise
Exercise savedExercise = await ExerciseApi().addExercise(exercise);
Cache().addExercise(savedExercise);
Cache().myTrainingPlan = _myPlan;
await Cache().saveMyTrainingPlan();
if (isDayDone()) {
this.add(TrainingPlanFinishDay());
} else {
emit(TrainingPlanReady());
}
} on Exception catch (e) {
emit(TrainingPlanError(message: e.toString()));
}
if (!isInDebugMode) {
CustomerRepository customerRepository = CustomerRepository();
customerRepository.customer = Cache().userLoggedIn;
MauticRepository mauticRepository = MauticRepository(customerRepository: customerRepository);
await mauticRepository.sendMauticExercise();
}
Track().track(TrackingEvent.training_plan_execute, eventValue: event.detail.exerciseType!.name);
}
if (isDayDone()) {
this.add(TrainingPlanFinishDay());
} else {
void _onChangeAlternate(TrainingPlanAlternateChange event, Emitter<TrainingPlanState> emit) {
emit(TrainingPlanLoading());
if (_myPlan == null || _myPlan!.details.length == 0) {
emit(TrainingPlanReady());
return;
}
int index = 0;
for (var planDetail in _myPlan!.details) {
int key = planDetail.customerTrainingPlanDetailsId!;
if (_alternatives[key]!.length >= event.index + 1 && _alternatives[key]![event.index].exerciseTypeId == event.detail.exerciseTypeId) {
CustomerTrainingPlanDetails alternative = _alternatives[key]![event.index];
_myPlan!.details[index] = alternative;
changeExerciseInDayNames(planDetail.exerciseTypeId!, planDetail.day!, alternative);
print("Changed alternative $alternative");
}
index++;
}
emit(TrainingPlanReady());
}
void changeExerciseInDayNames(int exerciseTypeId, String dayName, CustomerTrainingPlanDetails alternative) {
if (_myPlan != null && _myPlan!.days[dayName] != null) {
int index = 0;
for (var detail in _myPlan!.days[dayName]!) {
if (detail.exerciseTypeId == exerciseTypeId) {
_myPlan!.days[dayName]![index] = alternative;
}
index++;
}
}
}
@@ -333,90 +390,80 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
}
emit(TrainingPlanLoading());
_myDetail!.exerciseType!.trainingPlanState = ExerciseTypeTrainingPlanState.added;
_myDetail!.customerTrainingPlanDetailsId = _myPlan!.details.length + 1;
_myPlan!.details.add(this._myDetail!);
emit(TrainingPlanReady());
}
/*
@override
Stream<TrainingPlanState> mapEventToState(TrainingPlanEvent event) async* {
try {
if (event is TrainingPlanActivate) {
} else if (event is TrainingPlanWeightChange) {
} else if (event is TrainingPlanWeightChangeRecalculate) {
} else if (event is TrainingPlanRepeatsChange) {
} else if (event is TrainingPlanSetChange) {
} else if (event is TrainingPlanSaveExercise) {
} else if (event is TrainingPlanSkipExercise) {
} else if (event is TrainingPlanSkipEntireExercise) {
} else if (event is TrainingPlanFinishDay) {
} else if (event is TrainingPlanGoToRestart) {
yield TrainingPlanLoading();
restarting = true;
yield TrainingPlanDayReadyToRestart();
} else if (event is TrainingPlanAddExerciseType) {
} else if (event is TrainingPlanDeleteExerciseType) {
} else if (event is TrainingPlanCustomAddLoad) {
} else if (event is TrainingPlanChangeCancel) {
} else if (event is TrainingPlanFinishDropset) {
}
} on Exception catch (e) {
yield TrainingPlanError(message: e.toString());
}
} */
CustomerTrainingPlanDetails? createDetailFromExerciseType(ExerciseType exerciseType, CustomerTrainingPlanDetails origDetail) {
List<CustomerTrainingPlanDetails> list = [];
int index = 0;
TrainingPlanDetail? trainingPlanDetail;
if (_myTrainingPlan == null) {
setTrainingPlanFromCache();
void _onRestarting(TrainingPlanGoToRestart event, Emitter<TrainingPlanState> emit) async {
emit(TrainingPlanLoading());
restarting = true;
emit(TrainingPlanDayReadyToRestart());
}
void _onCreateException(TrainingPlanCreateException event, Emitter<TrainingPlanState> emit) async {
emit(TrainingPlanLoading());
print("Bloc execption caught: ${event.message}");
emit(TrainingPlanError(message: event.message));
}
/* ***************************************************
* Helper Functions
******************************************************/
void createAlternatives() {
if (_myPlan == null || _myPlan!.details.length == 0 || _myPlan!.trainingPlanId == null) {
return;
}
for (var planDetail in _myTrainingPlan!.details!) {
if (planDetail.exerciseTypeId == origDetail.exerciseTypeId!) {
trainingPlanDetail = planDetail;
_alternatives.clear();
TrainingPlanDetail? trainingPlanDetail;
_myTrainingPlan = trainingPlanRepository.getTrainingPlanById(_myPlan!.trainingPlanId!);
_myPlan!.details.forEach((detail) {
if (detail.alternatives.length > 0) {
detail.alternatives.forEach((alternative) {
if (_myTrainingPlan != null) {
for (var planDetail in _myTrainingPlan!.details!) {
if (planDetail.exerciseTypeId == detail.exerciseTypeId!) {
trainingPlanDetail = planDetail;
CustomerTrainingPlanDetails alternativeDetail =
trainingPlanRepository.createAlternativeDetail(_myPlan!, detail, trainingPlanDetail!, alternative.exerciseTypeId);
if (_alternatives[alternativeDetail.customerTrainingPlanDetailsId!] == null) {
_alternatives[alternativeDetail.customerTrainingPlanDetailsId!] = [];
_alternatives[detail.customerTrainingPlanDetailsId!]!.add(detail); // element zero
}
if (!existsAlternativeExercise(detail.customerTrainingPlanDetailsId!, alternativeDetail)) {
_alternatives[alternativeDetail.customerTrainingPlanDetailsId!]!.add(alternativeDetail);
}
}
}
} else {
if (_alternatives[detail.customerTrainingPlanDetailsId!] == null) {
_alternatives[detail.customerTrainingPlanDetailsId!] = [];
_alternatives[detail.customerTrainingPlanDetailsId!]!.add(detail); // element zero
}
}
});
} else {
if (_alternatives[detail.customerTrainingPlanDetailsId!] == null) {
_alternatives[detail.customerTrainingPlanDetailsId!] = [];
}
_alternatives[detail.customerTrainingPlanDetailsId!]!.add(detail);
}
print(
"Created alternaties for ${detail.exerciseTypeId} and repeat ${detail.repeats} -- ${_alternatives[detail.customerTrainingPlanDetailsId!]}");
});
}
bool existsAlternativeExercise(int customerTrainingPlanDetailsId, CustomerTrainingPlanDetails alternative) {
bool exists = false;
for (var actual in _alternatives[customerTrainingPlanDetailsId]!) {
if (actual.exerciseTypeId == alternative.exerciseTypeId) {
exists = true;
break;
}
index++;
}
if (trainingPlanDetail != null) {
list =
trainingPlanRepository.createDetail(_myPlan!, trainingPlanDetail, exerciseType.exerciseTypeId, index, changeExerciseType: true);
List<int> deleteIndicies = [];
index = 0;
_myPlan!.details.forEach((element) {
if (element.exerciseTypeId == origDetail.exerciseTypeId) {
deleteIndicies.add(index);
}
index++;
});
index = 0;
deleteIndicies.forEach((i) {
_myPlan!.details.removeAt(i - index);
index++;
});
_myPlan!.details.insertAll(deleteIndicies[0], list);
}
if (list.length > 0) {
return list[0];
} else {
return null;
}
return exists;
}
void backupDetail(CustomerTrainingPlanDetails detail) {
@@ -484,7 +531,7 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
}
if (isDone100Percent()) {
//this.add(TrainingPlanGoToRestart());
this.add(TrainingPlanGoToRestart());
print("---------------- TrainingPlanGoToRestart");
}
dayNames.clear();
@@ -519,6 +566,8 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
_myPlan!.days[dayName]!.addAll(_myPlan!.details);
}
getActiveDayIndex();
createAlternatives();
}
void activateTrainingPlanDays() {
@@ -820,7 +869,7 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
if (activeDayIndex >= dayNames.length) {
activeDayIndex = 0;
//this.add(TrainingPlanGoToRestart());
this.add(TrainingPlanGoToRestart());
print("---------------- TrainingPlanGoToRestart");
}
print("ActiveDayIndex $activeDayIndex");
+11 -19
View File
@@ -28,22 +28,6 @@ class TrainingPlanWeightChange extends TrainingPlanEvent {
List<Object> get props => [weight, detail];
}
class TrainingPlanWeightChangeUp extends TrainingPlanEvent {
final CustomerTrainingPlanDetails detail;
const TrainingPlanWeightChangeUp({required this.detail});
@override
List<Object> get props => [detail];
}
class TrainingPlanWeightChangeDown extends TrainingPlanEvent {
final CustomerTrainingPlanDetails detail;
const TrainingPlanWeightChangeDown({required this.detail});
@override
List<Object> get props => [detail];
}
class TrainingPlanWeightChangeRecalculate extends TrainingPlanEvent {
final CustomerTrainingPlanDetails detail;
final double weight;
@@ -121,11 +105,11 @@ class TrainingPlanChangeCancel extends TrainingPlanEvent {
class TrainingPlanAlternateChange extends TrainingPlanEvent {
final int index;
final ExerciseType exerciseType;
const TrainingPlanAlternateChange({required this.index, required this.exerciseType});
final CustomerTrainingPlanDetails detail;
const TrainingPlanAlternateChange({required this.index, required this.detail});
@override
List<Object> get props => [index, exerciseType];
List<Object> get props => [index, detail];
}
class TrainingPlanFinishDropset extends TrainingPlanEvent {
@@ -151,3 +135,11 @@ class TrainingPlanDeleteExerciseType extends TrainingPlanEvent {
@override
List<Object> get props => [exerciseType];
}
class TrainingPlanCreateException extends TrainingPlanEvent {
final String message;
const TrainingPlanCreateException({required this.message});
@override
List<Object> get props => [message];
}