Home > Enterprise >  How to score a learnr tutorial in R by the author?
How to score a learnr tutorial in R by the author?

Time:11-05

I am trying to create a quiz app using learnr package in R.I want to score the candidate at the or in progress and save the score in RData format.

I think the function ,get_tutorial_state(), may help but I don't know how to use it in my code.

Below is my code. Any help is appreciated.

---
title: "Quiz"
output:
  learnr::tutorial:
    progressive: true
    allow_skip: true
    language:
      en:
        button:
          nexttopic: Next Question
          previoustopic: Previous Question
runtime: shiny_prerendered
 
  
---
library(learnr)
knitr::opts_chunk$set(echo = FALSE)

Question 1

question("Check all that you have NOT done:",
  answer("installed R on my computer", message = "* Install R"),
  answer("installed the RStudio IDE", message = "* Install RStudio IDE"),
  answer("installed the tidyverse R package", message = "* Install Packages"),
  answer("None of the above. I've done them all.", correct = TRUE, message = "You can skip this tutorial!"),
  type = "multiple",
  incorrect = "This tutorial is here to help! To get set up read:"
)

Question 2

question("Where do you download R?",
    answer("www.rstudio.com/download"),
    answer("[cloud.r-project.org](http://cloud.r-project.org)", correct = TRUE, message = "You can also download R from [cran.r-project.org](http://cran.r-project.org)"),
    answer("www.r-project.org", message = "Good try, but not exactly. www.r-project.org doesn't provide a download link, but it does provide a link to one the websites above."),
    answer("www.r.com"),
    allow_retry = TRUE
  )

Questions

Some questions to verify that you understand the purposes of various base and recommended R packages:

quiz(caption = "",
  question("Which package contains functions for installing other R packages?",
    answer("base"),
    answer("tools"),
    answer("utils", correct = TRUE),
    answer("codetools")
  ),
  question("Which of the R packages listed below are used to create plots?",
    answer("lattice", correct = TRUE),
    answer("tools"),
    answer("stats"),
    answer("grid", correct = TRUE)
  )
)

CodePudding user response:

A basic implementation of get_tutorial_state() to display a score looks like this. You can append it to your .Rmd-document.

```{r context="server"}
shiny::observeEvent(
  input$get_score, 
  {
    objs2 = learnr:::get_tutorial_state()
    
    # Number of correct questions
    
    n_correct <- 
      # Access the $correct sublist item in each list item
        lapply(objs2, purrr::pluck, "correct") |>
           # make it a vector containing: TRUE and FALSE and NAs
           # NA is appearing for list items which don't have
           # a $correct subitem
                unlist() |> 
           # Taking the sum of a logical Vector returns the number of TRUEs
                sum(na.rm=TRUE)
    
    # Number of total questions
    
    total_questions <- 
      # 1. Access $type in each list item and make it a vector of types
      lapply(objs2, purrr::pluck, "type") |> unlist()
    
    # 2. Count the number of "question" in that vector
    total_questions <- total_questions[total_questions == "question"] |> 
      length()
      
      
    output$score = shiny::renderText(
      paste0(n_correct, " out of ", total_questions,
        " question(s) were correct.")
)
    invisible()
  }
)
```

```{r score, echo=FALSE}
shiny::actionButton("get_score", "Get Score")
shiny::br()
shiny::br()
shiny::textOutput("score")
```

The output looks like this:

get score output

How I got there

You can find a demo of how to use get_tutorial_state() in the the shiny app output

So get_tutorial_state returns a list.

This list contains one list item for each question (and, important: exercises as well, there are just no exercises in this demo). Inside each list item that represents a question, there is:

  • a $correct entry containing TRUE or FALSE.

In all list items, regardless whether it is for an exercise or a question, there is:

  • a $type entry containing "exercise" or "question".

You can harvest this information like I did in my solution code at the beginning.

My solution from above is extracting the necessary data out of the state list, this is done inside the server chunk.

I also changed the output format in the ui chunk to normal text because verbatim is not what I was looking for.

getting hands on the tutorial state table

If you want to better understand the structure of the tutorial state output list, it would be good to access it outside the shiny app.

In the above demo-state app, change the line

capture.output(str(objs))

to

capture.output(dput(objs))

which yields the following if I apply this tiny shiny app in your quiz tutorial. You can copy paste that and hence recreate the list in your "normal" RStudio Environment, to experiment with it.

list(check = list(type = "question", answer = "installed R on my computer", 
    correct = FALSE, timestamp = "2023-11-03 10:42:14.762 UTC"), 
    q2 = list(type = "question", answer = "www.rstudio.com/download", 
        correct = FALSE, timestamp = "2023-11-03 10:42:19.599 UTC"), 
    `packages-1` = list(type = "question", answer = "utils", 
        correct = TRUE, timestamp = "2023-11-03 10:42:25.129 UTC"), 
    `packages-2` = list(type = "question", answer = "lattice", 
        correct = FALSE, timestamp = "2023-11-03 10:42:31.806 UTC"))
  • Related