Skip to content

Commit

Permalink
Doc fixes (rstudio#62) and function pruning
Browse files Browse the repository at this point in the history
* comment out unused functions, move fxns to separate R files

* small doc changes for pkgdown

* doc fixes

* rebase/fix conflicts/fix docs for R CMD check

* barret review changes

* reflow docstring, noRd get_* functions

* condition pass_if fail_if all under one documentation

* remove period from grade_learnr to keep consistent with other fxns
  • Loading branch information
chendaniely authored Aug 14, 2019
1 parent 1fd6873 commit d5cf9de
Show file tree
Hide file tree
Showing 25 changed files with 314 additions and 202 deletions.
3 changes: 0 additions & 3 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ export(check_result)
export(condition)
export(evaluate_condition)
export(fail_if)
export(get_code)
export(get_solution_code)
export(get_user_code)
export(grade_learnr)
export(graded)
export(grading_demo)
Expand Down
43 changes: 28 additions & 15 deletions R/check_code.R
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
#' Check code structure
#' Check code against a solution
#'
#' \code{check_code()} compares user code to a solution (i.e. model code) and
#' describes the first way that the user code differs. If the user code exactly
#' matches the solution, \code{check_code()} returns a customizable success
#' message.
#' Checks the code expression or the code result against a solution.
#'
#' \code{check_code()} provides a *strict* check in that the user code must
#' exactly match the solution. It is not enough for the user code to be
#' \code{check_code()} compares student code to a solution (i.e. model code) and
#' describes the first way that the student code differs. If the student code
#' exactly matches the solution, \code{check_code()} returns a customizable
#' success message (\code{correct}). If the student code does not match the
#' solution, a customizable incorrect message (\code{incorrect}) can also be
#' provided.
#'
#' \code{check_code()} provides a *strict* check in that the student code must
#' exactly match the solution. It is not enough for the student code to be
#' equivalent to the solution code (e.g. to return the same result as the
#' solution).
#'
Expand All @@ -18,9 +22,10 @@
#' 2. Make a "-solution" code chunk for the exercise to be checked in a learnr
#' document. There is no need to supply a solution argument for
#' \code{check_code()} if you call it from the "-check" chunk of the same
#' exercise. Likewise, there is no need to supply a user argument when you call
#' \code{check_code()} from a learnr document (learnr will provide the code
#' that the student submits when it runs \code{check_code()}.
#' exercise. Likewise, there is no need to supply a student submitted code
#' argument when you call \code{check_code()} from a learnr document (learnr
#' will provide the code that the student submits when it runs
#' \code{check_code()}.
#'
#' For best results, name all arguments provided in the solution code.
#'
Expand All @@ -30,16 +35,24 @@
#' @template learnr_args
#' @template glue_correct
#' @template glue_incorrect
#' @param glue_pipe A glue string that returns the final message displayed when a user uses a pipe,
#' \code{$>$}. Defaults to \code{getOption("gradethis_glue_pipe")}.
#' @param glue_pipe A glue string that returns the final message displayed when
#' the student uses a pipe, \code{$>$}. Defaults to
#' \code{getOption("gradethis_glue_pipe")}.
#'
#' @return a \code{\link{graded}} object.
#' An incorrect message will describe the first way that the answer differs,
#' the message will be the content of the \code{glue_pipe} argument.
#' @return a \code{\link{graded}} object. An incorrect message will describe the
#' first way that the answer differs, the message will be the content of the
#' \code{glue_pipe} argument.
#'
#' @seealso \code{\link{check_code}}, \code{\link{check_result}}, and
#' \code{\link{test_result}}
#' @export
#' @examples
#' \dontrun{grading_demo()}
#'
#' # This is a manual example, see grading demo for learnr tutorial usage
#' y <- quote(sqrt(log(2)))
#' z <- quote(sqrt(log(1)))
#' check_code(grader_args = list(user_quo = y, solution_quo = z))
check_code <- function(
correct = NULL,
incorrect = NULL,
Expand Down
12 changes: 8 additions & 4 deletions R/check_result.R
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@

#' Check result of exercise code
#'
#' \code{check_result()} compares the final result of the user code to known \code{results}.
#' If the user result exactly matches a known \code{result}, \code{check_result}
#' \code{check_result()} compares the final result of the student code to known
#' \code{\link{pass_if}} and \code{\link{fail_if}} \code{\link{condition}}s.
#' If the student result exactly matches a known case, \code{check_result}
#' returns the matching message value.
#'
#' @param ... \code{\link{pass_if}} or \code{\link{fail_if}} conditions to check
#' @param ... \code{\link{pass_if}} or \code{\link{fail_if}} \code{\link{condition}}s to check
#' @template correct
#' @template incorrect
#' @template grader_args
#' @template learnr_args
#' @template glue_correct
#' @template glue_incorrect
#'
#' @return a \code{grader_graded} structure from either
#' @return a \code{\link{graded}} object from either
#' \code{\link{pass_if}} or \code{\link{fail_if}} containing a formatted
#' \code{correct} or \code{incorrect} message and whether or not a match was found.
#'
#' @seealso \code{\link{check_code}}, \code{\link{check_result}}, and \code{\link{test_result}}
#' @export
#' @examples
#' \dontrun{grading_demo()}
#'
#' @template check_result_examples
check_result <- function(
...,
correct = NULL,
Expand Down
21 changes: 17 additions & 4 deletions R/condition.R
Original file line number Diff line number Diff line change
@@ -1,18 +1,31 @@
#' Condition object
#' Captures what the user passes into \code{\link{pass_if}} or \code{\link{fail_if}},
#'
#' Captures what the student passes into \code{\link{pass_if}} or \code{\link{fail_if}},
#' figures out what type of object was passed into \code{x},
#' and returns a \code{grader_condition} object that will be passed into \code{evaluate_condi}
#' and returns a \code{grader_condition} object that will be passed into
#' \code{\link{evaluate_condition}}.
#'
#' @param x expression to be evaluated
#' @param message character string for message returned
#' @template x_condition
#' @param message character string for message returned (usually passed in from
#' \code{\link{pass_if}} or \code{\link{fail_if}}
#' @param correct logical whether the condition is the correct answer
#'
#' @return a \code{grader_condition} object that contains
#' the expression \code{x},
#' the message \code{message},
#' whether or not the expression is the correct answer or not, \code{correct},
#' the type of expression (formula, function, or value), \code{type}
#'
#' @describeIn condition
#' A condition object that contains the expression, message,
#' correct status, and condition type
#' @seealso \code{\link{pass_if}}, \code{\link{fail_if}}, and \code{\link{condition}}
#' @export
#'
#' @examples
#' \dontrun{grading_demo()}
#'
#' condition(~ identical(x = .result, 5), message = "Correct", correct = TRUE)
condition <- function(x, message, correct) {
type <-
if (rlang::is_formula(x)) {
Expand Down
1 change: 0 additions & 1 deletion R/detect_mistakes.R
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,6 @@ isolate_mismatch <- function(user, solution, i) {
NULL
}


real_name <- function(name) {
!is.null(name) && name != ""
}
Expand Down
28 changes: 19 additions & 9 deletions R/evaluate_condition.R
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
#' Evaluates a condition
#'
#' @param condi a \code{grader} \code{\link{condition}} object
#' Evaluates the \code{\link{condition}} object to return a \code{\link{graded}} value.
#'
#' @param condition a \code{\link{condition}} object
#' @param grader_args at minimum, a list that just contains the value for \code{solution_quo}
#' @param learnr_args at minimum, a list that just contains the value for \code{envir_prep}
#'
#' @return a \code{graded} value if \code{condi$x} is \code{TRUE} or
#' @return a \code{\link{graded}} value if \code{condi$x} is \code{TRUE} or
#' \code{NULL} if \code{condi$x} is \code{FALSE}
#' @export
evaluate_condition <- function(condi, grader_args, learnr_args) {
checkmate::assert_class(condi, "grader_condition")
#'
#' @examples
#' condi_formula_t <- condition(~ identical(.result, 5),
#' message = "my correct message",
#' correct = TRUE)
#' grader_args <- list()
#' learnr_args <- list(last_value = quote(5), envir_prep = new.env())
#' evaluate_condition(condi_formula_t, grader_args, learnr_args)
evaluate_condition <- function(condition, grader_args, learnr_args) {
checkmate::assert_class(condition, "grader_condition")

res <- switch(condi$type,
"formula" = evaluate_condi_formula(condi$x, learnr_args$last_value, learnr_args$envir_prep), # nolint
"function" = evaluate_condi_function(condi$x, learnr_args$last_value),
"value" = evaluate_condi_value(condi$x, learnr_args$last_value)
res <- switch(condition$type,
"formula" = evaluate_condi_formula(condition$x, learnr_args$last_value, learnr_args$envir_prep), # nolint
"function" = evaluate_condi_function(condition$x, learnr_args$last_value),
"value" = evaluate_condi_value(condition$x, learnr_args$last_value)
)

# if we compare something like a vector or dataframes to one another
Expand All @@ -32,7 +42,7 @@ evaluate_condition <- function(condi, grader_args, learnr_args) {

checkmate::assert_logical(res, len = 1, null.ok = FALSE)
if (res) {
return(graded(correct = condi$correct, message = condi$message))
return(graded(correct = condition$correct, message = condition$message))
} else {
return(NULL)
}
Expand Down
18 changes: 12 additions & 6 deletions R/get_code.R
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,27 @@
#' to extract user code and solution code.
#'
#' @seealso \code{\link{check_result}}, \code{\link{test_result}}, and \code{\link{check_code}}
#' @export
#' @rdname get_code
#' @param user,solution,expr An expression or quosure to evaluate.
#' @param name Name to print if a \code{NULL} expression is provided.
#'
#' @describeIn get_code Get student code
#' @inheritParams rlang::eval_tidy
#'
#' @noRd
get_user_code <- function(user = NULL, env = rlang::caller_env()) {
get_code(user, "user", env = env)
}
#' @export
#' @rdname get_code

#' @describeIn get_code Get solution code provided by instructor
#""
#' @noRd
get_solution_code <- function(solution = NULL, env = rlang::caller_env()) {
get_code(solution, "solution", env = env)
}
#' @export
#' @rdname get_code

#' @describeIn get_code Generic get code function
#'
#' @noRd
get_code <- function(expr = NULL, name = "<name not provided>", env = rlang::caller_env()) {
if (is.null(expr)) {
stop("'", name, "' not provided")
Expand Down
2 changes: 1 addition & 1 deletion R/glue.R
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#' Generate Glue string from expression
#'
#' Checks and validates arguments passed into \code{glue}.
#' Checks and validates arguments passed into \code{glue} to generate messages to the student.
#'
#' @param glue_expression A glue character expression string.
#' @param ... Values to be inserted into glue expression.
Expand Down
36 changes: 19 additions & 17 deletions R/grade_learnr.R
Original file line number Diff line number Diff line change
@@ -1,34 +1,36 @@
#' grade_learnr
#' A checker function to use with \code{learnr}
#'
#' A checker function to use with learnr
#'
#' For exercise checking, learnr tutorials require a function that learnr can
#' use in the background to run the code in each "-check" chunk and to format
#' the results into a format that learnr can display. The function must accept a
#' specific set of inputs and return a specific type of output (see \code{\link{graded}}).
#' Users are not intended to use the function themselves, but to pass it to the
#' For exercise checking, \code{learnr} tutorials require a function that
#' \code{learnr} can use in the background to run the code in each "-check"
#' chunk and to format the results into a format that \code{learnr} can display.
#' The function must accept a specific set of inputs and return a specific type
#' of output (see \code{\link{graded}}). Instructors are not intended to use the
#' \code{grade_learnr} function directly, but to pass it to the
#' \code{exercise.checker} knitr chunk option within the setup chunk of the
#' tutorial.
#' \code{learnr} tutorial.
#'
#' The grader package provides \code{grade_learnr} for this purpose. To enable
#' exercise checking in your learnr tutorial, set
#' To enable exercise checking in your learnr tutorial, set
#' \code{tutorial_options(exercise.checker = grade_learnr)} in the setup chunk
#' of your tutorial.
#'
#' Run \code{grading_demo()} to see an example learnr document
#' that uses \code{grade_learnr()}.
#' Run \code{grading_demo()} to see an example learnr document that uses
#' \code{grade_learnr()}.
#'
#' @param label Label for exercise chunk
#' @param solution_code Code provided within the “-solution” chunk for the exercise.
#' @param solution_code Code provided within the “-solution” chunk for the
#' exercise.
#' @param user_code R code submitted by the user
#' @param check_code Code provided within the “-check” chunk for the exercise.
#' @param envir_result The R environment after the execution of the chunk.
#' @param evaluate_result The return value from the \code{evaluate::evaluate} function.
#' @param envir_prep A copy of the R environment before the execution of the chunk.
#' @param evaluate_result The return value from the \code{evaluate::evaluate}
#' function.
#' @param envir_prep A copy of the R environment before the execution of the
#' chunk.
#' @param last_value The last value from evaluating the exercise.
#' @param ... Extra arguments supplied by learnr
#'
#' @return An R list which contains several fields indicating the result of the check.
#' @return An R list which contains several fields indicating the result of the
#' check.
#' @export
#'
#' @examples
Expand Down
2 changes: 1 addition & 1 deletion R/grading_demo.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#' If you are using the RStudio IDE, \code{grading_demo()} opens an example learnr
#' file that demonstrates how to use the grader package to check student code.
#'
#' The tutorial sets the learnr exercise. checker option to
#' The tutorial sets the learnr \code{exercise.checker} option to
#' \code{grade_learnr()} in the document's setup chunk.
#' It then uses three different exercise checking methods:
#' \code{\link{check_result}}, \code{\link{test_result}}, and \code{\link{check_code}}.
Expand Down
20 changes: 14 additions & 6 deletions R/pass_fail_if.R
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
#' Pass if condition matches
#' @template pass_fail_x_condition
#' @param message chracter string for message returned
#' Condition definition
#'
#' \code{pass_if} and \code{fail_if} are wrappers around \code{\link{condition}}
#' that sets the proper \code{correct} argument.
#' This allows the instructor to specify just the comparison code, \code{x},
#' and \code{message}.
#'
#' @describeIn condition
#' a condition that if matched means the student provided result is correct
#'
#' @export
#' @template check_result_examples
pass_if <- function(x, message = NULL) {
condition(x, message, correct = TRUE)
}

#' Fail if condition matches
#' @template pass_fail_x_condition
#' @param message chracter string for message returned
#' @describeIn condition
#' a condition that if matched means the student provided result is incorrect
#'
#' @export
fail_if <- function(x, message = NULL) {
condition(x, message, correct = FALSE)
Expand Down
5 changes: 3 additions & 2 deletions R/praise.R
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,13 @@
#' replicate(5, glue::glue("Random praise: {random_praise()}"))
#' replicate(5, glue::glue("Random encouragement: {random_encourage()}"))
#' @export
#' @rdname praise
#' @describeIn praise Returns a random praise message
random_praise <- function() {
sample(.praise, 1)
}

#' @export
#' @rdname praise
#' @describeIn praise Returns a random encouragement message
random_encourage <- function() {
sample(.encourage, 1)
}
Loading

0 comments on commit d5cf9de

Please sign in to comment.