hevy-shared 1.0.962 → 1.0.964

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/README.md +17 -2
  2. package/built/API/APIClient.d.ts +157 -0
  3. package/built/API/APIClient.js +381 -0
  4. package/built/API/index.d.ts +2 -0
  5. package/built/API/index.js +18 -0
  6. package/built/API/types.d.ts +38 -0
  7. package/built/API/types.js +18 -0
  8. package/built/adjustEventTokens.d.ts +16 -0
  9. package/built/adjustEventTokens.js +18 -0
  10. package/built/adminPermissions.d.ts +4 -0
  11. package/built/adminPermissions.js +22 -0
  12. package/built/async.d.ts +50 -0
  13. package/built/async.js +170 -0
  14. package/built/chat.d.ts +25 -23
  15. package/built/coachPlans.d.ts +2 -1
  16. package/built/coachPlans.js +2 -2
  17. package/built/cue.d.ts +12 -0
  18. package/built/cue.js +22 -0
  19. package/built/exerciseLocaleUtils.d.ts +17 -0
  20. package/built/exerciseLocaleUtils.js +62 -0
  21. package/built/filterExercises.d.ts +19 -3
  22. package/built/filterExercises.js +72 -60
  23. package/built/hevyTrainer.d.ts +250 -0
  24. package/built/hevyTrainer.js +676 -0
  25. package/built/index.d.ts +1217 -304
  26. package/built/index.js +268 -75
  27. package/built/muscleHeatmaps.d.ts +31 -0
  28. package/built/muscleHeatmaps.js +68 -0
  29. package/built/muscleSplits.d.ts +36 -0
  30. package/built/muscleSplits.js +100 -0
  31. package/built/normalizedWorkoutUtils.d.ts +88 -0
  32. package/built/normalizedWorkoutUtils.js +112 -0
  33. package/built/notifications.d.ts +215 -0
  34. package/built/notifications.js +9 -0
  35. package/built/routineUtils.d.ts +14 -0
  36. package/built/routineUtils.js +186 -0
  37. package/built/setIndicatorUtils.d.ts +4 -3
  38. package/built/setIndicatorUtils.js +15 -1
  39. package/built/tests/async.test.d.ts +1 -0
  40. package/built/tests/async.test.js +49 -0
  41. package/built/tests/hevyTrainer.test.d.ts +1 -0
  42. package/built/tests/hevyTrainer.test.js +1199 -0
  43. package/built/tests/muscleSplit.test.d.ts +1 -0
  44. package/built/tests/muscleSplit.test.js +153 -0
  45. package/built/tests/routineUtils.test.d.ts +1 -0
  46. package/built/tests/routineUtils.test.js +745 -0
  47. package/built/tests/testUtils.d.ts +85 -0
  48. package/built/tests/testUtils.js +319 -0
  49. package/built/tests/utils.test.js +748 -0
  50. package/built/tests/workoutVolume.test.js +165 -49
  51. package/built/translations/index.d.ts +2 -0
  52. package/built/translations/index.js +18 -0
  53. package/built/translations/translationUtils.d.ts +2 -0
  54. package/built/translations/translationUtils.js +61 -0
  55. package/built/translations/types.d.ts +8 -0
  56. package/built/translations/types.js +20 -0
  57. package/built/typeUtils.d.ts +70 -0
  58. package/built/typeUtils.js +55 -0
  59. package/built/units.d.ts +14 -7
  60. package/built/units.js +24 -14
  61. package/built/utils.d.ts +192 -5
  62. package/built/utils.js +598 -85
  63. package/built/websocket.d.ts +14 -2
  64. package/built/workoutVolume.d.ts +24 -5
  65. package/built/workoutVolume.js +25 -34
  66. package/package.json +30 -9
  67. package/.eslintignore +0 -2
  68. package/.eslintrc +0 -21
  69. package/.github/workflows/ci.yml +0 -15
  70. package/.github/workflows/npm-publish.yml +0 -59
  71. package/.github/workflows/pr-auto-assign.yml +0 -15
  72. package/.prettierrc.js +0 -5
  73. package/jest.config.js +0 -4
  74. package/src/chat.ts +0 -130
  75. package/src/coachPlans.ts +0 -57
  76. package/src/constants.ts +0 -14
  77. package/src/filterExercises.ts +0 -222
  78. package/src/index.ts +0 -1576
  79. package/src/setIndicatorUtils.ts +0 -137
  80. package/src/tests/utils.test.ts +0 -156
  81. package/src/tests/workoutVolume.test.ts +0 -93
  82. package/src/units.ts +0 -41
  83. package/src/utils.ts +0 -516
  84. package/src/websocket.ts +0 -36
  85. package/src/workoutVolume.ts +0 -175
  86. package/tsconfig.json +0 -70
