rstudio / gradethis

Tools for teachers to use with learnr
https://pkgs.rstudio.com/gradethis/
Other
160 stars 39 forks source link

gradethis does not work when namespaced #364

Open JosiahParry opened 1 week ago

JosiahParry commented 1 week ago

gradethis must be loaded globally using library(gradethis) otherwise code_feedback cannot be found.

mocked <- gradethis::mock_this_exercise("rnorm(10)", "rnorm(10)")
gradethis::grade_this_code()(mocked)
#> #> (gradethis::grade_this_code())(mocked)
#> Error in do_grade_this(): could not find function "code_feedback"
#> <gradethis_graded_this_code: [Neutral]
#>   A problem occurred with the grading code for this exercise.
#> >

Created on 2024-07-02 with reprex v2.1.0

gadenbuie commented 1 week ago

If you just want to compare code, you can call code_feedback() directly. It returns NULL if the user code is correct, or a (hopefully) helpful message as a character string if not.

gradethis::code_feedback("rnorm(10)", "rnorm(100)")
#> In `rnorm(10)`, I expected `100` where you wrote `10`.
JosiahParry commented 6 days ago

Thanks! It's not a complete replacement. Instead, I can use gradethis::random_praise() when the result is correct (NULL)

gadenbuie commented 6 days ago

You could also use the pass() and fail() helpers: https://pkgs.rstudio.com/gradethis/reference/graded.html

JosiahParry commented 6 days ago

Thank you! I'm having a bit of a tough time following the documentation since I am trying to use gradethis outside of the context of learnr so using pass() and fail() doesn't make much sense to me because you need to pass in the .result which is available from grade_this_code() and not code_feedback().

gadenbuie commented 6 days ago

using pass() and fail() doesn't make much sense to me because you need to pass in the .result

pass() and fail() don't need a result, they just take a string with the message you want to show. Here's a simple example with a light-weight grade_this_code() that doesn't do any user code evaluation.

solution <- "rnorm(10)"
user_correct <- solution
user_wrong <- "rnorm(100)"

code_grade <- function(user_code, solution) {
  feedback <- gradethis::code_feedback(user_code, solution)

  if (is.null(feedback)) {
    gradethis::pass()
  } else {
    gradethis::fail(feedback, encourage = TRUE)
  }
}

code_grade(user_correct, solution)
#> <gradethis_graded: [Correct] Amazing! Correct!>
code_grade(user_wrong, solution)
#> <gradethis_graded: [Incorrect]
#>   In `rnorm(100)`, I expected `10` where you wrote `100`. That's okay:
#>   you learn more from mistakes than successes. Let's do it one more
#>   time.
#> >

You can get the final pass/fail message directly from $message, but the graded object carries a small amount of additional information you might find useful.

str(code_grade(user_correct, solution))
#> List of 4
#>  $ message : 'glue' chr "Superb work! Correct!"
#>  $ correct : logi TRUE
#>  $ type    : NULL
#>  $ location: NULL
#>  - attr(*, "class")= chr [1:2] "gradethis_graded" "condition"