Title: | Interactive Tutorials for R |
---|---|
Description: | Create interactive tutorials using R Markdown. Use a combination of narrative, figures, videos, exercises, and quizzes to create self-paced tutorials for learning about R and R packages. |
Authors: | Garrick Aden-Buie [aut, cre] , Barret Schloerke [aut] , JJ Allaire [aut, ccp], Alexander Rossell Hayes [aut] , Nischal Shrestha [ctb] , Angela Li [ctb] (vignette), Posit, PBC [cph, fnd], Ajax.org B.V. [ctb, cph] (Ace library), Zeno Rocha [ctb, cph] (clipboard.js library), Nick Payne [ctb, cph] (Bootbox library), Jake Archibald [ctb, cph] (idb-keyval library), i18next authors [ctb, cph] (i18next library) |
Maintainer: | Garrick Aden-Buie <[email protected]> |
License: | Apache License (>= 2.0) |
Version: | 0.11.5.9000 |
Built: | 2024-12-03 05:12:36 UTC |
Source: | https://github.com/rstudio/learnr |
Create options for users when used in question_checkbox()
and
question_radio()
learnr questions. For question_text()
and
question_numeric()
, the individual answers aren't directly presented to
students, but their values can be used in determining if the student
submitted the correct answer. For flexible feedback from checkbox, text, and
numeric questions, answer_fn()
can be used to provide a function that
evaluates the student's submission and returns a custom result.
answer(text, correct = FALSE, message = NULL, label = text) answer_fn(fn, label = NULL)
answer(text, correct = FALSE, message = NULL, label = text) answer_fn(fn, label = NULL)
text |
The answer text or value; for selection-type questions this value is shown to the user. |
correct |
Logical value indicating whether the |
message |
A custom message shown when this answer is selected and when
the overall question result matches the state of this answer. For example,
the |
label |
The label shown when the option is presented to the user. |
fn |
A function used to evaluate the submitted answer. The function is
called with the student's submitted value as the first argument, so the
function should take at least one argument where the user's value will be
passed to the first argument. Inline purrr-style lambda functions
are allowed, see In the body of the function, you can perform arbitrary calculations to
decide if the submitted answer is or is not correct and to compose the
message presented to the user. To signal a final answer, call |
Returns a list with the "tutorial_question_answer"
class.
answer()
: Create an answer option
answer_fn()
: Evaluate the student's submission to determine correctness
and to return feedback.
answer(32, correct = FALSE) answer(42, correct = TRUE, message = "The meaning of life.")
answer(32, correct = FALSE) answer(42, correct = TRUE, message = "The meaning of life.")
List the tutorials that are currently available via installed R packages. Or list the specific tutorials that are contained within a given R package.
available_tutorials(package = NULL)
available_tutorials(package = NULL)
package |
Name of package |
available_tutorials()
returns a data.frame
containing "package",
"name", "title", "description", "package_dependencies", "private", and
"yaml_front_matter".
available_tutorials(package = "learnr")
available_tutorials(package = "learnr")
Helper method to communicate that the user's submission was correct or
incorrect. These functions were originally designed for developers to create
question_is_correct()
methods for custom question types, but they can also
be called inside the functions created by answer_fn()
to dynamically
determine the result and message provided to the user.
correct(messages = NULL) incorrect(messages = NULL) mark_as(correct, messages = NULL)
correct(messages = NULL) incorrect(messages = NULL) mark_as(correct, messages = NULL)
messages |
A vector of messages to be displayed. The type of message
will be determined by the |
correct |
Logical: is the question answer is correct |
Returns a list with class learnr_mark_as
to be returned from the
question_is_correct()
method for the learnr question type.
# Radio button question implementation of `question_is_correct` question_is_correct.radio <- function(question, value, ...) { for (ans in question$answers) { if (as.character(ans$option) == value) { return(mark_as(ans$correct, ans$message)) } } mark_as(FALSE, NULL) }
# Radio button question implementation of `question_is_correct` question_is_correct.radio <- function(question, value, ...) { for (ans in question$answers) { if (as.character(ans$option) == value) { return(mark_as(ans$correct, ans$message)) } } mark_as(FALSE, NULL) }
Method to disable all html tags to not allow users to interact with the html.
disable_all_tags(ele)
disable_all_tags(ele)
ele |
html tag element |
An htmltools HTML object with appended class = "disabled"
and
disabled
attributes on all tags.
# add an href to all a tags disable_all_tags( htmltools::tagList( htmltools::a(), htmltools::a() ) )
# add an href to all a tags disable_all_tags( htmltools::tagList( htmltools::a(), htmltools::a() ) )
Copy all items from the environment to a new environment. By default, the new environment will share the same parent environment.
duplicate_env(envir, parent = parent.env(envir))
duplicate_env(envir, parent = parent.env(envir))
envir |
environment to duplicate |
parent |
parent environment to set for the new environment. Defaults to
the parent environment of |
A duplicated copy of envir
whose parent env is parent
.
# Make a new environment with the object 'key' envir <- new.env() envir$key <- "value" "key" %in% ls() # FALSE "key" %in% ls(envir = envir) # TRUE # Duplicate the envir and show it contains 'key' new_envir <- duplicate_env(envir) "key" %in% ls(envir = new_envir) # TRUE
# Make a new environment with the object 'key' envir <- new.env() envir$key <- "value" "key" %in% ls() # FALSE "key" %in% ls(envir = envir) # TRUE # Duplicate the envir and show it contains 'key' new_envir <- duplicate_env(envir) "key" %in% ls(envir = new_envir) # TRUE
Register an event handler on a per-tutorial basis. Handlers for an event will be fired in the order that they were registered.
event_register_handler(event, callback)
event_register_handler(event, callback)
event |
The name of an event. |
callback |
A function to be invoked when an event with a specified name
occurs. The callback must take parameters |
In most cases, this will be called within a learnr document. If that is the case, then the handler will exist as long as the document (that is, the Shiny application) is running.
If this function is called in a learnr .Rmd document, it should be in a chunk
with context="server-start"
. If it is called with context="server"
, the
handler will be registered at least two times (once for the application as a
whole, and once per user session).
If this function is called outside of a learnr document, then the handler will persist until the learnr package is unloaded, typically when the R session is stopped.
A function which, if invoked, will remove the callback.
external_evaluator( endpoint = getOption("tutorial.external.host", Sys.getenv("TUTORIAL_EXTERNAL_EVALUATOR_HOST", NA)), max_curl_conns = 50 )
external_evaluator( endpoint = getOption("tutorial.external.host", Sys.getenv("TUTORIAL_EXTERNAL_EVALUATOR_HOST", NA)), max_curl_conns = 50 )
endpoint |
The HTTP(S) endpoint to POST the exercises to |
max_curl_conns |
The maximum number of simultaneous HTTP requests to the endpoint. |
A function that takes an expression (expr
), timelimit
, exercise
and session
.
Tutorial state storage handler that uses the filesystem as a backing store.
The directory will contain tutorial state data partitioned by user_id
,
tutorial_id
, and tutorial_version
(in that order)
filesystem_storage(dir, compress = TRUE)
filesystem_storage(dir, compress = TRUE)
dir |
Directory to store state data within |
compress |
Should |
Storage handler suitable for options(tutorial.storage = ...)
Mark a question as finalized by adding a question-final
class to the HTML
output at the top level, in addition to disabling all tags with
disable_all_tags()
.
finalize_question(ele)
finalize_question(ele)
ele |
html tag element |
An htmltools HTML object with appropriately appended classes such that a tutorial question is marked as the final answer.
# finalize the question UI finalize_question( htmltools::div( class = "custom-question", htmltools::div("answer 1"), htmltools::div("answer 2") ) )
# finalize the question UI finalize_question( htmltools::div( class = "custom-question", htmltools::div("answer 1"), htmltools::div("answer 2") ) )
Notes:
If custom question types are created, custom s3 formating methods may be implemented as well.
Due to the shiny runtime of questions, a text representation of quizzes, questions, and answers will be presented.
## S3 method for class 'tutorial_question_answer' format(x, ..., spacing = "") ## S3 method for class 'tutorial_question' format(x, ..., spacing = "") ## S3 method for class 'tutorial_quiz' format(x, ...) ## S3 method for class 'tutorial_question' print(x, ...) ## S3 method for class 'tutorial_question_answer' print(x, ...) ## S3 method for class 'tutorial_quiz' print(x, ...)
## S3 method for class 'tutorial_question_answer' format(x, ..., spacing = "") ## S3 method for class 'tutorial_question' format(x, ..., spacing = "") ## S3 method for class 'tutorial_quiz' format(x, ...) ## S3 method for class 'tutorial_question' print(x, ...) ## S3 method for class 'tutorial_question_answer' print(x, ...) ## S3 method for class 'tutorial_quiz' print(x, ...)
x |
object of interest |
... |
ignored |
spacing |
Text to be placed at the beginning of each new line |
ex_question <- question("What number is the letter A in the alphabet?", answer("8"), answer("14"), answer("1", correct = TRUE), answer("23"), incorrect = "See [here](https://en.wikipedia.org/wiki/English_alphabet) and try again.", allow_retry = TRUE ) cat(format(ex_question), "\n")
ex_question <- question("What number is the letter A in the alphabet?", answer("8"), answer("14"), answer("1", correct = TRUE), answer("23"), incorrect = "See [here](https://en.wikipedia.org/wiki/English_alphabet) and try again.", allow_retry = TRUE ) cat(format(ex_question), "\n")
Returns information about the current tutorial. Ideally the function should
be evaluated in a Shiny context, i.e. in a chunk with option
context = "server"
. Note that the values of this function may change after
the tutorial is completely initialized. If called in a non-reactive context,
get_tutorial_info()
will return default values that will most likely
correspond to the current tutorial.
get_tutorial_info( tutorial_path = NULL, session = getDefaultReactiveDomain(), ..., encoding = "UTF-8" )
get_tutorial_info( tutorial_path = NULL, session = getDefaultReactiveDomain(), ..., encoding = "UTF-8" )
tutorial_path |
Path to a tutorial |
session |
The |
... |
Arguments passed on to
|
encoding |
Ignored. The encoding is always assumed to be UTF-8. |
Returns an ordinary list with the following elements:
tutorial_id
: The ID of the tutorial, auto-generated or from the
tutorial$id
key in the tutorial's YAML front matter.
tutorial_version
: The tutorial's version, auto-generated or from the
tutorial$version
key in the tutorial's YAML front matter.
items
: A data frame with columns order
, label
, type
and data
describing the items (questions and exercises) in the tutorial. This item
is only available in the running tutorial, not during the static
pre-render step.
user_id
: The current user.
learnr_version
: The current version of the running learnr package.
language
: The current language of the tutorial, either as chosen by the
user or as specified in the language
item of the YAML front matter.
if (rmarkdown::pandoc_available("1.4")) { tutorial_rmd <- local({ # Use a temp copy of "Hello learnr" tutorial for this example src <- system.file( "tutorials", "hello", "hello.Rmd", package = "learnr" ) dest <- tempfile(fileext = ".Rmd") file.copy(src, dest) dest }) # ---- This is the example! ------------ # info <- get_tutorial_info(tutorial_rmd) # -------------------------------------- # # clean up the temporary Rmd used in this example unlink(tutorial_rmd) # This is the result of the example info }
if (rmarkdown::pandoc_available("1.4")) { tutorial_rmd <- local({ # Use a temp copy of "Hello learnr" tutorial for this example src <- system.file( "tutorials", "hello", "hello.Rmd", package = "learnr" ) dest <- tempfile(fileext = ".Rmd") file.copy(src, dest) dest }) # ---- This is the example! ------------ # info <- get_tutorial_info(tutorial_rmd) # -------------------------------------- # # clean up the temporary Rmd used in this example unlink(tutorial_rmd) # This is the result of the example info }
As a student progresses through a learnr tutorial, their progress is
stored in a Shiny reactive values list for their session (see
shiny::reactiveValues()
). Without arguments, get_tutorial_state()
returns
the full reactiveValues object that can be converted to a conventional list
with shiny::reactiveValuesToList()
. If the label
argument is provided,
the state of an individual question or exercise with that label is returned.
Calling get_tutorial_state()
introduces a reactive dependency on the state
of returned questions or exercises unless called within isolate()
. Note
that get_tutorial_state()
will only work for the tutorial author and must
be used in a reactive context, i.e. within shiny::observe()
,
shiny::observeEvent()
, or shiny::reactive()
. Any logic observing the
user's tutorial state must be written inside a context="server"
chunk in
the tutorial's R Markdown source.
get_tutorial_state(label = NULL, session = getDefaultReactiveDomain())
get_tutorial_state(label = NULL, session = getDefaultReactiveDomain())
label |
A length-1 character label of the exercise or question. |
session |
The |
A reactiveValues object or a single reactive value (if label
is
provided). The names of the full reactiveValues object correspond to the
label of the question or exercise. Each item contains the following
entries:
type
: One of "question"
or "exercise"
.
answer
: A character vector containing the user's submitted answer(s).
correct
: A logical indicating whether the user's answer was correct,
or a logical NA
if the submission was not checked for correctness.
timestamp
: The time at which the user's submission was completed, as
a character string in UTC, formatted as "%F %H:%M:%OS3 %Z"
.
One time initialization of R Markdown extensions required by the learnr package. This function is typically called automatically as a result of using exercises or questions.
initialize_tutorial()
initialize_tutorial()
If not previously run, initializes knitr hooks and provides the
required rmarkdown::shiny_prerendered_chunk()
s to initialize learnr.
knitr::knit_print
methods for question
and
quiz
## S3 method for class 'tutorial_question' knit_print(x, ...) ## S3 method for class 'tutorial_quiz' knit_print(x, ...)
## S3 method for class 'tutorial_question' knit_print(x, ...) ## S3 method for class 'tutorial_quiz' knit_print(x, ...)
x |
An R object to be printed |
... |
Additional arguments passed to the S3 method. Currently ignored,
except two optional arguments |
This wraps an expression so that it will be executed one time for a tutorial, based on some condition. The first time the condition is true, the expression will be executed; after that, the expression will not be evaluated again.
The execution state is stored so that if the expression is executed, then the user quits the tutorial and then returns to it, the expression will not be executed a second time.
A common use for one_time
is to execute an expression when a section is
viewed for the first time.
one_time(session, cond, expr, label = deparse(substitute(cond)))
one_time(session, cond, expr, label = deparse(substitute(cond)))
session |
A Shiny session object. |
cond |
A condition that is used as a filter. The first time the
condition evaluates to true, |
expr |
An expression that will be evaluated once, the first time that
|
label |
A unique identifier. This is used as an ID for the condition and
expression; if two calls to |
The result of evaluating expr
(one_time()
is intended to be
called within an event handler).
## Not run: # This goes in a {r context="server-start"} chunk # The expression with message() will be executed the first time the user # sees the section with ID "section-exercise-with-hint". event_register_handler("section_viewed", function(session, event, data) { one_time( session, data$sectionId == "section-exercise-with-hint", { message("Seeing ", data$sectionId, " for the first time.") } ) } ) ## End(Not run)
## Not run: # This goes in a {r context="server-start"} chunk # The expression with message() will be executed the first time the user # sees the section with ID "section-exercise-with-hint". event_register_handler("section_viewed", function(session, event, data) { one_time( session, data$sectionId == "section-exercise-with-hint", { message("Seeing ", data$sectionId, " for the first time.") } ) } ) ## End(Not run)
Creates a checkbox group tutorial quiz question. The student may select one or more checkboxes before submitting their answer.
question_checkbox( text, ..., correct = "Correct!", incorrect = "Incorrect", try_again = "Incorrect. Be sure to select every correct answer.", allow_retry = FALSE, random_answer_order = FALSE )
question_checkbox( text, ..., correct = "Correct!", incorrect = "Incorrect", try_again = "Incorrect. Be sure to select every correct answer.", allow_retry = FALSE, random_answer_order = FALSE )
text |
Question or option text |
... |
Answers created with |
correct |
For |
incorrect |
Text to print for an incorrect answer (defaults to
"Incorrect") when |
try_again |
Text to print for an incorrect answer
(defaults to "Incorrect. Be sure to select every correct answer.")
when |
allow_retry |
Allow retry for incorrect answers. Defaults to |
random_answer_order |
Display answers in a random order. |
Returns a learnr question of type "learnr_checkbox"
.
Other Interactive Questions:
question_numeric()
,
question_radio()
,
question_text()
,
quiz()
question_checkbox( "Select all the toppings that belong on a Margherita Pizza:", answer("tomato", correct = TRUE), answer("mozzarella", correct = TRUE), answer("basil", correct = TRUE), answer("extra virgin olive oil", correct = TRUE), answer("pepperoni", message = "Great topping! ... just not on a Margherita Pizza"), answer("onions"), answer("bacon"), answer("spinach"), random_answer_order = TRUE, allow_retry = TRUE, try_again = "Be sure to select all four toppings!" ) # Set up a question where there's no wrong answer. The answer options are # always shuffled, but the answer_fn() answer is always evaluated first. question_checkbox( "Which of the tidyverse packages is your favorite?", answer("dplyr"), answer("tidyr"), answer("ggplot2"), answer("tibble"), answer("purrr"), answer("stringr"), answer("forcats"), answer("readr"), answer_fn(function(value) { if (length(value) == 1) { correct(paste(value, "is my favorite tidyverse package, too!")) } else { correct("Yeah, I can't pick just one favorite package either.") } }), random_answer_order = TRUE )
question_checkbox( "Select all the toppings that belong on a Margherita Pizza:", answer("tomato", correct = TRUE), answer("mozzarella", correct = TRUE), answer("basil", correct = TRUE), answer("extra virgin olive oil", correct = TRUE), answer("pepperoni", message = "Great topping! ... just not on a Margherita Pizza"), answer("onions"), answer("bacon"), answer("spinach"), random_answer_order = TRUE, allow_retry = TRUE, try_again = "Be sure to select all four toppings!" ) # Set up a question where there's no wrong answer. The answer options are # always shuffled, but the answer_fn() answer is always evaluated first. question_checkbox( "Which of the tidyverse packages is your favorite?", answer("dplyr"), answer("tidyr"), answer("ggplot2"), answer("tibble"), answer("purrr"), answer("stringr"), answer("forcats"), answer("readr"), answer_fn(function(value) { if (length(value) == 1) { correct(paste(value, "is my favorite tidyverse package, too!")) } else { correct("Yeah, I can't pick just one favorite package either.") } }), random_answer_order = TRUE )
Creates a tutorial question asking the student to submit a number.
question_numeric( text, ..., correct = "Correct!", incorrect = "Incorrect", try_again = incorrect, allow_retry = FALSE, value = NULL, min = NA, max = NA, step = NA, options = list(), tolerance = 1.5e-08 )
question_numeric( text, ..., correct = "Correct!", incorrect = "Incorrect", try_again = incorrect, allow_retry = FALSE, value = NULL, min = NA, max = NA, step = NA, options = list(), tolerance = 1.5e-08 )
text |
Question or option text |
... |
Answers created with |
correct |
For |
incorrect |
Text to print for an incorrect answer (defaults to
"Incorrect") when |
try_again |
Text to print for an incorrect answer (defaults to
"Incorrect") when |
allow_retry |
Allow retry for incorrect answers. Defaults to |
value |
Initial value. |
min |
Minimum allowed value |
max |
Maximum allowed value |
step |
Interval to use when stepping between min and max |
options |
Extra options to be stored in the question object. This is
useful when using custom question types. See |
tolerance |
Submitted values within an absolute difference less than or
equal to |
Returns a learnr question of type "learnr_numeric"
.
Other Interactive Questions:
question_checkbox()
,
question_radio()
,
question_text()
,
quiz()
question_numeric( "What is pi rounded to 2 digits?", answer(3, message = "Don't forget to use the digits argument"), answer(3.1, message = "Too few digits"), answer(3.142, message = "Too many digits"), answer(3.14, correct = TRUE), allow_retry = TRUE, min = 3, max = 4, step = 0.01 ) question_numeric( "Can you think of an even number?", answer_fn(function(value) { if (value %% 2 == 0) { correct("even") } else if (value %% 2 == 1) { incorrect("odd") } }, label = "Is the number even?"), step = 1 )
question_numeric( "What is pi rounded to 2 digits?", answer(3, message = "Don't forget to use the digits argument"), answer(3.1, message = "Too few digits"), answer(3.142, message = "Too many digits"), answer(3.14, correct = TRUE), allow_retry = TRUE, min = 3, max = 4, step = 0.01 ) question_numeric( "Can you think of an even number?", answer_fn(function(value) { if (value %% 2 == 0) { correct("even") } else if (value %% 2 == 1) { incorrect("odd") } }, label = "Is the number even?"), step = 1 )
Creates a radio button tutorial quiz question. The student can select only one radio button before submitting their answer. Note: Multiple correct answers are allowed.
question_radio( text, ..., correct = "Correct!", incorrect = "Incorrect", try_again = incorrect, allow_retry = FALSE, random_answer_order = FALSE )
question_radio( text, ..., correct = "Correct!", incorrect = "Incorrect", try_again = incorrect, allow_retry = FALSE, random_answer_order = FALSE )
text |
Question or option text |
... |
Answers created with |
correct |
For |
incorrect |
Text to print for an incorrect answer (defaults to
"Incorrect") when |
try_again |
Text to print for an incorrect answer (defaults to
"Incorrect") when |
allow_retry |
Allow retry for incorrect answers. Defaults to |
random_answer_order |
Display answers in a random order. |
Returns a learnr question of type "learnr_radio"
.
Other Interactive Questions:
question_checkbox()
,
question_numeric()
,
question_text()
,
quiz()
question_radio( "Pick the letter B", answer("A"), answer("B", correct = TRUE), answer("C"), answer("D"), allow_retry = TRUE, random_answer_order = TRUE )
question_radio( "Pick the letter B", answer("A"), answer("B", correct = TRUE), answer("C"), answer("D"), allow_retry = TRUE, random_answer_order = TRUE )
Creates a tutorial question asking the student to enter text. The default
text input is appropriate for short or single-line text entry. For longer
text input, set the rows
and/or cols
argument to create a larger text
area.
When used with answer()
, the student's submission must match the answer
exactly, minus whitespace trimming if enabled with trim = TRUE
. For more
complicated submission evaluation, use answer_fn()
to provide a function
that checks the student's submission. For example, you could provide a
function that evaluates the user's submission using
regular expressions.
question_text( text, ..., correct = "Correct!", incorrect = "Incorrect", try_again = incorrect, allow_retry = FALSE, random_answer_order = FALSE, placeholder = "Enter answer here...", trim = TRUE, rows = NULL, cols = NULL, options = list() )
question_text( text, ..., correct = "Correct!", incorrect = "Incorrect", try_again = incorrect, allow_retry = FALSE, random_answer_order = FALSE, placeholder = "Enter answer here...", trim = TRUE, rows = NULL, cols = NULL, options = list() )
text |
Question or option text |
... |
Answers created with |
correct |
For |
incorrect |
Text to print for an incorrect answer (defaults to
"Incorrect") when |
try_again |
Text to print for an incorrect answer (defaults to
"Incorrect") when |
allow_retry |
Allow retry for incorrect answers. Defaults to |
random_answer_order |
Random answer order for text questions is automatically disabled to ensure that the submission is checked against each answer in the order they were provided by the author. |
placeholder |
A character string giving the user a hint as to what can be entered into the control. Internet Explorer 8 and 9 do not support this option. |
trim |
Logical to determine if whitespace before and after the answer
should be removed. Defaults to |
rows , cols
|
Defines the size of the text input area in terms of the
number of rows or character columns visible to the user. If either |
options |
Extra options to be stored in the question object. This is
useful when using custom question types. See |
Returns a learnr question of type "learnr_text"
.
Other Interactive Questions:
question_checkbox()
,
question_numeric()
,
question_radio()
,
quiz()
question_text( "Please enter the word 'C0rrect' below:", answer("correct", message = "Don't forget to capitalize"), answer("c0rrect", message = "Don't forget to capitalize"), answer("Correct", message = "Is it really an 'o'?"), answer("C0rrect ", message = "Make sure you do not have a trailing space"), answer("C0rrect", correct = TRUE), allow_retry = TRUE, trim = FALSE ) # This question uses an answer_fn() to give a hint when we think the # student is on the right track but hasn't found the value yet. question_text( "What's the most popular programming interview question?", answer("fizz buzz", correct = TRUE, "That's right!"), answer_fn(function(value) { if (grepl("(fi|bu)zz", value)) { incorrect("You're on the right track!") } }, label = "fizz or buzz") )
question_text( "Please enter the word 'C0rrect' below:", answer("correct", message = "Don't forget to capitalize"), answer("c0rrect", message = "Don't forget to capitalize"), answer("Correct", message = "Is it really an 'o'?"), answer("C0rrect ", message = "Make sure you do not have a trailing space"), answer("C0rrect", correct = TRUE), allow_retry = TRUE, trim = FALSE ) # This question uses an answer_fn() to give a hint when we think the # student is on the right track but hasn't found the value yet. question_text( "What's the most popular programming interview question?", answer("fizz buzz", correct = TRUE, "That's right!"), answer_fn(function(value) { if (grepl("(fi|bu)zz", value)) { incorrect("You're on the right track!") } }, label = "fizz or buzz") )
There are five methods used to define a custom question. Each S3 method
should correspond to the type = TYPE
supplied to the question.
question_ui_initialize.TYPE(question, value, ...)
Determines how the question is initially displayed to the users. This should return a shiny UI object that can be displayed using shiny::renderUI. For example, in the case of question_ui_initialize.radio
, it returns a shiny::radioButtons object. This method will be re-executed if the question is attempted again.
question_ui_completed.TYPE(question, ...)
Determines how the question is displayed after a submission. Just like question_ui_initialize
, this method should return an shiny UI object that can be displayed using shiny::renderUI.
question_is_valid.TYPE(question, value, ...)
This method should return a boolean that determines if the input answer is valid. Depending on the value, this function enables and disables the submission button.
question_is_correct.TYPE(question, value, ...)
question_ui_try_again <- function(question, value, ...)
Determines how the question is displayed to the users while the "Try again" screen is displayed. Usually this function will disable inputs to the question, i.e. prevent the student from changing the answer options. Similar to question_ui_initialize
, this should should return a shiny UI object that can be displayed using shiny::renderUI.
question_ui_initialize(question, value, ...) question_ui_try_again(question, value, ...) question_ui_completed(question, value, ...) question_is_valid(question, value, ...) question_is_correct(question, value, ...) ## Default S3 method: question_ui_initialize(question, value, ...) ## Default S3 method: question_ui_try_again(question, value, ...) ## Default S3 method: question_ui_completed(question, value, ...) ## Default S3 method: question_is_valid(question, value, ...) ## Default S3 method: question_is_correct(question, value, ...)
question_ui_initialize(question, value, ...) question_ui_try_again(question, value, ...) question_ui_completed(question, value, ...) question_is_valid(question, value, ...) question_is_correct(question, value, ...) ## Default S3 method: question_ui_initialize(question, value, ...) ## Default S3 method: question_ui_try_again(question, value, ...) ## Default S3 method: question_ui_completed(question, value, ...) ## Default S3 method: question_is_valid(question, value, ...) ## Default S3 method: question_is_correct(question, value, ...)
question |
question object used |
value |
user input value |
... |
future parameter expansion and custom arguments to be used in dispatched s3 methods. |
learnr question objects, UI elements, results or server methods.
For more information and question type extension examples, please
see the Custom Question Types section of the quiz_question
tutorial:
learnr::run_tutorial("quiz_question", "learnr")
.
q <- question( "Which package helps you teach programming skills?", answer("dplyr"), answer("learnr", correct = TRUE), answer("base") ) question_is_correct(q, "dplyr") question_is_correct(q, "learnr")
q <- question( "Which package helps you teach programming skills?", answer("dplyr"), answer("learnr", correct = TRUE), answer("base") ) question_is_correct(q, "dplyr") question_is_correct(q, "learnr")
Add interactive quiz questions to a tutorial. Each quiz question is executed within a shiny runtime to provide more flexibility in the types of questions offered. There are four default types of quiz questions:
learnr_radio
Radio button question. This question type will only allow for a single answer submission by the user. An answer must be marked for the user to submit their answer.
learnr_checkbox
Check box question. This question type will allow for one or more answers to be submitted by the user. At least one answer must be marked for the user to submit their answer.
learnr_text
Text box question. This question type will allow for free form text to be submitted by the user. At least one non-whitespace character must be added for the user to submit their answer.
learnr_numeric
Numeric question. This question type will allow for a number to be submitted by the user. At least one number must be added for the user to submit their answer.
Note, the print behavior has changed as the runtime is now Shiny based. If
question
s and quiz
es are printed in the console, the S3
structure and information will be displayed.
quiz(..., caption = rlang::missing_arg()) question( text, ..., type = c("auto", "single", "multiple", "learnr_radio", "learnr_checkbox", "learnr_text", "learnr_numeric"), correct = "Correct!", incorrect = "Incorrect", try_again = NULL, message = NULL, post_message = NULL, loading = NULL, submit_button = rlang::missing_arg(), try_again_button = rlang::missing_arg(), allow_retry = FALSE, random_answer_order = FALSE, options = list() )
quiz(..., caption = rlang::missing_arg()) question( text, ..., type = c("auto", "single", "multiple", "learnr_radio", "learnr_checkbox", "learnr_text", "learnr_numeric"), correct = "Correct!", incorrect = "Incorrect", try_again = NULL, message = NULL, post_message = NULL, loading = NULL, submit_button = rlang::missing_arg(), try_again_button = rlang::missing_arg(), allow_retry = FALSE, random_answer_order = FALSE, options = list() )
... |
One or more questions or answers |
caption |
Optional quiz caption (defaults to "Quiz") |
text |
Question or option text |
type |
Type of quiz question. Typically this can be automatically
determined based on the provided answers. Pass |
correct |
For |
incorrect |
Text to print for an incorrect answer (defaults to
"Incorrect") when |
try_again |
Text to print for an incorrect answer when |
message |
Additional message to display along with correct/incorrect feedback. This message is always displayed after a question submission. |
post_message |
Additional message to display along with
correct/incorrect feedback. If |
loading |
Loading text to display as a placeholder while the question is loaded. If not provided, generic "Loading..." or placeholder elements will be displayed. |
submit_button |
Label for the submit button. Defaults to |
try_again_button |
Label for the try again button. Defaults to |
allow_retry |
Allow retry for incorrect answers. Defaults to |
random_answer_order |
Display answers in a random order. |
options |
Extra options to be stored in the question object. This is
useful when using custom question types. See |
A learnr quiz, or collection of questions.
random_praise()
, random_encouragement()
For more information and question type extension examples, please
see the help documentation for question_methods
and view the question_type
tutorial:
learnr::run_tutorial("question_type", "learnr")
.
Other Interactive Questions:
question_checkbox()
,
question_numeric()
,
question_radio()
,
question_text()
quiz( question("What number is the letter A in the alphabet?", answer("8"), answer("14"), answer("1", correct = TRUE), answer("23"), incorrect = "See [here](https://en.wikipedia.org/wiki/English_alphabet) and try again.", allow_retry = TRUE ), question("Where are you right now? (select ALL that apply)", answer("Planet Earth", correct = TRUE), answer("Pluto"), answer("At a computing device", correct = TRUE), answer("In the Milky Way", correct = TRUE), incorrect = paste0("Incorrect. You're on Earth, ", "in the Milky Way, at a computer.") ) )
quiz( question("What number is the letter A in the alphabet?", answer("8"), answer("14"), answer("1", correct = TRUE), answer("23"), incorrect = "See [here](https://en.wikipedia.org/wiki/English_alphabet) and try again.", allow_retry = TRUE ), question("Where are you right now? (select ALL that apply)", answer("Planet Earth", correct = TRUE), answer("Pluto"), answer("At a computing device", correct = TRUE), answer("In the Milky Way", correct = TRUE), incorrect = paste0("Incorrect. You're on Earth, ", "in the Milky Way, at a computer.") ) )
Augment the random phrases available in random_praise()
and
random_encouragement()
with phrases of your own. Note that these phrases
are added to the existing phrases, rather than overwriting them.
random_phrases_add(language = "en", praise = NULL, encouragement = NULL)
random_phrases_add(language = "en", praise = NULL, encouragement = NULL)
language |
The language of the phrases to be added. |
praise , encouragement
|
A vector of praising or encouraging phrases, including final punctuation. |
Returns the previous custom phrases invisibly when called in the global setup chunk or interactively. Otherwise, it returns a shiny pre- rendered chunk.
To add random phrases in a learnr tutorial, you can either include one or
more calls to random_phrases_add()
in your global setup chunk:
```{r setup, include = FALSE}`r ''` library(learnr) random_phrases_add( language = "en", praise = "Great work!", encouragement = "I believe in you." ) ```
Alternatively, you can call random_phrases_add()
in a separate, standard
R chunk (with echo = FALSE
):
```{r setup-phrases, echo = FALSE}`r ''` random_phrases_add( language = "en", praise = c("Great work!", "You're awesome!"), encouragement = c("I believe in you.", "Yes we can!") ) ```
random_phrases_add("demo", praise = "Great!", encouragement = "Try again.") random_praise(language = "demo") random_encouragement(language = "demo")
random_phrases_add("demo", praise = "Great!", encouragement = "Try again.") random_praise(language = "demo") random_encouragement(language = "demo")
Random praises and encouragements sayings to compliment your question and quiz experience.
random_praise(language = NULL) random_encouragement(language = NULL)
random_praise(language = NULL) random_encouragement(language = NULL)
language |
The language for the random phrase. The currently supported
languages include: |
Character string with a random saying
random_praise() random_praise() random_encouragement() random_encouragement()
random_praise() random_praise() random_encouragement() random_encouragement()
Run a tutorial provided by an installed R package.
run_tutorial( name = NULL, package = NULL, ..., shiny_args = NULL, clean = FALSE, as_rstudio_job = NULL )
run_tutorial( name = NULL, package = NULL, ..., shiny_args = NULL, clean = FALSE, as_rstudio_job = NULL )
name |
Tutorial name (subdirectory within |
package |
Name of package. If |
... |
Unused. Included for future expansion and to ensure named arguments are used. |
shiny_args |
Additional arguments to forward to
|
clean |
When |
as_rstudio_job |
Runs the tutorial in the background as an RStudio job.
This is the default behavior when When running as an RStudio job, |
Starts a Shiny server running the learnr tutorial.
# display all "learnr" tutorials available_tutorials("learnr") # run basic example within learnr ## Not run: run_tutorial("hello", "learnr") ## End(Not run)
# display all "learnr" tutorials available_tutorials("learnr") # run basic example within learnr ## Not run: run_tutorial("hello", "learnr") ## End(Not run)
When rendering (or running) a document with R markdown, it inherits the current R Global environment. This will produce unexpected behaviors, such as poisoning the R Global environment with existing variables. By rendering the document in a new, safe R environment, a vanilla, rendered document is produced.
safe(expr, ..., show = TRUE, env = safe_env())
safe(expr, ..., show = TRUE, env = safe_env())
expr |
expression that contains all the necessary library calls to execute. Expressions within callr do not inherit the existing, loaded libraries. |
... |
parameters passed to |
show |
Logical that determines if output should be displayed |
env |
Environment to evaluate the document in |
The environment variable LEARNR_INTERACTIVE
will be set to "1"
or "0"
depending on if the calling session is interactive or not.
Using safe
should only be necessary when locally deployed.
The result of expr
.
## Not run: # Direct usage safe(run_tutorial("hello", package = "learnr")) # Programmatic usage library(rlang) expr <- quote(run_tutorial("hello", package = "learnr")) safe(!!expr) tutorial <- "hello" safe(run_tutorial(!!tutorial, package = "learnr")) ## End(Not run)
## Not run: # Direct usage safe(run_tutorial("hello", package = "learnr")) # Programmatic usage library(rlang) expr <- quote(run_tutorial("hello", package = "learnr")) safe(!!expr) tutorial <- "hello" safe(run_tutorial(!!tutorial, package = "learnr")) ## End(Not run)
Long-form tutorial which includes narrative, figures, videos, exercises, and questions.
tutorial( fig_width = 6.5, fig_height = 4, fig_retina = 2, fig_caption = TRUE, progressive = FALSE, allow_skip = FALSE, dev = "png", df_print = "paged", smart = TRUE, theme = "rstudio", highlight = "textmate", ace_theme = "textmate", mathjax = "default", extra_dependencies = NULL, css = NULL, includes = NULL, md_extensions = NULL, pandoc_args = NULL, language = "en", lib_dir = NULL, ... )
tutorial( fig_width = 6.5, fig_height = 4, fig_retina = 2, fig_caption = TRUE, progressive = FALSE, allow_skip = FALSE, dev = "png", df_print = "paged", smart = TRUE, theme = "rstudio", highlight = "textmate", ace_theme = "textmate", mathjax = "default", extra_dependencies = NULL, css = NULL, includes = NULL, md_extensions = NULL, pandoc_args = NULL, language = "en", lib_dir = NULL, ... )
fig_width |
Default width (in inches) for figures |
fig_height |
Default height (in inches) for figures |
fig_retina |
Scaling to perform for retina displays (defaults to 2, which
currently works for all widely used retina displays). Set to |
fig_caption |
|
progressive |
Display sub-topics progressively (i.e. wait until previous topics are either completed or skipped before displaying subsequent topics). |
allow_skip |
Allow users to skip sub-topics (especially useful when
|
dev |
Graphics device to use for figure output (defaults to png) |
df_print |
Method to be used for printing data frames. Valid values
include "default", "kable", "tibble", and "paged". The "default" method
uses a corresponding S3 method of |
smart |
Produce typographically correct output, converting straight
quotes to curly quotes, |
theme |
Visual theme ("rstudio", default", "cerulean", "journal", "flatly", "readable", "spacelab", "united", "cosmo", "lumen", "paper", "sandstone", "simplex", or "yeti"). |
highlight |
Syntax highlighting style. Supported styles include "default", "tango", "pygments", "kate", "monochrome", "espresso", "zenburn", "haddock", and "textmate". Pass ‘NULL’ to prevent syntax highlighting. Note, this value only pertains to standard rmarkdown code, not the Ace editor highlighting. |
ace_theme |
Ace theme supplied to the ace code editor for all exercises.
See |
mathjax |
Include mathjax. The "default" option uses an https URL from a
MathJax CDN. The "local" option uses a local version of MathJax (which is
copied into the output directory). You can pass an alternate URL or pass
|
extra_dependencies |
Extra dependencies as a list of the
|
css |
CSS and/or Sass files to include. Files with an extension of .sass
or .scss are compiled to CSS via |
includes |
Named list of additional content to include within the
document (typically created using the |
md_extensions |
Markdown extensions to be added or removed from the
default definition of R Markdown. See the |
pandoc_args |
Additional command line options to pass to pandoc |
language |
Language or custom text of the UI elements. See
|
lib_dir |
Directory to copy dependent HTML libraries (e.g. jquery,
bootstrap, etc.) into. By default this will be the name of the document with
|
... |
Forward parameters to html_document |
An rmarkdown::output_format()
for learnr tutorials.
tutorial()
tutorial()
HTML dependency for core tutorial JS and CSS. This should be included as a
dependency for custom tutorial formats that wish to ensure that that
tutorial.js
and tutorial.css
are loaded prior their own scripts and
stylesheets.
tutorial_html_dependency()
tutorial_html_dependency()
learnr's HTML dependencies
Set various tutorial options that control the display and evaluation of exercises.
tutorial_options( exercise.cap = NULL, exercise.eval = FALSE, exercise.timelimit = 30, exercise.lines = NULL, exercise.pipe = NULL, exercise.blanks = NULL, exercise.checker = NULL, exercise.error.check.code = NULL, exercise.completion = TRUE, exercise.diagnostics = TRUE, exercise.startover = TRUE, exercise.reveal_solution = TRUE )
tutorial_options( exercise.cap = NULL, exercise.eval = FALSE, exercise.timelimit = 30, exercise.lines = NULL, exercise.pipe = NULL, exercise.blanks = NULL, exercise.checker = NULL, exercise.error.check.code = NULL, exercise.completion = TRUE, exercise.diagnostics = TRUE, exercise.startover = TRUE, exercise.reveal_solution = TRUE )
exercise.cap |
Caption for exercise chunk (defaults to the engine's icon or the combination of the engine and |
exercise.eval |
Whether to pre-evaluate the exercise so the reader can
see some default output (defaults to |
exercise.timelimit |
Number of seconds to limit execution time to
(defaults to |
exercise.lines |
Lines of code for exercise editor (defaults to the number of lines in the code chunk). |
exercise.pipe |
The characters to enter when the user presses the
"Insert Pipe" keyboard shortcut in the exercise editor
( |
exercise.blanks |
A regular expression to be used to identify blanks in
submitted code that the user should fill in. If |
exercise.checker |
Function used to check exercise answers
(e.g., |
exercise.error.check.code |
A string containing R code to use for checking
code when an exercise evaluation error occurs (e.g., |
exercise.completion |
Use code completion in exercise editors. |
exercise.diagnostics |
Show diagnostics in exercise editors. |
exercise.startover |
Show "Start Over" button on exercise. |
exercise.reveal_solution |
Whether to reveal the exercise solution if a solution chunk is provided. |
Nothing. Invisibly sets knitr::opts_chunk settings.
if (interactive()) { tutorial_options(exercise.eval = TRUE, exercise.timelimt = 10) }
if (interactive()) { tutorial_options(exercise.eval = TRUE, exercise.timelimt = 10) }
List the R packages required to run a particular tutorial.
tutorial_package_dependencies(name = NULL, package = NULL)
tutorial_package_dependencies(name = NULL, package = NULL)
name |
The tutorial name. If |
package |
The R package providing the tutorial. If |
A character vector of package names that are required for execution.
tutorial_package_dependencies(package = "learnr")
tutorial_package_dependencies(package = "learnr")