-
Notifications
You must be signed in to change notification settings - Fork 0
Reference Implementations
Reference implementations can be considered as addon to the quiz_checker_env script. For every question, a reference implementation should be written which specifies the tests, creates and dumps answer lists, and provide paths to its caller. Here an example reference implementation(actually used) will be broken down into its major parts and will be explained.
Keeping this section as is and changing variables sect_count and q_count variables are enough to populate file_names variables with dump paths with correct naming and placement conventions. When there is only one section, this part should be updated slightly.
args <- commandArgs(trailingOnly=TRUE)
sect_count <- 2
q_count <- 3
template <- paste(rep("io/in_%s_sect0", sect_count), 1:sect_count, sep="")
template <- paste(c(sapply(paste(template, "_q0", sep=""), rep, q_count)), rep(1:q_count, sect_count), ".RData", sep="")
file_names <- sapply(template, sprintf, args[1], USE.NAMES = F)Since handle_submissions can be called multiple times in testing, initial check controls if this script is run before to generate answer lists. The beginning of the answer sheet could be used for helper functions and parameters such as static file names, generator functions that can generate various test inputs in the correct format.
# check for existence of files and if exists, return them to caller
if(!all(sapply(file_names, file.exists))) {
###
# This section has to be filled with the given naming convention
###
generator1 <- function(seed=30, len=5, siz=20) {
RNGversion("3.3.1")
set.seed(seed)
probs <- sample(c(0, rep(1, len - 1)))
levels <- sample(letters, len)
vec <- sample(levels, siz, replace = T, prob = probs)
return(list(vec=vec, levs=levels))
}
generator2 <- function(seed=1, len=5, siz=20) {
RNGversion("3.3.1")
set.seed(seed)
levels <- sample(letters, len)
fact <- factor(sample(levels, siz, replace = T), levels = levels)
return(list(fact=fact, lev=sample(levels, 1)))
}
generator3 <- function(seed=1, c=20, m=2, d=4, l=5, is_s1=T) {
RNGversion("3.3.1")
set.seed(seed)
rates <- rnorm(c, m, d)
brks <- NULL
if(is_s1) {
brks <- quantile(rates, seq(0, 1, len = l))
brks[length(brks)] <- Inf
brks[1] <- -Inf
labs <- letters[1:(length(brks)-1)]
} else {
labs <- if(l%%3==0) {
c("small", "large")
} else if(l%%3==1) {
c("low", "medium", "high")
} else {
c("poor", "fair", "good", "very good", "excellent")
}
}
params <- list(values=rates, breaks=brks, labels=labs)
if(!is_s1) names(params)[3] <- 'lab'
return(params)
}This section contains actual answers which could be shared with the students. True answers will be used in the test cases to generate expected results to save in answer lists.
# Section 1
# Q1
getc <- function(vec, levs)
{
fact <- factor(vec, levels = levs)
table(fact)
}
s1q1_1 <- generator1()
s1q1_2 <- generator1(50)
s1q1_3 <- generator1(70, 8)
s1q1_4 <- generator1(90, 11, 50)
# Q2
getn <- function(fact, lev)
{
fact2 <- factor(fact, ordered = T)
sum(fact2 >= lev)
}
s1q2_1 <- generator2()
s1q2_2 <- generator2(50)
s1q2_3 <- generator2(70, 8)
s1q2_4 <- generator2(90, 11, 50)
# Q3
splitf <- function(values, breaks, labels)
{
split(values, cut(values, breaks = breaks, labels = labels))
}
s1q3_1 <- generator3()
s1q3_2 <- generator3(50, 10, l = 4)
s1q3_3 <- generator3(70, 30, 4, 8, 6)
s1q3_4 <- generator3(90, 80, 8, 6, 10)
# Section 2
# Q1
generator4 <- function(seed=30, len=5, siz=20) {
RNGversion("3.3.1")
set.seed(seed)
lvls <- sample(letters, len+1)
fact <- factor(sample(lvls[-len-1], siz, replace = T), levels = lvls[-len-1])
return(list(fact=fact, new=lvls[len+1]))
}
addlevel <- function(fact, new)
{
levels(fact) <- c(levels(fact), new)
fact
}
s2q1_1 <- generator4()
s2q1_2 <- generator4(50)
s2q1_3 <- generator4(70, 8)
s2q1_4 <- generator4(90, 11, 50)
# Q2
getmax <- function(fact)
{
fact2 <- factor(fact, ordered = T)
sum(fact2 == max(fact2))
}
s2q2_1 <- generator2()[-2]
s2q2_2 <- generator2(50)[-2]
s2q2_3 <- generator2(70, 8)[-2]
s2q2_4 <- generator2(90, 11, 50)[-2]
# Q3
tof <- function(values, lab)
{
cats <- cut(values,
breaks = length(lab),
labels = lab)
data.frame(values, cats)
}
s2q3_1 <- generator3(l = 0, is_s1 = F)[-2]
s2q3_2 <- generator3(50, 10, l = 1, is_s1 = F)[-2]
s2q3_3 <- generator3(70, 30, 4, 8, l = 2, is_s1 = F)[-2]
s2q3_4 <- generator3(90, 80, 8, 6, l = 3, is_s1 = F)[-2]After having the inputs and correct answers, here reference implementation is followed by answer lists creation. The format of these lists is explained in Quiz Checker. The loaders list is created in the last line which is needed even when no loader exists.
### Section1
answers_sect1_q1 = list(
"FNC__getc"=list(s1q1_1, do.call("getc", s1q1_1)),
"FNC__getc"=list(s1q1_2, do.call("getc", s1q1_2)),
"FNC__getc"=list(s1q1_3, do.call("getc", s1q1_3)),
"FNC__getc"=list(s1q1_4, do.call("getc", s1q1_4))
)
answers_sect1_q2 = list(
"FNC__getn"=list(s1q2_1, list(getn1=as.numeric(do.call("getn", s1q2_1)),
getn2=do.call("getn", s1q2_1))),
"FNC__getn"=list(s1q2_2, list(getn1=as.numeric(do.call("getn", s1q2_2)),
getn2=do.call("getn", s1q2_2))),
"FNC__getn"=list(s1q2_3, list(getn1=as.numeric(do.call("getn", s1q2_3)),
getn2=do.call("getn", s1q2_3))),
"FNC__getn"=list(s1q2_4, list(getn1=as.numeric(do.call("getn", s1q2_4)),
getn2=do.call("getn", s1q2_4)))
)
answers_sect1_q3 = list(
"FNC__splitf"=list(s1q3_1, do.call("splitf", s1q3_1)),
"FNC__splitf"=list(s1q3_2, do.call("splitf", s1q3_2)),
"FNC__splitf"=list(s1q3_3, do.call("splitf", s1q3_3)),
"FNC__splitf"=list(s1q3_4, do.call("splitf", s1q3_4))
)
### Section2
answers_sect2_q1 = list(
"FNC__addlevel"=list(s2q1_1, do.call("addlevel", s2q1_1)),
"FNC__addlevel"=list(s2q1_2, do.call("addlevel", s2q1_2)),
"FNC__addlevel"=list(s2q1_3, do.call("addlevel", s2q1_3)),
"FNC__addlevel"=list(s2q1_4, do.call("addlevel", s2q1_4))
)
answers_sect2_q2 = list(
"FNC__getmax"=list(s2q2_1, do.call("getmax", s2q2_1)),
"FNC__getmax"=list(s2q2_2, do.call("getmax", s2q2_2)),
"FNC__getmax"=list(s2q2_3, do.call("getmax", s2q2_3)),
"FNC__getmax"=list(s2q2_4, do.call("getmax", s2q2_4))
)
answers_sect2_q3 = list(
"FNC__tof"=list(s2q3_1, do.call("tof", s2q3_1)),
"FNC__tof"=list(s2q3_2, do.call("tof", s2q3_2)),
"FNC__tof"=list(s2q3_3, do.call("tof", s2q3_3)),
"FNC__tof"=list(s2q3_4, do.call("tof", s2q3_4))
)
answers <- list(
answers_sect1_q1, answers_sect1_q2, answers_sect1_q3,
answers_sect2_q1, answers_sect2_q2, answers_sect2_q3
)
loaders <- c(NA, NA, NA, NA, NA, NA)This section can be used as-is as long as variables used here do exist with correct form as shown in this implementation.
###
# Fill up until this part and do not change the rest
###
path_trim <- function(path) { substr(path, 4, nchar(path)-6) }
var_names <- sapply(file_names, path_trim, USE.NAMES = F)
for(i in 1:length(var_names)) {
assign(var_names[i], answers[[i]])
if(!is.na(loaders[i])) {
assign("loader", loaders[i])
save(list = c("loader", var_names[i]), file = file_names[i])
} else {
save(list = var_names[i], file = file_names[i])
}
}
}After answer lists along with loaders are saved, file paths are returned to the caller.
This section can be used as-is as long as variables used here do exist with correct form as shown in this implementation.
# return filenames to caller
garb <- sapply(file_names, cat, "\n", sep="")