fix diagnose excess recorded volume

Keep extra recorded work visible in the log while naming it as an overtraining risk. Add a closed diagnostic case and test it without changing authored prescriptions.

Commit
fab9d31d4eb6eceacae5059edfd1a422b0006ab7
Author
Marius Peter <dev@marius-peter.com>
Author date
Committer
Marius Peter <dev@marius-peter.com>
Committer date
Changed files
lib/core/progression.ml
index 4c3d28a7..5b1969cb 100644..100644
@@ -102,9 +102,14 @@
102 102 | Too_heavy -> Format.pp_print_string ppf "load is too heavy for the window"
103 103
104 104 type diagnostic =
105 Added: | Excess_volume of int
105 106 | Extensions_on_every_stimulus of int
106 107 | Trained_under_recovered of int
107 108
109 Added: let excess_volume workout =
110 Added: List.length (Evidence.Workout.stimuli workout)
111 Added: > Evidence.Workout.filled_slots workout
112 Added:
108 113 let all_extended workout =
109 114 match Evidence.Workout.stimuli workout with
110 115 | [] -> false
@@ -118,13 +123,17 @@
118 123 let diagnose log =
119 124 let workouts = Evidence.Log.workouts log in
120 125 let count predicate = List.length (List.filter predicate workouts) in
126 Added: let excessive = count excess_volume in
121 127 let extended = count all_extended in
122 128 let overridden = count under_recovered in
123 129 let when_present n d = if n > 0 then [ d n ] else [] in
124 Removed: when_present extended (fun n -> Extensions_on_every_stimulus n)
130 Added: when_present excessive (fun n -> Excess_volume n)
131 Added: @ when_present extended (fun n -> Extensions_on_every_stimulus n)
125 132 @ when_present overridden (fun n -> Trained_under_recovered n)
126 133
127 134 let pp_diagnostic ppf = function
135 Added: | Excess_volume n ->
136 Added: Format.fprintf ppf "%d workout(s) recorded more stimuli than prescribed" n
128 137 | Extensions_on_every_stimulus n ->
129 138 Format.fprintf ppf "%d workout(s) extended every stimulus beyond failure"
130 139 n
lib/core/progression.mli
index 5963b71f..c6623434 100644..100644
@@ -44,7 +44,9 @@
44 44
45 45 val pp_load_verdict : Format.formatter -> load_verdict -> unit
46 46
47 Added: (** Counts recorded workouts that show each overtraining risk. *)
47 48 type diagnostic =
49 Added: | Excess_volume of int
48 50 | Extensions_on_every_stimulus of int
49 51 | Trained_under_recovered of int
50 52
test/test_progression.ml
index b18295b0..02f8629b 100644..100644
@@ -203,9 +203,11 @@
203 203 (Workout.start prescribed ~clearance ~started_at:(day 1))
204 204 stimuli
205 205
206 Removed: let laterals ?outcome load r =
207 Removed: Stimulus.make (Stimulus.Single (move ?outcome ~id:"laterals" load r))
206 Added: let stimulus ?outcome id load r =
207 Added: Stimulus.make (Stimulus.Single (move ?outcome ~id load r))
208 208
209 Added: let laterals ?outcome load r = stimulus ?outcome "laterals" load r
210 Added:
209 211 let extended =
210 212 Stimulus.Beyond_failure (Stimulus.Forced_reps, [ Stimulus.Negatives ])
211 213
@@ -219,6 +221,17 @@
219 221 "none" 0
220 222 (List.length
221 223 (Progression.diagnose (Evidence.Log.add Evidence.Log.empty w))) );
224 Added: ( "extra recorded volume is flagged",
225 Added: `Quick,
226 Added: fun () ->
227 Added: let w =
228 Added: performed ~clearance:cleared
229 Added: ~stimuli:[ laterals 12. 8; laterals 12. 6 ]
230 Added: in
231 Added: match Progression.diagnose (Evidence.Log.add Evidence.Log.empty w) with
232 Added: | [ Progression.Excess_volume n ] ->
233 Added: Alcotest.(check int) "one workout" 1 n
234 Added: | _ -> Alcotest.fail "expected the excess-volume diagnostic" );
222 235 ( "extending every stimulus is flagged",
223 236 `Quick,
224 237 fun () ->
@@ -235,7 +248,11 @@
235 248 fun () ->
236 249 let w =
237 250 performed ~clearance:cleared
238 Removed: ~stimuli:[ laterals ~outcome:extended 12. 8; laterals 10. 9 ]
251 Added: ~stimuli:
252 Added: [
253 Added: laterals ~outcome:extended 12. 8;
254 Added: stimulus "bent-over-laterals" 10. 9;
255 Added: ]
239 256 in
240 257 Alcotest.(check int)
241 258 "none" 0