rstudio / gradethis Goto Github PK
View Code? Open in Web Editor NEWTools for teachers to use with learnr
Home Page: https://pkgs.rstudio.com/gradethis/
License: Other
Tools for teachers to use with learnr
Home Page: https://pkgs.rstudio.com/gradethis/
License: Other
Line 61 of strict_check.R
has this:
} else if (suppressWarnings(user == solution)) {
However, at this point both user
and solution
can be quosures if strict_check
is being called by grade_learnr
, in which case the ==
fails. The code should check if these params are quosures and !!
if they are.
log(log(2, base = exp(1)), base = exp(1)) # both
I expected log(2) where you wrote log(2, base = exp(1)). That's okay: you learn more from mistakes than successes. Let's do it one more time.
log(log(2, base = exp(1))) # inner log
I did not expect your call to log() to include base = exp(). You may have included an unnecessary argument, or you may have left out or misspelled an important argument name. Let's try it again.
log(log(2), base = exp(1)) # outer log
I did not expect your call to log() to include base = exp(). You may have included an unnecessary argument, or you may have left out or misspelled an important argument name. Try it again; next time's the charm!
might need envir_prep. idk for sure. Not the priority right now
Originally posted by @schloerke in https://github.com/_render_node/MDIzOlB1bGxSZXF1ZXN0UmV2aWV3VGhyZWFkMTgzNDcyMDcyOnYy/pull_request_review_threads/discussion
not sure if this is needed since the function is called within check_result. but can come back to it if the instructor puts in a function that makes calls to variables in the environment.
When I submit an answer to the first question in grader::grading_demo()
, the doc closes, and I see this at the console:
Warning in grader_args$user : partial match of 'user' to 'user_quo'
Warning: Error in checker: `grade_learnr` should receive a `graded` value from every `-check` chunk
79: stop
78: checker
77: evaluate_exercise
74: observeEventHandler
3: <Anonymous>
1: rmarkdown::run
learnr
tutorial chunks to show inconsistencies (aka bugs)
~
when returning unpiped result:
column slicing. But seems the pipe is also involved. (#30 (comment))learnr
/grader
to take a long time (and also fail) (#30 (comment))check_code
can see if a function definition is correct, but if they differ it will fail (expected to return error message) (#30 (comment))check_code
evaluate the call? Or should it be comparing the call? (#30 (comment))Get the data:
wget https://raw.githubusercontent.com/hadley/tidy-data/master/data/billboard.csv
Load the data:
billboard <- readr::read_csv(here::here('data/billboard.csv'))
Example student code:
# student code
stu <- reshape2::melt(billboard,
id.vars = c("year", "artist.inverted", "track", "time",
"genre", "date.entered", "date.peaked"),
variable.name = "week",
value.name = "rank",
factorAsStrings = FALSE)
stu$week <- as.character(stu$week)
stu
.message
etc
#' @param solution_code R code submitted by the user
#' @param user_code Code provided within the “-solution” chunk for the exercise.
should be flipped
The code below should return sum(4, 1, 2, sqrt(4)
or return an error that advises people to avoid nesting .'s in sub-functions (because the correct behavior seems zany: 4 is inserted both at the dot and as the first argument).
pipe1 <- quote(4 %>% sum(1, 2, sqrt(.)))
unpipe(pipe1)
# sum(4, 1, 2, sqrt(.))
Add to .travis.yml
r_binary_packages:
- jimhester/lintr
- jimhester/covr
after_success:
- Rscript -e 'covr::codecov()'
- Rscript -e 'lintr::lint_package()'
Exec in R
usethis::use_coverage("codecov")
usethis::use_build_ignore(".lintr")
lintr::lint_package() %>%
as.data.frame %>%
dplyr::group_by(linter) %>%
dplyr::tally(sort = TRUE) %$%
sprintf(
"linters: with_defaults(\n %s\n NULL\n )\n",
paste0(linter, " = NULL, # ", n, collapse = "\n ")
) %>%
cat(file = ".lintr")
Description
's Suggests
.lintr::lint_package(path = '.', relative_path = TRUE, with_defaults(line_length_linter(100)))
praise/encouragement + question specific + correct/incorrect message
e.g.,
question specific (e.g., from pass_if)
v
"You did it! That's the correct answer. Next, we'll see how we can apply this to dataframes."
^ ^
praise/encouragement correct message
There's currently only 2. The "praise/encouragement" is overwritten by "correct".
Object params
is made in the document's global knitr setup chunk
> library(grader)
> demo <- system.file("tutorials", "solutions-demo/solutions-demo.Rmd", package = "grader")
> test_solutions(demo)
setup: ✔ package ‘purrr’ was built under R version 3.4.4
success-1-solution: ✔
warning-2-solution: ✔ NaNs produced
failure-3-solution: ✖ argument "x" is missing, with no default
success-4-solution: ✖ object 'params' not found
failure-5-solution: ✖ object 'knitr_result' not found
success-6-setup: ✔
success-6-solution: ✖ object 'params' not found
warning-7-setup: ✔ This is a warning message!
warning-7-solution: ✔
failure-8-setup: ✖ Uh oh. An error!
failure-8-solution: ✖ object 'two' not found
success-for-9: ✔
success-9-solution: ✖ object 'params' not found
warning-for-10: ✔ Uh oh. A Warning!
warning-10-solution: ✖ object 'params' not found
failure-for-11: ✖ Uh oh. An error!
failure-11-solution: ✖ object 'params' not found
success-for-9: ✔
success-12-solution: ✖ object 'params' not found
success-for-9: ✔
success-13-solution: ✖ object 'params' not found
warning-for-10: ✔ Uh oh. A Warning!
warning-14-solution: ✖ object 'params' not found
warning-for-10: ✔ Uh oh. A Warning!
warning-15-solution: ✖ object 'params' not found
failure-for-11: ✖ Uh oh. An error!
failure-16-solution: ✖ object 'params' not found
failure-for-11: ✖ Uh oh. An error!
failure-17-solution: ✖ object 'params' not found
usererr-18-solution: ✖ object 'params' not found
usererr-19-solution: ⚠ exercise.setup chunk_opt is not a single string.
success-6-setup: ✔
usererr-20-solution: ✖ could not find function "add_one"
rename grading-demo/grading-demo.Rmd
to gradethis-demo/gradethis-demo.Rmd
Both file and in gradethis_demo()
Grader is going through some API changes in #10 . Thank you all for your input and patience!
Two big motivations are at play: keep it simple (@garrettgman ), keep it clean (@wch ).
After talking it through with @blairj09, I think we have a clean, simple solution for check_result
.
passes
and fails
. (These names do not class with checkmate
or testthat
.)passes
and fails
can take:
~ identical(., value)
.
representing the user result
.
, there is no non-standard evaluation trickery to understand (such as a random ans
being available). As long as we state that .
is the user result, the validation can be processed however the user writes.TRUE
/ FALSE
TRUE
/ FALSE
TRUE
(from a formula / function) is returned, computation will stop. The respective message will be displayed as a correct (passes
) or incorrect (fails
) result.correct
or incorrect
params will be the default message for any passes
or fails
that do not provide a message. They will be glue
ed with appropriate information.Example:
check_result(
fails(5, "bad answer!"),
fails(~ . == 5, "bad answer!"),
fails(~ isTRUE(all.equal(., 5)), "bad answer!"),
fails(~ . %in% c(5,7), "bad answer!"),
fails(function(x) x == 5, "bad answer!"),
fails(function(x) x == 5),
fails(somepkg::some_method, "bad answer!"), # function(x) ...
passes(4, "good answer!"),
passes(~ . == 4, "good answer!"),
passes(~ . %in% c(4,6), "good answer!"),
passes(function(x) x == 4, "good answer!"),
passes(function(x) x == 4),
passes(somepkg::some_method, "good answer!"), # function(x) ...
correct = "You got it right!",
incorrect = "You got it wrong."
)
check_result
will be kept separate from test_result
. All tests will be executed for test_result
.
test_result
will take
test
object which will only accept formulas or functions as defined above (no values). The message supplied will be provided if any throw occurs.correct
and incorrect
will be glue
ed with appropriate information.Example:
test_result(
~ checkmate::assert_function(., args = "x"),
test(~ checkmate::assert_function(., args = "x"), "Make sure to have an 'x' argument!"),
somepkg::some_expectation, # function(x) ...
pryr::partial(checkmate::assert_function, args = "x"),
correct = "{num_correct} / {num_total} correct! {random_praise()}",
incorrect = "{num_correct} / {num_total} correct. {random_encourage()}"
)
Again, these are not set in stone... just a followup from discussions over the past 48 hrs.
cc @gvwilson
see: #21 (comment) from #11
the tests for grade_learnr
do not seem to work with messages within pass_if
, and the only the random praise is being passed along.
Conversation from this message: #36 (comment)
learnr
shows an error message and this is what is shown in the r console:
Error in evaluate_condition(resu, grader_args, learnr_args): Assertion on 'res' failed: Must be of type 'logical', not 'character'.
Reproducible bits below:
billboard <- structure(list(year = c(2000, 2000, 2000, 2000, 2000, 2000),
artist.inverted = c("Destiny's Child", "Santana", "Savage Garden",
"Madonna", "Aguilera, Christina", "Janet"), track = c("Independent Women Part I",
"Maria, Maria", "I Knew I Loved You", "Music", "Come On Over Baby (All I Want Is You)",
"Doesn't Really Matter"), time = structure(c(13080, 15480,
14820, 13500, 13080, 15420), class = c("hms", "difftime"), units = "secs"),
genre = c("Rock", "Rock", "Rock", "Rock", "Rock", "Rock"),
date.entered = structure(c(11223, 10999, 10887, 11181, 11174,
11125), class = "Date"), date.peaked = structure(c(11279,
11055, 10985, 11216, 11244, 11195), class = "Date"), x1st.week = c(78,
15, 71, 41, 57, 59), x2nd.week = c(63, 8, 48, 23, 47, 52),
x3rd.week = c(49, 6, 43, 18, 45, 43), x4th.week = c(33, 5,
31, 14, 29, 30), x5th.week = c(23, 2, 20, 2, 23, 29), x6th.week = c(15,
3, 13, 1, 18, 22), x7th.week = c(7, 2, 7, 1, 11, 15), x8th.week = c(5,
2, 6, 1, 9, 10), x9th.week = c(1, 1, 4, 1, 9, 10), x10th.week = c(1,
1, 4, 2, 11, 5), x11th.week = c(1, 1, 4, 2, 1, 1), x12th.week = c(1,
1, 6, 2, 1, 1), x13th.week = c(1, 1, 4, 2, 1, 1), x14th.week = c(1,
1, 2, 2, 1, 2), x15th.week = c(1, 1, 1, 4, 4, 2), x16th.week = c(1,
1, 1, 8, 8, 3), x17th.week = c(1, 1, 1, 11, 12, 3), x18th.week = c(1,
1, 2, 16, 22, 7), x19th.week = c(1, 8, 1, 20, 23, 8), x20th.week = c(2,
15, 2, 25, 43, 20), x21st.week = c(3, 19, 4, 27, 44, 25),
x22nd.week = c(7, 21, 8, 27, NA, 37), x23rd.week = c(10,
26, 8, 29, NA, 40), x24th.week = c(12, 36, 12, 44, NA, 41
), x25th.week = c(15, 48, 14, NA, NA, NA), x26th.week = c(22,
47, 17, NA, NA, NA), x27th.week = c(29, NA, 21, NA, NA, NA
), x28th.week = c(31, NA, 24, NA, NA, NA), x29th.week = c(NA,
NA, 30, NA, NA, NA), x30th.week = c(NA, NA, 34, NA, NA, NA
), x31st.week = c(NA, NA, 37, NA, NA, NA), x32nd.week = c(NA,
NA, 46, NA, NA, NA), x33rd.week = c(NA, NA, 47, NA, NA, NA
), x34th.week = c(NA_real_, NA_real_, NA_real_, NA_real_,
NA_real_, NA_real_), x35th.week = c(NA_real_, NA_real_, NA_real_,
NA_real_, NA_real_, NA_real_), x36th.week = c(NA_real_, NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_), x37th.week = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), x38th.week = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), x39th.week = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), x40th.week = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), x41st.week = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), x42nd.week = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), x43rd.week = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), x44th.week = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), x45th.week = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), x46th.week = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), x47th.week = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), x48th.week = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), x49th.week = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), x50th.week = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), x51st.week = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), x52nd.week = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), x53rd.week = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), x54th.week = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), x55th.week = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), x56th.week = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), x57th.week = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), x58th.week = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), x59th.week = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), x60th.week = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), x61st.week = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), x62nd.week = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), x63rd.week = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), x64th.week = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), x65th.week = c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), x66th.week = c(NA,
NA, NA, NA, NA, NA), x67th.week = c(NA, NA, NA, NA, NA, NA
), x68th.week = c(NA, NA, NA, NA, NA, NA), x69th.week = c(NA,
NA, NA, NA, NA, NA), x70th.week = c(NA, NA, NA, NA, NA, NA
), x71st.week = c(NA, NA, NA, NA, NA, NA), x72nd.week = c(NA,
NA, NA, NA, NA, NA), x73rd.week = c(NA, NA, NA, NA, NA, NA
), x74th.week = c(NA, NA, NA, NA, NA, NA), x75th.week = c(NA,
NA, NA, NA, NA, NA), x76th.week = c(NA, NA, NA, NA, NA, NA
)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA,
-6L))
user <- reshape2::melt(
head(billboard),
id.vars = c("year", "artist.inverted", "track", "time",
"genre", "date.entered", "date.peaked"),
variable.name = "week",
value.name = "rank",
factorAsStrings = TRUE
)
user$week <- as.character(user$week)
solution <- tidyr::gather(head(billboard), "week", "rank", x1st.week:x76th.week)
all.equal(tibble::as_tibble(user), tibble::as_tibble(solution))
learnr
document```{r zuzwislfkfnsoesa, exercise = TRUE}
# student code
user <- reshape2::melt(head(billboard), id.vars = c("year", "artist.inverted", "track",
time", "genre", "date.entered", "date.peaked"),
variable.name = "week",
value.name = "rank",
factorAsStrings = TRUE
)
user$week <- as.character(user$week)
```
```{r zuzwislfkfnsoesa-check}
solution <- tidyr::gather(head(billboard), "week", "rank", x1st.week:x76th.week)
grader::check_result(
grader::pass_if(~ all.equal(tibble::as_tibble(.result), tibble::as_tibble(solution)))
)
```
The function should take a tutorial ID (url?) and open the tutorial in the viewer pane.
How can we transition students from learnr tutorials to the IDE?
How can we provide more sophisticated tutorials that require the use of the IDE?
I would like to enable students to launch a learnr tutorial within the IDE viewer pane. The tutorial would be hosted online elsewhere, for example at shinyapps.io, and the student would access it through an iframe. This removes the need to provide the raw .Rmd to the student (which would contain the solutions).
Together with #2, this would create a complete assignment workflow.
There is a difference between 3 == NA
and NA == NA
. This is probably the notation (==
) that will be used by instructors, e.g., pass_if(~ .result == df)
When ==
is used in a comparison there is a difference between when the user and solution code are both NA
(maybe should return a TRUE
match), and when only one of them returns NA
. Right now they both return NA
, and I need to set na.rm = TRUE
to get a boolean value from all
that is not NA
if there is a missing value.
Does this mean we need to replace any calls to ==
with all.equal
or identical
?
here's a minimal example of what I'm trying to show:
> user <- c(1, 2, 3, NA)
> solution <- c(1, 2, 3, NA) ## both are missing
> user == solution
[1] TRUE TRUE TRUE NA
> all(user == solution)
[1] NA
> user <- c(1, 2, 3, NA)
> solution <- c(1, 2, 3, 4) ## the solutions don't actually match
> user == solution
[1] TRUE TRUE TRUE NA
> all(user == solution, na.rm = TRUE)
[1] TRUE
There are 2 versions of expect_message
functions
The one used in test_test_result.R
expect_message <- function(x, message, correct = FALSE) {
expect_s3_class(x, "grader_graded")
expect_equal(x$correct, correct)
expect_true(grepl(message, paste0(x$message, collapse = ""), fixed = TRUE))
}
and the rest
expect_message <- function(x, message) {
expect_s3_class(x, "grader_graded")
expect_true(!x$correct)
expect_true(grepl(message, paste0(x$message, collapse = ""), fixed = TRUE))
}
They are similar, but they should be re-written to use the same function signature (and conversely, the same expect
check)
Hadley brought up using rlang::call_standarise
instead of using pryr
. Not sure if the code in grader
created before rlang
, but should probably consider using the newer package
https://twitter.com/hadleywickham/status/1141091795440455686
> grader:::unpipe_all(head(who, 2) %>% gather(key, value, new_sp_m014:newrel_f65, na.rm = FALSE))
returns the follow results, which maybe related to #36, but also will explain why learnr
also shows this output.
("Afghanistan"("Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",
"Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",
"Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",
"Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",
"Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",
"Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",
"Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",
"Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",
"Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",
"Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",
"Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",
"Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",
"Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",
"Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",
"Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",
"Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",
"Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",
"Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",
"Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",
"Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",
"Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",
"Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",
"Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",
"Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",
"Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",
"Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",
"Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan",
"Afghanistan", "Afghanistan", "Afghanistan"))(iso2 = "AF"("AF",
"AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF",
"AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF",
"AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF",
"AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF",
"AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF",
"AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF",
"AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF",
"AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF",
"AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF",
"AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF",
"AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF", "AF"),
iso3 = "AFG"("AFG", "AFG", "AFG", "AFG", "AFG", "AFG", "AFG",
"AFG", "AFG", "AFG", "AFG", "AFG", "AFG", "AFG", "AFG",
"AFG", "AFG", "AFG", "AFG", "AFG", "AFG", "AFG", "AFG",
"AFG", "AFG", "AFG", "AFG", "AFG", "AFG", "AFG", "AFG",
"AFG", "AFG", "AFG", "AFG", "AFG", "AFG", "AFG", "AFG",
"AFG", "AFG", "AFG", "AFG", "AFG", "AFG", "AFG", "AFG",
"AFG", "AFG", "AFG", "AFG", "AFG", "AFG", "AFG", "AFG",
"AFG", "AFG", "AFG", "AFG", "AFG", "AFG", "AFG", "AFG",
"AFG", "AFG", "AFG", "AFG", "AFG", "AFG", "AFG", "AFG",
"AFG", "AFG", "AFG", "AFG", "AFG", "AFG", "AFG", "AFG",
"AFG", "AFG", "AFG", "AFG", "AFG", "AFG", "AFG", "AFG",
"AFG", "AFG", "AFG", "AFG", "AFG", "AFG", "AFG", "AFG",
"AFG", "AFG", "AFG", "AFG", "AFG", "AFG", "AFG", "AFG",
"AFG", "AFG", "AFG", "AFG", "AFG", "AFG", "AFG", "AFG"),
year = 1980L(1981L, 1980L, 1981L, 1980L, 1981L, 1980L, 1981L,
1980L, 1981L, 1980L, 1981L, 1980L, 1981L, 1980L, 1981L,
1980L, 1981L, 1980L, 1981L, 1980L, 1981L, 1980L, 1981L,
1980L, 1981L, 1980L, 1981L, 1980L, 1981L, 1980L, 1981L,
1980L, 1981L, 1980L, 1981L, 1980L, 1981L, 1980L, 1981L,
1980L, 1981L, 1980L, 1981L, 1980L, 1981L, 1980L, 1981L,
1980L, 1981L, 1980L, 1981L, 1980L, 1981L, 1980L, 1981L,
1980L, 1981L, 1980L, 1981L, 1980L, 1981L, 1980L, 1981L,
1980L, 1981L, 1980L, 1981L, 1980L, 1981L, 1980L, 1981L,
1980L, 1981L, 1980L, 1981L, 1980L, 1981L, 1980L, 1981L,
1980L, 1981L, 1980L, 1981L, 1980L, 1981L, 1980L, 1981L,
1980L, 1981L, 1980L, 1981L, 1980L, 1981L, 1980L, 1981L,
1980L, 1981L, 1980L, 1981L, 1980L, 1981L, 1980L, 1981L,
1980L, 1981L, 1980L, 1981L, 1980L, 1981L, 1980L, 1981L),
key = "new_sp_m014"("new_sp_m014", "new_sp_m1524", "new_sp_m1524",
"new_sp_m2534", "new_sp_m2534", "new_sp_m3544", "new_sp_m3544",
"new_sp_m4554", "new_sp_m4554", "new_sp_m5564", "new_sp_m5564",
"new_sp_m65", "new_sp_m65", "new_sp_f014", "new_sp_f014",
"new_sp_f1524", "new_sp_f1524", "new_sp_f2534", "new_sp_f2534",
"new_sp_f3544", "new_sp_f3544", "new_sp_f4554", "new_sp_f4554",
"new_sp_f5564", "new_sp_f5564", "new_sp_f65", "new_sp_f65",
"new_sn_m014", "new_sn_m014", "new_sn_m1524", "new_sn_m1524",
"new_sn_m2534", "new_sn_m2534", "new_sn_m3544", "new_sn_m3544",
"new_sn_m4554", "new_sn_m4554", "new_sn_m5564", "new_sn_m5564",
"new_sn_m65", "new_sn_m65", "new_sn_f014", "new_sn_f014",
"new_sn_f1524", "new_sn_f1524", "new_sn_f2534", "new_sn_f2534",
"new_sn_f3544", "new_sn_f3544", "new_sn_f4554", "new_sn_f4554",
"new_sn_f5564", "new_sn_f5564", "new_sn_f65", "new_sn_f65",
"new_ep_m014", "new_ep_m014", "new_ep_m1524", "new_ep_m1524",
"new_ep_m2534", "new_ep_m2534", "new_ep_m3544", "new_ep_m3544",
"new_ep_m4554", "new_ep_m4554", "new_ep_m5564", "new_ep_m5564",
"new_ep_m65", "new_ep_m65", "new_ep_f014", "new_ep_f014",
"new_ep_f1524", "new_ep_f1524", "new_ep_f2534", "new_ep_f2534",
"new_ep_f3544", "new_ep_f3544", "new_ep_f4554", "new_ep_f4554",
"new_ep_f5564", "new_ep_f5564", "new_ep_f65", "new_ep_f65",
"newrel_m014", "newrel_m014", "newrel_m1524", "newrel_m1524",
"newrel_m2534", "newrel_m2534", "newrel_m3544", "newrel_m3544",
"newrel_m4554", "newrel_m4554", "newrel_m5564", "newrel_m5564",
"newrel_m65", "newrel_m65", "newrel_f014", "newrel_f014",
"newrel_f1524", "newrel_f1524", "newrel_f2534", "newrel_f2534",
"newrel_f3544", "newrel_f3544", "newrel_f4554", "newrel_f4554",
"newrel_f5564", "newrel_f5564", "newrel_f65", "newrel_f65"),
value = NA_integer_(NA_integer_, NA_integer_, NA_integer_,
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_,
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_,
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_,
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_,
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_,
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_,
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_,
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_,
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_,
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_,
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_,
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_,
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_,
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_,
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_,
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_,
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_,
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_,
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_,
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_,
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_,
NA_integer_, NA_integer_, NA_integer_))
You need to evaluate everything in order to determine which s3 function is being called.
rlang::fn_fmls(mean)
$x
$...
this mean that the call_standardise_formals
will not work at the moment for mean
since the generic signature is just mean(x, ...)
. For example, if student puts mean(1:3, na.rm=FALSE)
, and the solution code is mean(1:3)
the github/pages
build is not working. It is constantly in the "yellow" phase (i.e., it doesn't pass, but it also isn't failing...).
This is making it so I cannot merge PRs
tidyr::gather(who, key, value, new_sp_m014:newrel_f65, ____ = ____)
It is fine to be forced to be returned last, but it should be documented
Stale branches, @garrettgman can these be deleted?
attempt-1.0
Updated last year by garrettgman
infix-checking-bug
Updated last year by garrettgman
pseudo-pipe-approach
Updated last year by garrettgman
outside-in
Updated last year by garrettgman
Put in more boilerplate text
aut
? ctb
? huh?
I need a way for students to submit their work to the teacher. Ideally, this would be integrated into a learnr button.
I'm not yet sure what exactly should be submitted. The log of the students work in the tutorial seems like a good candidate.
I'm not yet sure where the submission should go. One idea is that the submission function/button would place an entry in the master log that a teacher could then work with using grader tools.
@using the grader-demo in the tutorials folder, when clicking Submit Answer (the correct one or any) I receive:
Error : Base operators are not defined for quosures. Do you need to unquote the quosure? # Bad: myquosure1 == myquosure2 # Good: !!myquosure1 == !!myquosure2
Do you know why does this happen and how could I solve it? @garrettgman
Solved here: rstudio/rstudio#1579 (comment)
To use it, set something like the below in your .Rprofile:
setHook("rstudio.sessionInit", function(newSession) {
if (newSession)
message("Welcome to RStudio ", rstudioapi::getVersion())
}, action = "append")
The original issue from #16 should be fixed, but there were internal API changes (mainly from using the condition
object), so we need to fix the grader::grading_demo
file (or replace it entirely with a fully-fledged learnr
+ grader
example)
grade_
prefixes:
check_code
-> grade_code
check_result
-> grade_result
test_result
-> grade_test
grade_conditions
Others:
grading_demo
-> gradethis_demo
No checking function should handle empty user input
Needs to point to gradethis
not grader
Example in DESCRIPTION
person("Barret", "Schloerke", , "[email protected]", "aut",
comment = c(ORCID = "0000-0001-9986-114X"))
be able to use
grader::pass_if(~ .result == correct_df)
instead of only
grader::pass_if(~ .result == correct_df, message = "1337")
From the Nested Data section of https://tutorials.shinyapps.io/list-columns:
https://cran.r-project.org/web/packages/gradeR/index.html
going to have to rename this package, most likely
It's confusing and hard to test. There should never be a "it's voodoo" when explaining how it works.
Current:
check_result(args, grader_args, learnr_args) # checks result
Proposed:
ck_fn <- check_result(args) # returns function that accepts grader_args / learnr_args
ck_fn # will be called after "*-check" evaluation as `ck_fn(grader_args, learnr_args)`
This allows for any function to be produced in any way as long as a function is returned from the chunk that accepts grader_args
and learnr_args
. We do not need to be cautious of parameter expansion as grader_args
is already included and is a list.
This would require functions like check_result
to return a function that does the evaluation. Rough example:
new_check_result(...) {
results <- list(...)
function(grader_args, learnr_args) {
# check results here
graded(TRUE)
}
}
This would clean up the logic inside grade_learnr and would be much easier to enforce / document
From #17, the first code returns
I see that you are using pipe operators (e.g. %>%), so I want to let you know that this is how I am interpretting your code before I check it: ~gather(who, key, value, new_sp_m014:newrel_f65, na.rm = FALSE) I expected na.rm = TRUE where you wrote na.rm = FALSE. Try it again. I have a good feeling about this.
We should remove the ~
that appears in the message as it will confuse students. In this case , the ~
appears before gather
.
Discussion for this comment: #30 (comment)
links and tags still point to grader
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.