Question about answer_fn() and question_numeric() #797
-
I am creating a simple learnr exercise with a numerical answer using question_numeric(). As the parameter in the questions is randomly generated and the answer depends on the randomly generated parameter, I need to use the answer_fn() function within the question_numeric(). Specifically, answers within a certain range are all acceptable and the range depends on the parameter. I cannot solve this by specifying tolerance since the acceptable range varies with the parameter. Hence, I need to pass the value of this parameter to the function defined within answer_fn(). The example given in the Help page for question_numeric() below
the function defined within answer_fn() only takes one input (the submitted answer). Is there a way to pass the parameter to the function defined within answer_fn()? Thank you! More specifically, I want to create a question template that asks students to find the probability P(Z < z) for Z ~ N(0,1) using a normal probability table, where the value of z is randomly generated. As the normal table only give values for pnorm(z) for z up to 2 decimal places, if z has 3 or more decimal places, e.g., z = 2.343, then the learnr question should accept any values between pnorm(2.34) and pnorm(2.35) as the correct answer. Thus I need to write an answer_fn() function that takes z as an argument. Does anyone know how to do that? Below is the R codes I made, which doesn't work.
Best Regards, |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
I updated my question above. I describe the function I intended to create in greater detail. |
Beta Was this translation helpful? Give feedback.
-
The core problem you're encountering is that between rendering your tutorial's In other words, when the question is shown to the user, it has to be completely isolated from the code that was used to create the question. This is why The way to get around this is a little tricky. Basically you create the answer function outside of the There's a function in base R that shows you the arguments of a function, called Here's the final code that creates the question you want: # Pick a random z value
z = round(runif(1, min = -3.49, max = 3.49), 3)
# A grading function give the student's `value` and an *arbitrary* `z`
answer_z <- function(value, z) {
z_floor = ifelse(z >= round(z,2), round(z,2), round(z,2) - 0.01)
z_ceiling = ifelse(z <= round(z,2), round(z,2) , round(z,2) + 0.01)
if (value >= pnorm(z_floor) & value <= pnorm(z_ceiling)) {
correct()
}
}
# Assign the literal value of our randomly selected `z` to be used as
# the default value of the grading function's `z` argument
formals(answer_z)$z <- z
question_numeric(
paste0(
"Find the probability $P(Z < ", z, ")$ if ",
"$Z$ has a standard normal distribution N(0,1)? ",
"Keep *4 decimal places*. ",
"(The answer is ~", signif(pnorm(z), 6), ".)"
),
answer_fn(answer_z),
# answer(round(pnorm(z),4), correct = TRUE),
allow_retry = TRUE,
min = 0,
max = 1,
step = 0.0001
) |
Beta Was this translation helpful? Give feedback.
The core problem you're encountering is that between rendering your tutorial's
.Rmd
file and running the Shiny app that the student sees, the question created withquestion_numeric()
is written into static data. While theanswer_fn()
approach lets you define some code that is used to determine whether or not the student's answer is correct, technically in the interim the function body is written out as a character string.In other words, when the question is shown to the user, it has to be completely isolated from the code that was used to create the question. This is why
answer_fn()
needs a function that only takesvalue
as an argument.The way to get around this is a little tricky. Basi…