Refactor: Add support for Match, Gapselect, DDwtos and Calculated Moodle question types

This commit is contained in:
2026-04-11 21:20:46 +02:00
parent 6ce2c47cb4
commit 72be91d796
14 changed files with 1075 additions and 7 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+153
View File
@@ -0,0 +1,153 @@
<div id="question-124-10" class="que calculatedsimple interactive notyetanswered">
<div class="info">
<h3 class="no">Question <span class="qno">9</span></h3>
<div class="state">Tries remaining: 3</div>
<div class="grade">Marked out of 1.00</div>
<div class="questionflag editable" id="yui_3_18_1_1_1775934842056_72"><input type="hidden"
name="q124:10_:flagged" value="0"><input type="hidden"
value="qaid=801&amp;qubaid=124&amp;qid=1621&amp;slot=10&amp;checksum=7baed22ee2b738ef71503b27cd982b7d&amp;sesskey=iGNCxptJmv&amp;newstate="
class="questionflagpostdata">
<input type="hidden" class="questionflagvalue" id="q124:10_:flaggedcheckbox" name="q124:10_:flagged"
value="0"><a tabindex="0" class="aabtn" role="button" aria-pressed="false" aria-label="Flagged"
title="Flag this question for future reference"><img class="questionflagimage"
src="https://school.moodledemo.net/theme/image.php/boost/core/1775930536/i/unflagged" alt="">Flag
question</a>
</div>
<div class="editquestion"><a
href="https://school.moodledemo.net/question/bank/editquestion/question.php?cmid=1210&amp;returnurl=%2Fmod%2Fquiz%2Fattempt.php%3Fattempt%3D88%26cmid%3D1210%23question-124-10&amp;id=1621"><i
class="icon fa fa-pen fa-fw iconsmall" title="Edit" role="img" aria-label="Edit"></i>Edit
question</a></div><span class="badge bg-primary text-light">v1 (latest)</span>
</div>
<div class="content">
<div class="formulation clearfix">
<h4 class="accesshide">Question text</h4><input type="hidden" name="q124:10_:sequencecheck" value="1">
<div class="qtext" style="cursor: pointer;">
<div class="clearfix">
<p>This is an example of a simple calculated question. It's similar to the calculated question but
with fewer settings <img class="icon emoticon" alt="smile" title="smile"
src="https://school.moodledemo.net/theme/image.php/boost/core/1775930536/s/smiley"></p>
<p>You won a cool Moodle cooler box at a Moodle Moot and wonder how much it will hold. What is the
volume of your cooler box if its height is 6.4 its length is 9.9 and its width is 7.0?</p>
</div>
</div>
<div class="ablock d-flex flex-wrap align-items-center"><label for="q124:10_answer">Answer: <span
class="visually-hidden">Question 9</span></label><span class="answer"><input type="text"
name="q124:10_answer" id="q124:10_answer" size="30" class="form-control d-inline"></span></div>
<div class="im-controls"><button type="submit" id="q124:10_-submit" name="q124:10_-submit" value="1"
class="submit btn btn-secondary" data-savescrollposition="true">Check <span
class="visually-hidden">Question 9</span></button></div>
</div>
</div>
</div>
<div id="question-124-9" class="que calculatedmulti interactive notyetanswered">
<div class="info">
<h3 class="no">Question <span class="qno">8</span></h3>
<div class="state">Tries remaining: 3</div>
<div class="grade">Marked out of 1.00</div>
<div class="questionflag editable" id="yui_3_18_1_1_1775934842056_66"><input type="hidden"
name="q124:9_:flagged" value="0"><input type="hidden"
value="qaid=800&amp;qubaid=124&amp;qid=1620&amp;slot=9&amp;checksum=6f196762f980a0b2c9f887ed255c8a24&amp;sesskey=iGNCxptJmv&amp;newstate="
class="questionflagpostdata">
<input type="hidden" class="questionflagvalue" id="q124:9_:flaggedcheckbox" name="q124:9_:flagged"
value="0"><a tabindex="0" class="aabtn" role="button" aria-pressed="false" aria-label="Flagged"
title="Flag this question for future reference"><img class="questionflagimage"
src="https://school.moodledemo.net/theme/image.php/boost/core/1775930536/i/unflagged" alt="">Flag
question</a>
</div>
<div class="editquestion"><a
href="https://school.moodledemo.net/question/bank/editquestion/question.php?cmid=1210&amp;returnurl=%2Fmod%2Fquiz%2Fattempt.php%3Fattempt%3D88%26cmid%3D1210%23question-124-9&amp;id=1620"><i
class="icon fa fa-pen fa-fw iconsmall" title="Edit" role="img" aria-label="Edit"></i>Edit
question</a></div><span class="badge bg-primary text-light">v2 (latest)</span>
</div>
<div class="content">
<div class="formulation clearfix">
<h4 class="accesshide">Question text</h4><input type="hidden" name="q124:9_:sequencecheck" value="1">
<div class="qtext" style="cursor: pointer;">
<div class="clearfix">
<p>This is an example of a calculated multi-choice question. It is like the calculated question in
that the numbers used may vary with each student and question, but the equation remains the same
but it is different from the calculated question in that there is a choice of answers available.
</p>
<p>You are making a banner for your organisation's Moodle User Group meeting. Its length is 14 and
its height is 8 What is its area?</p>
<p>&nbsp;</p>
</div>
</div>
<fieldset class="ablock no-overflow visual-scroll-x">
<legend class="prompt h6 fw-normal visually-hidden"><span class="visually-hidden">Question 8</span>
Answer</legend>
<div class="answer">
<div class="r0"><input type="radio" name="q124:9_answer" value="0" id="q124:9_answer0"
aria-labelledby="q124:9_answer0_label">
<div class="d-flex w-auto" id="q124:9_answer0_label" data-region="answer-label">
<div class="flex-fill ms-1">6</div>
</div>
</div>
<div class="r1"><input type="radio" name="q124:9_answer" value="1" id="q124:9_answer1"
aria-labelledby="q124:9_answer1_label">
<div class="d-flex w-auto" id="q124:9_answer1_label" data-region="answer-label">
<div class="flex-fill ms-1">112</div>
</div>
</div>
<div class="r0"><input type="radio" name="q124:9_answer" value="2" id="q124:9_answer2"
aria-labelledby="q124:9_answer2_label">
<div class="d-flex w-auto" id="q124:9_answer2_label" data-region="answer-label">
<div class="flex-fill ms-1">22</div>
</div>
</div>
</div>
<div id="q124:9_clearchoice" class="qtype_multichoice_clearchoice visually-hidden" aria-hidden="true">
<input type="radio" name="q124:9_answer" id="q124:9_answer-1" value="-1" class="visually-hidden"
aria-hidden="true" checked="checked"><label for="q124:9_answer-1"><a tabindex="-1" role="button"
class="btn btn-link ms-3 mt-n1" href="#">Clear my choice</a></label>
</div>
</fieldset>
<div class="im-controls"><button type="submit" id="q124:9_-submit" name="q124:9_-submit" value="1"
class="submit btn btn-secondary" data-savescrollposition="true">Check <span
class="visually-hidden">Question 8</span></button></div>
</div>
</div>
</div>
<div id="question-124-8" class="que calculated interactive notyetanswered">
<div class="info">
<h3 class="no">Question <span class="qno">7</span></h3>
<div class="state">Tries remaining: 2</div>
<div class="grade">Marked out of 1.00</div>
<div class="questionflag editable" id="yui_3_18_1_1_1775934842056_60"><input type="hidden"
name="q124:8_:flagged" value="0"><input type="hidden"
value="qaid=799&amp;qubaid=124&amp;qid=1618&amp;slot=8&amp;checksum=b7d586e320edea342963eb06ad05faa0&amp;sesskey=iGNCxptJmv&amp;newstate="
class="questionflagpostdata">
<input type="hidden" class="questionflagvalue" id="q124:8_:flaggedcheckbox" name="q124:8_:flagged"
value="0"><a tabindex="0" class="aabtn" role="button" aria-pressed="false" aria-label="Flagged"
title="Flag this question for future reference"><img class="questionflagimage"
src="https://school.moodledemo.net/theme/image.php/boost/core/1775930536/i/unflagged" alt="">Flag
question</a>
</div>
<div class="editquestion"><a
href="https://school.moodledemo.net/question/bank/editquestion/question.php?cmid=1210&amp;returnurl=%2Fmod%2Fquiz%2Fattempt.php%3Fattempt%3D88%26cmid%3D1210%23question-124-8&amp;id=1618"><i
class="icon fa fa-pen fa-fw iconsmall" title="Edit" role="img" aria-label="Edit"></i>Edit
question</a></div><span class="badge bg-primary text-light">v1 (latest)</span>
</div>
<div class="content">
<div class="formulation clearfix">
<h4 class="accesshide">Question text</h4><input type="hidden" name="q124:8_:sequencecheck" value="1">
<div class="qtext" style="cursor: pointer;">
<div class="clearfix">
<p>This is an example of a calculated question. The numbers will vary but the formula stays the
same.&nbsp;</p>
<p>You're doing some training in your organisation. In your group you have 3 complete beginners and
14 relatively experienced Moodle users. How many are there in your group in total?</p>
<p><span>&nbsp;</span></p>
</div>
</div>
<div class="ablock d-flex flex-wrap align-items-center"><label for="q124:8_answer">Answer: <span
class="visually-hidden">Question 7</span></label><span class="answer"><input type="text"
name="q124:8_answer" id="q124:8_answer" size="30" class="form-control d-inline"></span></div>
<div class="im-controls"><button type="submit" id="q124:8_-submit" name="q124:8_-submit" value="1"
class="submit btn btn-secondary" data-savescrollposition="true">Check <span
class="visually-hidden">Question 7</span></button></div>
</div>
</div>
</div>
+232
View File
@@ -0,0 +1,232 @@
<div id="question-124-16" class="que ddwtos interactivecountback notyetanswered">
<div class="info">
<h3 class="no">Question <span class="qno">15</span></h3>
<div class="state">Tries remaining: 1</div>
<div class="grade">Marked out of 5.00</div>
<div class="questionflag editable" id="yui_3_18_1_1_1775933031480_108">
<input type="hidden" name="q124:16_:flagged" value="0" /><input
type="hidden"
value="qaid=814&amp;qubaid=124&amp;qid=1642&amp;slot=16&amp;checksum=2b637f444fcfdda7191b7f0620cd7533&amp;sesskey=xrcdi6NRF8&amp;newstate="
class="questionflagpostdata"
/>
<input
type="hidden"
class="questionflagvalue"
id="q124:16_:flaggedcheckbox"
name="q124:16_:flagged"
value="0"
/><a
tabindex="0"
class="aabtn"
role="button"
aria-pressed="false"
aria-label="Flagged"
title="Flag this question for future reference"
><img
class="questionflagimage"
src="https://school.moodledemo.net/theme/image.php/boost/core/1775926936/i/unflagged"
alt=""
/>Flag question</a
>
</div>
<div class="editquestion">
<a
href="https://school.moodledemo.net/question/bank/editquestion/question.php?cmid=1210&amp;returnurl=%2Fmod%2Fquiz%2Fattempt.php%3Fattempt%3D88%26cmid%3D1210%23question-124-16&amp;id=1642"
><i class="icon fa fa-pen fa-fw iconsmall" title="Edit" role="img" aria-label="Edit"></i
>Edit question</a
>
</div>
<span class="badge bg-primary text-light">v1 (latest)</span>
</div>
<div class="content">
<div class="formulation clearfix">
<h4 class="accesshide">Question text</h4>
<input type="hidden" name="q124:16_:sequencecheck" value="1" />
<div class="qtext" style="cursor: pointer">
<p>
<i
>Drag the capital city onto the correct country.There are a few extra just to confuse
you!</i
>
</p>
<p>
<i
>This is an example of a
<a href="https://docs.moodle.org/en/Drag_and_drop_into_text"
>Drag and drop into text question type.</a
></i
>
</p>
<hr />
<p>
The capital of England is
<span
class="place1 drop active group1"
tabindex="0"
style="width: 78px; height: 27px; line-height: 27px"
>&nbsp;<span class="accesshide">Blank 1 Question 15</span></span
>
which is fairly easy. But do you know that the capital of Wales is
<span
class="place2 drop active group1"
tabindex="0"
style="width: 78px; height: 27px; line-height: 27px"
>&nbsp;<span class="accesshide">Blank 2 Question 15</span></span
>
?
</p>
<p>
Scotland's capital city is the very beautiful
<span
class="place3 drop active group1"
tabindex="0"
style="width: 78px; height: 27px; line-height: 27px"
>&nbsp;<span class="accesshide">Blank 3 Question 15</span></span
>
while the Republic of Ireland has
<span
class="place4 drop active group1"
tabindex="0"
style="width: 78px; height: 27px; line-height: 27px"
>&nbsp;<span class="accesshide">Blank 4 Question 15</span></span
>
as its capital and Northern Ireland's capital is
<span
class="place5 drop active group1"
tabindex="0"
style="width: 78px; height: 27px; line-height: 27px"
>&nbsp;<span class="accesshide">Blank 5 Question 15</span></span
>
</p>
</div>
<div class="answercontainer">
<div class="user-select-none draggrouphomes1">
<span
class="draghome choice1 group1 dragplaceholder"
style="width: 80px; height: 29px; line-height: 27px"
>Glasgow</span
><span
class="draghome user-select-none choice1 group1 unplaced"
style="width: 80px; height: 29px; line-height: 27px"
>Glasgow</span
>
<span
class="draghome choice2 group1 dragplaceholder"
style="width: 80px; height: 29px; line-height: 27px"
>Dublin</span
><span
class="draghome user-select-none choice2 group1 unplaced"
style="width: 80px; height: 29px; line-height: 27px"
>Dublin</span
>
<span
class="draghome choice3 group1 dragplaceholder"
style="width: 80px; height: 29px; line-height: 27px"
>London</span
><span
class="draghome user-select-none choice3 group1 unplaced"
style="width: 80px; height: 29px; line-height: 27px"
>London</span
>
<span
class="draghome choice4 group1 dragplaceholder"
style="width: 80px; height: 29px; line-height: 27px"
>Cardiff</span
><span
class="draghome user-select-none choice4 group1 unplaced"
style="width: 80px; height: 29px; line-height: 27px"
>Cardiff</span
>
<span
class="draghome choice5 group1 dragplaceholder"
style="width: 80px; height: 29px; line-height: 27px"
>Cork</span
><span
class="draghome user-select-none choice5 group1 unplaced"
style="width: 80px; height: 29px; line-height: 27px"
>Cork</span
>
<span
class="draghome choice6 group1 dragplaceholder"
style="width: 80px; height: 29px; line-height: 27px"
>Belfast</span
><span
class="draghome user-select-none choice6 group1 unplaced"
style="width: 80px; height: 29px; line-height: 27px"
>Belfast</span
>
<span
class="draghome choice7 group1 dragplaceholder"
style="width: 80px; height: 29px; line-height: 27px"
>Derry</span
><span
class="draghome user-select-none choice7 group1 unplaced"
style="width: 80px; height: 29px; line-height: 27px"
>Derry</span
>
<span
class="draghome choice8 group1 dragplaceholder"
style="width: 80px; height: 29px; line-height: 27px"
>Edinburgh</span
><span
class="draghome user-select-none choice8 group1 unplaced"
style="width: 80px; height: 29px; line-height: 27px"
>Edinburgh</span
>
<span
class="draghome choice9 group1 dragplaceholder"
style="width: 80px; height: 29px; line-height: 27px"
>Swansea</span
><span
class="draghome user-select-none choice9 group1 unplaced"
style="width: 80px; height: 29px; line-height: 27px"
>Swansea</span
>
</div>
</div>
<input
type="hidden"
id="q124_16_p1"
class="placeinput place1 group1"
name="q124:16_p1"
value="0"
/><input
type="hidden"
id="q124_16_p2"
class="placeinput place2 group1"
name="q124:16_p2"
value="0"
/><input
type="hidden"
id="q124_16_p3"
class="placeinput place3 group1"
name="q124:16_p3"
value="0"
/><input
type="hidden"
id="q124_16_p4"
class="placeinput place4 group1"
name="q124:16_p4"
value="0"
/><input
type="hidden"
id="q124_16_p5"
class="placeinput place5 group1"
name="q124:16_p5"
value="0"
/>
<div class="im-controls">
<button
type="submit"
id="q124:16_-submit"
name="q124:16_-submit"
value="1"
class="submit btn btn-secondary"
data-savescrollposition="true"
>
Check <span class="visually-hidden">Question 15</span>
</button>
</div>
</div>
</div>
</div>
+176
View File
@@ -0,0 +1,176 @@
<div id="question-124-3" class="que match interactivecountback notyetanswered">
<div class="info">
<h3 class="no">Question <span class="qno">2</span></h3>
<div class="state">Tries remaining: 3</div>
<div class="grade">Marked out of 1.00</div>
<div class="questionflag editable" id="yui_3_18_1_1_1775932863373_30">
<input type="hidden" name="q124:3_:flagged" value="0" /><input
type="hidden"
value="qaid=801&amp;qubaid=124&amp;qid=1581&amp;slot=3&amp;checksum=35d5356ab101c7fac69fb355c4f95306&amp;sesskey=xrcdi6NRF8&amp;newstate="
class="questionflagpostdata"
/>
<input
type="hidden"
class="questionflagvalue"
id="q124:3_:flaggedcheckbox"
name="q124:3_:flagged"
value="0"
/><a
tabindex="0"
class="aabtn"
role="button"
aria-pressed="false"
aria-label="Flagged"
title="Flag this question for future reference"
><img
class="questionflagimage"
src="https://school.moodledemo.net/theme/image.php/boost/core/1775926936/i/unflagged"
alt=""
/>Flag question</a
>
</div>
<div class="editquestion">
<a
href="https://school.moodledemo.net/question/bank/editquestion/question.php?cmid=1210&amp;returnurl=%2Fmod%2Fquiz%2Fattempt.php%3Fattempt%3D88%26cmid%3D1210%23question-124-3&amp;id=1581"
><i class="icon fa fa-pen fa-fw iconsmall" title="Edit" role="img" aria-label="Edit"></i
>Edit question</a
>
</div>
<span class="badge bg-primary text-light">v3 (latest)</span>
</div>
<div class="content">
<div class="formulation clearfix">
<h4 class="accesshide">Question text</h4>
<input type="hidden" name="q124:3_:sequencecheck" value="1" />
<div class="qtext" id="q124:3_qtext" style="cursor: pointer">
<div class="clearfix">
<p>This is an example of a matching question type.</p>
<p>Match the Moodle features to their functionality:</p>
</div>
</div>
<div class="ablock">
<table class="answer" role="presentation">
<tbody role="presentation">
<tr class="r0" role="presentation">
<td class="text" id="q124:3_sub0_itemtext" role="presentation">
<p>Wiki</p>
</td>
<td class="control" role="presentation">
<label class="visually-hidden" for="menuq124:3_sub0">Answer 1 Question 2</label
><select
class="select form-select form-select d-inline-block ms-1"
aria-describedby="q124:3_qtext q124:3_sub0_itemtext"
id="menuq124:3_sub0"
name="q124:3_sub0"
>
<option selected="selected" value="0">Choose...</option>
<option value="1">quick poll</option>
<option value="2">collaborative editing</option>
<option value="3">Peer assessment</option>
<option value="4">interactive content</option>
<option value="5">branching activities</option>
</select>
</td>
</tr>
<tr class="r1" role="presentation">
<td class="text" id="q124:3_sub1_itemtext" role="presentation">
<p>Lesson</p>
</td>
<td class="control" role="presentation">
<label class="visually-hidden" for="menuq124:3_sub1">Answer 2 Question 2</label
><select
class="select form-select form-select d-inline-block ms-1"
aria-describedby="q124:3_sub1_itemtext"
id="menuq124:3_sub1"
name="q124:3_sub1"
>
<option selected="selected" value="0">Choose...</option>
<option value="1">quick poll</option>
<option value="2">collaborative editing</option>
<option value="3">Peer assessment</option>
<option value="4">interactive content</option>
<option value="5">branching activities</option>
</select>
</td>
</tr>
<tr class="r0" role="presentation">
<td class="text" id="q124:3_sub2_itemtext" role="presentation">
<p>H5P</p>
</td>
<td class="control" role="presentation">
<label class="visually-hidden" for="menuq124:3_sub2">Answer 3 Question 2</label
><select
class="select form-select form-select d-inline-block ms-1"
aria-describedby="q124:3_sub2_itemtext"
id="menuq124:3_sub2"
name="q124:3_sub2"
>
<option selected="selected" value="0">Choose...</option>
<option value="1">quick poll</option>
<option value="2">collaborative editing</option>
<option value="3">Peer assessment</option>
<option value="4">interactive content</option>
<option value="5">branching activities</option>
</select>
</td>
</tr>
<tr class="r1" role="presentation">
<td class="text" id="q124:3_sub3_itemtext" role="presentation">
<p>Workshop</p>
</td>
<td class="control" role="presentation">
<label class="visually-hidden" for="menuq124:3_sub3">Answer 4 Question 2</label
><select
class="select form-select form-select d-inline-block ms-1"
aria-describedby="q124:3_sub3_itemtext"
id="menuq124:3_sub3"
name="q124:3_sub3"
>
<option selected="selected" value="0">Choose...</option>
<option value="1">quick poll</option>
<option value="2">collaborative editing</option>
<option value="3">Peer assessment</option>
<option value="4">interactive content</option>
<option value="5">branching activities</option>
</select>
</td>
</tr>
<tr class="r0" role="presentation">
<td class="text" id="q124:3_sub4_itemtext" role="presentation">
<p>Choice</p>
</td>
<td class="control" role="presentation">
<label class="visually-hidden" for="menuq124:3_sub4">Answer 5 Question 2</label
><select
class="select form-select form-select d-inline-block ms-1"
aria-describedby="q124:3_sub4_itemtext"
id="menuq124:3_sub4"
name="q124:3_sub4"
>
<option selected="selected" value="0">Choose...</option>
<option value="1">quick poll</option>
<option value="2">collaborative editing</option>
<option value="3">Peer assessment</option>
<option value="4">interactive content</option>
<option value="5">branching activities</option>
</select>
</td>
</tr>
</tbody>
</table>
</div>
<div class="im-controls">
<button
type="submit"
id="q124:3_-submit"
name="q124:3_-submit"
value="1"
class="submit btn btn-secondary"
data-savescrollposition="true"
>
Check <span class="visually-hidden">Question 2</span>
</button>
</div>
</div>
</div>
</div>
+184
View File
@@ -0,0 +1,184 @@
<div id="question-124-17" class="que gapselect interactivecountback notyetanswered">
<div class="info">
<h3 class="no">Question <span class="qno">16</span></h3>
<div class="state">Tries remaining: 1</div>
<div class="grade">Marked out of 7.00</div>
<div class="questionflag editable" id="yui_3_18_1_1_1775933031480_114">
<input type="hidden" name="q124:17_:flagged" value="0" /><input
type="hidden"
value="qaid=815&amp;qubaid=124&amp;qid=1643&amp;slot=17&amp;checksum=c75ebf63f5c7bfcfaceaba8e41013eed&amp;sesskey=xrcdi6NRF8&amp;newstate="
class="questionflagpostdata"
/>
<input
type="hidden"
class="questionflagvalue"
id="q124:17_:flaggedcheckbox"
name="q124:17_:flagged"
value="0"
/><a
tabindex="0"
class="aabtn"
role="button"
aria-pressed="false"
aria-label="Flagged"
title="Flag this question for future reference"
><img
class="questionflagimage"
src="https://school.moodledemo.net/theme/image.php/boost/core/1775926936/i/unflagged"
alt=""
/>Flag question</a
>
</div>
<div class="editquestion">
<a
href="https://school.moodledemo.net/question/bank/editquestion/question.php?cmid=1210&amp;returnurl=%2Fmod%2Fquiz%2Fattempt.php%3Fattempt%3D88%26cmid%3D1210%23question-124-17&amp;id=1643"
><i class="icon fa fa-pen fa-fw iconsmall" title="Edit" role="img" aria-label="Edit"></i
>Edit question</a
>
</div>
<span class="badge bg-primary text-light">v1 (latest)</span>
</div>
<div class="content">
<div class="formulation clearfix">
<h4 class="accesshide">Question text</h4>
<input type="hidden" name="q124:17_:sequencecheck" value="1" />
<div class="qtext" style="cursor: pointer">
<p>
Do you know your Great Britain from your United Kingdom and your British Isles? Find out
here!
</p>
<p>
This question uses the
<a href="https://docs.moodle.org/en/Select_missing_words_question_type"
>Select missing words question type.&nbsp;</a
>
</p>
<p>****************************************************</p>
<p>
Scotland, England and
<span class="control group1"
><label class="visually-hidden" for="q124_17_p1">Blank 1 Question 16</label
><select
id="q124_17_p1"
class="select form-select form-select d-inline-block place1"
name="q124:17_p1"
>
<option value="">&nbsp;</option>
<option value="1">Cumberland</option>
<option value="2">Northern Ireland</option>
<option value="3">the Isle of Man</option>
<option value="4">the Republic of Ireland</option>
<option value="5">Wales</option>
</select>
</span>
together form &nbsp;<span class="control group2"
><label class="visually-hidden" for="q124_17_p2">Blank 2 Question 16</label
><select
id="q124_17_p2"
class="select form-select form-select d-inline-block place2"
name="q124:17_p2"
>
<option value="">&nbsp;</option>
<option value="1">the United Kingdom</option>
<option value="2">Great Britain</option>
<option value="3">the British Isles</option>
<option value="4">the Commonwealth</option>
</select>
</span>
</p>
<p>
Together with
<span class="control group1"
><label class="visually-hidden" for="q124_17_p3">Blank 3 Question 16</label
><select
id="q124_17_p3"
class="select form-select form-select d-inline-block place3"
name="q124:17_p3"
>
<option value="">&nbsp;</option>
<option value="1">Cumberland</option>
<option value="2">Northern Ireland</option>
<option value="3">the Isle of Man</option>
<option value="4">the Republic of Ireland</option>
<option value="5">Wales</option>
</select>
</span>
they also make up &nbsp;<span class="control group2"
><label class="visually-hidden" for="q124_17_p4">Blank 4 Question 16</label
><select
id="q124_17_p4"
class="select form-select form-select d-inline-block place4"
name="q124:17_p4"
>
<option value="">&nbsp;</option>
<option value="1">the United Kingdom</option>
<option value="2">Great Britain</option>
<option value="3">the British Isles</option>
<option value="4">the Commonwealth</option>
</select>
</span>
</p>
<p>
So what are the British Isles? They are
<span class="control group2"
><label class="visually-hidden" for="q124_17_p5">Blank 5 Question 16</label
><select
id="q124_17_p5"
class="select form-select form-select d-inline-block place5"
name="q124:17_p5"
>
<option value="">&nbsp;</option>
<option value="1">the United Kingdom</option>
<option value="2">Great Britain</option>
<option value="3">the British Isles</option>
<option value="4">the Commonwealth</option>
</select>
</span>
and
<span class="control group1"
><label class="visually-hidden" for="q124_17_p6">Blank 6 Question 16</label
><select
id="q124_17_p6"
class="select form-select form-select d-inline-block place6"
name="q124:17_p6"
>
<option value="">&nbsp;</option>
<option value="1">Cumberland</option>
<option value="2">Northern Ireland</option>
<option value="3">the Isle of Man</option>
<option value="4">the Republic of Ireland</option>
<option value="5">Wales</option>
</select> </span
>, together with many other islands and dependencies such as
<span class="control group1"
><label class="visually-hidden" for="q124_17_p7">Blank 7 Question 16</label
><select
id="q124_17_p7"
class="select form-select form-select d-inline-block place7"
name="q124:17_p7"
>
<option value="">&nbsp;</option>
<option value="1">Cumberland</option>
<option value="2">Northern Ireland</option>
<option value="3">the Isle of Man</option>
<option value="4">the Republic of Ireland</option>
<option value="5">Wales</option>
</select> </span
>.
</p>
</div>
<div class="im-controls">
<button
type="submit"
id="q124:17_-submit"
name="q124:17_-submit"
value="1"
class="submit btn btn-secondary"
data-savescrollposition="true"
>
Check <span class="visually-hidden">Question 16</span>
</button>
</div>
</div>
</div>
</div>
+2 -1
View File
@@ -58,7 +58,8 @@ function setUpMoodleGpt(config: Config) {
const inputTypeQuery = ['checkbox', 'radio', 'text', 'number']
.map(e => `input[type="${e}"]`)
.join(',');
const inputQuery = inputTypeQuery + ', textarea, select, [contenteditable], .qtype_essay_editor';
const inputQuery =
inputTypeQuery + ', textarea, select, [contenteditable], .qtype_essay_editor, .placeinput';
const forms = document.querySelectorAll('.formulation');
// For each form we inject a function on the queqtion
@@ -8,6 +8,9 @@ import handleCheckbox from 'background/core/questions/checkbox';
import handleSelect from 'background/core/questions/select';
import handleTextbox from 'background/core/questions/textbox';
import handleAtto from 'background/core/questions/atto';
import handleMatch from 'background/core/questions/match';
import handleGapSelect from 'background/core/questions/gapselect';
import handleDragDropText from 'background/core/questions/ddwtos';
type Props = {
config: Config;
@@ -31,6 +34,9 @@ function autoCompleteMode(props: Props) {
handleContentEditable,
handleTextbox,
handleNumber,
handleMatch,
handleGapSelect,
handleDragDropText,
handleSelect,
handleRadio,
handleCheckbox
+84 -2
View File
@@ -46,7 +46,10 @@ export function parseMoodleQuestion(
const container =
questionElement.closest('.que') || questionElement.closest('.formulation') || questionElement;
if (container.classList.contains('multichoice')) {
if (
container.classList.contains('multichoice') ||
container.classList.contains('calculatedmulti')
) {
const checkboxes = container.querySelectorAll<HTMLInputElement>(
'.answer input[type="checkbox"]'
);
@@ -81,7 +84,11 @@ export function parseMoodleQuestion(
};
}
if (container.classList.contains('numerical')) {
if (
container.classList.contains('numerical') ||
container.classList.contains('calculated') ||
container.classList.contains('calculatedsimple')
) {
return {
question_type: MoodleQuestionType.NUMERICAL,
question_text: normalizedQuestionText
@@ -95,5 +102,80 @@ export function parseMoodleQuestion(
};
}
if (container.classList.contains('match')) {
const subQuestions: { index: number; text: string }[] = [];
const firstSelectOptions: { index: number; text: string }[] = [];
const rows = container.querySelectorAll('tr');
let subIndex = 0;
rows.forEach(row => {
const textCell = row.querySelector('.text');
const select = row.querySelector('select');
if (textCell && select) {
subQuestions.push({ index: subIndex, text: normalizeText(textCell.textContent || '') });
if (subIndex === 0) {
const options = select.querySelectorAll('option');
let optionIndexCounter = 0;
Array.from(options)
.slice(1)
.forEach(opt => {
firstSelectOptions.push({
index: optionIndexCounter++,
text: normalizeText(opt.textContent || '')
});
});
}
subIndex++;
}
});
return {
question_type: MoodleQuestionType.MATCH,
question_text: normalizedQuestionText,
sub_questions: subQuestions,
options: firstSelectOptions
};
}
if (container.classList.contains('gapselect')) {
const selects = container.querySelectorAll('select');
const dropDowns: { index: number; options: { index: number; text: string }[] }[] = [];
selects.forEach((select, dropIndex) => {
const options = select.querySelectorAll('option');
const optArr: { index: number; text: string }[] = [];
let optionIndexCounter = 0;
Array.from(options)
.slice(1)
.forEach(opt => {
optArr.push({ index: optionIndexCounter++, text: normalizeText(opt.textContent || '') });
});
dropDowns.push({ index: dropIndex, options: optArr });
});
return {
question_type: MoodleQuestionType.SELECT_MISSING_WORD,
question_text: normalizedQuestionText,
drop_downs: dropDowns
};
}
if (container.classList.contains('ddwtos')) {
const dragContainer = container.querySelector('.answercontainer');
const draggables: { index: number; text: string }[] = [];
if (dragContainer) {
const dragHomes = dragContainer.querySelectorAll('.draghome.unplaced');
dragHomes.forEach((drag, idx) => {
draggables.push({ index: idx, text: normalizeText(drag.textContent || '') });
});
}
return {
question_type: MoodleQuestionType.DRAG_DROP_TEXT,
question_text: normalizedQuestionText,
draggables
};
}
return null;
}
+44
View File
@@ -0,0 +1,44 @@
import type Config from '../../types/config';
import type GPTAnswer from '../../types/gpt-answer';
import type { DragDropTextResponse } from '../../types/question-types';
import { MoodleQuestionType } from '../../types/question-types';
export default function handleDragDropText(
config: Config,
inputList: NodeListOf<HTMLElement>,
gptAnswer: GPTAnswer
): boolean {
if (!gptAnswer.response || gptAnswer.response.question_type !== MoodleQuestionType.DRAG_DROP_TEXT)
return false;
const response = gptAnswer.response as DragDropTextResponse;
const hiddenInputs = Array.from(inputList).filter(el =>
el.classList.contains('placeinput')
) as HTMLInputElement[];
for (const answer of response.correct_answers) {
const hiddenInput = hiddenInputs[answer.blank_index];
if (!hiddenInput) continue;
const container = hiddenInput.closest('.que');
if (!container) continue;
const dragHomes = container.querySelectorAll('.draghome.unplaced');
const targetDrag = dragHomes[answer.draggable_index];
if (!targetDrag) continue;
const choiceMatch = targetDrag.className.match(/choice(\d+)/);
if (!choiceMatch) continue;
const choiceValue = choiceMatch[1];
hiddenInput.value = choiceValue;
// visually update the drag drop UI string
const blankSpan = container.querySelector(`.place${answer.blank_index + 1}.drop`);
if (blankSpan) {
blankSpan.textContent = targetDrag.textContent;
}
}
return true;
}
@@ -0,0 +1,39 @@
import type Config from '../../types/config';
import type GPTAnswer from '../../types/gpt-answer';
import type { SelectMissingWordResponse } from '../../types/question-types';
import { MoodleQuestionType } from '../../types/question-types';
export default function handleGapSelect(
config: Config,
inputList: NodeListOf<HTMLElement>,
gptAnswer: GPTAnswer
): boolean {
if (
!gptAnswer.response ||
gptAnswer.response.question_type !== MoodleQuestionType.SELECT_MISSING_WORD
)
return false;
const response = gptAnswer.response as SelectMissingWordResponse;
const selects = Array.from(inputList).filter(
el => el.tagName === 'SELECT'
) as HTMLSelectElement[];
for (const answer of response.correct_answers) {
const selectEl = selects[answer.drop_down_index];
if (!selectEl) continue;
const options = selectEl.querySelectorAll('option');
const correctOption = options[answer.option_index + 1];
if (correctOption) {
if (config.mouseover) {
selectEl.addEventListener('click', () => (correctOption.selected = true), { once: true });
} else {
correctOption.selected = true;
}
}
}
return true;
}
+36
View File
@@ -0,0 +1,36 @@
import type Config from '../../types/config';
import type GPTAnswer from '../../types/gpt-answer';
import type { MatchResponse } from '../../types/question-types';
import { MoodleQuestionType } from '../../types/question-types';
export default function handleMatch(
config: Config,
inputList: NodeListOf<HTMLElement>,
gptAnswer: GPTAnswer
): boolean {
if (!gptAnswer.response || gptAnswer.response.question_type !== MoodleQuestionType.MATCH)
return false;
const response = gptAnswer.response as MatchResponse;
const selects = Array.from(inputList).filter(
el => el.tagName === 'SELECT'
) as HTMLSelectElement[];
for (const answer of response.correct_answers) {
const selectEl = selects[answer.sub_question_index];
if (!selectEl) continue;
const options = selectEl.querySelectorAll('option');
const correctOption = options[answer.option_index + 1]; // + 1 because index 0 is "Choose..."
if (correctOption) {
if (config.mouseover) {
selectEl.addEventListener('click', () => (correctOption.selected = true), { once: true });
} else {
correctOption.selected = true;
}
}
}
return true;
}
@@ -94,5 +94,77 @@ export const QuestionSchemas: Record<MoodleQuestionType, any> = {
additionalProperties: false
}
},
[MoodleQuestionType.MATCH]: {
name: 'match_response',
strict: true,
schema: {
type: 'object',
properties: {
question_type: { type: 'string', enum: [MoodleQuestionType.MATCH] },
correct_answers: {
type: 'array',
items: {
type: 'object',
properties: {
sub_question_index: { type: 'integer' },
option_index: { type: 'integer' }
},
required: ['sub_question_index', 'option_index'],
additionalProperties: false
}
}
},
required: ['question_type', 'correct_answers'],
additionalProperties: false
}
},
[MoodleQuestionType.SELECT_MISSING_WORD]: {
name: 'select_missing_word_response',
strict: true,
schema: {
type: 'object',
properties: {
question_type: { type: 'string', enum: [MoodleQuestionType.SELECT_MISSING_WORD] },
correct_answers: {
type: 'array',
items: {
type: 'object',
properties: {
drop_down_index: { type: 'integer' },
option_index: { type: 'integer' }
},
required: ['drop_down_index', 'option_index'],
additionalProperties: false
}
}
},
required: ['question_type', 'correct_answers'],
additionalProperties: false
}
},
[MoodleQuestionType.DRAG_DROP_TEXT]: {
name: 'drag_drop_text_response',
strict: true,
schema: {
type: 'object',
properties: {
question_type: { type: 'string', enum: [MoodleQuestionType.DRAG_DROP_TEXT] },
correct_answers: {
type: 'array',
items: {
type: 'object',
properties: {
blank_index: { type: 'integer' },
draggable_index: { type: 'integer' }
},
required: ['blank_index', 'draggable_index'],
additionalProperties: false
}
}
},
required: ['question_type', 'correct_answers'],
additionalProperties: false
}
},
[MoodleQuestionType.UNKNOWN]: undefined
};
+45 -2
View File
@@ -5,6 +5,9 @@ export enum MoodleQuestionType {
SHORT_TEXT = 'short_text',
NUMERICAL = 'numerical',
ESSAY = 'essay',
MATCH = 'match',
SELECT_MISSING_WORD = 'select_missing_word',
DRAG_DROP_TEXT = 'drag_drop_text',
UNKNOWN = 'unknown'
}
@@ -47,13 +50,35 @@ export interface EssayQuery {
question_text: string;
}
export interface MatchQuery {
question_type: MoodleQuestionType.MATCH;
question_text: string;
sub_questions: { index: number; text: string }[];
options: { index: number; text: string }[];
}
export interface SelectMissingWordQuery {
question_type: MoodleQuestionType.SELECT_MISSING_WORD;
question_text: string;
drop_downs: { index: number; options: { index: number; text: string }[] }[];
}
export interface DragDropTextQuery {
question_type: MoodleQuestionType.DRAG_DROP_TEXT;
question_text: string;
draggables: { index: number; text: string }[];
}
export type MoodleQuestionQuery =
| SingleChoiceQuery
| MultipleChoiceQuery
| TrueFalseQuery
| ShortTextQuery
| NumericalQuery
| EssayQuery;
| EssayQuery
| MatchQuery
| SelectMissingWordQuery
| DragDropTextQuery;
// ==== Expected LLM Responses ====
@@ -87,10 +112,28 @@ export interface EssayResponse {
correct_answer: string;
}
export interface MatchResponse {
question_type: MoodleQuestionType.MATCH;
correct_answers: { sub_question_index: number; option_index: number }[];
}
export interface SelectMissingWordResponse {
question_type: MoodleQuestionType.SELECT_MISSING_WORD;
correct_answers: { drop_down_index: number; option_index: number }[];
}
export interface DragDropTextResponse {
question_type: MoodleQuestionType.DRAG_DROP_TEXT;
correct_answers: { blank_index: number; draggable_index: number }[];
}
export type MoodleQuestionResponse =
| SingleChoiceResponse
| MultipleChoiceResponse
| TrueFalseResponse
| ShortTextResponse
| NumericalResponse
| EssayResponse;
| EssayResponse
| MatchResponse
| SelectMissingWordResponse
| DragDropTextResponse;