WT1.1.8+3 custom plan and training plan fixes
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import 'dart:async';
|
||||
import 'package:aitrainer_app/model/cache.dart';
|
||||
import 'package:aitrainer_app/model/exercise_plan_detail.dart';
|
||||
import 'package:aitrainer_app/model/model_change.dart';
|
||||
import 'package:aitrainer_app/model/workout_menu_tree.dart';
|
||||
@@ -29,6 +30,7 @@ class ExercisePlanBloc extends Bloc<ExercisePlanEvent, ExercisePlanState> {
|
||||
menuTreeRepository.sortByMuscleType();
|
||||
|
||||
menuTreeRepository.sortedTree.forEach((key, value) {
|
||||
print("menutree $key");
|
||||
List<WorkoutMenuTree> listWorkoutTree = value;
|
||||
listWorkoutTree.forEach((workoutTree) {
|
||||
workoutTree.selected = false;
|
||||
@@ -48,9 +50,13 @@ class ExercisePlanBloc extends Bloc<ExercisePlanEvent, ExercisePlanState> {
|
||||
Stream<ExercisePlanState> mapEventToState(ExercisePlanEvent event) async* {
|
||||
try {
|
||||
if (event is ExercisePlanLoad) {
|
||||
if (Cache().userLoggedIn == null || Cache().userLoggedIn!.customerId == null) {
|
||||
throw Exception("Please log in");
|
||||
}
|
||||
yield ExercisePlanLoading();
|
||||
Track().track(TrackingEvent.my_custom_exercise_plan);
|
||||
customerId = Cache().userLoggedIn!.customerId!;
|
||||
await this.getData();
|
||||
Track().track(TrackingEvent.my_custom_exercise_plan);
|
||||
yield ExercisePlanReady();
|
||||
}
|
||||
|
||||
|
||||
@@ -6,11 +6,15 @@ import 'package:aitrainer_app/model/customer_training_plan.dart';
|
||||
import 'package:aitrainer_app/model/customer_training_plan_details.dart';
|
||||
import 'package:aitrainer_app/model/exercise.dart';
|
||||
import 'package:aitrainer_app/model/exercise_plan_detail.dart';
|
||||
import 'package:aitrainer_app/model/exercise_type.dart';
|
||||
import 'package:aitrainer_app/model/workout_menu_tree.dart';
|
||||
import 'package:aitrainer_app/repository/training_plan_repository.dart';
|
||||
import 'package:aitrainer_app/service/exercise_service.dart';
|
||||
import 'package:aitrainer_app/util/app_language.dart';
|
||||
import 'package:aitrainer_app/util/enums.dart';
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
part 'training_plan_event.dart';
|
||||
part 'training_plan_state.dart';
|
||||
@@ -21,18 +25,34 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
|
||||
TrainingPlanBloc({required this.trainingPlanRepository, required this.menuBloc}) : super(TrainingPlanInitial());
|
||||
|
||||
CustomerTrainingPlan? _myPlan;
|
||||
CustomerTrainingPlanDetails? _myDetail;
|
||||
|
||||
bool started = false;
|
||||
final List<String> dayNames = [];
|
||||
bool restarting = false;
|
||||
bool celebrating = false;
|
||||
int activeDayIndex = 0;
|
||||
|
||||
CustomerTrainingPlan? getMyPlan() => this._myPlan;
|
||||
setMyPlan(CustomerTrainingPlan? myPlan) => this._myPlan = myPlan;
|
||||
|
||||
CustomerTrainingPlanDetails? getMyDetail() => this._myDetail;
|
||||
setMyDetail(CustomerTrainingPlanDetails? value) => this._myDetail = value;
|
||||
|
||||
@override
|
||||
Stream<TrainingPlanState> mapEventToState(TrainingPlanEvent event) async* {
|
||||
try {
|
||||
if (event is TrainingPlanActivate) {
|
||||
yield TrainingPlanLoading();
|
||||
_myPlan = await trainingPlanRepository.activateTrainingPlan(event.trainingPlanId);
|
||||
_myPlan!.type = CustomerTrainingPlanType.template;
|
||||
|
||||
menuBloc.menuTreeRepository.sortedTree.forEach((name, list) {
|
||||
final List<WorkoutMenuTree> menuList = list as List<WorkoutMenuTree>;
|
||||
menuList.forEach((element) {
|
||||
element.exerciseType!.trainingPlanState = ExerciseTypeTrainingPlanState.none;
|
||||
});
|
||||
});
|
||||
this.activateDays();
|
||||
Cache().myTrainingPlan = _myPlan;
|
||||
await Cache().saveMyTrainingPlan();
|
||||
@@ -47,6 +67,12 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
|
||||
|
||||
event.detail.repeats = event.repeats;
|
||||
|
||||
yield TrainingPlanReady();
|
||||
} else if (event is TrainingPlanSetChange) {
|
||||
yield TrainingPlanLoading();
|
||||
|
||||
event.detail.set = event.set;
|
||||
|
||||
yield TrainingPlanReady();
|
||||
} else if (event is TrainingPlanSaveExercise) {
|
||||
yield TrainingPlanLoading();
|
||||
@@ -74,12 +100,76 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
|
||||
|
||||
Cache().myTrainingPlan = _myPlan;
|
||||
await Cache().saveMyTrainingPlan();
|
||||
yield TrainingPlanReady();
|
||||
|
||||
if (isDayDone()) {
|
||||
this.add(TrainingPlanFinishDay());
|
||||
} else {
|
||||
yield TrainingPlanReady();
|
||||
}
|
||||
} else if (event is TrainingPlanSkipExercise) {
|
||||
yield TrainingPlanLoading();
|
||||
print("Skipping ${event.detail.exerciseTypeId}");
|
||||
event.detail.state = ExercisePlanDetailState.skipped;
|
||||
Cache().myTrainingPlan = _myPlan;
|
||||
await Cache().saveMyTrainingPlan();
|
||||
if (isDayDone()) {
|
||||
this.add(TrainingPlanFinishDay());
|
||||
} else {
|
||||
yield TrainingPlanReady();
|
||||
}
|
||||
} else if (event is TrainingPlanFinishDay) {
|
||||
yield TrainingPlanLoading();
|
||||
celebrating = true;
|
||||
yield TrainingPlanDayFinished();
|
||||
} else if (event is TrainingPlanGoToRestart) {
|
||||
yield TrainingPlanLoading();
|
||||
restarting = true;
|
||||
yield TrainingPlanDayReadyToRestart();
|
||||
} else if (event is TrainingPlanAddExerciseType) {
|
||||
if (_myDetail == null) {
|
||||
throw Exception("Create new Detail");
|
||||
}
|
||||
yield TrainingPlanLoading();
|
||||
_myDetail!.exerciseType!.trainingPlanState = ExerciseTypeTrainingPlanState.added;
|
||||
_myPlan!.details.add(this._myDetail!);
|
||||
yield TrainingPlanReady();
|
||||
} else if (event is TrainingPlanDeleteExerciseType) {
|
||||
if (_myPlan == null || _myPlan!.details.isEmpty) {
|
||||
throw Exception("No MyPlan");
|
||||
}
|
||||
yield TrainingPlanLoading();
|
||||
CustomerTrainingPlanDetails? remove;
|
||||
for (var detail in _myPlan!.details) {
|
||||
if (event.exerciseType.exerciseTypeId == detail.exerciseTypeId) {
|
||||
remove = detail;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (remove != null) {
|
||||
_myPlan!.details.remove(remove);
|
||||
}
|
||||
event.exerciseType.trainingPlanState = ExerciseTypeTrainingPlanState.none;
|
||||
yield TrainingPlanReady();
|
||||
} else if (event is TrainingPlanCustomAddLoad) {
|
||||
yield TrainingPlanLoading();
|
||||
addNewPlan();
|
||||
|
||||
_myDetail = CustomerTrainingPlanDetails();
|
||||
_myDetail!.exerciseType = event.exerciseType;
|
||||
_myDetail!.exerciseTypeId = event.exerciseType.exerciseTypeId;
|
||||
_myDetail!.repeats = 12;
|
||||
_myDetail!.weight = 30;
|
||||
_myDetail!.set = 3;
|
||||
_myDetail!.parallel = false;
|
||||
_myDetail!.day = "";
|
||||
_myDetail!.restingTime = 2;
|
||||
_myDetail!.state = ExercisePlanDetailState.start;
|
||||
|
||||
if (_myDetail!.exerciseType!.unitQuantityUnit != null) {
|
||||
_myDetail = trainingPlanRepository.getCalculatedWeightRepeats(event.exerciseType.exerciseTypeId, _myDetail!);
|
||||
} else {
|
||||
_myDetail!.weight = 0;
|
||||
}
|
||||
yield TrainingPlanReady();
|
||||
}
|
||||
} on Exception catch (e) {
|
||||
@@ -87,10 +177,51 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
|
||||
}
|
||||
}
|
||||
|
||||
void addNewPlan() {
|
||||
if (_myPlan == null) {
|
||||
_myPlan = CustomerTrainingPlan();
|
||||
} else {
|
||||
if (!_myPlan!.type.equalsTo(CustomerTrainingPlanType.custom)) {
|
||||
_myPlan!.details.clear();
|
||||
}
|
||||
}
|
||||
_myPlan!.trainingPlanId = 0;
|
||||
_myPlan!.name = "Custom";
|
||||
_myPlan!.customerId = Cache().userLoggedIn == null ? Cache().userLoggedIn!.customerId : 0;
|
||||
|
||||
_myPlan!.type = CustomerTrainingPlanType.custom;
|
||||
|
||||
restart();
|
||||
|
||||
print("New custom plan: $_myPlan");
|
||||
}
|
||||
|
||||
void restart() {
|
||||
if (_myPlan == null) {
|
||||
return;
|
||||
}
|
||||
for (var day in dayNames) {
|
||||
_myPlan!.days[day]!.clear();
|
||||
}
|
||||
_myPlan!.details.forEach((element) {
|
||||
element.state = ExercisePlanDetailState.start;
|
||||
element.exercises.clear();
|
||||
});
|
||||
dayNames.clear();
|
||||
Cache().myTrainingPlan = _myPlan;
|
||||
Cache().saveMyTrainingPlan();
|
||||
restarting = false;
|
||||
print("Restarting finished");
|
||||
}
|
||||
|
||||
void activateDays() {
|
||||
if (_myPlan == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isDone100Percent()) {
|
||||
this.add(TrainingPlanGoToRestart());
|
||||
}
|
||||
dayNames.clear();
|
||||
_myPlan!.days.clear();
|
||||
String dayName = ".";
|
||||
@@ -113,6 +244,7 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
|
||||
_myPlan!.days[""] = [];
|
||||
_myPlan!.days[""]!.addAll(_myPlan!.details);
|
||||
}
|
||||
getActiveDayIndex();
|
||||
}
|
||||
|
||||
CustomerTrainingPlanDetails? getTrainingPlanDetail(int trainingPlanDetailsId) {
|
||||
@@ -177,6 +309,7 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
|
||||
}
|
||||
}
|
||||
print("Next detail $next");
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
@@ -192,6 +325,18 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
|
||||
}
|
||||
}
|
||||
|
||||
bool isDayDone() {
|
||||
bool isDone = true;
|
||||
final String day = dayNames[activeDayIndex];
|
||||
for (var detail in _myPlan!.days[day]!) {
|
||||
if (!detail.state.equalsTo(ExercisePlanDetailState.finished) && !detail.state.equalsTo(ExercisePlanDetailState.skipped)) {
|
||||
isDone = false;
|
||||
}
|
||||
}
|
||||
print("Is Day '$day' done: $isDone");
|
||||
return isDone;
|
||||
}
|
||||
|
||||
double getOffset() {
|
||||
double offset = 5;
|
||||
if (_myPlan == null) {
|
||||
@@ -199,7 +344,8 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
|
||||
}
|
||||
int indexInProgress = 0;
|
||||
int indexInStart = 0;
|
||||
for (var detail in _myPlan!.details) {
|
||||
final String day = dayNames[this.activeDayIndex];
|
||||
for (var detail in _myPlan!.days[day]!) {
|
||||
if (detail.state == ExercisePlanDetailState.inProgress) {
|
||||
break;
|
||||
}
|
||||
@@ -213,4 +359,126 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
|
||||
offset = index * 80;
|
||||
return offset;
|
||||
}
|
||||
|
||||
bool isDone100Percent() {
|
||||
bool done = true;
|
||||
if (_myPlan == null || _myPlan!.details.isEmpty) {
|
||||
return false;
|
||||
}
|
||||
_myPlan!.details.forEach((element) {
|
||||
if (!element.state.equalsTo(ExercisePlanDetailState.finished) && !element.state.equalsTo(ExercisePlanDetailState.skipped)) {
|
||||
done = false;
|
||||
}
|
||||
});
|
||||
return done;
|
||||
}
|
||||
|
||||
int getActiveDayIndex() {
|
||||
if (restarting) {
|
||||
return 0;
|
||||
}
|
||||
if (_myPlan == null || _myPlan!.details.isEmpty) {
|
||||
throw Exception("No defined Training Plan");
|
||||
}
|
||||
|
||||
if (dayNames.isEmpty || dayNames.length == 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
activeDayIndex = 0;
|
||||
|
||||
for (var day in dayNames) {
|
||||
if (_myPlan!.days[day] == null) {
|
||||
throw Exception("Wrong activated day: $day does not exist");
|
||||
}
|
||||
bool isDone = true;
|
||||
_myPlan!.days[day]!.forEach((element) {
|
||||
if (!element.state.equalsTo(ExercisePlanDetailState.finished) && !element.state.equalsTo(ExercisePlanDetailState.skipped)) {
|
||||
isDone = false;
|
||||
}
|
||||
});
|
||||
if (!isDone) {
|
||||
break;
|
||||
}
|
||||
activeDayIndex++;
|
||||
}
|
||||
print("Active Day Index: $activeDayIndex");
|
||||
if (activeDayIndex >= dayNames.length) {
|
||||
activeDayIndex = 0;
|
||||
this.add(TrainingPlanGoToRestart());
|
||||
}
|
||||
|
||||
return activeDayIndex;
|
||||
}
|
||||
|
||||
String getCustomAddSummary() {
|
||||
String summary = "";
|
||||
if (_myDetail == null || _myDetail!.set == null || _myDetail!.repeats == null) {
|
||||
return summary;
|
||||
}
|
||||
summary = getMyDetail()!.set!.toStringAsFixed(0) + " x " + getMyDetail()!.repeats!.toStringAsFixed(0);
|
||||
return summary;
|
||||
}
|
||||
|
||||
String getExerciseName(Locale locale) {
|
||||
String exerciseName = "";
|
||||
if (_myDetail == null || _myDetail!.exerciseType == null) {
|
||||
return exerciseName;
|
||||
}
|
||||
exerciseName =
|
||||
AppLanguage().appLocal == Locale("en") ? getMyDetail()!.exerciseType!.name : getMyDetail()!.exerciseType!.nameTranslation;
|
||||
return exerciseName;
|
||||
}
|
||||
|
||||
String getWeightByExerciseType(ExerciseType exerciseType) {
|
||||
double weight = 0;
|
||||
|
||||
if (_myPlan == null || _myPlan!.details.isEmpty) {
|
||||
return weight.toStringAsFixed(0);
|
||||
}
|
||||
|
||||
for (var detail in _myPlan!.details) {
|
||||
if (exerciseType.exerciseTypeId == detail.exerciseTypeId) {
|
||||
weight = detail.weight!;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int decimal = weight % weight.round() == 0 ? 0 : 1;
|
||||
return weight.toStringAsFixed(decimal);
|
||||
}
|
||||
|
||||
String getSetByExerciseType(ExerciseType exerciseType) {
|
||||
int value = 0;
|
||||
|
||||
if (_myPlan == null || _myPlan!.details.isEmpty) {
|
||||
return value.toStringAsFixed(0);
|
||||
}
|
||||
|
||||
for (var detail in _myPlan!.details) {
|
||||
if (exerciseType.exerciseTypeId == detail.exerciseTypeId) {
|
||||
value = detail.set!;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return value.toStringAsFixed(0);
|
||||
}
|
||||
|
||||
String getRepeatsByExerciseType(ExerciseType exerciseType) {
|
||||
int value = 0;
|
||||
|
||||
if (_myPlan == null || _myPlan!.details.isEmpty) {
|
||||
return value.toStringAsFixed(0);
|
||||
}
|
||||
|
||||
for (var detail in _myPlan!.details) {
|
||||
if (exerciseType.exerciseTypeId == detail.exerciseTypeId) {
|
||||
value = detail.repeats!;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return value.toStringAsFixed(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,15 @@ class TrainingPlanRepeatsChange extends TrainingPlanEvent {
|
||||
List<Object> get props => [repeats, detail];
|
||||
}
|
||||
|
||||
class TrainingPlanSetChange extends TrainingPlanEvent {
|
||||
final CustomerTrainingPlanDetails detail;
|
||||
final int set;
|
||||
const TrainingPlanSetChange({required this.set, required this.detail});
|
||||
|
||||
@override
|
||||
List<Object> get props => [set, detail];
|
||||
}
|
||||
|
||||
class TrainingPlanSaveExercise extends TrainingPlanEvent {
|
||||
final CustomerTrainingPlanDetails detail;
|
||||
const TrainingPlanSaveExercise({required this.detail});
|
||||
@@ -45,8 +54,16 @@ class TrainingPlanSaveExercise extends TrainingPlanEvent {
|
||||
List<Object> get props => [detail];
|
||||
}
|
||||
|
||||
class TrainingPlanFinishTraining extends TrainingPlanEvent {
|
||||
const TrainingPlanFinishTraining();
|
||||
class TrainingPlanFinishDay extends TrainingPlanEvent {
|
||||
const TrainingPlanFinishDay();
|
||||
}
|
||||
|
||||
class TrainingPlanRestart extends TrainingPlanEvent {
|
||||
const TrainingPlanRestart();
|
||||
}
|
||||
|
||||
class TrainingPlanGoToRestart extends TrainingPlanEvent {
|
||||
const TrainingPlanGoToRestart();
|
||||
}
|
||||
|
||||
class TrainingPlanSkipExercise extends TrainingPlanEvent {
|
||||
@@ -56,3 +73,23 @@ class TrainingPlanSkipExercise extends TrainingPlanEvent {
|
||||
@override
|
||||
List<Object> get props => [detail];
|
||||
}
|
||||
|
||||
class TrainingPlanAddExerciseType extends TrainingPlanEvent {
|
||||
const TrainingPlanAddExerciseType();
|
||||
}
|
||||
|
||||
class TrainingPlanDeleteExerciseType extends TrainingPlanEvent {
|
||||
final ExerciseType exerciseType;
|
||||
const TrainingPlanDeleteExerciseType({required this.exerciseType});
|
||||
|
||||
@override
|
||||
List<Object> get props => [exerciseType];
|
||||
}
|
||||
|
||||
class TrainingPlanCustomAddLoad extends TrainingPlanEvent {
|
||||
final ExerciseType exerciseType;
|
||||
const TrainingPlanCustomAddLoad({required this.exerciseType});
|
||||
|
||||
@override
|
||||
List<Object> get props => [exerciseType];
|
||||
}
|
||||
|
||||
@@ -23,6 +23,14 @@ class TrainingPlanFinished extends TrainingPlanState {
|
||||
const TrainingPlanFinished();
|
||||
}
|
||||
|
||||
class TrainingPlanDayFinished extends TrainingPlanState {
|
||||
const TrainingPlanDayFinished();
|
||||
}
|
||||
|
||||
class TrainingPlanDayReadyToRestart extends TrainingPlanState {
|
||||
const TrainingPlanDayReadyToRestart();
|
||||
}
|
||||
|
||||
class TrainingPlanError extends TrainingPlanState {
|
||||
final String message;
|
||||
const TrainingPlanError({required this.message});
|
||||
|
||||
Reference in New Issue
Block a user