[OCaml] High Intensity Training Online
1
module Muscle = struct
2
type t =
3
| Pecs
4
| Delts
5
| Triceps
6
| Biceps
7
| Forearms
8
| Lats
9
| Traps
10
| Erectors
11
| Quadriceps
12
| Hamstrings
13
| Glutes
14
| Calves
15
| Abdominals
16
17
let equal = ( = )
18
end
19
20
type equipment =
21
| Barbell
22
| Cable
23
| Dumbbell
24
| Machine
25
| Bodyweight
26
| Unspecified
27
28
type movement =
29
| Fly
30
| Crossover
31
| Pec_deck
32
| Press
33
| Lateral_raise
34
| French_press
35
| Pressdown
36
| Dip
37
| Pullover
38
| Pulldown
39
| Row
40
| Chin
41
| Shrug
42
| Hyperextension
43
| Deadlift
44
| Curl
45
| Leg_extension
46
| Leg_press
47
| Squat
48
| Leg_curl
49
| Calf_raise
50
| Sit_up
51
52
type variation =
53
| Standard
54
| Incline
55
| Bent_over
56
| Rear_delt
57
| Lying
58
| Triceps
59
| Close_grip_palms_up
60
| Straight_arm
61
| Preacher
62
63
type key = { equipment : equipment; movement : movement; variation : variation }
64
type id = string
65
type mechanic = Isolation | Compound
66
67
type t = {
68
key : key;
69
id : id;
70
name : string;
71
mechanic : mechanic;
72
muscles : Muscle.t list;
73
}
74
75
let make_key ~equipment ~movement ~variation =
76
{ equipment; movement; variation }
77
78
let key_equal = ( = )
79
let key t = t.key
80
let id t = t.id
81
let name t = t.name
82
let equal a b = key_equal a.key b.key
83
let pp ppf t = Format.pp_print_string ppf t.name
84
85
let iso ~key ~id ~name muscle =
86
{ key; id; name; mechanic = Isolation; muscles = [ muscle ] }
87
88
let comp ~key ~id ~name muscles =
89
{ key; id; name; mechanic = Compound; muscles }
90
91
(* The movements HD1 names, in the order its Ideal Routine introduces them.
92
The stable [id] preserves external serialization. The structured [key] is the
93
catalog identity. [Unspecified] records where HD1 names no equipment. *)
94
let dumbbell_flyes =
95
make_key ~equipment:Dumbbell ~movement:Fly ~variation:Standard
96
97
let cable_crossovers =
98
make_key ~equipment:Cable ~movement:Crossover ~variation:Standard
99
100
let pec_deck =
101
make_key ~equipment:Machine ~movement:Pec_deck ~variation:Standard
102
103
let incline_presses =
104
make_key ~equipment:Unspecified ~movement:Press ~variation:Incline
105
106
let laterals =
107
make_key ~equipment:Unspecified ~movement:Lateral_raise ~variation:Standard
108
109
let bent_over_laterals =
110
make_key ~equipment:Dumbbell ~movement:Lateral_raise ~variation:Bent_over
111
112
let reverse_pec_deck =
113
make_key ~equipment:Machine ~movement:Pec_deck ~variation:Rear_delt
114
115
let lying_french_presses =
116
make_key ~equipment:Unspecified ~movement:French_press ~variation:Lying
117
118
let pressdowns =
119
make_key ~equipment:Cable ~movement:Pressdown ~variation:Standard
120
121
let triceps_machine =
122
make_key ~equipment:Machine ~movement:Press ~variation:Triceps
123
124
let dips = make_key ~equipment:Bodyweight ~movement:Dip ~variation:Standard
125
126
let pullovers =
127
make_key ~equipment:Unspecified ~movement:Pullover ~variation:Standard
128
129
let straight_arm_pulldowns =
130
make_key ~equipment:Cable ~movement:Pulldown ~variation:Straight_arm
131
132
let close_grip_pulldowns =
133
make_key ~equipment:Cable ~movement:Pulldown ~variation:Close_grip_palms_up
134
135
let bent_over_rows =
136
make_key ~equipment:Barbell ~movement:Row ~variation:Bent_over
137
138
let chins = make_key ~equipment:Bodyweight ~movement:Chin ~variation:Standard
139
let shrugs = make_key ~equipment:Unspecified ~movement:Shrug ~variation:Standard
140
141
let hyperextensions =
142
make_key ~equipment:Bodyweight ~movement:Hyperextension ~variation:Standard
143
144
let deadlifts =
145
make_key ~equipment:Barbell ~movement:Deadlift ~variation:Standard
146
147
let curls = make_key ~equipment:Barbell ~movement:Curl ~variation:Standard
148
149
let preacher_curls =
150
make_key ~equipment:Barbell ~movement:Curl ~variation:Preacher
151
152
let leg_extensions =
153
make_key ~equipment:Machine ~movement:Leg_extension ~variation:Standard
154
155
let leg_presses =
156
make_key ~equipment:Machine ~movement:Leg_press ~variation:Standard
157
158
let squats = make_key ~equipment:Barbell ~movement:Squat ~variation:Standard
159
160
let leg_curls =
161
make_key ~equipment:Machine ~movement:Leg_curl ~variation:Standard
162
163
let calf_raises =
164
make_key ~equipment:Unspecified ~movement:Calf_raise ~variation:Standard
165
166
let sit_ups =
167
make_key ~equipment:Bodyweight ~movement:Sit_up ~variation:Standard
168
169
let catalog =
170
[
171
iso ~key:dumbbell_flyes ~id:"dumbbell-flyes" ~name:"Dumbbell Flyes"
172
Muscle.Pecs;
173
iso ~key:cable_crossovers ~id:"cable-crossovers" ~name:"Cable Crossovers"
174
Muscle.Pecs;
175
iso ~key:pec_deck ~id:"pec-deck" ~name:"Pec Deck" Muscle.Pecs;
176
comp ~key:incline_presses ~id:"incline-press" ~name:"Incline Presses"
177
[ Muscle.Pecs; Muscle.Delts; Muscle.Triceps ];
178
iso ~key:laterals ~id:"laterals" ~name:"Laterals" Muscle.Delts;
179
iso ~key:bent_over_laterals ~id:"bent-over-laterals"
180
~name:"Bent-over Dumbbell Laterals" Muscle.Delts;
181
iso ~key:reverse_pec_deck ~id:"reverse-pec-deck"
182
~name:"Pec Deck (rear delts)" Muscle.Delts;
183
iso ~key:lying_french_presses ~id:"lying-french-press"
184
~name:"Lying French Presses" Muscle.Triceps;
185
iso ~key:pressdowns ~id:"pressdowns" ~name:"Pressdowns" Muscle.Triceps;
186
iso ~key:triceps_machine ~id:"triceps-machine" ~name:"Triceps Machine"
187
Muscle.Triceps;
188
comp ~key:dips ~id:"dips" ~name:"Dips"
189
[ Muscle.Triceps; Muscle.Pecs; Muscle.Delts ];
190
iso ~key:pullovers ~id:"pullovers" ~name:"Pullovers" Muscle.Lats;
191
iso ~key:straight_arm_pulldowns ~id:"straight-arm-pulldowns"
192
~name:"Straight-Arm Pulldowns" Muscle.Lats;
193
comp ~key:close_grip_pulldowns ~id:"close-grip-pulldowns"
194
~name:"Close-grip, palms-up Pulldowns"
195
[ Muscle.Lats; Muscle.Biceps; Muscle.Forearms ];
196
comp ~key:bent_over_rows ~id:"bent-over-rows" ~name:"Bent-over Barbell Rows"
197
[ Muscle.Lats; Muscle.Biceps; Muscle.Forearms; Muscle.Erectors ];
198
comp ~key:chins ~id:"chins" ~name:"Chins"
199
[ Muscle.Lats; Muscle.Biceps; Muscle.Forearms ];
200
iso ~key:shrugs ~id:"shrugs" ~name:"Shrugs" Muscle.Traps;
201
iso ~key:hyperextensions ~id:"hyperextensions" ~name:"Hyperextensions"
202
Muscle.Erectors;
203
comp ~key:deadlifts ~id:"deadlifts" ~name:"Deadlifts"
204
[
205
Muscle.Erectors;
206
Muscle.Glutes;
207
Muscle.Hamstrings;
208
Muscle.Quadriceps;
209
Muscle.Traps;
210
];
211
iso ~key:curls ~id:"curls" ~name:"Curls" Muscle.Biceps;
212
iso ~key:preacher_curls ~id:"preacher-curls" ~name:"Preacher Curls"
213
Muscle.Biceps;
214
iso ~key:leg_extensions ~id:"leg-extensions" ~name:"Leg Extensions"
215
Muscle.Quadriceps;
216
comp ~key:leg_presses ~id:"leg-presses" ~name:"Leg Presses"
217
[ Muscle.Quadriceps; Muscle.Glutes; Muscle.Hamstrings ];
218
comp ~key:squats ~id:"squats" ~name:"Squats"
219
[ Muscle.Quadriceps; Muscle.Glutes; Muscle.Hamstrings; Muscle.Erectors ];
220
iso ~key:leg_curls ~id:"leg-curls" ~name:"Leg Curls" Muscle.Hamstrings;
221
iso ~key:calf_raises ~id:"calf-raises" ~name:"Calf Raises" Muscle.Calves;
222
iso ~key:sit_ups ~id:"sit-ups" ~name:"Sit-Ups" Muscle.Abdominals;
223
]
224
225
let find sought =
226
List.find_opt (fun exercise -> key_equal exercise.key sought) catalog
227
228
let find_id sought =
229
List.find_opt (fun exercise -> String.equal exercise.id sought) catalog
230
231
(* Mutually substitutable catalog keys. Grouping guarantees symmetry: every
232
member of a group may stand in for every other. Each group is one of HD1's
233
own "or" lists. *)
234
let substitution_groups =
235
[
236
[ dumbbell_flyes; cable_crossovers; pec_deck ];
237
[ lying_french_presses; pressdowns; triceps_machine ];
238
[ bent_over_laterals; reverse_pec_deck ];
239
[ pullovers; straight_arm_pulldowns ];
240
[ close_grip_pulldowns; bent_over_rows; chins ];
241
[ hyperextensions; deadlifts ];
242
[ curls; preacher_curls ];
243
[ leg_presses; squats ];
244
]
245
246
let group_of exercise =
247
List.find_opt (List.exists (key_equal exercise.key)) substitution_groups
248
|> Option.value ~default:[]
249
250
let permitted_substitutes exercise =
251
group_of exercise
252
|> List.filter (fun key -> not (key_equal key exercise.key))
253
|> List.filter_map find
254
255
let may_substitute ~original ~candidate =
256
List.exists (equal candidate) (permitted_substitutes original)
257
258
let may_pre_exhaust ~isolation ~compound =
259
match (isolation.mechanic, compound.mechanic, isolation.muscles) with
260
| Isolation, Compound, [ target ] ->
261
List.exists (Muscle.equal target) compound.muscles
262
&& List.length compound.muscles >= 2
263
| _ -> false
264