[OCaml] High Intensity Training Online
refactor Separate feedback from workouts
Feedback can be reported independently of workout completion. Keep it as\ntimestamped typed evidence instead of mutating a workout record.
Changed files
lib/app/service.ml
@@ -124,16 +124,6 @@
124
124
| Error error -> Error (Rejected_edit error)
125
125
| Ok workout -> replace t { record with Repository.workout })
126
126
127
Removed:
let set_feedback t id feedback =
128
Removed:
match R.find t.repo id with
129
Removed:
| None -> Error Unknown_workout
130
Removed:
| Some record -> (
131
Removed:
match
132
Removed:
Evidence.Workout.set_feedback record.Repository.workout feedback
133
Removed:
with
134
Removed:
| Error error -> Error (Rejected_edit error)
135
Removed:
| Ok workout -> replace t { record with Repository.workout })
136
Removed:
137
127
let history t = R.history t.repo
138
128
139
129
let progress t exercise =
lib/app/service.mli
@@ -77,12 +77,6 @@
77
77
Evidence.Stimulus.t ->
78
78
(Repository.record, edit_error) result
79
79
80
Removed:
val set_feedback :
81
Removed:
t ->
82
Removed:
Repository.workout_id ->
83
Removed:
Evidence.Workout.Feedback.t ->
84
Removed:
(Repository.record, edit_error) result
85
Removed:
86
80
val history : t -> Repository.record list
87
81
88
82
val progress :
lib/core/evidence.ml
@@ -71,65 +71,53 @@
71
71
Format.fprintf ppf "%a then %a" Movement.pp first Movement.pp second
72
72
end
73
73
74
Removed:
module Workout = struct
75
Removed:
type shape = As_single | As_pair
76
Removed:
type completeness = Complete | Incomplete
74
Added:
module Feedback = struct
75
Added:
type level = Below_usual | Usual | Above_usual
77
76
78
Removed:
module Feedback = struct
79
Removed:
type sleep = Sleep_poor | Sleep_ordinary | Sleep_good
80
Removed:
type appetite = Appetite_reduced | Appetite_ordinary | Appetite_increased
77
Added:
type signal =
78
Added:
| Sleep of level
79
Added:
| Appetite of level
80
Added:
| Readiness of level
81
Added:
| Motivation of level
82
Added:
| Difficulty of level
83
Added:
| Pain
84
Added:
| Injury
85
Added:
| Preparation_insufficient
81
86
82
Removed:
type illness_stress =
83
Removed:
| No_illness_or_stress
84
Removed:
| Illness
85
Removed:
| Stress
86
Removed:
| Illness_and_stress
87
Added:
type t = { reported_at : Recovery.timestamp; signals : signal list }
88
Added:
type error = Duplicate_signal of signal
87
89
88
Removed:
type motivation = Motivation_low | Motivation_ordinary | Motivation_high
89
Removed:
type recovery = Recovery_poor | Recovery_ordinary | Recovery_good
90
Added:
let same_category left right =
91
Added:
match (left, right) with
92
Added:
| Sleep _, Sleep _
93
Added:
| Appetite _, Appetite _
94
Added:
| Readiness _, Readiness _
95
Added:
| Motivation _, Motivation _
96
Added:
| Difficulty _, Difficulty _
97
Added:
| Pain, Pain
98
Added:
| Injury, Injury
99
Added:
| Preparation_insufficient, Preparation_insufficient ->
100
Added:
true
101
Added:
| _ -> false
90
102
91
Removed:
type difficulty =
92
Removed:
| Difficulty_easier
93
Removed:
| Difficulty_expected
94
Removed:
| Difficulty_harder
103
Added:
let make ~reported_at signals =
104
Added:
let rec validate seen = function
105
Added:
| [] -> Ok { reported_at; signals }
106
Added:
| signal :: rest ->
107
Added:
if List.exists (same_category signal) seen then
108
Added:
Error (Duplicate_signal signal)
109
Added:
else validate (signal :: seen) rest
110
Added:
in
111
Added:
validate [] signals
95
112
96
Removed:
type t = {
97
Removed:
sleep : sleep;
98
Removed:
appetite : appetite;
99
Removed:
illness_stress : illness_stress;
100
Removed:
pain_injury : bool;
101
Removed:
pain_detail : string option;
102
Removed:
motivation : motivation;
103
Removed:
recovery : recovery;
104
Removed:
difficulty : difficulty;
105
Removed:
note : string option;
106
Removed:
}
113
Added:
let reported_at t = t.reported_at
114
Added:
let signals t = t.signals
115
Added:
end
107
116
108
Removed:
let make ~sleep ~appetite ~illness_stress ~pain_injury ?pain_detail
109
Removed:
~motivation ~recovery ~difficulty ?note () =
110
Removed:
{
111
Removed:
sleep;
112
Removed:
appetite;
113
Removed:
illness_stress;
114
Removed:
pain_injury;
115
Removed:
pain_detail;
116
Removed:
motivation;
117
Removed:
recovery;
118
Removed:
difficulty;
119
Removed:
note;
120
Removed:
}
117
Added:
module Workout = struct
118
Added:
type shape = As_single | As_pair
119
Added:
type completeness = Complete | Incomplete
121
120
122
Removed:
let sleep t = t.sleep
123
Removed:
let appetite t = t.appetite
124
Removed:
let illness_stress t = t.illness_stress
125
Removed:
let pain_injury t = t.pain_injury
126
Removed:
let pain_detail t = t.pain_detail
127
Removed:
let motivation t = t.motivation
128
Removed:
let recovery t = t.recovery
129
Removed:
let difficulty t = t.difficulty
130
Removed:
let note t = t.note
131
Removed:
end
132
Removed:
133
121
type error =
134
122
| Not_prescribed of Exercise.id
135
123
| Delivery_mismatch of {
@@ -144,7 +132,6 @@
144
132
clearance : Recovery.clearance;
145
133
started_at : Recovery.timestamp;
146
134
ended_at : Recovery.timestamp option;
147
Removed:
feedback : Feedback.t option;
148
135
performed : (int * Stimulus.t) list;
149
136
}
150
137
@@ -163,21 +150,13 @@
163
150
| Not_finished -> Format.pp_print_string ppf "this workout is not finished"
164
151
165
152
let start prescription ~clearance ~started_at =
166
Removed:
{
167
Removed:
prescription;
168
Removed:
clearance;
169
Removed:
started_at;
170
Removed:
ended_at = None;
171
Removed:
feedback = None;
172
Removed:
performed = [];
173
Removed:
}
153
Added:
{ prescription; clearance; started_at; ended_at = None; performed = [] }
174
154
175
155
let prescription t = t.prescription
176
156
let clearance t = t.clearance
177
157
let started_at t = t.started_at
178
158
let ended_at t = t.ended_at
179
159
let is_finished t = Option.is_some t.ended_at
180
Removed:
let feedback t = t.feedback
181
160
let stimuli t = List.map snd (List.rev t.performed)
182
161
183
162
let duration t =
@@ -252,11 +231,6 @@
252
231
match t.ended_at with
253
232
| None -> { t with ended_at = Some ended_at }
254
233
| Some _ -> t
255
Removed:
256
Removed:
let set_feedback t feedback =
257
Removed:
match t.ended_at with
258
Removed:
| None -> Error Not_finished
259
Removed:
| Some _ -> Ok { t with feedback = Some feedback }
260
234
261
235
let pp ppf t =
262
236
Format.fprintf ppf "%a (%d of %d)" Prescription.Workout.pp t.prescription
lib/core/evidence.mli
@@ -51,56 +51,34 @@
51
51
val pp : Format.formatter -> t -> unit
52
52
end
53
53
54
Added:
(** Typed signals reported at a point in time. *)
55
Added:
module Feedback : sig
56
Added:
type level = Below_usual | Usual | Above_usual
57
Added:
58
Added:
type signal =
59
Added:
| Sleep of level
60
Added:
| Appetite of level
61
Added:
| Readiness of level
62
Added:
| Motivation of level
63
Added:
| Difficulty of level
64
Added:
| Pain
65
Added:
| Injury
66
Added:
| Preparation_insufficient
67
Added:
68
Added:
type t
69
Added:
type error = Duplicate_signal of signal
70
Added:
71
Added:
val make : reported_at:Recovery.timestamp -> signal list -> (t, error) result
72
Added:
val reported_at : t -> Recovery.timestamp
73
Added:
val signals : t -> signal list
74
Added:
end
75
Added:
54
76
(** A performed or in-progress prescribed workout. *)
55
77
module Workout : sig
56
78
type t
57
79
type shape = As_single | As_pair
58
80
type completeness = Complete | Incomplete
59
81
60
Removed:
module Feedback : sig
61
Removed:
type sleep = Sleep_poor | Sleep_ordinary | Sleep_good
62
Removed:
type appetite = Appetite_reduced | Appetite_ordinary | Appetite_increased
63
Removed:
64
Removed:
type illness_stress =
65
Removed:
| No_illness_or_stress
66
Removed:
| Illness
67
Removed:
| Stress
68
Removed:
| Illness_and_stress
69
Removed:
70
Removed:
type motivation = Motivation_low | Motivation_ordinary | Motivation_high
71
Removed:
type recovery = Recovery_poor | Recovery_ordinary | Recovery_good
72
Removed:
73
Removed:
type difficulty =
74
Removed:
| Difficulty_easier
75
Removed:
| Difficulty_expected
76
Removed:
| Difficulty_harder
77
Removed:
78
Removed:
type t
79
Removed:
80
Removed:
val make :
81
Removed:
sleep:sleep ->
82
Removed:
appetite:appetite ->
83
Removed:
illness_stress:illness_stress ->
84
Removed:
pain_injury:bool ->
85
Removed:
?pain_detail:string ->
86
Removed:
motivation:motivation ->
87
Removed:
recovery:recovery ->
88
Removed:
difficulty:difficulty ->
89
Removed:
?note:string ->
90
Removed:
unit ->
91
Removed:
t
92
Removed:
93
Removed:
val sleep : t -> sleep
94
Removed:
val appetite : t -> appetite
95
Removed:
val illness_stress : t -> illness_stress
96
Removed:
val pain_injury : t -> bool
97
Removed:
val pain_detail : t -> string option
98
Removed:
val motivation : t -> motivation
99
Removed:
val recovery : t -> recovery
100
Removed:
val difficulty : t -> difficulty
101
Removed:
val note : t -> string option
102
Removed:
end
103
Removed:
104
82
type error =
105
83
| Not_prescribed of Exercise.id
106
84
| Delivery_mismatch of {
@@ -124,9 +102,6 @@
124
102
val finish : t -> ended_at:Recovery.timestamp -> t
125
103
(** Sets [ended_at] once; later calls retain the first value. *)
126
104
127
Removed:
val set_feedback : t -> Feedback.t -> (t, error) result
128
Removed:
(** Requires a finished workout. *)
129
Removed:
130
105
val prescription : t -> Prescription.Workout.t
131
106
val clearance : t -> Recovery.clearance
132
107
val started_at : t -> Recovery.timestamp
@@ -134,7 +109,6 @@
134
109
val is_finished : t -> bool
135
110
val duration : t -> Recovery.duration option
136
111
val completeness : t -> completeness
137
Removed:
val feedback : t -> Feedback.t option
138
112
139
113
val stimuli : t -> Stimulus.t list
140
114
(** Performance order. *)
lib/web/pages.ml
@@ -443,12 +443,7 @@
443
443
Printf.sprintf "ended %d"
444
444
(Recovery.timestamp_to_unix_seconds time)
445
445
in
446
Removed:
let feedback =
447
Removed:
if Option.is_some (Evidence.Workout.feedback w) then
448
Removed:
"; feedback saved"
449
Removed:
else "; no feedback"
450
Removed:
in
451
Removed:
ended ^ "; " ^ completeness ^ feedback
446
Added:
ended ^ "; " ^ completeness
452
447
in
453
448
li
454
449
[
@@ -467,76 +462,4 @@
467
462
(Evidence.Workout.stimuli w));
468
463
])
469
464
records));
470
Removed:
]
471
Removed:
472
Removed:
let feedback ~record =
473
Removed:
let option name values =
474
Removed:
match
475
Removed:
List.map
476
Removed:
(fun (value, label) -> Form.Option ([], value, Some (txt label), false))
477
Removed:
values
478
Removed:
with
479
Removed:
| first :: rest -> Form.select ~name Form.string first rest
480
Removed:
| [] -> assert false
481
Removed:
in
482
Removed:
shell ~title:"Workout feedback"
483
Removed:
[
484
Removed:
h2 [ txt "Workout complete" ];
485
Removed:
p
486
Removed:
[
487
Removed:
txt "Record any context; this feedback is not scored or interpreted.";
488
Removed:
];
489
Removed:
Form.post_form ~service:Routes.feedback
490
Removed:
(fun (workout, rest) ->
491
Removed:
let sleep, rest = rest in
492
Removed:
let appetite, rest = rest in
493
Removed:
let illness_stress, rest = rest in
494
Removed:
let pain, rest = rest in
495
Removed:
let pain_detail, rest = rest in
496
Removed:
let motivation, rest = rest in
497
Removed:
let recovery, rest = rest in
498
Removed:
let difficulty, note = rest in
499
Removed:
[
500
Removed:
Form.input ~input_type:`Hidden ~name:workout
501
Removed:
~value:(record.Repository.id :> string)
502
Removed:
Form.string;
503
Removed:
label [ txt "Sleep" ];
504
Removed:
option sleep
505
Removed:
[ ("poor", "poor"); ("ordinary", "ordinary"); ("good", "good") ];
506
Removed:
label [ txt "Appetite" ];
507
Removed:
option appetite
508
Removed:
[
509
Removed:
("reduced", "reduced");
510
Removed:
("ordinary", "ordinary");
511
Removed:
("increased", "increased");
512
Removed:
];
513
Removed:
label [ txt "Illness or stress" ];
514
Removed:
option illness_stress
515
Removed:
[
516
Removed:
("none", "none");
517
Removed:
("illness", "illness");
518
Removed:
("stress", "stress");
519
Removed:
("both", "both");
520
Removed:
];
521
Removed:
label [ txt "Pain or injury" ];
522
Removed:
Form.input ~input_type:`Checkbox ~name:pain Form.bool;
523
Removed:
Form.input ~input_type:`Text ~name:pain_detail Form.string;
524
Removed:
label [ txt "Motivation" ];
525
Removed:
option motivation
526
Removed:
[ ("low", "low"); ("ordinary", "ordinary"); ("high", "high") ];
527
Removed:
label [ txt "Perceived recovery" ];
528
Removed:
option recovery
529
Removed:
[ ("poor", "poor"); ("ordinary", "ordinary"); ("good", "good") ];
530
Removed:
label [ txt "Exercise difficulty" ];
531
Removed:
option difficulty
532
Removed:
[
533
Removed:
("easier", "easier");
534
Removed:
("expected", "expected");
535
Removed:
("harder", "harder");
536
Removed:
];
537
Removed:
label [ txt "Overall note" ];
538
Removed:
Form.input ~input_type:`Text ~name:note Form.string;
539
Removed:
Form.input ~input_type:`Submit ~value:"Save feedback" Form.string;
540
Removed:
])
541
Removed:
();
542
465
]
lib/web/pages.mli
@@ -23,6 +23,5 @@
23
23
page
24
24
25
25
val log_workout : record_id:string option -> workout:Evidence.Workout.t -> page
26
Removed:
val feedback : record:Repository.record -> page
27
26
val history : records:Repository.record list -> page
28
27
val problem : title:string -> detail:string -> page
lib/web/routes.ml
@@ -101,19 +101,6 @@
101
101
(Eliom_parameter.unit, Eliom_parameter.(string "routine")))
102
102
()
103
103
104
Removed:
(* POST /feedback — attach categorical feedback to a finished workout. *)
105
Removed:
let feedback =
106
Removed:
Eliom_service.create ~path:(Eliom_service.Path [ "feedback" ])
107
Removed:
~meth:
108
Removed:
(Eliom_service.Post
109
Removed:
( Eliom_parameter.unit,
110
Removed:
Eliom_parameter.(
111
Removed:
string "workout" ** string "sleep" ** string "appetite"
112
Removed:
** string "illness_stress" ** bool "pain" ** string "pain_detail"
113
Removed:
** string "motivation" ** string "recovery" ** string "difficulty"
114
Removed:
** string "note") ))
115
Removed:
()
116
Removed:
117
104
(* GET /edit — add prescribed records to a saved workout without changing its end. *)
118
105
let edit =
119
106
Eliom_service.create ~path:(Eliom_service.Path [ "edit" ])
lib/web/services.ml
@@ -106,71 +106,6 @@
106
106
if text = "" then None else Some text
107
107
in
108
108
109
Removed:
let feedback_of_strings ~sleep:sleep_text ~appetite:appetite_text
110
Removed:
~illness_stress:illness_stress_text ~pain ~pain_detail:pain_detail_text
111
Removed:
~motivation:motivation_text ~recovery:recovery_text
112
Removed:
~difficulty:difficulty_text ~note:note_text =
113
Removed:
let open Evidence.Workout.Feedback in
114
Removed:
let sleep =
115
Removed:
match sleep_text with
116
Removed:
| "poor" -> Some Sleep_poor
117
Removed:
| "ordinary" -> Some Sleep_ordinary
118
Removed:
| "good" -> Some Sleep_good
119
Removed:
| _ -> None
120
Removed:
in
121
Removed:
let appetite =
122
Removed:
match appetite_text with
123
Removed:
| "reduced" -> Some Appetite_reduced
124
Removed:
| "ordinary" -> Some Appetite_ordinary
125
Removed:
| "increased" -> Some Appetite_increased
126
Removed:
| _ -> None
127
Removed:
in
128
Removed:
let illness_stress =
129
Removed:
match illness_stress_text with
130
Removed:
| "none" -> Some No_illness_or_stress
131
Removed:
| "illness" -> Some Illness
132
Removed:
| "stress" -> Some Stress
133
Removed:
| "both" -> Some Illness_and_stress
134
Removed:
| _ -> None
135
Removed:
in
136
Removed:
let motivation =
137
Removed:
match motivation_text with
138
Removed:
| "low" -> Some Motivation_low
139
Removed:
| "ordinary" -> Some Motivation_ordinary
140
Removed:
| "high" -> Some Motivation_high
141
Removed:
| _ -> None
142
Removed:
in
143
Removed:
let recovery =
144
Removed:
match recovery_text with
145
Removed:
| "poor" -> Some Recovery_poor
146
Removed:
| "ordinary" -> Some Recovery_ordinary
147
Removed:
| "good" -> Some Recovery_good
148
Removed:
| _ -> None
149
Removed:
in
150
Removed:
let difficulty =
151
Removed:
match difficulty_text with
152
Removed:
| "easier" -> Some Difficulty_easier
153
Removed:
| "expected" -> Some Difficulty_expected
154
Removed:
| "harder" -> Some Difficulty_harder
155
Removed:
| _ -> None
156
Removed:
in
157
Removed:
match
158
Removed:
(sleep, appetite, illness_stress, motivation, recovery, difficulty)
159
Removed:
with
160
Removed:
| ( Some sleep,
161
Removed:
Some appetite,
162
Removed:
Some illness_stress,
163
Removed:
Some motivation,
164
Removed:
Some recovery,
165
Removed:
Some difficulty ) ->
166
Removed:
Some
167
Removed:
(make ~sleep ~appetite ~illness_stress ~pain_injury:pain
168
Removed:
?pain_detail:(optional_text pain_detail_text)
169
Removed:
~motivation ~recovery ~difficulty ?note:(optional_text note_text)
170
Removed:
())
171
Removed:
| _ -> None
172
Removed:
in
173
Removed:
174
109
(* The slot names which prescribed stimulus is being answered. *)
175
110
let target_workout workout_id =
176
111
if workout_id = "" then
@@ -297,34 +232,8 @@
297
232
298
233
Eliom_registration.Html.register ~service:Routes.finish (fun () () ->
299
234
match Service.finish service ~ended_at:(now ()) with
300
Removed:
| Some record -> Lwt.return (Pages.feedback ~record)
235
Added:
| Some _ -> Lwt.return (Pages.history ~records:(Service.history service))
301
236
| None ->
302
237
Lwt.return
303
238
(Pages.problem ~title:"No workout in progress"
304
Removed:
~detail:"There was nothing to finish."));
305
Removed:
306
Removed:
Eliom_registration.Html.register ~service:Routes.feedback
307
Removed:
(fun () (workout, rest) ->
308
Removed:
let sleep, rest = rest in
309
Removed:
let appetite, rest = rest in
310
Removed:
let illness_stress, rest = rest in
311
Removed:
let pain, rest = rest in
312
Removed:
let pain_detail, rest = rest in
313
Removed:
let motivation, rest = rest in
314
Removed:
let recovery, rest = rest in
315
Removed:
let difficulty, note = rest in
316
Removed:
let id = Repository.workout_id workout in
317
Removed:
Lwt.return
318
Removed:
(match
319
Removed:
feedback_of_strings ~sleep ~appetite ~illness_stress ~pain
320
Removed:
~pain_detail ~motivation ~recovery ~difficulty ~note
321
Removed:
with
322
Removed:
| None ->
323
Removed:
Pages.problem ~title:"Invalid feedback"
324
Removed:
~detail:"Choose one of the offered answers."
325
Removed:
| Some feedback -> (
326
Removed:
match Service.set_feedback service id feedback with
327
Removed:
| Ok _ -> Pages.history ~records:(Service.history service)
328
Removed:
| Error _ ->
329
Removed:
Pages.problem ~title:"Could not save feedback"
330
Removed:
~detail:"The finished workout was not found.")))
239
Added:
~detail:"There was nothing to finish."))
test/test_evidence.ml
@@ -465,41 +465,35 @@
465
465
Alcotest.(check (option string))
466
466
"note" (Some "controlled negative")
467
467
(Stimulus.note (List.hd (Workout.stimuli workout))) );
468
Removed:
( "feedback requires finish and completeness updates after later edits",
468
Added:
( "feedback rejects duplicate signal categories",
469
469
`Quick,
470
470
fun () ->
471
Added:
let open Feedback in
472
Added:
match
473
Added:
make ~reported_at:(at 60) [ Sleep Below_usual; Sleep Above_usual ]
474
Added:
with
475
Added:
| Error (Duplicate_signal (Sleep Above_usual)) -> ()
476
Added:
| _ -> Alcotest.fail "expected duplicate sleep rejection" );
477
Added:
( "feedback retains its report time and signals",
478
Added:
`Quick,
479
Added:
fun () ->
480
Added:
let open Feedback in
471
481
let feedback =
472
Removed:
Workout.Feedback.make ~sleep:Workout.Feedback.Sleep_good
473
Removed:
~appetite:Workout.Feedback.Appetite_ordinary
474
Removed:
~illness_stress:Workout.Feedback.No_illness_or_stress
475
Removed:
~pain_injury:false ~motivation:Workout.Feedback.Motivation_high
476
Removed:
~recovery:Workout.Feedback.Recovery_good
477
Removed:
~difficulty:Workout.Feedback.Difficulty_expected ()
482
Added:
ok
483
Added:
(make ~reported_at:(at 60)
484
Added:
[
485
Added:
Sleep Above_usual;
486
Added:
Appetite Usual;
487
Added:
Readiness Above_usual;
488
Added:
Motivation Above_usual;
489
Added:
Difficulty Usual;
490
Added:
Preparation_insufficient;
491
Added:
])
478
492
in
479
Removed:
Alcotest.(check bool)
480
Removed:
"feedback rejected before finish" true
481
Removed:
(Result.is_error (Workout.set_feedback (fresh ()) feedback));
482
Removed:
let workout = Workout.finish (fresh ()) ~ended_at:(at 60) in
483
Removed:
let workout = ok (Workout.set_feedback workout feedback) in
484
Removed:
Alcotest.(check bool)
485
Removed:
"incomplete" true
486
Removed:
(match Workout.completeness workout with
487
Removed:
| Workout.Incomplete -> true
488
Removed:
| Complete -> false);
489
Removed:
let workout =
490
Removed:
List.fold_left
491
Removed:
(fun w stimulus -> ok (Workout.add_stimulus w stimulus))
492
Removed:
workout day_one_stimuli
493
Removed:
in
494
Removed:
Alcotest.(check bool)
495
Removed:
"complete after edits" true
496
Removed:
(match Workout.completeness workout with
497
Removed:
| Workout.Complete -> true
498
Removed:
| Incomplete -> false);
499
493
Alcotest.(check int)
500
Removed:
"end time retained" 60
501
Removed:
(Recovery.timestamp_to_unix_seconds
502
Removed:
(Option.get (Workout.ended_at workout))) );
494
Added:
"report time" 60
495
Added:
(Recovery.timestamp_to_unix_seconds (reported_at feedback));
496
Added:
Alcotest.(check int) "six signals" 6 (List.length (signals feedback)) );
503
497
]
504
498
505
499
let suite =
test/test_service.ml
@@ -194,15 +194,6 @@
194
194
let s = service () in
195
195
ignore (ok (S.begin_workout s ~routine:ideal ~now:(day 1) ()));
196
196
let record = Option.get (S.finish s ~ended_at:(at 120)) in
197
Removed:
let feedback =
198
Removed:
Workout.Feedback.make ~sleep:Workout.Feedback.Sleep_ordinary
199
Removed:
~appetite:Workout.Feedback.Appetite_ordinary
200
Removed:
~illness_stress:Workout.Feedback.No_illness_or_stress
201
Removed:
~pain_injury:false ~motivation:Workout.Feedback.Motivation_ordinary
202
Removed:
~recovery:Workout.Feedback.Recovery_ordinary
203
Removed:
~difficulty:Workout.Feedback.Difficulty_expected ()
204
Removed:
in
205
Removed:
let record = ok (S.set_feedback s record.Repository.id feedback) in
206
197
let record =
207
198
List.fold_left
208
199
(fun record stimulus ->
@@ -217,10 +208,7 @@
217
208
Alcotest.(check int)
218
209
"original end" 120
219
210
(Recovery.timestamp_to_unix_seconds
220
Removed:
(Option.get (Workout.ended_at record.Repository.workout)));
221
Removed:
Alcotest.(check bool)
222
Removed:
"feedback retained" true
223
Removed:
(Option.is_some (Workout.feedback record.Repository.workout)) );
211
Added:
(Option.get (Workout.ended_at record.Repository.workout))) );
224
212
]
225
213
226
214
let assessment_tests =