Packages

Reference Elixir validator for WPL (Wellness Plan Language) — JSON Schema + semantic invariants

Current section

Files

Jump to
wpl_validator lib wpl validator rules invalid_prescription.ex
Raw

lib/wpl/validator/rules/invalid_prescription.ex

defmodule WPL.Validator.Rules.InvalidPrescription do
@moduledoc false
use WPL.Validator.Rule
alias WPL.Validator.{Error, WalkContext}
@valid_types MapSet.new(["sets_reps", "time", "distance", "amrap", "continuous", "intervals"])
@impl true
def enter_activity(ctx, activity, path) do
if Map.get(activity, "type") == "exercise" do
check_prescription(ctx, activity, path)
else
ctx
end
end
defp check_prescription(ctx, activity, path) do
prescription = Map.get(activity, "prescription")
if is_map(prescription) do
validate_prescription(ctx, prescription, "#{path}/prescription")
else
ctx
end
end
defp validate_prescription(ctx, p, pres_path) do
case Map.fetch(p, "type") do
:error ->
WalkContext.emit(ctx, %Error{
path: pres_path,
code: :invalid_prescription,
message: "prescription missing 'type'",
severity: :error,
meta: %{reason: :missing_type}
})
{:ok, t} when is_binary(t) ->
if MapSet.member?(@valid_types, t) do
ctx
|> check_sets_reps(p, t, pres_path)
|> check_time(p, t, pres_path)
else
WalkContext.emit(ctx, %Error{
path: pres_path,
code: :invalid_prescription,
message: "unknown prescription type '#{t}'",
severity: :error,
meta: %{reason: :unknown_type, prescription_type: t}
})
end
{:ok, t} ->
WalkContext.emit(ctx, %Error{
path: pres_path,
code: :invalid_prescription,
message: "unknown prescription type '#{t}'",
severity: :error,
meta: %{reason: :unknown_type, prescription_type: t}
})
end
end
defp check_sets_reps(ctx, p, "sets_reps", pres_path) do
if Map.get(p, "sets") == nil and Map.get(p, "reps") == nil do
WalkContext.emit(ctx, %Error{
path: pres_path,
code: :invalid_prescription,
message: "sets_reps prescription requires 'sets' or 'reps'",
severity: :error,
meta: %{reason: :sets_reps_requires_sets_or_reps}
})
else
ctx
end
end
defp check_sets_reps(ctx, _p, _type, _path), do: ctx
defp check_time(ctx, p, "time", pres_path) do
if Map.get(p, "duration") == nil do
WalkContext.emit(ctx, %Error{
path: pres_path,
code: :invalid_prescription,
message: "time prescription requires 'duration'",
severity: :error,
meta: %{reason: :time_requires_duration}
})
else
ctx
end
end
defp check_time(ctx, _p, _type, _path), do: ctx
end