Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sylvaticus main #6

Merged
merged 4 commits into from
Mar 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "QuizQuestions"
uuid = "612c44de-1021-4a21-84fb-7261cf5eb2d4"
authors = ["jverzani <jverzani@gmail.com> and contributors"]
version = "0.2.0"
version = "0.3.0"

[deps]
Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a"
Expand Down
2 changes: 1 addition & 1 deletion src/QuizQuestions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ include("question_types.jl")
include("html_templates.jl")
include("show_methods.jl")

export numericq, radioq, booleanq, yesnoq, stringq
export numericq, radioq, multiq, booleanq, yesnoq, stringq

end
40 changes: 37 additions & 3 deletions src/html_templates.jl
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
## Could tidy up this HTML to make it look nicer
html_templates = Dict()

const grading_partial = """
grading_partial = """
if(correct) {
msgBox.innerHTML = "<div class='pluto-output admonition note alert alert-success'><span class='glyphicon glyphicon-thumbs-up'>👍&nbsp;Correct</span></div>";
msgBox.innerHTML = "<div class='pluto-output admonition note alert alert-success'><span class='glyphicon glyphicon-thumbs-up'>👍&nbsp; {{#:CORRECT}}{{{:CORRECT}}}{{/:CORRECT}}{{^:CORRECT}}Correct{{/:CORRECT}} </span></div>";
} else {
msgBox.innerHTML = "<div class='pluto-output admonition alert alert-danger'><span class='glyphicon glyphicon-thumbs-down'>👎&nbsp; Incorrect</span></div>";
msgBox.innerHTML = "<div class='pluto-output admonition alert alert-danger'><span class='glyphicon glyphicon-thumbs-down'>👎&nbsp; {{#:INCORRECT}}{{{:INCORRECT}}}{{/:INCORRECT}}{{^:INCORRECT}}Incorrect{{/:INCORRECT}} </span></div>";
}
"""

Expand Down Expand Up @@ -82,3 +82,37 @@ rb.addEventListener("change", function() {
$(grading_partial)
})});
"""

html_templates["Multiq"] = mt"""
{{#:ITEMS}}
<div class="form-check">
<label>
<input class="form-check-input" type="checkbox" name="check_{{:ID}}"
id="check_{{:ID}}_{{:VALUE}}" value="{{:VALUE}}">
<span = class="label-body">
{{{:LABEL}}}
</span>
</input>
</label>
</div>
{{/:ITEMS}}
"""

html_templates["multi_grading_script"] = """
document.querySelectorAll('input[name="check_{{:ID}}"]').forEach(function(rb) {
rb.addEventListener("change", function() {
var choice_buttons = document.getElementsByName("check_{{:ID}}");
selected = [];
for (var i=0; i < choice_buttons.length; i++) {
if (choice_buttons[i].checked) {
selected.push(i+1)
}
}
var a = selected;
b = {{{:CORRECT_ANSWER}}};
// https://stackoverflow.com/questions/7837456/how-to-compare-arrays-in-javascript
correct = (a.length === b.length && a.find((v,i) => v !== b[i]) === undefined)
var msgBox = document.getElementById('{{:ID}}_message');
$(grading_partial)
})});
"""
54 changes: 54 additions & 0 deletions src/question_types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,60 @@ function radioq(choices, answer::Integer;
end




##
mutable struct Multiq <: Question
choices
answer
values
labels
label
hint
inline
end

"""
multiq(choices, answers; label="", hint="", keep_order=false)

Multiple choice question (one *or more* of several)

Arguments:

* `choices`: indexable collection of choices. As seen in the example, choices can be formatted with markdown.

* `answers::Vector{Int}`: index of correct choice(s)

* `keep_order::Boolean`: if `true` keeps display order of choices, otherwise they are shuffled.

* `inline::Bool`: hint to render inline (or not) if supported

* `label`: optional label for the form element

* `hint`: optional plain-text hint that can be seen on hover

Example:

```
choices = ["pear", "tomato", "banana"]
answers = [1,3]
multiplecq(choices, answers; hint="not the red one!")
```

"""
function multiq(choices, answers;
label="", hint="", inline::Bool=(hint!=""),
keep_order::Bool=false)
inds = collect(1:length(choices))
values = copy(inds)
labels = choices
!keep_order && shuffle!(inds)

Multiq(choices[inds], findall(in(answers), inds),
values, labels[inds], label, hint, inline)
end


"""
booleanq(ans; [label, hint])
True of false questions:
Expand Down
30 changes: 30 additions & 0 deletions src/show_methods.jl
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,33 @@ function Base.show(io::IO, m::MIME"text/html", x::Radioq)
)

end

function Base.show(io::IO, m::MIME"text/html", x::Multiq)

ID = randstring()

choices = string.(x.choices)
items = [_make_item(i, choice) for (i,choice) ∈ enumerate(choices)]

GRADING_SCRIPT = Mustache.render(html_templates["multi_grading_script"];
ID = ID,
CORRECT_ANSWER = x.answer,
INCORRECT = "Not yet",
CORRECT = "Correct"
)
FORM = Mustache.render(html_templates["Multiq"];
ID = ID,
ITEMS = items,
INLINE = x.inline ? " inline" : ""
)

Mustache.render(io, html_templates["question_tpl"],
ID = ID,
TYPE = "radio",
FORM = FORM,
GRADING_SCRIPT = GRADING_SCRIPT,
LABEL=_markdown_to_html(x.label),
HINT = x.hint # use HINT in question
)

end