@@ -1,18 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.popularExerciseTemplateIds = exports.filterExercises = void 0;
4
- const lodash_1 = require("lodash");
3
+ exports.popularExerciseTemplateIds = exports.getExerciseMatches = void 0;
5
4
  const utils_1 = require("./utils");
6
- const filterExercises = ({ exercises, muscleGroupFilter, equipmentType, searchText, language, }) => {
5
+ const lodash_1 = require("lodash");
6
+ const getExerciseMatches = ({ exercises, muscleGroupFilter, equipmentType, searchText, language, }) => {
7
7
  let result = exercises;
8
8
  result = filterExercisesWithMuscleGroup(muscleGroupFilter, result);
9
9
  result = filterExercisesWithEquipment(equipmentType, result);
10
10
  const normalizedSearchText = normalizeSearchText(searchText, language);
11
- result = filterExercisesWithSearchText(normalizedSearchText, result, language);
12
- result = orderExercisesWithSearchText(normalizedSearchText, result);
13
- return result;
11
+ let matches = filterExercisesWithSearchText(normalizedSearchText, result, language);
12
+ matches = orderExercisesWithSearchText(normalizedSearchText, matches);
13
+ return matches;
14
14
  };
15
- exports.filterExercises = filterExercises;
15
+ exports.getExerciseMatches = getExerciseMatches;
16
16
  const filterExercisesWithMuscleGroup = (muscleGroup, exercises) => {
17
17
  if (muscleGroup === 'all_muscles') {
18
18
  return exercises;
@@ -25,41 +25,52 @@ const filterExercisesWithEquipment = (equipmentType, exercises) => {
25
25
  }
26
26
  return exercises.filter((rd) => rd.equipment_category === equipmentType);
27
27
  };
28
+ // Old filter exercise functionality, will be removed when new feature goes live
28
29
  const filterExercisesWithSearchText = (searchText, exercises, language) => {
29
30
  if (searchText.length === 0) {
30
- return exercises;
31
+ return exercises.map((e) => ({ exercise: e, matchType: 'other' }));
31
32
  }
32
- return exercises.filter((e) => {
33
+ const matches = [];
34
+ for (const e of exercises) {
33
35
  const searchableSearchText = searchable(searchText);
34
36
  const searchableEnglishTitle = searchable(e.title);
35
- const searchableLocalizedTitleMap = {
36
- en: searchable(e.title),
37
- es: e.es_title ? searchable(e.es_title) : undefined,
38
- de: e.de_title ? searchable(e.de_title) : undefined,
39
- fr: e.fr_title ? searchable(e.fr_title) : undefined,
40
- it: e.it_title ? searchable(e.it_title) : undefined,
41
- pt: e.pt_title ? searchable(e.pt_title) : undefined,
42
- tr: e.tr_title ? searchable(e.tr_title) : undefined,
43
- zh_CN: e.zh_cn_title ? searchable(e.zh_cn_title) : undefined,
44
- zh_TW: e.zh_tw_title ? searchable(e.zh_tw_title) : undefined,
45
- ru: e.ru_title ? searchable(e.ru_title) : undefined,
46
- ja: e.ja_title ? searchable(e.ja_title) : undefined,
47
- ko: e.ko_title ? searchable(e.ko_title) : undefined,
48
- };
37
+ const searchableLocalizedTitleMap = !e.is_custom
38
+ ? {
39
+ en: searchable(e.title),
40
+ es: e.es_title ? searchable(e.es_title) : undefined,
41
+ de: e.de_title ? searchable(e.de_title) : undefined,
42
+ fr: e.fr_title ? searchable(e.fr_title) : undefined,
43
+ it: e.it_title ? searchable(e.it_title) : undefined,
44
+ pt: e.pt_title ? searchable(e.pt_title) : undefined,
45
+ tr: e.tr_title ? searchable(e.tr_title) : undefined,
46
+ zh_CN: e.zh_cn_title ? searchable(e.zh_cn_title) : undefined,
47
+ zh_TW: e.zh_tw_title ? searchable(e.zh_tw_title) : undefined,
48
+ ru: e.ru_title ? searchable(e.ru_title) : undefined,
49
+ ja: e.ja_title ? searchable(e.ja_title) : undefined,
50
+ ko: e.ko_title ? searchable(e.ko_title) : undefined,
51
+ }
52
+ : {
53
+ en: searchable(e.title),
54
+ };
49
55
  const searchableLocalizedTitle = searchableLocalizedTitleMap[language] || searchableLocalizedTitleMap.en;
50
56
  const searchableLocalizedMuscleGroupName = searchable(e.localized_muscle_group_name);
51
57
  const searchableMuscleGroup = searchable(e.muscle_group);
52
58
  const searchableMisspelledDumbbellEquipment = e.equipment_category === 'dumbbell' ? 'dumbell' : '';
53
- const searchableTags = e.manual_tag ? searchable(e.manual_tag) : '';
54
- const searchableAka = e.aka ? searchable(e.aka) : '';
59
+ const searchableTags = !e.is_custom && e.manual_tag ? searchable(e.manual_tag) : '';
60
+ const searchableAka = !e.is_custom && e.aka ? searchable(e.aka) : '';
55
61
  if (searchableLocalizedTitle.includes(searchableSearchText) ||
56
- searchableEnglishTitle.includes(searchableSearchText) ||
57
- searchableLocalizedMuscleGroupName.includes(searchableSearchText) ||
62
+ searchableEnglishTitle.includes(searchableSearchText)) {
63
+ matches.push({ exercise: e, matchType: 'title' });
64
+ continue;
65
+ }
66
+ else if (searchableLocalizedMuscleGroupName.includes(searchableSearchText) ||
58
67
  searchableMuscleGroup.includes(searchableSearchText)) {
59
- return true;
68
+ matches.push({ exercise: e, matchType: 'muscle_group' });
69
+ continue;
60
70
  }
61
71
  if (e.is_custom && 'custom'.includes(searchableSearchText)) {
62
- return true;
72
+ matches.push({ exercise: e, matchType: 'custom' });
73
+ continue;
63
74
  }
64
75
  const splitSearch = searchableSearchText.split(' ');
65
76
  const splitTitle = [
@@ -75,28 +86,29 @@ const filterExercisesWithSearchText = (searchText, exercises, language) => {
75
86
  // title ['arnold', 'press', '(barbell)']
76
87
  // search ['press', 'bar']
77
88
  if ((0, lodash_1.intersectionWith)(splitSearch, splitTitle, (search, title) => title.includes(search)).length === splitSearch.length) {
78
- return true;
89
+ matches.push({ exercise: e, matchType: 'other' });
90
+ continue;
79
91
  }
80
- return false;
81
- });
92
+ }
93
+ return matches;
82
94
  };
83
- const orderExercisesWithSearchText = (searchText, exercises) => {
95
+ const orderExercisesWithSearchText = (searchText, exerciseMatches) => {
84
96
  if (searchText.length === 0) {
85
- return exercises;
97
+ return exerciseMatches;
86
98
  }
87
- return exercises
88
- .reduce((accu, currentExercise) => {
89
- const lowercaseTitle = currentExercise.title.toLowerCase();
99
+ return exerciseMatches
100
+ .reduce((accu, currentMatch) => {
101
+ const lowercaseTitle = currentMatch.exercise.title.toLowerCase();
90
102
  if (lowercaseTitle.startsWith(searchText)) {
91
103
  accu.push({
92
- exercise: currentExercise,
93
- weight: currentExercise.priority * 2,
104
+ exercise: currentMatch,
105
+ weight: currentMatch.exercise.priority * 2,
94
106
  });
95
107
  return accu;
96
108
  }
97
109
  accu.push({
98
- exercise: currentExercise,
99
- weight: currentExercise.priority,
110
+ exercise: currentMatch,
111
+ weight: currentMatch.exercise.priority,
100
112
  });
101
113
  return accu;
102
114
  }, [])
@@ -126,24 +138,24 @@ const searchable = (str) => {
126
138
  * users who don't have any workouts logged.
127
139
  */
128
140
  exports.popularExerciseTemplateIds = [
129
- 'B8127AD1',
130
- '11A123F3',
131
- 'D04AC939',
132
- '75A4F6C4',
133
- '422B08F1',
134
- 'C7973E0E',
135
- '07B38369',
136
- '3601968B',
137
- '6A6C31A5',
138
- '0393F233',
139
- '37FCC2BB',
140
- '55E6546F',
141
- '94B7239B',
142
- 'C6272009',
143
- '878CD1D0',
144
- '651F844C',
145
- '79D0BB3A',
146
- '93A552C6',
147
- '7E3BC8B6',
141
+ 'B8127AD1', // Lying Leg Curl (Machine)"
142
+ '11A123F3', // Seated Leg Curl (Machine)"
143
+ 'D04AC939', // Squat (Barbell)"
144
+ '75A4F6C4', // Leg Extension (Machine)"
145
+ '422B08F1', // Lateral Raise (Dumbbell)"
146
+ 'C7973E0E', // Leg Press (Machine)"
147
+ '07B38369', // Incline Bench Press (Dumbbell)"
148
+ '3601968B', // Bench Press (Dumbbell)"
149
+ '6A6C31A5', // Lat Pulldown (Cable)"
150
+ '0393F233', // Seated Cable Row - V Grip (Cable)"
151
+ '37FCC2BB', // Bicep Curl (Dumbbell)"
152
+ '55E6546F', // Bent Over Row (Barbell)"
153
+ '94B7239B', // Triceps Rope Pushdown"
154
+ 'C6272009', // Deadlift (Barbell)"
155
+ '878CD1D0', // Shoulder Press (Dumbbell)"
156
+ '651F844C', // Cable Fly Crossovers"
157
+ '79D0BB3A', // Bench Press (Barbell)"
158
+ '93A552C6', // Triceps Pushdown"
159
+ '7E3BC8B6', // Hammer Curl (Dumbbell)"
148
160
  'BE640BA0', // Face Pull
149
161
  ];
@@ -0,0 +1,250 @@
1
+ import { WeeklyTrainingFrequency, TrainingGoal, TrainingLevel, SimplifiedMuscleGroup, MuscleGroup, LibraryExercise, ExerciseCategory, GranularEquipment, HevyTrainerProgramEquipment, RestTimerLength } from '.';
2
+ export type HevyTrainerExerciseCategory = typeof hevyTrainerExerciseCategories[number];
3
+ export type HevyTrainerRoutineName = typeof routineNames[number];
4
+ export declare const workoutDurationOptions: readonly [40, 60, 80];
5
+ export type WorkoutDurationMinutes = typeof workoutDurationOptions[number];
6
+ export declare const trainerGymTypes: readonly ["home_gym", "garage_gym", "commercial_gym", "full_gym"];
7
+ export type TrainerGymType = typeof trainerGymTypes[number];
8
+ export declare const granularEquipmentDefaults: {
9
+ [key in TrainerGymType]: GranularEquipment[];
10
+ };
11
+ export declare const trainerEquipmentToGranularEquipments: (equipments: HevyTrainerProgramEquipment[]) => GranularEquipment[];
12
+ /**
13
+ * Converts granular equipment values back to the old HevyTrainerProgramEquipment
14
+ * types for backwards compatibility with old mobile clients.
15
+ */
16
+ export declare const granularEquipmentsToTrainerEquipments: (granularEquipments: GranularEquipment[]) => HevyTrainerProgramEquipment[];
17
+ export declare const hevyTrainerExerciseCategories: readonly ["compound", "isolation"];
18
+ export declare const defaultDurationPerFrequency: Record<WeeklyTrainingFrequency, WorkoutDurationMinutes>;
19
+ export declare const routineNames: readonly ["full_body_1", "full_body_2_a", "full_body_2_b", "full_body_3_a", "full_body_3_b", "full_body_3_c", "upper_1_a", "lower_1_a", "upper_1_b", "lower_1_b", "push_1", "pull_1", "legs_1", "upper_2", "lower_2", "push_2_a", "pull_2_a", "legs_2_a", "push_2_b", "pull_2_b", "legs_2_b"];
20
+ export type exerciseId = string;
21
+ export interface ExerciseSelectionCriteria {
22
+ exerciseCategory: HevyTrainerExerciseCategory | 'all';
23
+ equipments: GranularEquipment[];
24
+ routineBarbellExerciseCount: number;
25
+ level: TrainingLevel;
26
+ goal: TrainingGoal;
27
+ muscleGroup: MuscleGroup;
28
+ frequency: WeeklyTrainingFrequency;
29
+ }
30
+ export interface ExerciseSelectionContext {
31
+ programUsedExerciseIds?: Set<string>;
32
+ routineUsedExerciseIds?: Set<string>;
33
+ excludedExerciseIds?: Set<string>;
34
+ }
35
+ export interface ExerciseSelectionParams<T extends HevyTrainerLibraryExercise> {
36
+ sortedExercises: Record<MuscleGroup, T[]>;
37
+ handPickedExercises?: T[];
38
+ criteria: ExerciseSelectionCriteria;
39
+ context: ExerciseSelectionContext;
40
+ }
41
+ export interface ExerciseSelectionTraceEntry {
42
+ pass: 1 | 2 | 3 | 4 | 5 | 6;
43
+ label: string;
44
+ candidatePoolSize: number;
45
+ selectedExerciseId?: string;
46
+ }
47
+ export interface ExerciseSelectionTrace {
48
+ entries: ExerciseSelectionTraceEntry[];
49
+ selectedPass?: 1 | 2 | 3 | 4 | 5 | 6;
50
+ }
51
+ export interface ProgramGenerationParams<T extends HevyTrainerLibraryExercise> {
52
+ trainerAlgorithmSettings: TrainerAlgorithmSettings;
53
+ frequency: WeeklyTrainingFrequency;
54
+ goal: TrainingGoal;
55
+ level: TrainingLevel;
56
+ equipments: GranularEquipment[];
57
+ workoutDurationMinutes: WorkoutDurationMinutes;
58
+ restTimerLength: RestTimerLength;
59
+ exerciseStore: T[];
60
+ focusMuscle?: SimplifiedMuscleGroup;
61
+ excludedExerciseIds?: Set<string>;
62
+ /**
63
+ * When enabled, includes exercise selection trace breadcrumbs in the result
64
+ * for debugging. Intended for troubleshooting on backoffice; keep off in
65
+ * normal usage on the app.
66
+ */
67
+ debugExerciseSelectionTrace?: boolean;
68
+ }
69
+ export interface ProgramExerciseSelectionTraceRecord {
70
+ routine: HevyTrainerRoutineName;
71
+ prescriptionIndex: number;
72
+ prescription: ExercisePrescription;
73
+ resolvedMuscleGroup: MuscleGroup;
74
+ criteria: ExerciseSelectionCriteria;
75
+ selectedExerciseId?: string;
76
+ trace: ExerciseSelectionTrace;
77
+ }
78
+ export type TrainerProgramAttemptWithTraces = TrainerProgramAttempt & {
79
+ exerciseSelectionTraces: ProgramExerciseSelectionTraceRecord[];
80
+ };
81
+ export type FrequencyString = 'one_day' | 'two_days' | 'three_days' | 'four_days' | 'five_days' | 'six_days';
82
+ export declare const frequencyMap: Record<WeeklyTrainingFrequency, FrequencyString>;
83
+ export declare const programSplits: Record<WeeklyTrainingFrequency, HevyTrainerRoutineName[]>;
84
+ export type SetsPerGoal = {
85
+ [key in TrainingGoal]: number;
86
+ };
87
+ export type SetsPerFrequency = {
88
+ [key in FrequencyString]: SetsPerGoal;
89
+ };
90
+ export interface RepRange {
91
+ rep_range_start: number;
92
+ rep_range_end: number;
93
+ }
94
+ export type RepRangesPerCategory = {
95
+ [key in HevyTrainerExerciseCategory]: RepRange;
96
+ };
97
+ export type RepRanges = {
98
+ [key in TrainingGoal]: RepRangesPerCategory;
99
+ };
100
+ export type RestTimersPerCategory = {
101
+ [key in HevyTrainerExerciseCategory]: number;
102
+ };
103
+ export type CategoryPerRestTimerLength = {
104
+ [key in RestTimerLength]: RestTimersPerCategory;
105
+ };
106
+ export type RestTimers = {
107
+ [key in TrainingGoal]: CategoryPerRestTimerLength;
108
+ };
109
+ export type ExercisePriorities = {
110
+ [key in MuscleGroup]: exerciseId[];
111
+ };
112
+ export type ExerciseNotes = {
113
+ [key in exerciseId]: string;
114
+ };
115
+ export interface ExercisePrescription {
116
+ muscle_group: MuscleGroup | 'focus_muscle';
117
+ category: HevyTrainerExerciseCategory;
118
+ warmup_set_count?: number;
119
+ min_workout_duration_limit?: WorkoutDurationMinutes;
120
+ }
121
+ export type ExerciseReplacements = {
122
+ [key in exerciseId]: exerciseId[];
123
+ };
124
+ export interface WorkoutTemplate {
125
+ exercises: ExercisePrescription[];
126
+ notes?: string;
127
+ }
128
+ export type Templates = {
129
+ [key in HevyTrainerRoutineName]: WorkoutTemplate;
130
+ };
131
+ export interface BackofficeTrainerPreset {
132
+ id?: number;
133
+ username: string;
134
+ title?: string;
135
+ is_default?: boolean;
136
+ updated_at?: string;
137
+ settings: TrainerAlgorithmSettings;
138
+ }
139
+ export interface TrainerAlgorithmSettings {
140
+ sets: SetsPerFrequency;
141
+ rep_ranges: RepRanges;
142
+ rest_timers: RestTimers;
143
+ templates: Templates;
144
+ exercise_priorities: ExercisePriorities;
145
+ exercise_notes: ExerciseNotes;
146
+ exercise_replacements: ExerciseReplacements;
147
+ }
148
+ export interface TrainerProgramExercise {
149
+ exerciseTemplate: HevyTrainerLibraryExercise;
150
+ muscleGroup: MuscleGroup | 'focus_muscle';
151
+ category: HevyTrainerExerciseCategory;
152
+ sets: number;
153
+ warmupSetCount?: number;
154
+ repRangeStart: number;
155
+ repRangeEnd: number;
156
+ restTimerSeconds: number;
157
+ notes?: string;
158
+ }
159
+ export interface TrainerProgramRoutine {
160
+ name: HevyTrainerRoutineName;
161
+ exercises: TrainerProgramExercise[];
162
+ notes?: string;
163
+ }
164
+ export interface TrainerProgram {
165
+ name: WeeklyTrainingFrequency;
166
+ routines: TrainerProgramRoutine[];
167
+ }
168
+ export declare const getTrainerSetCount: (trainerAlgorithmSettings: TrainerAlgorithmSettings, goal: TrainingGoal, frequency: WeeklyTrainingFrequency) => number;
169
+ export declare const getTrainerRepRange: (trainerAlgorithmSettings: TrainerAlgorithmSettings, goal: TrainingGoal, exerciseCategory: HevyTrainerExerciseCategory) => RepRange;
170
+ export declare const getTrainerRestTimerSeconds: (trainerAlgorithmSettings: TrainerAlgorithmSettings, goal: TrainingGoal, length: RestTimerLength, exerciseCategory: HevyTrainerExerciseCategory) => number;
171
+ /**
172
+ * Normalizes the exercise category to a HevyTrainerExerciseCategory
173
+ * - Treat custom exercises and exercises with no category as `compound`
174
+ * - Treat `assistance-compound` as `compound`
175
+ * - Treat `isolation` as `isolation`
176
+ * @param exercise - The exercise to normalize the category for
177
+ * @returns The normalized exercise category
178
+ */
179
+ export declare const normalizeExerciseCategory: (exercise: {
180
+ is_custom: boolean;
181
+ category?: ExerciseCategory;
182
+ }) => HevyTrainerExerciseCategory;
183
+ /**
184
+ * Checks if an exercise is compatible with the user's selected granular equipments
185
+ *
186
+ * - If the exercise has no granular equipments, it is compatible no matter what the user has selected
187
+ * - Otherwise, the exercise is only allowed if the user has all the granular equipments
188
+ */
189
+ export declare const isEquipmentCompatible: (exercise: HevyTrainerLibraryExercise, userSelectedGranularEquipments: GranularEquipment[]) => boolean;
190
+ /**
191
+ * Sorts exercises by priority for each muscle group based on the provided priorities
192
+ * and adds any remaining exercises from the store that weren't in the priorities.
193
+ *
194
+ * @param exercisePriorities - Object mapping muscle groups to arrays of exercise IDs in priority order
195
+ * @param exerciseStore - Array of all available exercises
196
+ * @returns Object mapping muscle groups to arrays of exercises sorted by priority
197
+ */
198
+ export declare const getPrioritySortedExercises: <T extends HevyTrainerLibraryExercise>(exercisePriorities: ExercisePriorities, exerciseStore: T[]) => Record<MuscleGroup, T[]>;
199
+ /**
200
+ * Selects the best exercise for a given prescription using a multi-pass strategy
201
+ */
202
+ type PickExerciseResult<T extends HevyTrainerLibraryExercise> = {
203
+ exercise?: T;
204
+ trace: ExerciseSelectionTrace;
205
+ };
206
+ export declare function pickExerciseForPrescription<T extends HevyTrainerLibraryExercise>(params: ExerciseSelectionParams<T> & {
207
+ withTrace: true;
208
+ }): PickExerciseResult<T>;
209
+ export declare function pickExerciseForPrescription<T extends HevyTrainerLibraryExercise>(params: ExerciseSelectionParams<T>): T | undefined;
210
+ export type HevyTrainerLibraryExercise = Pick<LibraryExercise, 'id' | 'title' | 'priority' | 'muscle_group' | 'other_muscles' | 'exercise_type' | 'equipment_category' | 'category' | 'level' | 'goal' | 'granular_equipments'>;
211
+ export interface ExercisePrescriptionError {
212
+ type: 'exercise_not_found';
213
+ prescription: ExercisePrescription;
214
+ muscleGroup: MuscleGroup;
215
+ context: {
216
+ goal: TrainingGoal;
217
+ level: TrainingLevel;
218
+ equipments: GranularEquipment[];
219
+ focusMuscle?: SimplifiedMuscleGroup;
220
+ };
221
+ }
222
+ export interface TrainerProgramExerciseResult {
223
+ success: true;
224
+ exercise: TrainerProgramExercise;
225
+ }
226
+ export interface TrainerProgramExerciseError {
227
+ success: false;
228
+ error: ExercisePrescriptionError;
229
+ }
230
+ export type TrainerProgramExerciseAttempt = TrainerProgramExerciseResult | TrainerProgramExerciseError;
231
+ export interface TrainerProgramResult {
232
+ success: true;
233
+ program: TrainerProgram;
234
+ }
235
+ export interface TrainerProgramError {
236
+ success: false;
237
+ errors: ExercisePrescriptionError[];
238
+ partialProgram: TrainerProgram;
239
+ }
240
+ export type TrainerProgramAttempt = TrainerProgramResult | TrainerProgramError;
241
+ /**
242
+ * Generates a complete training program based on the provided parameters
243
+ * - debugExerciseSelectionTrace: true -> includes exercise selection trace breadcrumbs in the result for debugging.
244
+ * - debugExerciseSelectionTrace: false -> no exercise selection trace breadcrumbs in the result.
245
+ */
246
+ export declare function generateProgram<T extends HevyTrainerLibraryExercise>(params: ProgramGenerationParams<T> & {
247
+ debugExerciseSelectionTrace: true;
248
+ }): TrainerProgramAttemptWithTraces;
249
+ export declare function generateProgram<T extends HevyTrainerLibraryExercise>(params: ProgramGenerationParams<T>): TrainerProgramAttempt;
250
+ export {};