From ae2f6029e5b885b1059ea283c9047f00f3cea131 Mon Sep 17 00:00:00 2001 From: Antonello Lobianco Date: Tue, 29 Mar 2022 13:09:53 +0200 Subject: [PATCH 1/4] Attempt to add multiple choice question --- src/QuizQuestions.jl | 2 +- src/question_types.jl | 54 +++++++++++++++++++++++++++++++++++++++++++ src/show_methods.jl | 28 ++++++++++++++++++++++ 3 files changed, 83 insertions(+), 1 deletion(-) diff --git a/src/QuizQuestions.jl b/src/QuizQuestions.jl index 33937db..e7d6800 100644 --- a/src/QuizQuestions.jl +++ b/src/QuizQuestions.jl @@ -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, multiplecq, booleanq, yesnoq, stringq end diff --git a/src/question_types.jl b/src/question_types.jl index 489a0bb..88465fe 100644 --- a/src/question_types.jl +++ b/src/question_types.jl @@ -107,6 +107,60 @@ function radioq(choices, answer::Integer; end + + +## +mutable struct Multiplecq <: Question + choices + answers + values + labels + label + hint + inline +end + +""" + multiplecq(choices, answers; label="", hint="", keep_order=false) + +Multiple choice question (several possible) + +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 multiplecq(choices, answers::Vector{Int}; + label="", hint="", inline::Bool=(hint!=""), + keep_order::Bool=false) + inds = collect(1:length(choices)) + values = copy(inds) + labels = choices + !keep_order && shuffle!(inds) + + Multiplecq(choices[inds], findall(in(answers), inds), + values, labels[inds], label, hint, inline) +end + + """ booleanq(ans; [label, hint]) True of false questions: diff --git a/src/show_methods.jl b/src/show_methods.jl index 830fbc1..d56c509 100644 --- a/src/show_methods.jl +++ b/src/show_methods.jl @@ -108,3 +108,31 @@ function Base.show(io::IO, m::MIME"text/html", x::Radioq) ) end + +function Base.show(io::IO, m::MIME"text/html", x::Multiplecq) + + ID = randstring() + + choices = string.(x.choices) + items = [_make_item(i, choice) for (i,choice) ∈ enumerate(choices)] + + GRADING_SCRIPT = Mustache.render(html_templates["radio_grading_script"]; + ID = ID, + CORRECT_ANSWER = x.answer + ) + FORM = Mustache.render(html_templates["Radioq"]; + 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 From 2ab4282cd7492439e21aa6506011b45e8db4f3ba Mon Sep 17 00:00:00 2001 From: jverzani Date: Tue, 29 Mar 2022 10:44:06 -0400 Subject: [PATCH 2/4] add multiq show method --- src/QuizQuestions.jl | 2 +- src/html_templates.jl | 40 +++++++++++++++++++++++++++++++++++++--- src/question_types.jl | 12 ++++++------ src/show_methods.jl | 11 ++++++----- 4 files changed, 50 insertions(+), 15 deletions(-) diff --git a/src/QuizQuestions.jl b/src/QuizQuestions.jl index e7d6800..4c21483 100644 --- a/src/QuizQuestions.jl +++ b/src/QuizQuestions.jl @@ -8,6 +8,6 @@ include("question_types.jl") include("html_templates.jl") include("show_methods.jl") -export numericq, radioq, multiplecq, booleanq, yesnoq, stringq +export numericq, radioq, multiq, booleanq, yesnoq, stringq end diff --git a/src/html_templates.jl b/src/html_templates.jl index ebad5dc..b408b3e 100644 --- a/src/html_templates.jl +++ b/src/html_templates.jl @@ -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 = "
👍 Correct
"; + msgBox.innerHTML = "
👍  {{#:CORRECT}}{{:CORRECT}}{{/:CORRECT}}{{^:CORRECT}}Correct{{:/CORRECT}}
"; } else { - msgBox.innerHTML = "
👎  Incorrect
"; + msgBox.innerHTML = "
👎  {{#:INCORRECT}}{{:INCORRECT}}{{/:INCORRECT}}{{^:INCORRECT}}Incorrect{{:/INCORRECT}}
"; } """ @@ -82,3 +82,37 @@ rb.addEventListener("change", function() { $(grading_partial) })}); """ + +html_templates["Multiq"] = mt""" +{{#:ITEMS}} +
+ +
+{{/: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) +})}); +""" diff --git a/src/question_types.jl b/src/question_types.jl index 88465fe..e9e18f3 100644 --- a/src/question_types.jl +++ b/src/question_types.jl @@ -110,9 +110,9 @@ end ## -mutable struct Multiplecq <: Question +mutable struct Multiq <: Question choices - answers + answer values labels label @@ -121,9 +121,9 @@ mutable struct Multiplecq <: Question end """ - multiplecq(choices, answers; label="", hint="", keep_order=false) + multiq(choices, answers; label="", hint="", keep_order=false) -Multiple choice question (several possible) +Multiple choice question (one *or more* of several) Arguments: @@ -148,7 +148,7 @@ multiplecq(choices, answers; hint="not the red one!") ``` """ -function multiplecq(choices, answers::Vector{Int}; +function multiq(choices, answers; label="", hint="", inline::Bool=(hint!=""), keep_order::Bool=false) inds = collect(1:length(choices)) @@ -156,7 +156,7 @@ function multiplecq(choices, answers::Vector{Int}; labels = choices !keep_order && shuffle!(inds) - Multiplecq(choices[inds], findall(in(answers), inds), + Multiq(choices[inds], findall(in(answers), inds), values, labels[inds], label, hint, inline) end diff --git a/src/show_methods.jl b/src/show_methods.jl index d56c509..bb0394a 100644 --- a/src/show_methods.jl +++ b/src/show_methods.jl @@ -109,18 +109,19 @@ function Base.show(io::IO, m::MIME"text/html", x::Radioq) end -function Base.show(io::IO, m::MIME"text/html", x::Multiplecq) +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["radio_grading_script"]; - ID = ID, - CORRECT_ANSWER = x.answer + GRADING_SCRIPT = Mustache.render(html_templates["multi_grading_script"]; + ID = ID, + CORRECT_ANSWER = x.answer, + INCORRECT = "Not yet" ) - FORM = Mustache.render(html_templates["Radioq"]; + FORM = Mustache.render(html_templates["Multiq"]; ID = ID, ITEMS = items, INLINE = x.inline ? " inline" : "" From 3fcde198accb33daa6915612fa3b61cd04f8d84e Mon Sep 17 00:00:00 2001 From: jverzani Date: Tue, 29 Mar 2022 10:51:55 -0400 Subject: [PATCH 3/4] fix template --- src/html_templates.jl | 4 ++-- src/show_methods.jl | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/html_templates.jl b/src/html_templates.jl index b408b3e..0175698 100644 --- a/src/html_templates.jl +++ b/src/html_templates.jl @@ -3,9 +3,9 @@ html_templates = Dict() grading_partial = """ if(correct) { - msgBox.innerHTML = "
👍  {{#:CORRECT}}{{:CORRECT}}{{/:CORRECT}}{{^:CORRECT}}Correct{{:/CORRECT}}
"; + msgBox.innerHTML = "
👍  {{#:CORRECT}}{{{:CORRECT}}}{{/:CORRECT}}{{^:CORRECT}}Correct{{/:CORRECT}}
"; } else { - msgBox.innerHTML = "
👎  {{#:INCORRECT}}{{:INCORRECT}}{{/:INCORRECT}}{{^:INCORRECT}}Incorrect{{:/INCORRECT}}
"; + msgBox.innerHTML = "
👎  {{#:INCORRECT}}{{{:INCORRECT}}}{{/:INCORRECT}}{{^:INCORRECT}}Incorrect{{/:INCORRECT}}
"; } """ diff --git a/src/show_methods.jl b/src/show_methods.jl index bb0394a..a687048 100644 --- a/src/show_methods.jl +++ b/src/show_methods.jl @@ -119,7 +119,8 @@ function Base.show(io::IO, m::MIME"text/html", x::Multiq) GRADING_SCRIPT = Mustache.render(html_templates["multi_grading_script"]; ID = ID, CORRECT_ANSWER = x.answer, - INCORRECT = "Not yet" + INCORRECT = "Not yet", + CORRECT = "Correct" ) FORM = Mustache.render(html_templates["Multiq"]; ID = ID, From 8238a6aee3b6536b36ba77635d34001a5baec040 Mon Sep 17 00:00:00 2001 From: jverzani Date: Tue, 29 Mar 2022 17:05:35 -0400 Subject: [PATCH 4/4] version bump --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index ea80d6a..e3b5085 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "QuizQuestions" uuid = "612c44de-1021-4a21-84fb-7261cf5eb2d4" authors = ["jverzani and contributors"] -version = "0.2.0" +version = "0.3.0" [deps] Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a"