Skip to content
Open
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 .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ jobs:
- name: Add filter & commons qtype
run: |
moodle-plugin-ci add-plugin wiris/moodle-filter_wiris
moodle-plugin-ci add-plugin --branch ${GITHUB_REF##*/} wiris/moodle-qtype_wq
moodle-plugin-ci add-plugin --branch main wiris/moodle-qtype_wq

- name: Install moodle-plugin-ci
run: |
Expand Down
70 changes: 69 additions & 1 deletion question.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,39 @@ class qtype_matchwiris_question extends qtype_wq_question implements question_au
public $choices;
public $right;

public $originalchoices;

// Added override in order to exclude repeating values.
public function start_attempt(question_attempt_step $step, $variant) {

if ($this->originalchoices == null) {
$this->originalchoices = $this->base->choices;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we define this twice?

}

parent::start_attempt($step, $variant);
$this->extend_variables_and_check_right_array();

// We call the parent start_attempt method again in order to set the choiceorder.
parent::start_attempt($step, $variant);
}

public function grade_response(array $response) {
$this->extend_variables_and_check_right_array();

list($right, $total) = $this->get_num_parts_right($response);
$fraction = $right / $total;
return array($fraction, question_state::graded_state_for_fraction($fraction));
}

public function join_all_text() {
$text = parent::join_all_text();

// Stems (matching left hand side).
foreach ($this->stems as $key => $value) {
$text .= ' ' . $value;
}
// Choices (matching right hand side).
foreach ($this->choices as $key => $value) {
foreach ($this->originalchoices as $key => $value) {
$text .= ' ' . $value;
}
// Combined feedback.
Expand All @@ -55,8 +80,51 @@ public function get_stem_order() {
public function get_choice_order() {
return $this->base->get_choice_order();
}

public function get_right_choice_for($stemid) {
$this->extend_variables_and_check_right_array();

return $this->base->get_right_choice_for($stemid);
}


public function get_correct_response() {
$response = array();
foreach ($this->base->get_stem_order() as $key => $stemid) {
$response[$this->field($key)] = $this->get_right_choice_for($stemid);
}
return $response;
}

// Added in order to fix the issue where variables with duplicated values
// may repeat choices and evaluate wrong.
protected function extend_variables_and_check_right_array() {
foreach ($this->base->choices as $choice) {
$key = array_search($choice, $this->base->choices);
$this->base->choices[$key] = $this->expand_variables_text($choice);
}

// Getting right array done again.
foreach ($this->base->choices as $choice) {
$keys = array_keys($this->base->choices, $choice);
if (count($keys) > 1) {
$defkey = $keys[0];
foreach ($keys as $key) {
if ($key != $keys[0]) {
// We get rid of repeated choices.
unset($this->base->choices[$key]);
$this->base->right[$key] = $defkey;
}
}
}
}
}

/**
* @param int $key stem number
* @return string the question-type variable name.
*/
protected function field($key) {
return 'sub' . $key;
}
}
44 changes: 33 additions & 11 deletions tests/behat/matchwiris_alg_play.feature
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@qtype @qtype_wq @qtype_matchwiris @qtype_matchwiris_alg_play
Feature: A student can answer a MAtch Wiris question type
Feature: A student can answer a Match Wiris question type
In order to answer the question
As a student
I need to match the fields
Expand All @@ -20,9 +20,10 @@ Feature: A student can answer a MAtch Wiris question type
| contextlevel | reference | name |
| Course | C1 | Default for C1 |
And the following "questions" exist:
| questioncategory | qtype | name | template |
| Default for C1 | matchwiris | Match Wiris | foursubq |
| Default for C1 | matchwiris | Match Formula | twosubqformula |
| questioncategory | qtype | name | template |
| Default for C1 | matchwiris | Match Wiris | foursubq |
| Default for C1 | matchwiris | Match Formula | twosubqformula |
| Default for C1 | matchwiris | Repeated Answers | repeatedanswers |

@javascript
Scenario: A student executes a match wiris question
Expand All @@ -36,17 +37,17 @@ Feature: A student can answer a MAtch Wiris question type
And I am on "Course 1" course homepage
And I follow "Quiz 1"
And I press "Attempt quiz now"
And I set the field with xpath "//table[@class='answer']//td[@class='control']//select[contains(@id, '1_sub0')]" to "1"
And I set the field with xpath "//table[@class='answer']//td[@class='control']//select[contains(@id, '1_sub1')]" to "2"
And I set the field with xpath "//table[@class='answer']//td[@class='control']//select[contains(@id, '1_sub2')]" to "3"
And I set the field with xpath "//table[@class='answer']//td[@class='control']//select[contains(@id, '1_sub3')]" to "4"
And I set the field with xpath "//table[@class='answer']//td[@class='control']//select[contains(@id, '1_sub0')]" to "5"
And I set the field with xpath "//table[@class='answer']//td[@class='control']//select[contains(@id, '1_sub1')]" to "6"
And I set the field with xpath "//table[@class='answer']//td[@class='control']//select[contains(@id, '1_sub2')]" to "7"
And I set the field with xpath "//table[@class='answer']//td[@class='control']//select[contains(@id, '1_sub3')]" to "8"
And I click on "Finish attempt" "button"
And I click on "Submit all and finish" "button"
And I click on "//input[@type='button']" "xpath_element"
Then Generalfeedback should exist

@javascript
Scenario: A student executes a match wiris questio with formulas and feedback
Scenario: A student executes a match wiris question with formulas and feedback
Given the following "activities" exist:
| activity | name | intro | course | idnumber |
| quiz | Quiz 1 | Quiz 1 description | C1 | quiz1 |
Expand All @@ -57,10 +58,31 @@ Feature: A student can answer a MAtch Wiris question type
And I am on "Course 1" course homepage
And I follow "Quiz 1"
And I press "Attempt quiz now"
And I set the field with xpath "//table[@class='answer']//td[@class='control']//select[contains(@id, '1_sub0')]" to "1"
And I set the field with xpath "//table[@class='answer']//td[@class='control']//select[contains(@id, '1_sub1')]" to "2"
And I set the field with xpath "//table[@class='answer']//td[@class='control']//select[contains(@id, '1_sub0')]" to "2^(1/2)/45"
And I set the field with xpath "//table[@class='answer']//td[@class='control']//select[contains(@id, '1_sub1')]" to "2·x^2+2/3"
And I click on "Finish attempt" "button"
And I click on "Submit all and finish" "button"
And I click on "//input[@type='button']" "xpath_element"
Then Generalfeedback should exist
And Wirisformula should exist

@javascript @qtype_matchwiris_alg_play
Scenario: A student executes a match wiris with repeated answers
Given the following "activities" exist:
| activity | name | intro | course | idnumber |
| quiz | Quiz 1 | Quiz 1 description | C1 | quiz1 |
And quiz "Quiz 1" contains the following questions:
| question | page |
| Repeated Answers | 1 |
When I log in as "student1"
And I am on "Course 1" course homepage
And I follow "Quiz 1"
And I press "Attempt quiz now"
And I set the field with xpath "//table[@class='answer']//td[@class='control']//select[contains(@id, '1_sub0')]" to "5"
And I set the field with xpath "//table[@class='answer']//td[@class='control']//select[contains(@id, '1_sub1')]" to "6"
And I set the field with xpath "//table[@class='answer']//td[@class='control']//select[contains(@id, '1_sub2')]" to "6"
And I set the field with xpath "//table[@class='answer']//td[@class='control']//select[contains(@id, '1_sub3')]" to "8"
And I click on "Finish attempt" "button"
And I click on "Submit all and finish" "button"
And I click on "//input[@type='button']" "xpath_element"
Then Generalfeedback should exist
86 changes: 75 additions & 11 deletions tests/helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
*/
class qtype_matchwiris_test_helper extends question_test_helper {
public function get_test_questions() {
return array('foursubq', 'twosubqformula');
return array('foursubq', 'twosubqformula', 'repeatedanswers');
}

/**
Expand All @@ -57,10 +57,10 @@ public function get_matchwiris_question_form_data_foursubq() {
test_question_maker::set_standard_combined_feedback_form_data($q);

$q->subquestions = array(
0 => array('text' => 'One', 'format' => FORMAT_HTML),
1 => array('text' => 'Two', 'format' => FORMAT_HTML),
2 => array('text' => 'Three', 'format' => FORMAT_HTML),
3 => array('text' => 'Four', 'format' => FORMAT_HTML));
0 => array('text' => 'Five', 'format' => FORMAT_HTML),
1 => array('text' => 'Six', 'format' => FORMAT_HTML),
2 => array('text' => 'Seven', 'format' => FORMAT_HTML),
3 => array('text' => 'Eight', 'format' => FORMAT_HTML));

$q->subanswers = array(
0 => '#a',
Expand All @@ -83,14 +83,14 @@ public function get_matchwiris_question_form_data_foursubq() {
</property></properties><session version="3.0" lang="en"><task><title>
<math xmlns="http://www.w3.org/1998/Math/MathML"><mtext>Sheet 1</mtext></math></title><group><command>
<input><math xmlns="http://www.w3.org/1998/Math/MathML"><mi mathvariant="normal">a</mi><mo>=</mo>
<mn>1</mn></math></input><output><math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>
<mn>5</mn></math></input><output><math xmlns="http://www.w3.org/1998/Math/MathML"><mn>5</mn></math>
</output></command><command><input><math xmlns="http://www.w3.org/1998/Math/MathML">
<mi mathvariant="normal">b</mi><mo>=</mo><mn>2</mn></math></input><output>
<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>2</mn></math></output></command><command><input>
<math xmlns="http://www.w3.org/1998/Math/MathML"><mi mathvariant="normal">c</mi><mo>=</mo><mn>3</mn>
</math></input><output><math xmlns="http://www.w3.org/1998/Math/MathML"><mn>3</mn></math></output>
<mi mathvariant="normal">b</mi><mo>=</mo><mn>6</mn></math></input><output>
<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>6</mn></math></output></command><command><input>
<math xmlns="http://www.w3.org/1998/Math/MathML"><mi mathvariant="normal">c</mi><mo>=</mo><mn>7</mn>
</math></input><output><math xmlns="http://www.w3.org/1998/Math/MathML"><mn>7</mn></math></output>
</command><command><input><math xmlns="http://www.w3.org/1998/Math/MathML"><mi mathvariant="normal">
d</mi><mo>=</mo><mn>4</mn></math></input><output><math xmlns="http://www.w3.org/1998/Math/MathML"><mn>4
d</mi><mo>=</mo><mn>8</mn></math></input><output><math xmlns="http://www.w3.org/1998/Math/MathML"><mn>8
</mn></math></output></command><command><input><math xmlns="http://www.w3.org/1998/Math/MathML"/>
</input></command></group></task></session><constructions><construction group="1">
{&quot;elements&quot;:[],&quot;constraints&quot;:[],&quot;displays&quot;:[],&quot;handwriting&quot;:[]}
Expand Down Expand Up @@ -162,6 +162,70 @@ public function get_matchwiris_question_form_data_twosubqformula() {
return $q;
}

/**
* Makes a match question about completing four blanks in some text.
* @return object the question definition data, as it might be returned from
* the question editing form.
*/
public function get_matchwiris_question_form_data_repeatedanswers() {
$q = new stdClass();
$q->name = 'Matching wiris question';
$q->questiontext = array('text' => 'Match the numbers.', 'format' => FORMAT_HTML);
$q->generalfeedback = array('text' => 'General feedback.', 'format' => FORMAT_HTML);
$q->defaultmark = 1;
$q->penalty = 0.3333333;

$q->shuffleanswers = 0;
test_question_maker::set_standard_combined_feedback_form_data($q);

$q->subquestions = array(
0 => array('text' => 'Five', 'format' => FORMAT_HTML),
1 => array('text' => 'Six', 'format' => FORMAT_HTML),
2 => array('text' => 'Six', 'format' => FORMAT_HTML),
3 => array('text' => 'Eight', 'format' => FORMAT_HTML));

$q->subanswers = array(
0 => '#a',
1 => '#b',
2 => '#c',
3 => '#d'
);

$q->noanswers = 4;

// Wiris specific information.
$q->wirisquestion = '<question><wirisCasSession><![CDATA[<wiriscalc version="3.2"><title>
<math xmlns="http://www.w3.org/1998/Math/MathML"><mtext>Untitled&#xa0;calc</mtext></math></title>
<properties><property name="decimal_separator">.</property><property name="digit_group_separator">
</property><property name="float_format">mg</property><property name="imaginary_unit">i</property>
<property name="implicit_times_operator">false</property><property name="item_separator">,</property>
<property name="lang">en</property><property name="precision">4</property>
<property name="quizzes_question_options">true</property><property name="save_settings_in_cookies">
false</property><property name="times_operator">·</property><property name="use_degrees">false
</property></properties><session version="3.0" lang="en"><task><title>
<math xmlns="http://www.w3.org/1998/Math/MathML"><mtext>Sheet 1</mtext></math></title><group><command>
<input><math xmlns="http://www.w3.org/1998/Math/MathML"><mi mathvariant="normal">a</mi><mo>=</mo>
<mn>5</mn></math></input><output><math xmlns="http://www.w3.org/1998/Math/MathML"><mn>5</mn></math>
</output></command><command><input><math xmlns="http://www.w3.org/1998/Math/MathML">
<mi mathvariant="normal">b</mi><mo>=</mo><mn>6</mn></math></input><output>
<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>6</mn></math></output></command><command><input>
<math xmlns="http://www.w3.org/1998/Math/MathML"><mi mathvariant="normal">c</mi><mo>=</mo><mn>6</mn>
</math></input><output><math xmlns="http://www.w3.org/1998/Math/MathML"><mn>6</mn></math></output>
</command><command><input><math xmlns="http://www.w3.org/1998/Math/MathML"><mi mathvariant="normal">
d</mi><mo>=</mo><mn>8</mn></math></input><output><math xmlns="http://www.w3.org/1998/Math/MathML"><mn>8
</mn></math></output></command><command><input><math xmlns="http://www.w3.org/1998/Math/MathML"/>
</input></command></group></task></session><constructions><construction group="1">
{&quot;elements&quot;:[],&quot;constraints&quot;:[],&quot;displays&quot;:[],&quot;handwriting&quot;:[]}
</construction></constructions></wiriscalc>]]></wirisCasSession><correctAnswers><correctAnswer>
</correctAnswer></correctAnswers><assertions><assertion name="syntax_math"/>
<assertion name="equivalent_symbolic"><param name="tolerance">0.001</param>
<param name="tolerance_digits">false</param><param name="relative_tolerance">true</param></assertion>
</assertions><slots><slot><initialContent></initialContent></slot></slots></question>';
$q->wirislang = 'en';

return $q;
}

/**
* Makes a matching question to classify 'Dog', 'Frog', 'Toad' and 'Cat' as
* 'Mammal', 'Amphibian' or 'Insect'.
Expand Down
8 changes: 4 additions & 4 deletions version.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@

defined('MOODLE_INTERNAL') || die();

$plugin->version = 2021050700;
$plugin->release = '4.2.7';
$plugin->version = 2021091300;
$plugin->release = '4.3.0';
$plugin->requires = 2011060313;
$plugin->maturity = MATURITY_RC;
$plugin->maturity = MATURITY_STABLE;
$plugin->component = 'qtype_matchwiris';
$plugin->dependencies = array (
'qtype_wq' => 2021050700
'qtype_wq' => 2021091300
);