Resolve an exercise's variables into a concrete instance: each variable
in declaration order is taken from options.values if present, else
evaluated (expression) or sampled (min/max/step), then
rounded to its display precision; every reference to a declared variable
is substituted across the whole exercise. Returns the concrete exercise,
the values and the tolerances of pure-reference accept entries. An
exercise without variables (absent, null or empty) comes back as
the same object, literal {{...}} included (a Jinja2 lesson is not
parametric). Never mutates the input. Throws when an expression does not
evaluate (it does not parse, or uses a name declared after it); a lesson
that passes validateLesson has neither.
Resolve an exercise's
variablesinto a concrete instance: each variable in declaration order is taken fromoptions.valuesif present, else evaluated (expression) or sampled (min/max/step), then rounded to its display precision; every reference to a declared variable is substituted across the whole exercise. Returns the concrete exercise, the values and the tolerances of pure-referenceacceptentries. An exercise withoutvariables(absent,nullor empty) comes back as the same object, literal{{...}}included (a Jinja2 lesson is not parametric). Never mutates the input. Throws when an expression does not evaluate (it does not parse, or uses a name declared after it); a lesson that passesvalidateLessonhas neither.