Skip to content

Commit

Permalink
Matrix: Reimplement get_possible_responses() for stats #746912
Browse files Browse the repository at this point in the history
  • Loading branch information
mkassaei committed Jan 24, 2024
1 parent 916f198 commit 1d43ba3
Show file tree
Hide file tree
Showing 5 changed files with 199 additions and 24 deletions.
49 changes: 49 additions & 0 deletions question.php
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,55 @@ public function is_complete_response(array $response): bool {
return true;
}

public function classify_response(array $response) {
if (!$this->is_complete_response($response)) {
return [$this->id => question_classified_response::no_response()];
}
$selectedchoices = [];
foreach ($this->roworder as $key => $rowid) {
$fieldname = $this->field($key);
if (array_key_exists($fieldname, $response) && $response[$fieldname]) {
$selectedchoices[$rowid] = 1;
}
}
$choices = [];
foreach ($this->roworder as $key => $rowid) {
$row = $this->rows[$rowid];
if ($key === ($row->number - 1)) {
$fraction = 0;
foreach ($this->columns as $colid => $column) {
if (isset($selectedchoices[$colid])) {
$fraction = 1;
}
$choices[$colid] = new question_classified_response($column->number, $column->name, $fraction);
}
}
}
return $choices;
}

public function prepare_simulated_post_data($simulatedresponse) {
$postdata = [];
$subquestions = array_keys($simulatedresponse);
$answers = array_values($simulatedresponse);

foreach ($this->roworder as $key => $rowid) {
$row = $this->rows[$rowid];
if ($row->name !== $subquestions[$key]) {
continue;
}
if ($key === ($row->number - 1) && $row->name === $subquestions[$key]) {
foreach ($this->columns as $colid => $column) {
if ($column->name !== $answers[$key]) {
continue;
}
$postdata['rowanswers' . $key] = $column->number;
}
}
}
return $postdata;
}

