module Form = Dream_html.Form
type fields =
| Single of {
load : float;
reps : int;
extension : Evidence.Stimulus.extension option;
}
| Pair of {
iso_load : float;
iso_reps : int;
comp_load : float;
comp_reps : int;
extension : Evidence.Stimulus.extension option;
}
let extension = function
| "" -> Ok None
| "forced" -> Ok (Some Evidence.Stimulus.Forced_reps)
| "negatives" -> Ok (Some Evidence.Stimulus.Negatives)
| "rest-pause" -> Ok (Some Evidence.Stimulus.Rest_pause)
| "static" -> Ok (Some Evidence.Stimulus.Static_hold)
| _ -> Error "error.extension"
let load value =
match Form.float ~min:0. value with
| Ok value -> Ok value
| Error "error.expected.int" -> Error "error.expected.number"
| Error _ -> Error "error.load"
let reps value =
match Form.int value with
| Error error -> Error error
| Ok value when value > 0 -> Ok value
| Ok _ -> Error "error.reps"
let fields prescription =
let open Form in
match Prescription.Stimulus.delivery prescription with
| Prescription.Stimulus.Single _ ->
let+ load = required load "load"
and+ reps = required reps "reps"
and+ extension = required extension "extension" in
Single { load; reps; extension }
| Prescription.Stimulus.Pre_exhaust _ ->
let+ iso_load = required load "iso_load"
and+ iso_reps = required reps "iso_reps"
and+ comp_load = required load "comp_load"
and+ comp_reps = required reps "comp_reps"
and+ extension = required extension "extension" in
Pair { iso_load; iso_reps; comp_load; comp_reps; extension }
let stimulus prescription =
let open Form in
let* values = fields prescription in
match (Prescription.Stimulus.delivery prescription, values) with
| Prescription.Stimulus.Single exercise, Single { load; reps; extension } ->
let outcome =
match extension with
| None -> Evidence.Stimulus.Positive_failure
| Some extension -> Evidence.Stimulus.Beyond_failure (extension, [])
in
ok
(Evidence.Stimulus.make
(Evidence.Stimulus.Single
(Evidence.Stimulus.Effort.make ~exercise ~load ~reps ~outcome)))
| ( Prescription.Stimulus.Pre_exhaust { isolation; compound },
Pair { iso_load; iso_reps; comp_load; comp_reps; extension } ) ->
let second_outcome =
match extension with
| None -> Evidence.Stimulus.Positive_failure
| Some extension -> Evidence.Stimulus.Beyond_failure (extension, [])
in
let first =
Evidence.Stimulus.Effort.make ~exercise:isolation ~load:iso_load
~reps:iso_reps ~outcome:Evidence.Stimulus.Positive_failure
in
let second =
Evidence.Stimulus.Effort.make ~exercise:compound ~load:comp_load
~reps:comp_reps ~outcome:second_outcome
in
ok (Evidence.Stimulus.make (Evidence.Stimulus.Pair { first; second }))
| _ -> assert false
let override = Form.required Form.bool "override"
(* --- profile --- *)
(* The raw username string; the domain normalizes and validates it downstream. *)
let profile_username = Form.required Form.string "username"
(* Current and new password, both required. Passwords carry no policy here; the
service verifies the current one before storing the new one. *)
let profile_password =
let open Form in
let+ current = required string "current" and+ next = required string "next" in
(current, next)
(* --- application feedback --- *)
let app_feedback = Form.required Form.string "message"
(* --- error presentation --- *)
let message = function
| "error.required" -> "Enter a value."
| "error.expected.number" -> "Enter a valid number."
| "error.expected.int" -> "Enter a valid whole number."
| "error.reps" -> "Enter at least one repetition."
| "error.load" -> "Enter a finite, nonnegative load."
| "error.extension" -> "Select one of the offered endings."
| key -> key
let errors_to_text errors =
errors |> List.map (fun (_, key) -> message key) |> String.concat " "