import 'dart:collection'; import 'package:workouttest_util/util/app_language.dart'; import 'package:workouttest_util/model/cache.dart'; import 'package:workouttest_util/model/customer.dart'; import 'package:workouttest_util/model/exercise.dart'; import 'package:workouttest_util/model/exercise_type.dart'; import 'package:workouttest_util/model/workout_menu_tree.dart'; import 'package:workouttest_util/service/exercise_service.dart'; import 'package:intl/intl.dart'; import 'package:workouttest_util/util/logging.dart'; class ExerciseRepository with Logging { Exercise? exercise; Customer? customer; ExerciseType? exerciseType; List? exerciseList; List? exerciseLogList = []; List? actualExerciseList = []; bool noRegistration = false; double rmWendler = 0; double rmMcglothlin = 0; double rmLombardi = 0; double rmMayhew = 0; double rmOconner = 0; double rmWathen = 0; DateTime? start; DateTime? end; ExerciseRepository() { createNew(); } createNew() { exercise = Exercise(); exercise!.dateAdd = DateTime.now(); } setQuantity(double quantity) { if (exercise == null) { createNew(); } exercise!.quantity = quantity; } setUnitQuantity(double unitQuantity) { if (exercise == null) { createNew(); } exercise!.unitQuantity = unitQuantity; } setUnit(String unit) { if (exercise == null) { createNew(); } exercise!.unit = unit; } setDatetimeExercise(DateTime datetimeExercise) { if (exercise == null) { createNew(); } exercise!.dateAdd = datetimeExercise; } double? get unitQuantity => exercise!.unitQuantity; double? get quantity => exercise!.quantity; Exercise? getExercise() => exercise; Future addExercise() async { if (customer == null) { throw Exception("Please log in"); } final Exercise modelExercise = exercise!; modelExercise.customerId = customer!.customerId; modelExercise.exerciseTypeId = exerciseType!.exerciseTypeId; if (exerciseType!.unitQuantity != "1") { modelExercise.unitQuantity = null; } Exercise copy = modelExercise.copy(); actualExerciseList!.add(copy); //final int index = actualExerciseList.length - 1; //print("$index. actual exercise " + actualExerciseList[index].toJson().toString()); Exercise savedExercise = await ExerciseApi().addExercise(modelExercise); //actualExerciseList[index].exerciseId = savedExercise.exerciseId; if (customer!.customerId == Cache().userLoggedIn!.customerId) { Cache().addExercise(savedExercise); } else if (Cache().getTrainee() != null && customer!.customerId == Cache().getTrainee()!.customerId) { Cache().addExerciseTrainee(savedExercise); } return savedExercise; } void addExerciseNoRegistration() { final Exercise modelExercise = exercise!; modelExercise.exerciseTypeId = exerciseType!.exerciseTypeId; if (exerciseType!.unitQuantity != "1") { modelExercise.unitQuantity = null; } Exercise copy = modelExercise.copy(); actualExerciseList!.add(copy); exerciseList = []; exerciseList!.add(copy); noRegistration = true; } void initExercise() { createNew(); exerciseType = exerciseType; setUnit(exerciseType!.unit); exercise!.exerciseTypeId = exerciseType!.exerciseTypeId; setQuantity(12); setUnitQuantity(30); exercise!.exercisePlanDetailId = 0; exercise!.exerciseId = 0; start = DateTime.now(); } Future deleteExercise(Exercise exercise) async { await ExerciseApi().deleteExercise(exercise); } setCustomer(Customer customer) => customer = customer; setExerciseType(ExerciseType exerciseType) => exerciseType = exerciseType; Future> getExercisesByCustomer(int customerId) async { final results = await ExerciseApi().getExercisesByCustomer(customerId); exerciseList = results; if (Cache().userLoggedIn != null) { if (customerId == Cache().userLoggedIn!.customerId) { Cache().setExercises(exerciseList!); } else if (Cache().getTrainee() != null && customerId == Cache().getTrainee()!.customerId) { Cache().setExercisesTrainee(exerciseList!); } } return exerciseList!; } List? getExerciseList() { exerciseList = Cache().getExercises(); return exerciseList; } List? getExerciseListTrainee() { exerciseList = Cache().getExercisesTrainee(); return exerciseList; } String? nextMissingBaseExercise(SplayTreeMap sortedTree) { exerciseList ??= Cache().getExercises(); if (exerciseList == null) { return null; } String? missingTreeName; String? foundTreeName; bool isBreak = false; sortedTree.forEach((key, list) { List listByMuscle = list as List; String treeName = key as String; treeName = treeName.substring(3); foundTreeName = null; for (var exercise in listByMuscle) { missingTreeName ??= treeName; if (exercise.base) { if (exerciseList != null) { for (var element in exerciseList!) { if (element.exerciseTypeId == exercise.exerciseTypeId) { foundTreeName = treeName; //print("Found " + foundTreeName + " Missing actual: " + missingTreeName); isBreak = true; } } } } } if (foundTreeName == null && !isBreak) { missingTreeName = treeName; isBreak = true; } }); return missingTreeName; } void getBaseExerciseFinishedPercent() { List checkedExerciseTypeId = []; List baseTreeItem = []; List checkedBaseTreeItem = []; int count1RMExercises = 0; LinkedHashMap tree = Cache().getWorkoutMenuTree(); if (tree.isEmpty) { return; } tree.forEach((key, value) { WorkoutMenuTree treeItem = value; if (treeItem.exerciseType != null && treeItem.exerciseType!.base == true && !baseTreeItem.contains(treeItem.parent)) { baseTreeItem.add(treeItem.parent); } }); exerciseList ??= Cache().getExercises(); if (exerciseList == null) { return; } for (var element in exerciseList!) { Exercise exercise = element; if (!checkedExerciseTypeId.contains(exercise.exerciseTypeId)) { checkedExerciseTypeId.add(exercise.exerciseTypeId!); tree.forEach((key, value) { WorkoutMenuTree treeItem = value; if (treeItem.exerciseType != null && treeItem.exerciseType!.base == true && exercise.exerciseTypeId == treeItem.exerciseType!.exerciseTypeId && !checkedBaseTreeItem.contains(treeItem.parent)) { //print ("id: " + exercise.exerciseTypeId.toString()); checkedBaseTreeItem.add(treeItem.parent); count1RMExercises++; } }); } } //print ("checkedExerciseTypeid: " + checkedExerciseTypeId.toString()); //print ("baseTreeItem: " + baseTreeItem.toString()); //print ("count1RMExercises: " + count1RMExercises.toString()); final double percent = count1RMExercises / baseTreeItem.length; Cache().setPercentExercises(percent); } void getLastExercise() { List? exercises = getExerciseList(); Exercise? lastExercise = exercises == null ? null : exercises[0]; if (exercises != null) { for (var element in exercises) { Exercise actualExercise = element; if (actualExercise.dateAdd!.compareTo(lastExercise!.dateAdd!) > 0) { lastExercise = actualExercise; } } } exercise = lastExercise; customer = Cache().userLoggedIn!; exerciseType = getExerciseTypeById(exercise!.exerciseTypeId!); return; } ExerciseType? getExerciseTypeById(int exerciseTypeId) { ExerciseType? actualExerciseType; List? exercises = Cache().getExerciseTypes(); if (exercises != null) { for (var element in exercises) { ExerciseType exerciseType = element; if (exerciseType.exerciseTypeId == exerciseTypeId) { actualExerciseType = exerciseType; } } } if (actualExerciseType == null) { throw Exception("Data error, no ExerciseType for exerciseTypeId $exerciseTypeId"); } return actualExerciseType; } void getSameExercise(int exerciseTypeId, String day) { if (!noRegistration) { actualExerciseList = []; } if (exerciseList != null) { int index = 0; for (int i = 0; i < exerciseList!.length; i++) { Exercise exercise = exerciseList![i]; final String exerciseDate = DateFormat("yyyy-MM-dd", AppLanguage().appLocal.toString()).format(exercise.dateAdd!); if (exerciseTypeId == exercise.exerciseTypeId && exerciseDate == day && index < 4) { actualExerciseList!.add(exercise); index++; } } } } double calculate1RM(Exercise exercise) { double weight = exercise.unitQuantity!; double repeat = 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; } double getBest1RM(Exercise exercise) { double result = 0; if (exerciseList == null || exerciseList!.isEmpty) { exerciseList = Cache().getExercises(); } final int exerciseTypeId = exercise.exerciseTypeId!; double toCompare = calculate1RM(exercise); result = toCompare; final String today = DateFormat("yyyy-MM-dd", AppLanguage().appLocal.toString()).format(DateTime.now()); List oldExercises = []; if (exerciseList == null) { return toCompare; } for (var exercise in exerciseList!) { final String exerciseDate = DateFormat("yyyy-MM-dd", AppLanguage().appLocal.toString()).format(exercise.dateAdd!); if (exercise.exerciseTypeId == exerciseTypeId && exerciseDate.compareTo(today) < 0) { oldExercises.add(exercise); } } if (oldExercises.isNotEmpty) { oldExercises.sort((a, b) { double sumA = 0; double sumB = 0; if (a.unitQuantity != null && b.unitQuantity != null) { sumA = a.quantity! * a.unitQuantity!; sumB = b.quantity! * b.unitQuantity!; } else { sumA = a.quantity!; sumB = b.quantity!; } return sumA >= sumB ? 1 : -1; }); double withCompare = calculate1RM(oldExercises.last); //result = toCompare >= withCompare ? (1 - toCompare / withCompare) * 100 : (1 - toCompare / withCompare) * -100; result = toCompare >= withCompare ? toCompare : withCompare; } return result; } double getLast1RMPercent(Exercise exercise) { double result = 0; if (exerciseList == null || exerciseList!.isEmpty) { exerciseList = Cache().getExercises(); } final int exerciseTypeId = exercise.exerciseTypeId!; double toCompare = calculate1RM(exercise); final String today = DateFormat("yyyy-MM-dd", AppLanguage().appLocal.toString()).format(exercise.dateAdd!); List oldExercises = []; if (exerciseList == null) { return result; } for (var exercise in exerciseList!) { final String exerciseDate = DateFormat("yyyy-MM-dd", AppLanguage().appLocal.toString()).format(exercise.dateAdd!); if (exercise.exerciseTypeId == exerciseTypeId && exerciseDate.compareTo(today) < 0) { oldExercises.add(exercise); } } if (oldExercises.isNotEmpty) { double withCompare = calculate1RM(oldExercises.first); result = toCompare >= withCompare ? (toCompare / withCompare) * 100 : (1 - toCompare / withCompare) * -100; } return result; } double getBestVolume(Exercise exercise) { double result = 0; if (exerciseList == null || exerciseList!.isEmpty) { exerciseList = Cache().getExercises(); } final int exerciseTypeId = exercise.exerciseTypeId!; double toCompare = exercise.unitQuantity != null ? exercise.quantity! * exercise.unitQuantity! : exercise.quantity!; result = toCompare; final String today = DateFormat("yyyy-MM-dd", AppLanguage().appLocal.toString()).format(DateTime.now()); List oldExercises = []; if (exerciseList == null) { return toCompare; } for (var exercise in exerciseList!) { final String exerciseDate = DateFormat("yyyy-MM-dd", AppLanguage().appLocal.toString()).format(exercise.dateAdd!); if (exercise.exerciseTypeId == exerciseTypeId && exerciseDate.compareTo(today) < 0) { oldExercises.add(exercise); } } if (oldExercises.isNotEmpty) { oldExercises.sort((a, b) { double sumA = 0; double sumB = 0; if (a.unitQuantity != null && b.unitQuantity != null) { sumA = a.quantity! * a.unitQuantity!; sumB = b.quantity! * b.unitQuantity!; } else { sumA = a.quantity!; sumB = b.quantity!; } return sumA >= sumB ? 1 : -1; }); double withCompare = oldExercises.last.unitQuantity != null ? oldExercises.last.quantity! * oldExercises.last.unitQuantity! : oldExercises.last.quantity!; //result = toCompare >= withCompare ? (1 - toCompare / withCompare) * 100 : (1 - toCompare / withCompare) * -100; //print("Last Best: ${oldExercises.last} - result: $result"); result = toCompare >= withCompare ? toCompare : withCompare; } return result; } double getLastExercisePercent(Exercise exercise) { double result = 0; if (exerciseList == null || exerciseList!.isEmpty) { exerciseList = Cache().getExercises(); } final int exerciseTypeId = exercise.exerciseTypeId!; double toCompare = exercise.unitQuantity != null ? exercise.quantity! * exercise.unitQuantity! : exercise.quantity!; final String today = DateFormat("yyyy-MM-dd", AppLanguage().appLocal.toString()).format(exercise.dateAdd!); List oldExercises = []; if (exerciseList == null) { return result; } for (var exercise in exerciseList!) { final String exerciseDate = DateFormat("yyyy-MM-dd", AppLanguage().appLocal.toString()).format(exercise.dateAdd!); if (exercise.exerciseTypeId == exerciseTypeId && exerciseDate.compareTo(today) < 0) { oldExercises.add(exercise); } } if (oldExercises.isNotEmpty) { double withCompare = oldExercises.first.unitQuantity != null ? oldExercises.first.quantity! * oldExercises.first.unitQuantity! : oldExercises.first.quantity!; result = toCompare >= withCompare ? (toCompare / withCompare) * 100 : (1 - toCompare / withCompare) * -100; log("Last Last: ${oldExercises.first} vs. $exercise - - result: $result"); } return result; } void sortByDate() { if (exerciseList == null || exerciseList!.isEmpty) { return; } exerciseList!.sort((a, b) { final String datePartA = DateFormat('yyyyMMdd', AppLanguage().appLocal.toString()).format(a.dateAdd!); String aId = "${datePartA}_${a.exerciseTypeId}"; final String datePartB = DateFormat('yyyyMMdd', AppLanguage().appLocal.toString()).format(b.dateAdd!); String bId = "${datePartB}_${b.exerciseTypeId}"; return bId.compareTo(aId); }); exerciseLogList = []; String summary = ""; String prevDate = DateFormat("yyyy-MM-dd", AppLanguage().appLocal.toString()).format(exerciseList![0].dateAdd!); int prevExerciseTypeId = exerciseList![0].exerciseTypeId!; Exercise prevExercise = exerciseList![0]; int prevCount = 0; for (int i = 0; i < exerciseList!.length; i++) { Exercise exercise = exerciseList![i]; int exerciseTypeId = exercise.exerciseTypeId!; String exerciseDate = DateFormat("yyyy-MM-dd", AppLanguage().appLocal.toString()).format(exercise.dateAdd!); //print(" -- $prevExerciseTypeId - '$prevDate' against $exerciseTypeId - '$exerciseDate'"); if (exerciseTypeId != prevExerciseTypeId || prevDate != exerciseDate) { ExerciseType? exerciseType = Cache().getExerciseTypeById(prevExercise.exerciseTypeId!); String unit = exerciseType != null && exerciseType.unitQuantityUnit != null ? exerciseType.unitQuantityUnit! : prevExercise.unit!; prevExercise.summary = "$summary $unit"; exerciseLogList!.add(prevExercise); //print("Log add " + exercise.toJson().toString()); summary = ""; prevCount = 0; } String delimiter = ""; if (prevCount > 0) delimiter = ", "; double quantity = exercise.quantity == null ? 0 : exercise.quantity!; summary += delimiter + quantity.toStringAsFixed(0); ExerciseType? exerciseType = Cache().getExerciseTypeById(exercise.exerciseTypeId!); //print("exerciseType " + (exerciseType == null ? "NULL" : exerciseType.name) + " ID " + exercise.exerciseTypeId.toString()); if (exerciseType != null) { if (exerciseType.unitQuantity == "1") { summary += "x${exercise.unitQuantity!.toStringAsFixed(0)}"; } //print(" --- sum " + exerciseType.name + " $summary"); } prevExerciseTypeId = exerciseTypeId; prevDate = exerciseDate; prevExercise = exercise; prevCount++; } prevExercise.summary = summary; exerciseLogList!.add(prevExercise); } List getExercisesByExerciseTypeId(int exerciseTypeId) { List list = []; List? allExercise = Cache().getExercises(); if (allExercise == null) { return list; } for (var element in allExercise) { if (element.exerciseTypeId == exerciseTypeId) { list.add(element); } } return list; } }