public function grade_response(array $response): array {
// Retrieve the number of right responses and the total number of responses.
[$numrightparts, $total] = $this->get_num_parts_right($response);
Expand Down
40 changes: 17 additions & 23 deletions questiontype.php
Original file line number Diff line number Diff line change
Expand Up @@ -316,30 +316,24 @@ public function get_num_correct_choices(stdClass $questiondata): int {
}

public function get_possible_responses($questiondata) {
if ($questiondata->options->single) {
$responses = [];

// TODO: Sort out this funtion to work with rows and columns, etc.
foreach ($questiondata->options->answers as $aid => $answer) {
$responses[$aid] = new question_possible_response(
question_utils::to_plain_text($answer->answer, $answer->answerformat),
$answer->fraction);
}

$responses[null] = question_possible_response::no_response();
return [$questiondata->id => $responses];
} else {
$parts = [];

foreach ($questiondata->options->answers as $aid => $answer) {
$parts[$aid] = [
$aid => new question_possible_response(question_utils::to_plain_text(
$answer->answer, $answer->answerformat), $answer->fraction),
];
$question = $this->make_question_instance($questiondata);
$this->initialise_question_instance($question, $questiondata);
$subqs = [];
$responses = [];
foreach ($question->rows as $rowid => $row) {
foreach ($question->columns as $colid => $col) {
$responseclass = $question->html_to_text($row->name . ': ' . $col->name, FORMAT_PLAIN);
if (in_array($col->number, array_keys($row->correctanswers))) {
$fraction = 1;
} else {
$fraction = 0;
}
$responses[$colid] = new question_possible_response($responseclass, $fraction);
}
$responses[null] = question_possible_response::no_response();
$subqs[$rowid - 1] = $responses;
}

return $parts;
}
return $subqs;
}

public function import_from_xml($data, $question, qformat_xml $format, $extra = null) {
Expand Down
2 changes: 1 addition & 1 deletion tests/helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public function get_oumatrix_question_data_animals_single(): stdClass {
'name' => 'Birds',
],
14 => (object) [
'id' => 13,
'id' => 14,
'number' => 4,
'name' => 'Mammals',
],
Expand Down
47 changes: 47 additions & 0 deletions tests/question_single_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
namespace qtype_oumatrix;
use question_attempt_step;
use question_state;
use question_classified_response;

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

Expand Down Expand Up @@ -60,6 +61,52 @@ public function test_is_gradable_response(): void {
$this->assertEquals($question->is_gradable_response($response), $question->is_complete_response($response));
}

public function test_classify_response_single(): void {
$question = \test_question_maker::make_question('oumatrix', 'animals_single');
$question->start_attempt(new question_attempt_step(), 1);
$response = $question->prepare_simulated_post_data(
['Bee' => 'Insects', 'Salmon' => 'Fish', 'Seagull' => 'Birds', 'Dog' => 'Mammals']);
$this->assertEquals([
11 => new question_classified_response(1, 'Insects', 1),
12 => new question_classified_response(2, 'Fish', 1),
13 => new question_classified_response(3, 'Birds', 1),
14 => new question_classified_response(4, 'Mammals', 1),
], $question->classify_response($response));

//TODO: Sorry I did not manage to sort this out properly
//$expected = [
// 0 => [
// 1 => new question_classified_response(1, 'Bee: Insects', 1),
// 2 => new question_classified_response(2, 'Bee: Fish', 1),
// 3 => new question_classified_response(3, 'Bee: Birds', 1),
// 4 => new question_classified_response(4, 'Bee: Mammals', 1),
// null => question_classified_response::no_response(),
// ],
// 1 => [
// 1 => new question_classified_response(1, 'Salmon: Insects', 0),
// 2 => new question_classified_response(2, 'Salmon: Fish', 1),
// 3 => new question_classified_response(3, 'Salmon: Birds', 0),
// 4 => new question_classified_response(4, 'Salmon: Mammals', 0),
// null => question_classified_response::no_response(),
// ],
// 2 => [
// 1 => new question_classified_response(1, 'Seagull: Insects', 0),
// 2 => new question_classified_response(2, 'Seagull: Fish', 0),
// 3 => new question_classified_response(3, 'Seagull: Birds', 1),
// 4 => new question_classified_response(4, 'Seagull: Mammals', 0),
// null => question_classified_response::no_response(),
// ],
// 3 => [
// 1 => new question_classified_response(1, 'Dog: Insects', 0),
// 2 => new question_classified_response(2, 'Dog: Fish', 0),
// 3 => new question_classified_response(3, 'Dog: Birds', 0),
// 4 => new question_classified_response(4, 'Dog: Mammals', 1),
// null => question_classified_response::no_response(),
// ],
//];
//$this->assertEquals($expected, $question->classify_response($response));
}

public function test_is_same_response(): void {
$question = \test_question_maker::make_question('oumatrix');
$question->start_attempt(new question_attempt_step(), 1);
Expand Down
85 changes: 85 additions & 0 deletions tests/questiontype_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@
use qtype_oumatrix;
use qtype_oumatrix_edit_form;
use qtype_oumatrix_test_helper;
use question_bank;
use question_possible_response;

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

global $CFG;

require_once($CFG->dirroot . '/question/engine/tests/helpers.php');
require_once($CFG->dirroot . '/question/type/oumatrix/tests/helper.php');
require_once($CFG->dirroot . '/question/type/oumatrix/questiontype.php');
Expand Down Expand Up @@ -70,6 +73,88 @@ public function test_get_random_guess_score_broken_question(): void {
$this->assertNull($this->qtype->get_random_guess_score($q));
}

public function test_get_possible_responses_single(): void {
$this->resetAfterTest();
$generator = $this->getDataGenerator()->get_plugin_generator('core_question');
$category = $generator->create_question_category([]);
$createdquestion = $generator->create_question('oumatrix', 'animals_single',
['category' => $category->id, 'name' => 'Test question']);
$q = question_bank::load_question_data($createdquestion->id);
$expected = [
0 => [
1 => new question_possible_response('Bee: Insects', 1),
2 => new question_possible_response('Bee: Fish', 0),
3 => new question_possible_response('Bee: Birds', 0),
4 => new question_possible_response('Bee: Mammals', 0),
null => question_possible_response::no_response(),
],
1 => [
1 => new question_possible_response('Salmon: Insects', 0),
2 => new question_possible_response('Salmon: Fish', 1),
3 => new question_possible_response('Salmon: Birds', 0),
4 => new question_possible_response('Salmon: Mammals', 0),
null => question_possible_response::no_response(),
],
2 => [
1 => new question_possible_response('Seagull: Insects', 0),
2 => new question_possible_response('Seagull: Fish', 0),
3 => new question_possible_response('Seagull: Birds', 1),
4 => new question_possible_response('Seagull: Mammals', 0),
null => question_possible_response::no_response(),
],
3 => [
1 => new question_possible_response('Dog: Insects', 0),
2 => new question_possible_response('Dog: Fish', 0),
3 => new question_possible_response('Dog: Birds', 0),
4 => new question_possible_response('Dog: Mammals', 1),
null => question_possible_response::no_response(),
],
];
$this->assertEquals($expected, $this->qtype->get_possible_responses($q));
}

public function test_get_possible_responses_multiple(): void {
$this->resetAfterTest();
$generator = $this->getDataGenerator()->get_plugin_generator('core_question');
$category = $generator->create_question_category([]);
$createdquestion = $generator->create_question('oumatrix', 'food_multiple',
['category' => $category->id, 'name' => 'Test question']);
$q = question_bank::load_question_data($createdquestion->id);
$expected = [
0 => [
1 => new question_possible_response('Proteins: Chicken breast', 1),
2 => new question_possible_response('Proteins: Carrot', 0),
3 => new question_possible_response('Proteins: Salmon fillet', 1),
4 => new question_possible_response('Proteins: Asparagus', 0),
5 => new question_possible_response('Proteins: Olive oil', 0),
6 => new question_possible_response('Proteins: Steak', 1),
7 => new question_possible_response('Proteins: Potato', 0),
null => question_possible_response::no_response(),
],
1 => [
1 => new question_possible_response('Vegetables: Chicken breast', 0),
2 => new question_possible_response('Vegetables: Carrot', 1),
3 => new question_possible_response('Vegetables: Salmon fillet', 0),
4 => new question_possible_response('Vegetables: Asparagus', 1),
5 => new question_possible_response('Vegetables: Olive oil', 0),
6 => new question_possible_response('Vegetables: Steak', 0),
7 => new question_possible_response('Vegetables: Potato', 1),
null => question_possible_response::no_response(),
],
2 => [
1 => new question_possible_response('Fats: Chicken breast', 0),
2 => new question_possible_response('Fats: Carrot', 0),
3 => new question_possible_response('Fats: Salmon fillet', 0),
4 => new question_possible_response('Fats: Asparagus', 0),
5 => new question_possible_response('Fats: Olive oil', 1),
6 => new question_possible_response('Fats: Steak',0),
7 => new question_possible_response('Fats: Potato', 0),
null => question_possible_response::no_response(),
],
];
$this->assertEquals($expected, $this->qtype->get_possible_responses($q));
}

public function get_save_question_which() {
return [['animals_single'], ['oumatrix_multiple']];
}
Expand Down

0 comments on commit 1d43ba3

Please sign in to comment.