Search code examples
rshinylearnr

Programmatically create a question_text with multiple answers in r learnr:tutorial


I have the following code with 4 correct answers. I want the students to input all 4 of them. Instead of defining 24 permutations of the answers, I want 4 field boxes that would only accept an answer once.

question_text(
  "Input all paths:",
    answer("ABEF", correct = TRUE),
    answer("ABCDG", correct = TRUE),
    answer("ABCDEF",correct = TRUE),
    answer("ABDEF", correct = TRUE),
    incorrect = "Direction from top to bottom of the plate",
  allow_retry = TRUE,
  trim = TRUE
)

EDIT

I tried this approach but I do not think I can set the answer as anything other than a single text:

library(gtools)
pat <- permutations(4, 4, c("ABEF","ABCDG","ABCDEF","ABDEF"))
question_text(
  "Input all possible rupture paths:",
    answer(pat, correct = TRUE),
  allow_retry = TRUE,
  trim = TRUE
)

Even if I set pat <- c("ABEF","ABCDG","ABCDEF","ABDEF") it does not run successfully. How can define multiple answers at the same time without writing them out.


Solution

  • I'm not sure about your desired output - however, please check the following.

    Referring to:

    How can define multiple answers at the same time without writing them out.

    You can use lapply to create the answers and do.call to pass the different arguments to question_text:

    library(learnr)
    
    do.call(question_text, c(
      list("Input all paths:"),
      lapply(c("ABEF", "ABCDG", "ABCDEF", "ABDEF"), answer, correct = TRUE),
      list(
        incorrect = "Direction from top to bottom of the plate",
        allow_retry = TRUE,
        trim = TRUE
      )
    ))
    

    as *.Rmd file:

    ---
    title: "Tutorial"
    output: learnr::tutorial
    runtime: shiny_prerendered
    ---
    
    ```{r setup, include=FALSE}
    library(learnr)
    knitr::opts_chunk$set(echo = FALSE)
    ```
    
    
    ```{r two-plus-two, exercise=FALSE}
    do.call(question_text, c(
      list("Input all paths:"),
      lapply(c("ABEF", "ABCDG", "ABCDEF", "ABDEF"), answer, correct = TRUE),
      list(
        incorrect = "Direction from top to bottom of the plate",
        allow_retry = TRUE,
        trim = TRUE
      )
    ))
    ```
    

    result

    Regarding:

    I want 4 field boxes that would only accept an answer once

    Edit: Added an event handler to access to the answers provided by the user.

    ---
    title: "Tutorial"
    output: learnr::tutorial
    runtime: shiny_prerendered
    ---
    
    ```{r setup, include=FALSE}
    library(learnr)
    knitr::opts_chunk$set(echo = FALSE)
    
    questions <-
      mapply(
        FUN = question_text,
        lapply(c("ABEF", "ABCDG", "ABCDEF", "ABDEF"), answer, correct = TRUE),
        text = paste("Question", 1:4),
        incorrect = paste("Incorrect", 1:4),
        MoreArgs = list(allow_retry = TRUE,
                        trim = TRUE),
        SIMPLIFY = FALSE
      )
    ```
    
    ```{r q1, echo = FALSE}
    do.call(quiz, c(list(caption = "Quiz 1"), questions))
    ```
    
    ```{r context="server-start"}
    event_register_handler("question_submission", function(session, event, data) {
      # names(data):
      # "label"    "question" "answer"   "correct"
      message("event: question_submission: ", data$answer)
    })
    ```
    

    result2