import 'package:aitrainer_app/model/cache.dart'; 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_tree.dart'; import 'package:aitrainer_app/model/fitness_state.dart'; import 'package:aitrainer_app/model/training_plan.dart'; import 'package:aitrainer_app/model/training_plan_detail.dart'; import 'package:aitrainer_app/repository/training_plan_day_repository.dart'; import 'package:aitrainer_app/util/app_language.dart'; import 'package:aitrainer_app/util/common.dart'; class TrainingPlanRepository { ExerciseTree? parentTree; List getPlansByParent(String parent) { final List resultList = []; final List? exerciseTree = Cache().getExerciseTree(); int? parentId; if (exerciseTree != null) { exerciseTree.forEach((element) { if (element.internalName == parent) { parentId = element.treeId; parentTree = element; } }); } final List? plans = Cache().getTrainingPlans(); if (plans != null && parentId != null) { plans.forEach((element) { if (element.treeId == parentId) { resultList.add(element); } }); } return resultList; } /// 1. deactivate old training plans - update all /// 2. calculate customer_training_plan_details weights / repleats /// 3. create new customer_training_plan CustomerTrainingPlan? activateTrainingPlan(int trainingPlanId) { print(" **** Activate Plan: $trainingPlanId"); // 1. deactivate if (Cache().getCustomerTrainingPlans() != null) { Cache().getCustomerTrainingPlans()!.forEach((plan) { plan.active = false; if (plan.customerTrainingPlanId != null) { //TrainingPlanApi().updateCustomerTrainingPlan(plan, plan.customerTrainingPlanId!); } }); } CustomerTrainingPlan plan = CustomerTrainingPlan(); plan.customerId = Cache().userLoggedIn!.customerId; plan.trainingPlanId = trainingPlanId; plan.active = true; plan.status = "open"; plan.dateAdd = DateTime.now(); TrainingPlan? trainingPlan = this.getTrainingPlanById(trainingPlanId); if (trainingPlan == null || trainingPlan.details == null) { print("trainingPlan null"); return null; } plan.name = trainingPlan.nameTranslations[AppLanguage().appLocal.toString()]; // 3 calculate weights int index = 0; int exerciseTypeIdOrig = 0; trainingPlan.details!.forEach((elem) { List list = createDetail(plan, elem, exerciseTypeIdOrig, index); exerciseTypeIdOrig = elem.exerciseTypeId; list.forEach((element) { plan.details.add(element); index++; }); }); Cache().myTrainingPlan = plan; return plan; } CustomerTrainingPlanDetails createAlternativeDetail( CustomerTrainingPlan plan, CustomerTrainingPlanDetails detail, TrainingPlanDetail elem, int exerciseTypeId) { CustomerTrainingPlanDetails alternativeDetail = CustomerTrainingPlanDetails(); alternativeDetail.copy(detail); alternativeDetail.exerciseTypeId = exerciseTypeId; alternativeDetail.exerciseType = Cache().getExerciseTypeById(exerciseTypeId); if (elem.weight == -1) { if (alternativeDetail.exerciseType!.unitQuantityUnit != null) { alternativeDetail = getCalculatedWeightRepeats(elem.exerciseTypeId, alternativeDetail); } else { alternativeDetail.weight = 0; } } else if (elem.weight == -2) { final CustomerTrainingPlanDetails calculated = this.isWeightCalculatedByExerciseType(elem.exerciseTypeId, alternativeDetail, plan); if (calculated.weight != -1) { alternativeDetail.weight = calculated.weight; } else { alternativeDetail.weight = -2; } } else { alternativeDetail.weight = elem.weight; } //print("Detail $alternativeDetail exerciseType: ${alternativeDetail.exerciseType!.exerciseTypeId}"); return alternativeDetail; } List createDetail(CustomerTrainingPlan plan, TrainingPlanDetail elem, int exerciseTypeIdOrig, int index, {bool changeExerciseType = false}) { List list = []; CustomerTrainingPlanDetails detail = CustomerTrainingPlanDetails(); detail.customerTrainingPlanDetailsId = ++index; detail.trainingPlanDetailsId = elem.trainingPlanDetailId; detail.exerciseTypeId = changeExerciseType ? exerciseTypeIdOrig : elem.exerciseTypeId; detail.repeats = elem.repeats; detail.set = elem.set; detail.dayId = elem.dayId; TrainingPlanDayRepository trainingPlanDayRepository = TrainingPlanDayRepository(); detail.day = trainingPlanDayRepository.getNameById(elem.dayId); detail.parallel = elem.parallel; detail.restingTime = elem.restingTime; detail.exerciseType = Cache().getExerciseTypeById(detail.exerciseTypeId!); detail.alternatives = Common.getExerciseTypeAlternatives(detail.exerciseTypeId); if (elem.weight == -1) { if (detail.exerciseType!.unitQuantityUnit != null) { detail = getCalculatedWeightRepeats(elem.exerciseTypeId, detail); } else { detail.weight = 0; } } else if (elem.weight == -2) { final CustomerTrainingPlanDetails calculated = this.isWeightCalculatedByExerciseType(elem.exerciseTypeId, detail, plan); if (calculated.weight != -1) { detail.weight = calculated.weight; } else { detail.weight = -2; } } else { detail.weight = elem.weight; } print("Detail $detail exerciseType: ${detail.exerciseType!.exerciseTypeId}"); detail.state = ExercisePlanDetailState.start; if (detail.weight != null && detail.weight! > 0) { detail.baseOneRepMax = Common.calculate1RM(detail.weight!, detail.repeats!.toDouble()); } // first repeat: 50% more if (detail.weight != null && detail.weight! > 0 && exerciseTypeIdOrig != detail.exerciseTypeId && detail.repeats! > 0) { CustomerTrainingPlanDetails firstDetail = CustomerTrainingPlanDetails(); firstDetail.copy(detail); firstDetail.repeats = (detail.repeats! * 1.5).round(); firstDetail.baseOneRepMax = Common.calculate1RM(firstDetail.weight!, firstDetail.repeats!.toDouble()); firstDetail.set = 1; detail.set = detail.set! - 1; if (detail.set! > 0) { index++; } detail.customerTrainingPlanDetailsId = index; list.add(firstDetail); } if (detail.set! > 0) { list.add(detail); } return list; } CustomerTrainingPlanDetails isWeightCalculatedByExerciseType( int exerciseTypeId, CustomerTrainingPlanDetails detail, CustomerTrainingPlan plan) { CustomerTrainingPlanDetails calculated = detail; for (var element in plan.details) { if (element.exerciseTypeId == exerciseTypeId) { calculated = element; break; } } return calculated; } TrainingPlan? getTrainingPlanById(int trainingPlanId) { TrainingPlan? plan; if (Cache().getTrainingPlans() == null) { return plan; } for (var trainingPlan in Cache().getTrainingPlans()!) { if (trainingPlan.trainingPlanId == trainingPlanId) { plan = trainingPlan; break; } } return plan; } int? getTrainingPlanByInternalName(String internalName) { int? id; if (Cache().getTrainingPlans() == null) { return id; } for (var trainingPlan in Cache().getTrainingPlans()!) { //print("internal ${trainingPlan.internalName}"); if (trainingPlan.internalName == internalName) { id = trainingPlan.trainingPlanId; break; } } return id; } CustomerTrainingPlanDetails getCalculatedWeightRepeats(int exerciseTypeId, CustomerTrainingPlanDetails detail) { double weight = -1; if (Cache().getExercises() == null) { detail.weight = weight; detail.isTest = true; return detail; } Exercise? lastExercise1RM; DateTime dt = DateTime.now().subtract(Duration(days: 30)); List exercises = Cache().getExercises()!; exercises.sort((a, b) { // reverse return a.dateAdd!.compareTo(b.dateAdd!); }); exercises.forEach((exercise) { if (exercise.exerciseTypeId == exerciseTypeId && exercise.dateAdd!.compareTo(dt) >= 0) { detail.weight = weight; lastExercise1RM = exercise; //print("last exercise: $exercise"); } }); if (lastExercise1RM == null || lastExercise1RM!.unitQuantity == null) { detail.weight = weight; detail.isTest = true; return detail; } double oneRepMax = calculateMax1RMSameDay(lastExercise1RM!); // Common.calculate1RM(lastExercise1RM!.unitQuantity!, lastExercise1RM!.quantity!); //print("Exercise $exerciseTypeId - 1RM : $oneRepMax"); weight = oneRepMax * Common.get1RMPercent(detail.repeats!); //print("Exercise $exerciseTypeId - weight : $weight"); //weight = Common.roundWeight(weight); //detail.weight = Common.calculateWeigthByChangedQuantity(detail.weight!, detail.repeats!.toDouble(), lastExercise1RM!.quantity!); //weight = lastExercise1RM!.unitQuantity! * detail.repeats! / lastExercise1RM!.quantity!; weight = Common.roundWeight(weight); print("Recaluclated weight ${detail.weight} - repeat: ${detail.repeats}"); //detail.repeats = Common.calculateQuantityByChangedWeight(oneRepMax, weight, detail.repeats!.toDouble()); detail.weight = weight; return detail; } double calculateMax1RMSameDay(Exercise actual) { List exercises = Cache().getExercises()!; double max1RM = 0.0; exercises.forEach((exercise) { if (actual.exerciseTypeId == exercise.exerciseTypeId && actual.dateAdd!.year == exercise.dateAdd!.year && actual.dateAdd!.month == exercise.dateAdd!.month && actual.dateAdd!.day == exercise.dateAdd!.day) { double oneRepMax = Common.calculate1RM(exercise.unitQuantity!, exercise.quantity!); if (max1RM < oneRepMax) { max1RM = oneRepMax; } } }); return max1RM; } int getOriginalRepeats(int trainingPlanId, CustomerTrainingPlanDetails detail) { TrainingPlan? plan = getTrainingPlanById(trainingPlanId); if (plan == null) { return 0; } int originalRepeats = 0; plan.details!.forEach((element) { if (element.trainingPlanDetailId == detail.trainingPlanDetailsId) { originalRepeats = element.repeats ?? 0; } }); return originalRepeats; } double getOriginalWeight(int trainingPlanId, CustomerTrainingPlanDetails detail) { TrainingPlan? plan = getTrainingPlanById(trainingPlanId); if (plan == null) { return 0; } double originalWeight = 0; plan.details!.forEach((element) { if (element.trainingPlanDetailId == detail.trainingPlanDetailsId) { originalWeight = element.weight ?? 0; } }); return originalWeight; } CustomerTrainingPlanDetails recalculateDetailFixRepeats(int trainingPlanId, CustomerTrainingPlanDetails detail) { TrainingPlan? plan = getTrainingPlanById(trainingPlanId); if (plan == null) { return detail; } int originalRepeats = getOriginalRepeats(trainingPlanId, detail); detail.weight = Common.calculateWeigthByChangedQuantity(detail.weight!, detail.repeats!.toDouble(), originalRepeats.toDouble()); detail.weight = Common.roundWeight(detail.weight!); print("Recalculated weight: ${detail.weight}"); detail.repeats = originalRepeats; return detail; } CustomerTrainingPlanDetails recalculateDetailFixRepeatsSet1( int trainingPlanId, CustomerTrainingPlanDetails detail, CustomerTrainingPlanDetails detailWithData) { TrainingPlan? plan = getTrainingPlanById(trainingPlanId); if (plan == null) { return detail; } int originalRepeats = getOriginalRepeats(trainingPlanId, detail); detail.weight = Common.calculateWeigthByChangedQuantity(detailWithData.weight!, detailWithData.repeats!.toDouble(), originalRepeats.toDouble()); detail.weight = Common.roundWeight(detail.weight!); print("Recalculated weight: ${detail.weight}"); detail.repeats = originalRepeats; return detail; } CustomerTrainingPlanDetails recalculateDetail( int trainingPlanId, CustomerTrainingPlanDetails detail, CustomerTrainingPlanDetails nextDetail) { CustomerTrainingPlanDetails recalculatedDetail = nextDetail; // 1. get original repeats // 1a get original plan TrainingPlan? plan = getTrainingPlanById(trainingPlanId); if (plan == null) { return recalculatedDetail; } // 1.b get the original detail's repeat int originalRepeats = detail.repeats!; plan.details!.forEach((element) { if (element.trainingPlanDetailId == detail.trainingPlanDetailsId) { originalRepeats = element.repeats ?? 0; } }); // 2 get recalculated repeats recalculatedDetail.weight = Common.calculateWeigthByChangedQuantity(detail.weight!, detail.repeats!.toDouble(), originalRepeats.toDouble()); recalculatedDetail.weight = Common.roundWeight(recalculatedDetail.weight!); print("recalculated repeats for $originalRepeats: ${recalculatedDetail.weight}"); //recalculatedDetail.repeats = originalRepeats; return recalculatedDetail; } void generateTrainingPlan() { int? trainingPlanId; if (Cache().userLoggedIn == null) { return; } bool isWoman = Cache().userLoggedIn!.sex == "w"; if (Cache().userLoggedIn!.goal == "shape_forming") { if (Cache().userLoggedIn!.fitnessLevel == FitnessState.beginner) { trainingPlanId = isWoman ? getTrainingPlanByInternalName("women_shape_L1") : getTrainingPlanByInternalName("man_routine1"); } else if (Cache().userLoggedIn!.fitnessLevel == FitnessState.intermediate) { trainingPlanId = isWoman ? getTrainingPlanByInternalName("women_shape_L2") : getTrainingPlanByInternalName("man_routine3"); } else if (Cache().userLoggedIn!.fitnessLevel == FitnessState.advanced) { trainingPlanId = isWoman ? getTrainingPlanByInternalName("women_shape_L3") : getTrainingPlanByInternalName("man_routine4"); } else { trainingPlanId = isWoman ? getTrainingPlanByInternalName("women_shape_L4") : getTrainingPlanByInternalName("man_routine2"); } } else if (Cache().userLoggedIn!.goal == "muscle_endurance") { if (Cache().userLoggedIn!.fitnessLevel == FitnessState.beginner) { trainingPlanId = isWoman ? getTrainingPlanByInternalName("man_se_l1") : getTrainingPlanByInternalName("man_se_l1"); } else if (Cache().userLoggedIn!.fitnessLevel == FitnessState.intermediate) { trainingPlanId = isWoman ? getTrainingPlanByInternalName("man_se_l2") : getTrainingPlanByInternalName("man_se_l2"); } else if (Cache().userLoggedIn!.fitnessLevel == FitnessState.advanced) { trainingPlanId = isWoman ? getTrainingPlanByInternalName("man_se_l3") : getTrainingPlanByInternalName("man_se_l3"); } else { trainingPlanId = isWoman ? getTrainingPlanByInternalName("man_se_l4") : getTrainingPlanByInternalName("man_se_l4"); } } else if (Cache().userLoggedIn!.goal == "gain_strength") { if (Cache().userLoggedIn!.fitnessLevel == FitnessState.beginner) { trainingPlanId = isWoman ? getTrainingPlanByInternalName("man_power_l1") : getTrainingPlanByInternalName("man_power_l1"); } else if (Cache().userLoggedIn!.fitnessLevel == FitnessState.intermediate) { trainingPlanId = isWoman ? getTrainingPlanByInternalName("man_power_l2") : getTrainingPlanByInternalName("man_power_l2"); } else if (Cache().userLoggedIn!.fitnessLevel == FitnessState.advanced) { trainingPlanId = isWoman ? getTrainingPlanByInternalName("man_power_l3") : getTrainingPlanByInternalName("man_power_l3"); } else { trainingPlanId = isWoman ? getTrainingPlanByInternalName("man_power_l4") : getTrainingPlanByInternalName("man_power_l4"); } } else if (Cache().userLoggedIn!.goal == "gain_muscle") { if (Cache().userLoggedIn!.fitnessLevel == FitnessState.beginner) { trainingPlanId = isWoman ? getTrainingPlanByInternalName("woman_beginner") : getTrainingPlanByInternalName("beginner_man"); } else if (Cache().userLoggedIn!.fitnessLevel == FitnessState.intermediate) { trainingPlanId = isWoman ? getTrainingPlanByInternalName("woman_beginner_split") : getTrainingPlanByInternalName("man_foundation"); } else if (Cache().userLoggedIn!.fitnessLevel == FitnessState.advanced) { trainingPlanId = isWoman ? getTrainingPlanByInternalName("woman_advanced") : getTrainingPlanByInternalName("basic_mass_building"); } else { trainingPlanId = isWoman ? getTrainingPlanByInternalName("man_routine2") : getTrainingPlanByInternalName("mass_building"); } } print("Generated plan $trainingPlanId fitness ${Cache().userLoggedIn!.fitnessLevel} - ${FitnessState.beginner}"); if (trainingPlanId != null) { CustomerTrainingPlan? customerTrainingPlan = activateTrainingPlan(trainingPlanId); if (customerTrainingPlan != null) { Cache().myTrainingPlan = customerTrainingPlan; Cache().saveMyTrainingPlan(); } } } }