Skip to content

Commit

Permalink
Add random replication of quiz questions
Browse files Browse the repository at this point in the history
Resolves #16
  • Loading branch information
mitchelloharawild committed Dec 14, 2023
1 parent 2a0ceaa commit 531d472
Show file tree
Hide file tree
Showing 12 changed files with 97 additions and 41 deletions.
1 change: 0 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ Imports:
knitr,
rlang,
rmarkdown,
stringr,
xfun,
yaml
URL: https://github.com/emitanaka/moodlequiz,
Expand Down
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ export(cloze_numerical)
export(cloze_shortanswer)
export(cloze_singlechoice)
export(moodlequiz)
export(moodlequiz_xml)
import(rmarkdown)
66 changes: 58 additions & 8 deletions R/quiz-xml.R
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,49 @@ moodlequiz <- function(replicates = 1L,
...) {
pre_knit <- function (input, ...) {
output <- tempfile(fileext = ".xml")
rmarkdown::render(
input, output_format = "moodlequiz_xml", output_file = output, quiet = TRUE

replicate_prefix <- if(replicates > 1)
paste0(" R", formatC(seq_len(replicates), width = nchar(replicates), format = "d", flag = "0"))
else
""

# Repeatedly render to XML format
xml <- lapply(replicate_prefix, function(prefix) {
rmarkdown::render(
input, output_format = "moodlequiz::moodlequiz_xml", output_options = list(replicate = prefix),
output_file = output, quiet = FALSE
)
xfun::read_utf8(output)
})

# Combine into a single XML for upload
xfun::write_utf8(
c(
'<?xml version="1.0" encoding="UTF-8"?>\n<quiz>',
do.call(c, xml),
'</quiz>'
),
xfun::with_ext(input, "xml")
)

# Prevent knitting of document
render_env <- rlang::caller_env(n = 2)
rlang::env_poke(
render_env, nm = "requires_knit", value = FALSE,
inherit = TRUE, create = FALSE
)
# Change input to dummy md with Moodle XML import instructions
input <- system.file("instructions.md", package = "moodlequiz")
rlang::env_poke(
render_env, nm = "input", value = input,
inherit = TRUE, create = FALSE
)
file.copy(output, xfun::with_ext(input, "xml"))
rlang::env_poke(
render_env, nm = "output_file", value = normalizePath(render_env$output_file),
inherit = TRUE, create = FALSE
)

input
}

# return format
Expand All @@ -39,7 +78,9 @@ moodlequiz <- function(replicates = 1L,
)
}

moodlequiz_xml <- function(replicates = 1L,
#' @keywords internal
#' @export
moodlequiz_xml <- function(replicate = "",
self_contained = TRUE,
extra_dependencies = NULL,
theme = NULL,
Expand All @@ -48,12 +89,20 @@ moodlequiz_xml <- function(replicates = 1L,
md_extensions = NULL,
pandoc_args = NULL,
...) {
pre_processor <- function (metadata, input_file, ...) {
metadata$moodlequiz$replicate <- replicate
xfun::write_utf8(
c(
"---", yaml::as.yaml(metadata), "---",
split_rmd(input_file)$body
),
input_file
)
list()
}

post_processor <- function(metadata, input_file, output_file, ...) {
post_processor <- function (metadata, input_file, output_file, ...) {
# Convert content within pandoc divs to quiz questions
# xml <- xml2::read_xml(output_file)
# questions <- xml2::xml_find_all(xml, '//cdata')

xml <- xfun::read_utf8(output_file)
xml <- gsub("<cdata>", replacement = "<![CDATA[", xml, fixed = TRUE)
xml <- gsub("</cdata>", replacement = "]]>", xml, fixed = TRUE)
Expand All @@ -71,6 +120,7 @@ moodlequiz_xml <- function(replicates = 1L,
out <- output_format(
knitr = knitr_options(),
pandoc = pandoc_options(to = "html", ext = ".xml", lua_filters = filters),
pre_processor = pre_processor,
post_processor = post_processor,
base_format = bookdown::html_document2(
highlight = NULL,
Expand Down
2 changes: 1 addition & 1 deletion R/utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ split_rmd = function(file) {
body = if (i[2] == n) {
character()
} else {
lapply(split(x, cut(seq_along(x), breaks = c(i[-1]-1, n))), `[`, -1L)
x[(i[2]+1):n]
}
)
}
Expand Down
13 changes: 9 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,25 +36,28 @@ the x, y, color, and size are mapped randomly to one of the variables in
the `mtcars` data.

---
output: moodlequiz::moodlequiz
output:
moodlequiz::moodlequiz:
replicates: 5
title: Drawing a scatterplot
times: 5
category: datavis
moodlequiz:
category: datavis-scatterplots
---

## Scatterplots
# Data

```{r setup, include = FALSE}
library(tidyverse)
library(rlang)
library(moodlequiz)
knitr::opts_chunk$set(echo = FALSE,
results = "hide",
fig.height = 4,
fig.width = 5,
fig.path = "",
fig.cap = "",
fig.align = "center")
library(moodlequiz)
```

```{r data}
Expand All @@ -73,6 +76,8 @@ the `mtcars` data.
str(mtcars)
```

# Plot

As a starting point, you decide to draw a scatter plot for some variables. Complete the code below to get the target plot below:

```r
Expand Down
12 changes: 6 additions & 6 deletions inst/examples/draw-scatterplots.Rmd
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
---
output: moodlequiz::moodlequiz
output:
moodlequiz::moodlequiz:
replicates: 5
title: Drawing a scatterplot
times: 5
moodlequiz:
category: datavis
category: datavis-scatterplots
---

# Scatterplots

## Data
# Data

```{r setup, include = FALSE}
library(tidyverse)
Expand Down Expand Up @@ -39,7 +39,7 @@ You have been asked to analyse the `mtcars` data. The variables and the class ty
str(mtcars)
```

## Plot
# Plot

As a starting point, you decide to draw a scatter plot for some variables. Complete the code below to get the target plot below:

Expand Down
22 changes: 8 additions & 14 deletions inst/header.lua
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
local moodle_category = [[
<question type="category">
<category>
<text>$course$/%s</text>
</category>
</question>
]]

local base_category = nil
local cloze_pattern = "{%d+:"
local replicate_num = ""

function process_header (elem)
if (elem.classes[1] == "header" or elem.level > 2) then return elem end
elem.classes = {'question'}
elem.classes = {"question"}
elem.attributes.name = pandoc.utils.stringify(elem.content[1])
if (elem.level == 1) then
elem.attributes.type = 'category'
elem.attributes.type = "category"
if (elem.attributes.category == nil) then
elem.attributes.category = elem.identifier
end
Expand All @@ -24,8 +17,9 @@ end


function moodlequiz_meta(meta)
if (meta.moodlequiz ~= nil and meta.moodlequiz.category ~= nil) then
base_category = pandoc.utils.stringify(meta.moodlequiz.category)
if (meta.moodlequiz ~= nil) then
if (meta.moodlequiz.category ~= nil) then base_category = pandoc.utils.stringify(meta.moodlequiz.category) end
if (meta.moodlequiz.replicate ~= nil) then replicate_num = pandoc.utils.stringify(meta.moodlequiz.replicate) end
end
end

Expand Down Expand Up @@ -76,7 +70,7 @@ function header_questions(doc)
end
end

question_name_fmt = "Q%0" .. tostring(n_questions):len() .. "i: %s"
question_name_fmt = "Q%0" .. tostring(n_questions):len() .. "i%s: %s"
question_num = 0
for i,el in pairs(hblocks) do
-- Look for cloze tags to set default question type 'description' or 'cloze'
Expand All @@ -99,7 +93,7 @@ function header_questions(doc)
-- Add question number prefix for ordering
if (el.attributes.type ~= "category") then
question_num = question_num + 1
hblocks[i].attributes.name = question_name_fmt:format(question_num, el.attributes.name)
hblocks[i].attributes.name = question_name_fmt:format(question_num, replicate_num, el.attributes.name)
end
end

Expand Down
5 changes: 5 additions & 0 deletions inst/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
title: Your quiz is ready!
---

Here's how to import the questions into Moodle.
5 changes: 0 additions & 5 deletions inst/moodle.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1 @@
<?xml version="1.0" encoding="UTF-8"?>
<quiz>

$body$

</quiz>
2 changes: 1 addition & 1 deletion man/choices.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/cloze.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions man/moodlequiz.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 531d472

Please sign in to comment.