From a4cf6711e7186b420cc56fda7bed7f567e9ebfc3 Mon Sep 17 00:00:00 2001 From: Daniel Chen Date: Tue, 6 Aug 2019 23:30:46 -0400 Subject: [PATCH] Development branch housing stable API (#53 #48 #47 #57) * Message creation changes in check_result (#48) * changes + tests to check_result messages * I think I covered all message cases for check_result * remove test_message_check_result.R * unit tests for checking messages [wip] * add default gradethis options to .onLoad * correct message changes + tests for check_result * uncomment incorrect tests and fix them * rename match/correct to .is_match/.is_correct * res returns a single bool using `all` and raises warning (#47) * make sure res returns a single bool using `all` * add reshape2, tibble, and tidyr to suggests section of DESCRPTION * user/solution into fxns and skip tests if no pkg * move common custom expect fxns to helper-expect.R * add a warning before calling all() when length(res) > * add documentation about == and identical * remove dependencies only from billboard test https://github.com/rstudio-education/grader/pull/47#discussion_r308276771 * Glue message upgrade + tests (#57), doc+DESCRIPTION changes * upgrade glue_message ability (pair with barret) * upgrade glue message generation for check result/code * upgrade glue_message ability (pair with barret) * upgrade glue message generation for check result/code * fix R CMD check warnings * small doc changes + lint fixes * add \link to docs * add \code brackets * add \link * add \code brackets to docs * barret review changes --- .Rbuildignore | 1 + DESCRIPTION | 1 - R/check_code.R | 65 +- R/check_result.R | 40 +- R/glue.R | 30 + R/pass_fail_condi.R | 13 +- R/test_result.R | 10 +- R/view_tutorial.R | 2 +- R/zzz.R | 17 + inst/tutorials/grading-demo/grading-demo.Rmd | 3 +- man-roxygen/correct.R | 5 +- man-roxygen/glue_correct.R | 2 + man-roxygen/glue_incorrect.R | 2 + man-roxygen/grader_args.R | 3 +- man-roxygen/incorrect.R | 1 + man-roxygen/learnr_args.R | 3 +- man-roxygen/pass_fail_x_condition.R | 5 + man/check_code.Rd | 34 +- man/check_result.Rd | 34 +- man/fail_if.Rd | 6 +- man/pass_if.Rd | 6 +- man/test_result.Rd | 10 +- scripts/billboard.R | 44 + tests/testthat/billboard.R | 1261 ++++++++++++++++++ tests/testthat/helper-expect.R | 35 + tests/testthat/test_check_code.R | 15 - tests/testthat/test_check_result_condi.R | 10 - tests/testthat/test_check_result_df.R | 15 + tests/testthat/test_condi.R | 20 - tests/testthat/test_glue_message.R | 16 + tests/testthat/test_grade_learnr.R | 12 +- tests/testthat/test_message_check_result.R | 152 +++ tests/testthat/test_test_result.R | 39 +- 33 files changed, 1727 insertions(+), 185 deletions(-) create mode 100644 R/glue.R create mode 100644 R/zzz.R create mode 100644 man-roxygen/glue_correct.R create mode 100644 man-roxygen/glue_incorrect.R create mode 100644 man-roxygen/incorrect.R create mode 100644 man-roxygen/pass_fail_x_condition.R create mode 100644 scripts/billboard.R create mode 100644 tests/testthat/billboard.R create mode 100644 tests/testthat/helper-expect.R create mode 100644 tests/testthat/test_check_result_df.R create mode 100644 tests/testthat/test_glue_message.R create mode 100644 tests/testthat/test_message_check_result.R diff --git a/.Rbuildignore b/.Rbuildignore index 73551ef7..87a3a3c3 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -9,3 +9,4 @@ ^man-roxygen$ ^\.lintr$ ^\.vscode$ +^scripts/ diff --git a/DESCRIPTION b/DESCRIPTION index 82914eb2..65c7f95d 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -26,7 +26,6 @@ Imports: knitr, callr, learnr (>= 0.9.2.9001), - stringr, readr, checkmate, testthat diff --git a/R/check_code.R b/R/check_code.R index b7b01588..96c7cca4 100644 --- a/R/check_code.R +++ b/R/check_code.R @@ -24,35 +24,31 @@ #' #' For best results, name all arguments provided in the solution code. #' -#' @param correct A character string to display if the student answer matches -#' the solution code. -#' This character string will be run through \code{glue::\link[glue]{glue_data}} with -#' \code{list(correct = TRUE, message = NULL)}. -#' @param incorrect A character string to display if the student answer matches -#' the solution code. -#' This character string will be run through \code{glue::\link[glue]{glue_data}} with -#' \code{list(correct = FALSE, message = "")} -#' where message is the error found while comparing the user solution to the known solution. +#' @template correct +#' @template incorrect #' @template grader_args #' @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")}. #' #' @return a \code{grader_graded} structure from \code{\link{result}}. #' An incorrect message will describe the first way that the answer differs, #' the message will be the content of the \code{correct} #' argument. #' -#' -#' -#' -#' #' @export #' @examples #' \dontrun{grading_demo()} check_code <- function( - correct = "{random_praise()} Correct!", - incorrect = "{message} {random_encourage()}", - grader_args = list(), # provided by `grade_learnr` - learnr_args = list() # provided by `grade_learnr` + correct = NULL, + incorrect = NULL, + grader_args = list(), + learnr_args = list(), + glue_correct = getOption("gradethis_glue_correct"), + glue_incorrect = getOption("gradethis_glue_incorrect"), + glue_pipe = getOption("gradethis_glue_pipe") ) { chkm8_single_character(correct) chkm8_single_character(incorrect) @@ -66,33 +62,28 @@ check_code <- function( return( graded( correct = TRUE, - message = glue::glue_data( - list( - correct = TRUE, - message = NULL - ), - correct + message = glue_message( + glue_correct, + .is_correct = TRUE, + .message = NULL, + .correct = correct ) ) ) } - message <- glue::glue_data( - list( - correct = FALSE, - message = is_same_info$message - ), - incorrect + message <- glue_message( + glue_incorrect, + .is_correct = FALSE, + .message = is_same_info$message, + .incorrect = incorrect ) if (uses_pipe(user)) { - message <- glue::glue_data( - list( - user = user, - message = message - ), - "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:\n\n{deparse(unpipe_all(user))}\n\n{message}" + message <- glue_message( + glue_pipe, + .user = user, + .message = message, + .incorrect = incorrect ) } diff --git a/R/check_result.R b/R/check_result.R index 39237d14..5cc17260 100644 --- a/R/check_result.R +++ b/R/check_result.R @@ -5,16 +5,13 @@ #' If the user result exactly matches a known \code{result}, \code{check_result} #' returns the matching message value. #' +#' @param ... \code{\link{pass_if}} or \code{\link{fail_if}} conditions to check #' @template correct -#' @param incorrect A character string to display if the student answer matches -#' a known answer. -#' This character string will be run through -#' \code{glue::\link[glue]{glue_data}} with -#' \code{list(correct = FALSE, message = "")}. -#' where message is the matched result message. +#' @template incorrect #' @template grader_args #' @template learnr_args -#' @param ... ignored +#' @template glue_correct +#' @template glue_incorrect #' #' @return a \code{grader_graded} structure from either #' \code{\link{pass_if}} or \code{\link{fail_if}} containing a formatted @@ -25,22 +22,23 @@ #' \dontrun{grading_demo()} check_result <- function( ..., - correct = "{paste0(random_praise(), if (nchar(message) > 0) \" \", message)}", - incorrect = "{paste0(message, if(nchar(message) > 0) \" \", random_encourage())}", - grader_args = list(), # provided by `grade_learnr` - learnr_args = list() # provided by `grade_learnr` + correct = NULL, + incorrect = NULL, + grader_args = list(), + learnr_args = list(), + glue_correct = getOption("gradethis_glue_correct"), + glue_incorrect = getOption("gradethis_glue_incorrect") ) { + results <- list(...) chkm8_item_class(results, "grader_condition") - chkm8_single_character(correct) - chkm8_single_character(incorrect) if (!any(vapply(results, `[[`, logical(1), "correct"))) { stop("At least one correct result must be provided") } # init final answer as not found - final_result <- graded(correct = FALSE, NULL) + final_result <- graded(correct = FALSE, message = NULL) found_match <- FALSE for (resu in results) { @@ -52,13 +50,13 @@ check_result <- function( } } - message <- glue::glue_data( - list( - matched = found_match, - correct = final_result$correct, - message = final_result$message - ), - {if (final_result$correct) correct else incorrect} # nolint + message <- glue_message( + {if (final_result$correct) glue_correct else glue_incorrect}, # nolint + .is_match = found_match, + .is_correct = final_result$correct, + .message = final_result$message, + .correct = correct, + .incorrect = incorrect ) return(graded( diff --git a/R/glue.R b/R/glue.R new file mode 100644 index 00000000..003d5e87 --- /dev/null +++ b/R/glue.R @@ -0,0 +1,30 @@ +#' Generate Glue string from expression +#' +#' Checks and validates arguments passed into \code{glue}. +#' +#' @param glue_expression A glue character expression string. +#' @param ... Values to be inserted into glue expression. +#' @noRd +glue_message <- function( + glue_expression, + ... +) { + params <- list(...) + param_names <- names(params) + is_bool <- grepl("^\\.is_", param_names) + bool_names <- param_names[is_bool] + char_names <- param_names[!is_bool] + + if (length(bool_names) > 1) { + params[bool_names] <- lapply(params[bool_names], function(x){x %||% NA}) # nolint + } + + params[char_names] <- lapply(char_names, function(char_name) { + x <- params[[char_name]] %||% "" # convert NULL strings to "" to work with glue + chkm8_single_character(x, char_name) + x + }) + + ret <- glue::glue_data(params, glue_expression) + return(ret) +} diff --git a/R/pass_fail_condi.R b/R/pass_fail_condi.R index 078c73ea..714edac4 100644 --- a/R/pass_fail_condi.R +++ b/R/pass_fail_condi.R @@ -1,5 +1,5 @@ #' Pass if condition matches -#' @param x a formula, function, or value, that returns \code{TRUE} or \code{FALSE} +#' @template pass_fail_x_condition #' @param message chracter string for message returned #' @export pass_if <- function(x, message = NULL) { @@ -7,7 +7,7 @@ pass_if <- function(x, message = NULL) { } #' Fail if condition matches -#' @param x a formula, function, or value, that returns \code{TRUE} or \code{FALSE} +#' @template pass_fail_x_condition #' @param message chracter string for message returned #' @export fail_if <- function(x, message = NULL) { @@ -67,6 +67,15 @@ evaluate_condition <- function(condi, grader_args, learnr_args) { "value" = evaluate_condi_value(condi$x, learnr_args$last_value) ) + # if we compare something like a vector or dataframes to one another + # we need to collapse the result down to a single boolean value + if (length(res) > 1) { + ## this isn't the best way to handle NA values so we raise a warning. + ## https://github.com/rstudio-education/grader/issues/46 # nolint + warning(glue::glue("I got a length of {length(res)}, instead of 1 during the conditional check.\n Did you use == ? If so, consider using idential()")) # nolint + res <- !all(is.na(res)) && all(res, na.rm = TRUE) + } + # implement when we add a `exec`/`expect` api to check_result # will account for function returns # if (inherits(res, 'grader_graded')) {return(res)} # nolint diff --git a/R/test_result.R b/R/test_result.R index 4a0e68a4..993d84ab 100644 --- a/R/test_result.R +++ b/R/test_result.R @@ -30,13 +30,9 @@ test_result <- function( ..., correct = "{num_correct}/{num_total} correct! {random_praise()}", - incorrect = paste0( - "{num_correct}/{num_total} correct. ", - "Fix this first: '{errors[1]}'. ", - "{random_encourage()}" - ), - grader_args = list(), # provided by `grade_learnr` - learnr_args = list() # provided by `grade_learnr` + incorrect = "", + grader_args = list(), + learnr_args = list() ) { tests <- grader_tests(...) chkm8_class(tests, "grader_tests") diff --git a/R/view_tutorial.R b/R/view_tutorial.R index 921961f0..dba5220f 100644 --- a/R/view_tutorial.R +++ b/R/view_tutorial.R @@ -92,7 +92,7 @@ add_tutorial <- function(name, package) { # Check that the .Rprofile does not already load a tutorial if (file.exists(rprofile)) { text <- readr::read_file(rprofile) - if (stringr::str_detect(text, "view_tutorial\\(")) { + if (grepl("view_tutorial(", text, fixed = TRUE)) { stop( "This project already loads a tutorial upon opening.\n", "Please remove the tutorial by manually opening the ", diff --git a/R/zzz.R b/R/zzz.R new file mode 100644 index 00000000..6f31d023 --- /dev/null +++ b/R/zzz.R @@ -0,0 +1,17 @@ +gradethis_default_options <- list( + gradethis_glue_correct = "{ random_praise() } { .message } { .correct }", + gradethis_glue_incorrect = "{ .message } { .incorrect } { random_encourage() }", + + gradethis_glue_pipe = paste0( + "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:\n\n{deparse(unpipe_all(.user))}\n\n{.message}") +) + +.onLoad <- function(libname, pkgname) { + op <- options() + toset <- !(names(gradethis_default_options) %in% names(op)) + if (any(toset)) options(gradethis_default_options[toset]) + + invisible() +} diff --git a/inst/tutorials/grading-demo/grading-demo.Rmd b/inst/tutorials/grading-demo/grading-demo.Rmd index 2e4391af..faba9023 100644 --- a/inst/tutorials/grading-demo/grading-demo.Rmd +++ b/inst/tutorials/grading-demo/grading-demo.Rmd @@ -19,7 +19,8 @@ knitr::opts_chunk$set(echo = FALSE) ### Check Exercise Result -`gradethis` can check for the final returned value. This grading approach does not inspect the code. It only inspects the final result. +`gradethis` can check for the final returned value. +This grading approach does not inspect the code. It only inspects the final result. See `?check_result` for more information. diff --git a/man-roxygen/correct.R b/man-roxygen/correct.R index 7e074d8b..0ab9edbb 100644 --- a/man-roxygen/correct.R +++ b/man-roxygen/correct.R @@ -1,4 +1 @@ -#' @param correct A character string to display if the student answer matches -#' a known answer. -#' This character string will be run through \code{glue::\link[glue]{glue_data}} with \code{list(correct = TRUE, message = "")}. where message is the matched result message. -#' \code{matched} is a boolean value about whether the submitted is found in a set of provided values. +#' @param correct A character string to display if the student answer matches a known correct answer. diff --git a/man-roxygen/glue_correct.R b/man-roxygen/glue_correct.R new file mode 100644 index 00000000..308893b3 --- /dev/null +++ b/man-roxygen/glue_correct.R @@ -0,0 +1,2 @@ +#' @param glue_correct A glue string that returns the final correct message displayed. +#' Defaults to \code{getOption("gradethis_glue_correct")}. diff --git a/man-roxygen/glue_incorrect.R b/man-roxygen/glue_incorrect.R new file mode 100644 index 00000000..62ff6c61 --- /dev/null +++ b/man-roxygen/glue_incorrect.R @@ -0,0 +1,2 @@ +#' @param glue_incorrect A glue string that returns the final incorrect message displayed. +#' Defaults to \code{getOption("gradethis_glue_incorrect")}. diff --git a/man-roxygen/grader_args.R b/man-roxygen/grader_args.R index 3d031161..8de5ec99 100644 --- a/man-roxygen/grader_args.R +++ b/man-roxygen/grader_args.R @@ -1,4 +1,5 @@ -#' @param grader_args A list of parameters passed to \code{grader} functions (provided by \code{grade_learnr}). This contains: \describe{ +#' @param grader_args A list of parameters passed to \code{grader} functions (provided by \code{\link{grade_learnr}}). +#' This contains: \describe{ #' \item{\code{user_quo}}{Quoted R code submitted by the user. Ex: \code{rlang::\link[rlang]{quo}(1)} } #' \item{\code{solution_quo}}{[Optional] Quoted solution R code provided by the \code{*-solution} chunk for an exercise.} #' } diff --git a/man-roxygen/incorrect.R b/man-roxygen/incorrect.R new file mode 100644 index 00000000..6423e760 --- /dev/null +++ b/man-roxygen/incorrect.R @@ -0,0 +1 @@ +#' @param incorrect A character string to display if the student answer matches a known incorrect answer. diff --git a/man-roxygen/learnr_args.R b/man-roxygen/learnr_args.R index 1d9602d6..6215789b 100644 --- a/man-roxygen/learnr_args.R +++ b/man-roxygen/learnr_args.R @@ -1 +1,2 @@ -#' @param learnr_args A list of all parameters passed to \code{\link{grade_learnr}} by \code{learnr}. See \url{https://rstudio.github.io/learnr/exercises.html#exercise_checking} for more details. +#' @param learnr_args A list of all parameters passed to \code{\link{grade_learnr}} by \code{learnr}. +#' See \url{https://rstudio.github.io/learnr/exercises.html#exercise_checking} for more details. diff --git a/man-roxygen/pass_fail_x_condition.R b/man-roxygen/pass_fail_x_condition.R new file mode 100644 index 00000000..d7ae9cbc --- /dev/null +++ b/man-roxygen/pass_fail_x_condition.R @@ -0,0 +1,5 @@ +#' @param x A formula, function, or value, that returns \code{TRUE} or \code{FALSE}. +#' When comparing objects that are greater than length 1 (e.g., vectors, dataframes, matricies, etc) +#' A boolean vector will be returned if the user uses \code{==}, not a single boolean value. +#' \code{grader} will run the vector through \code{all(..., na.rm = TRUE)} to check for the boolean value. +#' It is advised that the user use \code{identical()} instead of \code{==} in this case. diff --git a/man/check_code.Rd b/man/check_code.Rd index a3842a3a..1608ae45 100644 --- a/man/check_code.Rd +++ b/man/check_code.Rd @@ -4,28 +4,34 @@ \alias{check_code} \title{Check code structure} \usage{ -check_code(correct = "{random_praise()} Correct!", - incorrect = "{message} {random_encourage()}", grader_args = list(), - learnr_args = list()) +check_code(correct = NULL, incorrect = NULL, grader_args = list(), + learnr_args = list(), + glue_correct = getOption("gradethis_glue_correct"), + glue_incorrect = getOption("gradethis_glue_incorrect"), + glue_pipe = getOption("gradethis_glue_pipe")) } \arguments{ -\item{correct}{A character string to display if the student answer matches -the solution code. -This character string will be run through \code{glue::\link[glue]{glue_data}} with -\code{list(correct = TRUE, message = NULL)}.} +\item{correct}{A character string to display if the student answer matches a known correct answer.} -\item{incorrect}{A character string to display if the student answer matches -the solution code. -This character string will be run through \code{glue::\link[glue]{glue_data}} with -\code{list(correct = FALSE, message = "")} -where message is the error found while comparing the user solution to the known solution.} +\item{incorrect}{A character string to display if the student answer matches a known incorrect answer.} -\item{grader_args}{A list of parameters passed to \code{grader} functions (provided by \code{grade_learnr}). This contains: \describe{ +\item{grader_args}{A list of parameters passed to \code{grader} functions (provided by \code{\link{grade_learnr}}). +This contains: \describe{ \item{\code{user_quo}}{Quoted R code submitted by the user. Ex: \code{rlang::\link[rlang]{quo}(1)} } \item{\code{solution_quo}}{[Optional] Quoted solution R code provided by the \code{*-solution} chunk for an exercise.} }} -\item{learnr_args}{A list of all parameters passed to \code{\link{grade_learnr}} by \code{learnr}. See \url{https://rstudio.github.io/learnr/exercises.html#exercise_checking} for more details.} +\item{learnr_args}{A list of all parameters passed to \code{\link{grade_learnr}} by \code{learnr}. +See \url{https://rstudio.github.io/learnr/exercises.html#exercise_checking} for more details.} + +\item{glue_correct}{A glue string that returns the final correct message displayed. +Defaults to \code{getOption("gradethis_glue_correct")}.} + +\item{glue_incorrect}{A glue string that returns the final incorrect message displayed. +Defaults to \code{getOption("gradethis_glue_incorrect")}.} + +\item{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")}.} } \value{ a \code{grader_graded} structure from \code{\link{result}}. diff --git a/man/check_result.Rd b/man/check_result.Rd index 7d787a86..3274cff8 100644 --- a/man/check_result.Rd +++ b/man/check_result.Rd @@ -4,32 +4,32 @@ \alias{check_result} \title{Check result of exercise code} \usage{ -check_result(..., - correct = "{paste0(random_praise(), if (nchar(message) > 0) \\" \\", message)}", - incorrect = "{paste0(message, if(nchar(message) > 0) \\" \\", random_encourage())}", - grader_args = list(), learnr_args = list()) +check_result(..., correct = NULL, incorrect = NULL, + grader_args = list(), learnr_args = list(), + glue_correct = getOption("gradethis_glue_correct"), + glue_incorrect = getOption("gradethis_glue_incorrect")) } \arguments{ -\item{...}{ignored} +\item{...}{\code{\link{pass_if}} or \code{\link{fail_if}} conditions to check} -\item{correct}{A character string to display if the student answer matches -a known answer. -This character string will be run through \code{glue::\link[glue]{glue_data}} with \code{list(correct = TRUE, message = "")}. where message is the matched result message. -\code{matched} is a boolean value about whether the submitted is found in a set of provided values.} +\item{correct}{A character string to display if the student answer matches a known correct answer.} -\item{incorrect}{A character string to display if the student answer matches -a known answer. -This character string will be run through -\code{glue::\link[glue]{glue_data}} with -\code{list(correct = FALSE, message = "")}. -where message is the matched result message.} +\item{incorrect}{A character string to display if the student answer matches a known incorrect answer.} -\item{grader_args}{A list of parameters passed to \code{grader} functions (provided by \code{grade_learnr}). This contains: \describe{ +\item{grader_args}{A list of parameters passed to \code{grader} functions (provided by \code{\link{grade_learnr}}). +This contains: \describe{ \item{\code{user_quo}}{Quoted R code submitted by the user. Ex: \code{rlang::\link[rlang]{quo}(1)} } \item{\code{solution_quo}}{[Optional] Quoted solution R code provided by the \code{*-solution} chunk for an exercise.} }} -\item{learnr_args}{A list of all parameters passed to \code{\link{grade_learnr}} by \code{learnr}. See \url{https://rstudio.github.io/learnr/exercises.html#exercise_checking} for more details.} +\item{learnr_args}{A list of all parameters passed to \code{\link{grade_learnr}} by \code{learnr}. +See \url{https://rstudio.github.io/learnr/exercises.html#exercise_checking} for more details.} + +\item{glue_correct}{A glue string that returns the final correct message displayed. +Defaults to \code{getOption("gradethis_glue_correct")}.} + +\item{glue_incorrect}{A glue string that returns the final incorrect message displayed. +Defaults to \code{getOption("gradethis_glue_incorrect")}.} } \value{ a \code{grader_graded} structure from either diff --git a/man/fail_if.Rd b/man/fail_if.Rd index 64302fa0..ed66397c 100644 --- a/man/fail_if.Rd +++ b/man/fail_if.Rd @@ -7,7 +7,11 @@ fail_if(x, message = NULL) } \arguments{ -\item{x}{a formula, function, or value, that returns \code{TRUE} or \code{FALSE}} +\item{x}{A formula, function, or value, that returns \code{TRUE} or \code{FALSE}. +When comparing objects that are greater than length 1 (e.g., vectors, dataframes, matricies, etc) +A boolean vector will be returned if the user uses \code{==}, not a single boolean value. +\code{grader} will run the vector through \code{all(..., na.rm = TRUE)} to check for the boolean value. +It is advised that the user use \code{identical()} instead of \code{==} in this case.} \item{message}{chracter string for message returned} } diff --git a/man/pass_if.Rd b/man/pass_if.Rd index 43d293ab..a4336cd3 100644 --- a/man/pass_if.Rd +++ b/man/pass_if.Rd @@ -7,7 +7,11 @@ pass_if(x, message = NULL) } \arguments{ -\item{x}{a formula, function, or value, that returns \code{TRUE} or \code{FALSE}} +\item{x}{A formula, function, or value, that returns \code{TRUE} or \code{FALSE}. +When comparing objects that are greater than length 1 (e.g., vectors, dataframes, matricies, etc) +A boolean vector will be returned if the user uses \code{==}, not a single boolean value. +\code{grader} will run the vector through \code{all(..., na.rm = TRUE)} to check for the boolean value. +It is advised that the user use \code{identical()} instead of \code{==} in this case.} \item{message}{chracter string for message returned} } diff --git a/man/test_result.Rd b/man/test_result.Rd index e18221ce..5499edbc 100644 --- a/man/test_result.Rd +++ b/man/test_result.Rd @@ -6,9 +6,7 @@ \usage{ test_result(..., correct = "{num_correct}/{num_total} correct! {random_praise()}", - incorrect = paste0("{num_correct}/{num_total} correct. ", - "Fix this first: '{errors[1]}'. ", "{random_encourage()}"), - grader_args = list(), learnr_args = list()) + incorrect = "", grader_args = list(), learnr_args = list()) } \arguments{ \item{...}{ignored} @@ -29,12 +27,14 @@ test_result(..., \item \code{errors}: Vector of errors found }} -\item{grader_args}{A list of parameters passed to \code{grader} functions (provided by \code{grade_learnr}). This contains: \describe{ +\item{grader_args}{A list of parameters passed to \code{grader} functions (provided by \code{\link{grade_learnr}}). +This contains: \describe{ \item{\code{user_quo}}{Quoted R code submitted by the user. Ex: \code{rlang::\link[rlang]{quo}(1)} } \item{\code{solution_quo}}{[Optional] Quoted solution R code provided by the \code{*-solution} chunk for an exercise.} }} -\item{learnr_args}{A list of all parameters passed to \code{\link{grade_learnr}} by \code{learnr}. See \url{https://rstudio.github.io/learnr/exercises.html#exercise_checking} for more details.} +\item{learnr_args}{A list of all parameters passed to \code{\link{grade_learnr}} by \code{learnr}. +See \url{https://rstudio.github.io/learnr/exercises.html#exercise_checking} for more details.} } \value{ a \code{grader_graded} structure from \code{\link{result}} containing diff --git a/scripts/billboard.R b/scripts/billboard.R new file mode 100644 index 00000000..af6b4b2b --- /dev/null +++ b/scripts/billboard.R @@ -0,0 +1,44 @@ +library(magrittr) + +# function to create the dput output in tests/testthat/billboard.R +billboard <- readr::read_csv("https://raw.githubusercontent.com/hadley/tidy-data/master/data/billboard.csv") %>% + head() + +create_user_df_melt <- function() { + user <- reshape2::melt( + 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) + return(user) +} + +create_solution_df_tidy <- function() { + solution <- tidyr::gather(billboard, "week", "rank", x1st.week:x76th.week) + return(solution) +} + +billboard_file <- file('tests/testthat/billboard.R') +temp1 <- tempfile() +dput(tibble::as_tibble(create_user_df_melt()), file = temp1) + +temp2 <- tempfile() +dput(tibble::as_tibble(create_solution_df_tidy()), file = temp2) + +cat( + "# nolint start", + "\n", + "billboard_user <-", paste0(readLines(temp1), + collapse = "\n"), + "\n\n", + "billboard_solution <-", paste0(readLines(temp2), + collapse = "\n"), + "\n", + "# nolint end\n", + file = billboard_file, append = TRUE) + +close(billboard_file) diff --git a/tests/testthat/billboard.R b/tests/testthat/billboard.R new file mode 100644 index 00000000..77488c8e --- /dev/null +++ b/tests/testthat/billboard.R @@ -0,0 +1,1261 @@ +# nolint start + billboard_user <- structure(list(year = c(2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000), artist.inverted = c("Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420), class = c("hms", "difftime"), units = "secs"), + genre = c("Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock"), date.entered = structure(c(11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125), class = "Date"), date.peaked = structure(c(11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195), class = "Date"), week = c("x1st.week", + "x1st.week", "x1st.week", "x1st.week", "x1st.week", "x1st.week", + "x2nd.week", "x2nd.week", "x2nd.week", "x2nd.week", "x2nd.week", + "x2nd.week", "x3rd.week", "x3rd.week", "x3rd.week", "x3rd.week", + "x3rd.week", "x3rd.week", "x4th.week", "x4th.week", "x4th.week", + "x4th.week", "x4th.week", "x4th.week", "x5th.week", "x5th.week", + "x5th.week", "x5th.week", "x5th.week", "x5th.week", "x6th.week", + "x6th.week", "x6th.week", "x6th.week", "x6th.week", "x6th.week", + "x7th.week", "x7th.week", "x7th.week", "x7th.week", "x7th.week", + "x7th.week", "x8th.week", "x8th.week", "x8th.week", "x8th.week", + "x8th.week", "x8th.week", "x9th.week", "x9th.week", "x9th.week", + "x9th.week", "x9th.week", "x9th.week", "x10th.week", "x10th.week", + "x10th.week", "x10th.week", "x10th.week", "x10th.week", "x11th.week", + "x11th.week", "x11th.week", "x11th.week", "x11th.week", "x11th.week", + "x12th.week", "x12th.week", "x12th.week", "x12th.week", "x12th.week", + "x12th.week", "x13th.week", "x13th.week", "x13th.week", "x13th.week", + "x13th.week", "x13th.week", "x14th.week", "x14th.week", "x14th.week", + "x14th.week", "x14th.week", "x14th.week", "x15th.week", "x15th.week", + "x15th.week", "x15th.week", "x15th.week", "x15th.week", "x16th.week", + "x16th.week", "x16th.week", "x16th.week", "x16th.week", "x16th.week", + "x17th.week", "x17th.week", "x17th.week", "x17th.week", "x17th.week", + "x17th.week", "x18th.week", "x18th.week", "x18th.week", "x18th.week", + "x18th.week", "x18th.week", "x19th.week", "x19th.week", "x19th.week", + "x19th.week", "x19th.week", "x19th.week", "x20th.week", "x20th.week", + "x20th.week", "x20th.week", "x20th.week", "x20th.week", "x21st.week", + "x21st.week", "x21st.week", "x21st.week", "x21st.week", "x21st.week", + "x22nd.week", "x22nd.week", "x22nd.week", "x22nd.week", "x22nd.week", + "x22nd.week", "x23rd.week", "x23rd.week", "x23rd.week", "x23rd.week", + "x23rd.week", "x23rd.week", "x24th.week", "x24th.week", "x24th.week", + "x24th.week", "x24th.week", "x24th.week", "x25th.week", "x25th.week", + "x25th.week", "x25th.week", "x25th.week", "x25th.week", "x26th.week", + "x26th.week", "x26th.week", "x26th.week", "x26th.week", "x26th.week", + "x27th.week", "x27th.week", "x27th.week", "x27th.week", "x27th.week", + "x27th.week", "x28th.week", "x28th.week", "x28th.week", "x28th.week", + "x28th.week", "x28th.week", "x29th.week", "x29th.week", "x29th.week", + "x29th.week", "x29th.week", "x29th.week", "x30th.week", "x30th.week", + "x30th.week", "x30th.week", "x30th.week", "x30th.week", "x31st.week", + "x31st.week", "x31st.week", "x31st.week", "x31st.week", "x31st.week", + "x32nd.week", "x32nd.week", "x32nd.week", "x32nd.week", "x32nd.week", + "x32nd.week", "x33rd.week", "x33rd.week", "x33rd.week", "x33rd.week", + "x33rd.week", "x33rd.week", "x34th.week", "x34th.week", "x34th.week", + "x34th.week", "x34th.week", "x34th.week", "x35th.week", "x35th.week", + "x35th.week", "x35th.week", "x35th.week", "x35th.week", "x36th.week", + "x36th.week", "x36th.week", "x36th.week", "x36th.week", "x36th.week", + "x37th.week", "x37th.week", "x37th.week", "x37th.week", "x37th.week", + "x37th.week", "x38th.week", "x38th.week", "x38th.week", "x38th.week", + "x38th.week", "x38th.week", "x39th.week", "x39th.week", "x39th.week", + "x39th.week", "x39th.week", "x39th.week", "x40th.week", "x40th.week", + "x40th.week", "x40th.week", "x40th.week", "x40th.week", "x41st.week", + "x41st.week", "x41st.week", "x41st.week", "x41st.week", "x41st.week", + "x42nd.week", "x42nd.week", "x42nd.week", "x42nd.week", "x42nd.week", + "x42nd.week", "x43rd.week", "x43rd.week", "x43rd.week", "x43rd.week", + "x43rd.week", "x43rd.week", "x44th.week", "x44th.week", "x44th.week", + "x44th.week", "x44th.week", "x44th.week", "x45th.week", "x45th.week", + "x45th.week", "x45th.week", "x45th.week", "x45th.week", "x46th.week", + "x46th.week", "x46th.week", "x46th.week", "x46th.week", "x46th.week", + "x47th.week", "x47th.week", "x47th.week", "x47th.week", "x47th.week", + "x47th.week", "x48th.week", "x48th.week", "x48th.week", "x48th.week", + "x48th.week", "x48th.week", "x49th.week", "x49th.week", "x49th.week", + "x49th.week", "x49th.week", "x49th.week", "x50th.week", "x50th.week", + "x50th.week", "x50th.week", "x50th.week", "x50th.week", "x51st.week", + "x51st.week", "x51st.week", "x51st.week", "x51st.week", "x51st.week", + "x52nd.week", "x52nd.week", "x52nd.week", "x52nd.week", "x52nd.week", + "x52nd.week", "x53rd.week", "x53rd.week", "x53rd.week", "x53rd.week", + "x53rd.week", "x53rd.week", "x54th.week", "x54th.week", "x54th.week", + "x54th.week", "x54th.week", "x54th.week", "x55th.week", "x55th.week", + "x55th.week", "x55th.week", "x55th.week", "x55th.week", "x56th.week", + "x56th.week", "x56th.week", "x56th.week", "x56th.week", "x56th.week", + "x57th.week", "x57th.week", "x57th.week", "x57th.week", "x57th.week", + "x57th.week", "x58th.week", "x58th.week", "x58th.week", "x58th.week", + "x58th.week", "x58th.week", "x59th.week", "x59th.week", "x59th.week", + "x59th.week", "x59th.week", "x59th.week", "x60th.week", "x60th.week", + "x60th.week", "x60th.week", "x60th.week", "x60th.week", "x61st.week", + "x61st.week", "x61st.week", "x61st.week", "x61st.week", "x61st.week", + "x62nd.week", "x62nd.week", "x62nd.week", "x62nd.week", "x62nd.week", + "x62nd.week", "x63rd.week", "x63rd.week", "x63rd.week", "x63rd.week", + "x63rd.week", "x63rd.week", "x64th.week", "x64th.week", "x64th.week", + "x64th.week", "x64th.week", "x64th.week", "x65th.week", "x65th.week", + "x65th.week", "x65th.week", "x65th.week", "x65th.week", "x66th.week", + "x66th.week", "x66th.week", "x66th.week", "x66th.week", "x66th.week", + "x67th.week", "x67th.week", "x67th.week", "x67th.week", "x67th.week", + "x67th.week", "x68th.week", "x68th.week", "x68th.week", "x68th.week", + "x68th.week", "x68th.week", "x69th.week", "x69th.week", "x69th.week", + "x69th.week", "x69th.week", "x69th.week", "x70th.week", "x70th.week", + "x70th.week", "x70th.week", "x70th.week", "x70th.week", "x71st.week", + "x71st.week", "x71st.week", "x71st.week", "x71st.week", "x71st.week", + "x72nd.week", "x72nd.week", "x72nd.week", "x72nd.week", "x72nd.week", + "x72nd.week", "x73rd.week", "x73rd.week", "x73rd.week", "x73rd.week", + "x73rd.week", "x73rd.week", "x74th.week", "x74th.week", "x74th.week", + "x74th.week", "x74th.week", "x74th.week", "x75th.week", "x75th.week", + "x75th.week", "x75th.week", "x75th.week", "x75th.week", "x76th.week", + "x76th.week", "x76th.week", "x76th.week", "x76th.week", "x76th.week" + ), rank = c(78, 15, 71, 41, 57, 59, 63, 8, 48, 23, 47, 52, + 49, 6, 43, 18, 45, 43, 33, 5, 31, 14, 29, 30, 23, 2, 20, + 2, 23, 29, 15, 3, 13, 1, 18, 22, 7, 2, 7, 1, 11, 15, 5, 2, + 6, 1, 9, 10, 1, 1, 4, 1, 9, 10, 1, 1, 4, 2, 11, 5, 1, 1, + 4, 2, 1, 1, 1, 1, 6, 2, 1, 1, 1, 1, 4, 2, 1, 1, 1, 1, 2, + 2, 1, 2, 1, 1, 1, 4, 4, 2, 1, 1, 1, 8, 8, 3, 1, 1, 1, 11, + 12, 3, 1, 1, 2, 16, 22, 7, 1, 8, 1, 20, 23, 8, 2, 15, 2, + 25, 43, 20, 3, 19, 4, 27, 44, 25, 7, 21, 8, 27, NA, 37, 10, + 26, 8, 29, NA, 40, 12, 36, 12, 44, NA, 41, 15, 48, 14, NA, + NA, NA, 22, 47, 17, NA, NA, NA, 29, NA, 21, NA, NA, NA, 31, + NA, 24, NA, NA, NA, NA, NA, 30, NA, NA, NA, NA, NA, 34, NA, + NA, NA, NA, NA, 37, NA, NA, NA, NA, NA, 46, NA, NA, NA, NA, + NA, 47, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA)), row.names = c(NA, -456L +), class = c("tbl_df", "tbl", "data.frame")) + + billboard_solution <- structure(list(year = c(2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, +2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000), artist.inverted = c("Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "Destiny's Child", +"Santana", "Savage Garden", "Madonna", "Aguilera, Christina", +"Janet", "Destiny's Child", "Santana", "Savage Garden", "Madonna", +"Aguilera, Christina", "Janet", "Destiny's Child", "Santana", +"Savage Garden", "Madonna", "Aguilera, Christina", "Janet", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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", "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, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420, 13080, 15480, 14820, 13500, 13080, 15420, +13080, 15480, 14820, 13500, 13080, 15420, 13080, 15480, 14820, +13500, 13080, 15420), class = c("hms", "difftime"), units = "secs"), + genre = c("Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", "Rock", + "Rock", "Rock"), date.entered = structure(c(11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125, 11223, 10999, 10887, 11181, 11174, + 11125, 11223, 10999, 10887, 11181, 11174, 11125, 11223, 10999, + 10887, 11181, 11174, 11125), class = "Date"), date.peaked = structure(c(11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195, 11279, 11055, 10985, 11216, + 11244, 11195, 11279, 11055, 10985, 11216, 11244, 11195, 11279, + 11055, 10985, 11216, 11244, 11195), class = "Date"), week = c("x1st.week", + "x1st.week", "x1st.week", "x1st.week", "x1st.week", "x1st.week", + "x2nd.week", "x2nd.week", "x2nd.week", "x2nd.week", "x2nd.week", + "x2nd.week", "x3rd.week", "x3rd.week", "x3rd.week", "x3rd.week", + "x3rd.week", "x3rd.week", "x4th.week", "x4th.week", "x4th.week", + "x4th.week", "x4th.week", "x4th.week", "x5th.week", "x5th.week", + "x5th.week", "x5th.week", "x5th.week", "x5th.week", "x6th.week", + "x6th.week", "x6th.week", "x6th.week", "x6th.week", "x6th.week", + "x7th.week", "x7th.week", "x7th.week", "x7th.week", "x7th.week", + "x7th.week", "x8th.week", "x8th.week", "x8th.week", "x8th.week", + "x8th.week", "x8th.week", "x9th.week", "x9th.week", "x9th.week", + "x9th.week", "x9th.week", "x9th.week", "x10th.week", "x10th.week", + "x10th.week", "x10th.week", "x10th.week", "x10th.week", "x11th.week", + "x11th.week", "x11th.week", "x11th.week", "x11th.week", "x11th.week", + "x12th.week", "x12th.week", "x12th.week", "x12th.week", "x12th.week", + "x12th.week", "x13th.week", "x13th.week", "x13th.week", "x13th.week", + "x13th.week", "x13th.week", "x14th.week", "x14th.week", "x14th.week", + "x14th.week", "x14th.week", "x14th.week", "x15th.week", "x15th.week", + "x15th.week", "x15th.week", "x15th.week", "x15th.week", "x16th.week", + "x16th.week", "x16th.week", "x16th.week", "x16th.week", "x16th.week", + "x17th.week", "x17th.week", "x17th.week", "x17th.week", "x17th.week", + "x17th.week", "x18th.week", "x18th.week", "x18th.week", "x18th.week", + "x18th.week", "x18th.week", "x19th.week", "x19th.week", "x19th.week", + "x19th.week", "x19th.week", "x19th.week", "x20th.week", "x20th.week", + "x20th.week", "x20th.week", "x20th.week", "x20th.week", "x21st.week", + "x21st.week", "x21st.week", "x21st.week", "x21st.week", "x21st.week", + "x22nd.week", "x22nd.week", "x22nd.week", "x22nd.week", "x22nd.week", + "x22nd.week", "x23rd.week", "x23rd.week", "x23rd.week", "x23rd.week", + "x23rd.week", "x23rd.week", "x24th.week", "x24th.week", "x24th.week", + "x24th.week", "x24th.week", "x24th.week", "x25th.week", "x25th.week", + "x25th.week", "x25th.week", "x25th.week", "x25th.week", "x26th.week", + "x26th.week", "x26th.week", "x26th.week", "x26th.week", "x26th.week", + "x27th.week", "x27th.week", "x27th.week", "x27th.week", "x27th.week", + "x27th.week", "x28th.week", "x28th.week", "x28th.week", "x28th.week", + "x28th.week", "x28th.week", "x29th.week", "x29th.week", "x29th.week", + "x29th.week", "x29th.week", "x29th.week", "x30th.week", "x30th.week", + "x30th.week", "x30th.week", "x30th.week", "x30th.week", "x31st.week", + "x31st.week", "x31st.week", "x31st.week", "x31st.week", "x31st.week", + "x32nd.week", "x32nd.week", "x32nd.week", "x32nd.week", "x32nd.week", + "x32nd.week", "x33rd.week", "x33rd.week", "x33rd.week", "x33rd.week", + "x33rd.week", "x33rd.week", "x34th.week", "x34th.week", "x34th.week", + "x34th.week", "x34th.week", "x34th.week", "x35th.week", "x35th.week", + "x35th.week", "x35th.week", "x35th.week", "x35th.week", "x36th.week", + "x36th.week", "x36th.week", "x36th.week", "x36th.week", "x36th.week", + "x37th.week", "x37th.week", "x37th.week", "x37th.week", "x37th.week", + "x37th.week", "x38th.week", "x38th.week", "x38th.week", "x38th.week", + "x38th.week", "x38th.week", "x39th.week", "x39th.week", "x39th.week", + "x39th.week", "x39th.week", "x39th.week", "x40th.week", "x40th.week", + "x40th.week", "x40th.week", "x40th.week", "x40th.week", "x41st.week", + "x41st.week", "x41st.week", "x41st.week", "x41st.week", "x41st.week", + "x42nd.week", "x42nd.week", "x42nd.week", "x42nd.week", "x42nd.week", + "x42nd.week", "x43rd.week", "x43rd.week", "x43rd.week", "x43rd.week", + "x43rd.week", "x43rd.week", "x44th.week", "x44th.week", "x44th.week", + "x44th.week", "x44th.week", "x44th.week", "x45th.week", "x45th.week", + "x45th.week", "x45th.week", "x45th.week", "x45th.week", "x46th.week", + "x46th.week", "x46th.week", "x46th.week", "x46th.week", "x46th.week", + "x47th.week", "x47th.week", "x47th.week", "x47th.week", "x47th.week", + "x47th.week", "x48th.week", "x48th.week", "x48th.week", "x48th.week", + "x48th.week", "x48th.week", "x49th.week", "x49th.week", "x49th.week", + "x49th.week", "x49th.week", "x49th.week", "x50th.week", "x50th.week", + "x50th.week", "x50th.week", "x50th.week", "x50th.week", "x51st.week", + "x51st.week", "x51st.week", "x51st.week", "x51st.week", "x51st.week", + "x52nd.week", "x52nd.week", "x52nd.week", "x52nd.week", "x52nd.week", + "x52nd.week", "x53rd.week", "x53rd.week", "x53rd.week", "x53rd.week", + "x53rd.week", "x53rd.week", "x54th.week", "x54th.week", "x54th.week", + "x54th.week", "x54th.week", "x54th.week", "x55th.week", "x55th.week", + "x55th.week", "x55th.week", "x55th.week", "x55th.week", "x56th.week", + "x56th.week", "x56th.week", "x56th.week", "x56th.week", "x56th.week", + "x57th.week", "x57th.week", "x57th.week", "x57th.week", "x57th.week", + "x57th.week", "x58th.week", "x58th.week", "x58th.week", "x58th.week", + "x58th.week", "x58th.week", "x59th.week", "x59th.week", "x59th.week", + "x59th.week", "x59th.week", "x59th.week", "x60th.week", "x60th.week", + "x60th.week", "x60th.week", "x60th.week", "x60th.week", "x61st.week", + "x61st.week", "x61st.week", "x61st.week", "x61st.week", "x61st.week", + "x62nd.week", "x62nd.week", "x62nd.week", "x62nd.week", "x62nd.week", + "x62nd.week", "x63rd.week", "x63rd.week", "x63rd.week", "x63rd.week", + "x63rd.week", "x63rd.week", "x64th.week", "x64th.week", "x64th.week", + "x64th.week", "x64th.week", "x64th.week", "x65th.week", "x65th.week", + "x65th.week", "x65th.week", "x65th.week", "x65th.week", "x66th.week", + "x66th.week", "x66th.week", "x66th.week", "x66th.week", "x66th.week", + "x67th.week", "x67th.week", "x67th.week", "x67th.week", "x67th.week", + "x67th.week", "x68th.week", "x68th.week", "x68th.week", "x68th.week", + "x68th.week", "x68th.week", "x69th.week", "x69th.week", "x69th.week", + "x69th.week", "x69th.week", "x69th.week", "x70th.week", "x70th.week", + "x70th.week", "x70th.week", "x70th.week", "x70th.week", "x71st.week", + "x71st.week", "x71st.week", "x71st.week", "x71st.week", "x71st.week", + "x72nd.week", "x72nd.week", "x72nd.week", "x72nd.week", "x72nd.week", + "x72nd.week", "x73rd.week", "x73rd.week", "x73rd.week", "x73rd.week", + "x73rd.week", "x73rd.week", "x74th.week", "x74th.week", "x74th.week", + "x74th.week", "x74th.week", "x74th.week", "x75th.week", "x75th.week", + "x75th.week", "x75th.week", "x75th.week", "x75th.week", "x76th.week", + "x76th.week", "x76th.week", "x76th.week", "x76th.week", "x76th.week" + ), rank = c(78, 15, 71, 41, 57, 59, 63, 8, 48, 23, 47, 52, + 49, 6, 43, 18, 45, 43, 33, 5, 31, 14, 29, 30, 23, 2, 20, + 2, 23, 29, 15, 3, 13, 1, 18, 22, 7, 2, 7, 1, 11, 15, 5, 2, + 6, 1, 9, 10, 1, 1, 4, 1, 9, 10, 1, 1, 4, 2, 11, 5, 1, 1, + 4, 2, 1, 1, 1, 1, 6, 2, 1, 1, 1, 1, 4, 2, 1, 1, 1, 1, 2, + 2, 1, 2, 1, 1, 1, 4, 4, 2, 1, 1, 1, 8, 8, 3, 1, 1, 1, 11, + 12, 3, 1, 1, 2, 16, 22, 7, 1, 8, 1, 20, 23, 8, 2, 15, 2, + 25, 43, 20, 3, 19, 4, 27, 44, 25, 7, 21, 8, 27, NA, 37, 10, + 26, 8, 29, NA, 40, 12, 36, 12, 44, NA, 41, 15, 48, 14, NA, + NA, NA, 22, 47, 17, NA, NA, NA, 29, NA, 21, NA, NA, NA, 31, + NA, 24, NA, NA, NA, NA, NA, 30, NA, NA, NA, NA, NA, 34, NA, + NA, NA, NA, NA, 37, NA, NA, NA, NA, NA, 46, NA, NA, NA, NA, + NA, 47, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA, NA, NA, NA, NA, NA, NA, NA)), row.names = c(NA, -456L +), class = c("tbl_df", "tbl", "data.frame")) +# nolint end diff --git a/tests/testthat/helper-expect.R b/tests/testthat/helper-expect.R new file mode 100644 index 00000000..b467531f --- /dev/null +++ b/tests/testthat/helper-expect.R @@ -0,0 +1,35 @@ +expect_correct <- function(x) { + expect_s3_class(x, "grader_graded") + expect_true(x$correct) +} + +expect_wrong <- function(x) { + expect_s3_class(x, "grader_graded") + expect_false(x$correct) +} + +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)) +} + +expect_condi <- function(x) { + checkmate::expect_names(names(x), identical.to = c("x", "message", "correct", "type")) + checkmate::expect_character(x$message, null.ok = TRUE) + checkmate::expect_logical(x$correct, null.ok = FALSE, len = 1) + checkmate::expect_choice(x$type, choices = c("formula", "function", "value")) + checkmate::expect_class(x, "grader_condition") +} + +expect_condi_correct <- function(x, message = NULL) { + expect_condi(x) + expect_equal(x$message, message) + expect_true(x$correct) +} + +expect_condi_error <- function(x, message = NULL) { + expect_condi(x) + expect_equal(x$message, message) + expect_false(x$correct) +} diff --git a/tests/testthat/test_check_code.R b/tests/testthat/test_check_code.R index 460d022a..2af680d5 100644 --- a/tests/testthat/test_check_code.R +++ b/tests/testthat/test_check_code.R @@ -1,21 +1,6 @@ context("Check Code") # these tests are largely redundant exercises that have been tested against detect_mistakes() -expect_correct <- function(x) { - expect_s3_class(x, "grader_graded") - expect_true(x$correct) -} - -expect_wrong <- function(x) { - expect_s3_class(x, "grader_graded") - expect_false(x$correct) -} - -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)) -} test_that("Spots differences in atomics", { diff --git a/tests/testthat/test_check_result_condi.R b/tests/testthat/test_check_result_condi.R index da342d18..d2474f5f 100644 --- a/tests/testthat/test_check_result_condi.R +++ b/tests/testthat/test_check_result_condi.R @@ -1,15 +1,5 @@ context("Check Result Condi") -expect_correct <- function(x) { - expect_s3_class(x, "grader_graded") - expect_true(x$correct) -} - -expect_wrong <- function(x) { - expect_s3_class(x, "grader_graded") - expect_false(x$correct) -} - test_that("Provide a passing solution. Give the students a fighting chance!", { testthat::expect_error( check_result( diff --git a/tests/testthat/test_check_result_df.R b/tests/testthat/test_check_result_df.R new file mode 100644 index 00000000..01dd1fbf --- /dev/null +++ b/tests/testthat/test_check_result_df.R @@ -0,0 +1,15 @@ +context("Check Result Condi") + +test_that("Comparing dataframes, testing for null env", { + source(testthat::test_path("billboard.R")) + + # check that the results are the same + testthat::expect_equal(billboard_user, billboard_solution) + + expect_correct( + check_result( + pass_if(~ .result == billboard_solution, "This is a correct message"), + learnr_args = list(last_value = billboard_user, envir_prep = new.env()) + ) + ) +}) diff --git a/tests/testthat/test_condi.R b/tests/testthat/test_condi.R index 1d14ab09..b3d519bb 100644 --- a/tests/testthat/test_condi.R +++ b/tests/testthat/test_condi.R @@ -1,25 +1,5 @@ context("Check condi") -expect_condi <- function(x) { - checkmate::expect_names(names(x), identical.to = c("x", "message", "correct", "type")) - checkmate::expect_character(x$message, null.ok = TRUE) - checkmate::expect_logical(x$correct, null.ok = FALSE, len = 1) - checkmate::expect_choice(x$type, choices = c("formula", "function", "value")) - checkmate::expect_class(x, "grader_condition") -} - -expect_condi_correct <- function(x, message = NULL) { - expect_condi(x) - expect_equal(x$message, message) - expect_true(x$correct) -} - -expect_condi_error <- function(x, message = NULL) { - expect_condi(x) - expect_equal(x$message, message) - expect_false(x$correct) -} - grader_args <- list() learnr_args <- list(last_value = quote(5), envir_prep = new.env()) condi_formula_t <- condition(~ .result == 5, message = "my correct message", correct = TRUE) diff --git a/tests/testthat/test_glue_message.R b/tests/testthat/test_glue_message.R new file mode 100644 index 00000000..9fb3eddb --- /dev/null +++ b/tests/testthat/test_glue_message.R @@ -0,0 +1,16 @@ +context("Glue Message") + +test_that("Check NULL, NA", { + testthat::expect_equal(glue_message("{.is_bool}", .is_bool = NA), "NA") + testthat::expect_equal(glue_message("{.is_bool}", .is_bool = NULL), character(0L)) + + testthat::expect_equal(glue_message("{.char}", .char = NULL), "") + testthat::expect_equal(glue_message("{.char}", .char = NULL), "") +}) + +test_that("Check message construction", { + testthat::expect_equal(glue_message("{.is_bool} {.char}", + .is_bool = TRUE, + .char = "hello"), + "TRUE hello") +}) diff --git a/tests/testthat/test_grade_learnr.R b/tests/testthat/test_grade_learnr.R index 89006c24..2a654659 100644 --- a/tests/testthat/test_grade_learnr.R +++ b/tests/testthat/test_grade_learnr.R @@ -49,20 +49,20 @@ test_that("Grade learnr check_result", { test_grade_learnr( user_code = "4", check_code = "check_result( - pass_if(~ .result == 4, 'yes. you did it'), - correct = 'this other correct message. {message}' + pass_if(~ .result == 4, 'yes. you did it.'), + correct = 'this other correct message.', + glue_correct = '{ .message } { .correct }' )" ), - "this other correct message. yes. you did it" + "yes. you did it. this other correct message." ) }) - test_that("Grade learnr check_code", { expect_correct( test_grade_learnr( user_code = "4", - check_code = "check_code(correct = 'This works')", + check_code = "check_code(correct = 'This works', glue_correct = '{.correct}')", solution_code = "4" ), "This works" @@ -71,7 +71,7 @@ test_that("Grade learnr check_code", { expect_wrong( test_grade_learnr( user_code = "exp(log(2))", - check_code = "check_code(incorrect = '{message}')", + check_code = "check_code(glue_incorrect = '{.message}')", solution_code = "exp(log(1))" ), "I expected 1 where you wrote 2." diff --git a/tests/testthat/test_message_check_result.R b/tests/testthat/test_message_check_result.R new file mode 100644 index 00000000..fb4393d2 --- /dev/null +++ b/tests/testthat/test_message_check_result.R @@ -0,0 +1,152 @@ +context("Check test_result messages") + +expect_message <- function(x, message, correct) { + expect_s3_class(x, "grader_graded") + expect_equal(x$correct, correct) + expect_true(grepl(message, paste0(x$message, collapse = ""), fixed = TRUE)) +} + +test_that("Correct messages without random praise", { + glue_correct_no_praise <- "{ .message } { .correct }" + + expect_message( + check_result( + pass_if(~ .result == 5, message = "A pass_if message."), + correct = "A correct message.", + grader_args = list(), + learnr_args = list(last_value = 5, envir_prep = new.env()), + glue_correct = glue_correct_no_praise + ), + message = "A pass_if message. A correct message.", + correct = TRUE + ) + + expect_message( + check_result( + pass_if(~ .result == 5), + correct = "Only a correct message.", + grader_args = list(), + learnr_args = list(last_value = 5, envir_prep = new.env()), + glue_correct = glue_correct_no_praise + ), + message = "Only a correct message.", + correct = TRUE + ) + + expect_message( + check_result( + pass_if(~ .result == 5, "Only a pass_if message."), + grader_args = list(), + learnr_args = list(last_value = 5, envir_prep = new.env()), + glue_correct = glue_correct_no_praise + ), + message = "Only a pass_if message.", + correct = TRUE + ) + + expect_message( + check_result( + pass_if(~ .result == 5), + grader_args = list(), + learnr_args = list(last_value = 5, envir_prep = new.env()), + glue_correct = glue_correct_no_praise + ), + message = "", + correct = TRUE + ) +}) + +test_that("Incorrect messages no match pass_if", { + glue_incorrect_no_praise <- "{ .message } { .incorrect }" + + expect_message( + check_result( + pass_if(~ .result == 42), + grader_args = list(), + learnr_args = list(last_value = 5, envir_prep = new.env()), + glue_incorrect = glue_incorrect_no_praise + ), + message = "", + correct = FALSE + ) + + expect_message( + check_result( + pass_if(~ .result == 42, message = "This does nothing (expected)."), + grader_args = list(), + learnr_args = list(last_value = 5, envir_prep = new.env()) + ), + message = "", + correct = FALSE + ) + + expect_message( + check_result( + pass_if(~ .result == 42, message = "This does nothing (expected)."), + grader_args = list(), + learnr_args = list(last_value = 5, envir_prep = new.env()), + incorrect = "hello" + ), + message = "hello", + correct = FALSE + ) + + expect_message( + check_result( + pass_if(~ .result == 42), + grader_args = list(), + learnr_args = list(last_value = 5, envir_prep = new.env()), + incorrect = "incorrect with no pass_if message" + ), + message = "incorrect with no pass_if message", + correct = FALSE + ) +}) + +test_that("Incorrect messages match fail_if", { + expect_message( + check_result( + pass_if(~ .result == 42), + fail_if(~ .result == 5), + grader_args = list(), + learnr_args = list(last_value = 5, envir_prep = new.env()) + ), + message = "", + correct = FALSE + ) + + expect_message( + check_result( + pass_if(~ .result == 42, message = "No match here."), + fail_if(~ .result == 5, message = "Found an incorrect match."), + grader_args = list(), + learnr_args = list(last_value = 5, envir_prep = new.env()) + ), + message = "Found an incorrect match.", + correct = FALSE + ) + + expect_message( + check_result( + pass_if(~ .result == 42, message = "No match here."), + fail_if(~ .result == 5, message = "Found an incorrect match."), + grader_args = list(), + learnr_args = list(last_value = 5, envir_prep = new.env()), + incorrect = "hello" + ), + message = "Found an incorrect match. hello", + correct = FALSE + ) + + expect_message( + check_result( + pass_if(~ .result == 42), + fail_if(~ .result == 5), + grader_args = list(), + learnr_args = list(last_value = 5, envir_prep = new.env()), + incorrect = "incorrect with no fail_if message." + ), + message = "incorrect with no fail_if message.", + correct = FALSE + ) +}) diff --git a/tests/testthat/test_test_result.R b/tests/testthat/test_test_result.R index 5e21e34d..7ff17a1b 100644 --- a/tests/testthat/test_test_result.R +++ b/tests/testthat/test_test_result.R @@ -1,10 +1,7 @@ context("Test Result") # these tests are largely redundant exercises that have been tested against detect_mistakes() -expect_correct <- function(x) { - expect_s3_class(x, "grader_graded") - expect_true(x$correct) -} + expect_message <- function(x, message, correct = FALSE) { expect_s3_class(x, "grader_graded") expect_equal(x$correct, correct) @@ -23,23 +20,25 @@ test_that("Spots differences in atomics", { "1/1", TRUE ) - expect_message( - test_result( - grader_args = list(user_quo = user), - checkmate::expect_numeric, - checkmate::expect_character - ), - "1/2", FALSE - ) + # nolint start + # expect_message( + # test_result( + # grader_args = list(user_quo = user), + # checkmate::expect_numeric, + # checkmate::expect_character + # ), + # "1/2", FALSE + # ) - expect_message( - test_result( - grader_args = list(user_quo = user), - checkmate::expect_numeric, - test("test: is character", checkmate::expect_character) - ), - "test: is character", FALSE - ) + # expect_message( + # test_result( + # grader_args = list(user_quo = user), + # checkmate::expect_numeric, + # test("test: is character", checkmate::expect_character) + # ), + # "test: is character", FALSE + # ) + # nolint end })