diff --git a/classes/column.php b/classes/column.php index 217a6bf..b933de6 100644 --- a/classes/column.php +++ b/classes/column.php @@ -52,35 +52,35 @@ class column { * @param int $number * @param string $name */ - public function __construct(int $id, int $questionid = 0, int $number = 0, string $name = '') { + public function __construct(int $id = 0, int $questionid = 0, int $number = 0, string $name = '') { $this->questionid = $questionid; $this->number = $number; $this->name = $name; $this->id = $id; + //$this->column = $this->populate(); } - public function populate(stdClass $column) { - $this->column = $column; - $this->id = $column->id; - $this->questionid = $column->questionid; - $this->number = $column->number; - $this->name = $column->name; + private function populate(): ?stdClass { + if ($this->questionid && $this->number && $this->name) { + $column = new stdClass(); + $column->questionid = $this->questionid; + $column->number = $this->number; + $column->name = $this->name; + return $column; + } + return null; } /** * Return a column object * - * @param int $id + * @param string $name * @return stdClass * @throws \dml_exception */ - public function get_a_column_by_id(int $id): ?stdClass { - global $DB; - //if ($this->column->id === $id) { - // return $this->column; - //} - if ($column = $DB->get_record('qtype_oumatrix_columns', ['id' => $id])) { - return $column; + public function get_column_by_name(string $name): ?stdClass { + if ($name === $this->name) { + return $this->column; } return null; } diff --git a/classes/row.php b/classes/row.php index 88ecf5e..5576602 100644 --- a/classes/row.php +++ b/classes/row.php @@ -56,18 +56,20 @@ class row { /** * Construct the matrix object to be used by rows and colums objects. * + * @param int $id * @param int $questionid * @param int $numberofrows * @param int $numberofcolumns */ - public function __construct(int $id, int $questionid = 0, int $number = 0, string $name = '', array $correctanswers = [], string $feedback = '', int $feedbackformat = 1) { - $this->id = $id; + public function __construct(int $id = 0, int $questionid = 0, int $number = 0, string $name = '', array $correctanswers = [], + string $feedback = '', int $feedbackformat = 0) { $this->questionid = $questionid; $this->number = $number; $this->name = $name; $this->correctanswers = $correctanswers; $this->feedback = $feedback; $this->feedbackformat = $feedbackformat; + $this->id = $id; } /** @@ -84,22 +86,26 @@ public function get_a_row_by_id(int $id): ?stdClass { return null; } - public function create_default_row(int $questionid, int $number = 1, string $name = 'row', string $feedback = '', int $feedbackformat = 2) { + public function create_default_row(int $questionid, int $number = 1, string $name = 'row', array $correctanswers = [], + string $feedback = '', int $feedbackformat = 0) { global $DB; $row = new stdClass(); $row->questionid = $questionid; $row->number = $number; $row->name = $name; + $row->correctanswers = json_encode($correctanswers); $row->feedback = $feedback; $row->feedbackformat = $feedbackformat; return $row; } - public function create_row(int $questionid, int $number = 1, string $name = 'row', string $feedback = '', int $feedbackformat = 2) { + public function create_row(int $questionid, int $number = 1, string $name = 'row', array $correctanswers = [], + string $feedback = '', int $feedbackformat = 0) { $row = new stdClass(); $row->questionid = $questionid; $row->number = $number; $row->name = $name; + $row->correctanswers = json_encode($correctanswers); $row->feedback = $feedbackformat; $row->feedbackformat = $feedbackformat; return $row; @@ -112,27 +118,6 @@ public function setCorrectanswers(array $correctanswers): void { $this->correctanswers = $correctanswers; } - /** - * Create default rows. - * - * @param int $questionid - * @param int $rowstart - * @param int $numberofrows - * @return void - * @throws \dml_exception - */ - public function create_default_rows(int $questionid, int $rowstart = 1, int $numberofrows = 0) { - global $DB; - if ($numberofrows === 0) { - $numberofrows = $this->numberofrows; - } - for ($r = $rowstart; $r <= $numberofrows; $r++) { - $row = $this->create_a_default_row($questionid, $r, 'r'.$r, ); - $row->id = $DB->insert_record('qtype_oumatrix_rows', $row); - $this->rows[] = $row; - } - } - /** * Retunr a row. * @@ -160,26 +145,6 @@ public function delete_a_row(int $rownumber) { $DB->delete_records('qtype_oumatrix_rows', ['questionid' => $this->questionid, 'number' => $rownumber]); } - /** - * Return an array of rows. - * - * @param int $numberofrows - * @return array|null - * @throws \dml_exception - */ - public function get_rows(int $numberofrows = 0): ?array { - $rows = []; - // If there is no changes in number of rows - if ($this->numberofrows === $numberofrows) { - for ($r = 1; $r <= $numberofrows; $r++) { - $rows[] = $this->get_a_row($r); - } - return $rows; - } else { - return $this->create_default_rows($this->questionid, 1); - } - } - /** * @return int */ diff --git a/edit_oumatrix_form.php b/edit_oumatrix_form.php index 0170a7e..1fb0479 100644 --- a/edit_oumatrix_form.php +++ b/edit_oumatrix_form.php @@ -26,8 +26,6 @@ use \qtype_oumatirx\row; use \qtype_oumatirx\column; -defined('MOODLE_INTERNAL') || die(); - /** * Editing form for the oumatrix question type. * @@ -36,46 +34,29 @@ */ class qtype_oumatrix_edit_form extends question_edit_form { - /** - * The default starting number of columns (answers). - */ - protected const COL_NUM_START = 3; + /** The default starting number of columns (answers). */ + private const COL_NUM_START = 3; - /** - * The number of columns (answers) that get added at a time. - */ - protected const COL_NUM_ADD = 2; + /** The number of columns (answers) that get added at a time. */ + private const COL_NUM_ADD = 2; - /** - * The default starting number of rows (question row). - */ - protected const ROW_NUM_START = 4; - - /** - * The number of rows (question row) that get added at a time. - */ - protected const ROW_NUM_ADD = 2; + /**The default starting number of rows (question row). */ + private const ROW_NUM_START = 4; - /** @var int Number of rows. */ - protected $numrows; + /** The number of rows (question row) that get added at a time.*/ + private const ROW_NUM_ADD = 2; /** @var int Number of columns. */ - protected $numcolumns; - - /** @var array The grid options. */ - protected $gridoptions; + private $numcolumns; - /** @var object The matrix row object. */ - protected $rowinfo = null; - - /** @var object The matrix column (answer) object. */ - protected $columninfo = null; + /** @var int Number of rows. */ + private $numrows; /** @var string answermode of rows. */ - protected $inputtype; + private $inputtype; /** @var string grading method of rows. */ - protected $grademethod; + private $grademethod; /** * Add question-type specific form fields. @@ -86,7 +67,7 @@ protected function definition_inner($mform) { // Sett the number of columns and rows.self::COL_NUM_START; $this->numcolumns = $this->numcolumns ?? self::COL_NUM_START; - $this->numrows = $this->numrows ??self::ROW_NUM_START; + $this->numrows = $this->numrows ?? self::ROW_NUM_START; $qtype = 'qtype_oumatrix'; $answermodemenu = [ @@ -162,24 +143,24 @@ public function qtype() { public function data_preprocessing($question) { $question = parent::data_preprocessing($question); - //$question = $this->data_preprocessing_answers($question, true); $question = $this->data_preprocessing_combined_feedback($question, true); $question = $this->data_preprocessing_hints($question, true, true); $question = $this->data_preprocessing_options($question,); + print_object('data_preprocessing() 1111111111111111111111'); + print_object($question); + print_object('data_preprocessing() 222222222222222222222'); return $question; } - protected function data_preprocessing_options($question) { + function data_preprocessing_options($question) { if (empty($question->options)) { return $question; } + $question->inputtype = $question->options->inputtype; + $question->grademethod = $question->options->grademethod; + $question->shuffleanswers = $question->options->shuffleanswers; + $question->shownumcorrect = $question->options->shownumcorrect; - if (!empty($question->options)) { - $question->inputtype = $question->options->inputtype; - $question->grademethod = $question->options->grademethod; - $question->shuffleanswers = $question->options->shuffleanswers; - $question->shownumcorrect = $question->options->shownumcorrect; - } $this->data_preprocessing_columns($question); $this->data_preprocessing_rows($question); return $question; @@ -191,16 +172,18 @@ protected function data_preprocessing_options($question) { * @param object $question The data being passed to the form. * @return object The modified data. */ - protected function data_preprocessing_columns($question) { + private function data_preprocessing_columns($question) { if (empty($question->options->columns)) { return $question; } - $question->columnname = []; foreach ($question->options->columns as $column) { + if (trim($column->name ?? '') === '') { + continue; + } $question->columnname[] = $column->name; } - //$this->numcolumns = count($question->options->columns); + //$this->numcolumns = count($question->columnname); return $question; } @@ -210,8 +193,7 @@ protected function data_preprocessing_columns($question) { * @param object $question The data being passed to the form. * @return object The modified data. */ - protected function data_preprocessing_rows($question) { - $feedback = []; + private function data_preprocessing_rows($question) { if (empty($question->options->rows)) { return $question; } @@ -227,6 +209,7 @@ protected function data_preprocessing_rows($question) { $itemid = (int)$row->id ?? null; // Prepare the feedback editor to display files in draft area. + $feedback = []; $feedbackdraftitemid = file_get_submitted_draft_itemid('feedback['.$key.']'); $feedback[$key]['text'] = file_prepare_draft_area( $feedbackdraftitemid, @@ -244,7 +227,6 @@ protected function data_preprocessing_rows($question) { $key++; } $question->feedback = $feedback; - //$this->numrows = count($question->options->rows); return $question; } @@ -255,10 +237,10 @@ protected function format_correct_answers_multiple($rownumber, $answers, $questi $rowanswerslabel = "rowanswers".$anslabel; $question->$rowanswerslabel[$rownumber] = $decodedanswers[$column->name]; } - } + } protected function get_hint_fields($withclearwrong = false, $withshownumpartscorrect = false) { - list($repeated, $repeatedoptions) = parent::get_hint_fields($withclearwrong, $withshownumpartscorrect); + [$repeated, $repeatedoptions] = parent::get_hint_fields($withclearwrong, $withshownumpartscorrect); $repeatedoptions['hintclearwrong']['disabledif'] = ['single', 'eq', 1]; $repeatedoptions['hintshownumcorrect']['disabledif'] = ['single', 'eq', 1]; return [$repeated, $repeatedoptions]; @@ -272,8 +254,7 @@ protected function get_hint_fields($withclearwrong = false, $withshownumpartscor * @param bool $withshownumpartscorrect Show number correct. * @return object The modified data. */ - protected function data_preprocessing_hints($question, $withclearwrong = false, - $withshownumpartscorrect = false) { + protected function data_preprocessing_hints($question, $withclearwrong = false, $withshownumpartscorrect = false) { if (empty($question->hints)) { return $question; } @@ -315,8 +296,6 @@ protected function add_per_column_fields(MoodleQuickForm $mform, string $label, protected function get_per_column_fields($mform, $label, $repeatedoptions, $columns) { $repeated = []; - // $repeated[] = $mform->createElement('editor', 'columnname', $label, ['rows' => 2], $this->editoroptions); - // TODO: If needed replace the line below the line above. $repeated[] = $mform->createElement('text', 'columnname', $label, ['size' => 40]); $mform->setType('columnname', PARAM_RAW); $repeatedoptions['column']['type'] = PARAM_RAW; @@ -358,23 +337,18 @@ protected function add_per_row_fields(MoodleQuickForm $mform, string $label, * @param array $rows * @return array */ - protected function get_per_row_fields(MoodleQuickForm $mform, string $label, array &$repeatedoptions, array &$rows): array { - //print_object($this->question); + protected function get_per_row_fields(MoodleQuickForm $mform, string $label, array $repeatedoptions, array $rows): array { $repeated = []; $rowoptions = []; - // $rowoptions[] = $mform->createElement('editor', 'rowname', $label, ['rows' => 2], $this->editoroptions); - // TODO: If needed replace the line below the line above. $rowoptions[] = $mform->createElement('text', 'rowname', 'Name', ['size' => 40]); - // Get the list answer input type (radio buttons or checkbexs). - //$inputtype = $this->question->options->inputtype ?? get_config('qtype_oumatrix', 'inputtype'); - for ($i = 1; $i <= $this->numcolumns; $i++) { - $anslabel = get_string('a', 'qtype_oumatrix', $i); + // Get the list answer input type (radio buttons or checkboxes). + for ($i = 0; $i < $this->numcolumns; $i++) { + $anslabel = get_string('a', 'qtype_oumatrix', $i+1); if ($this->inputtype === 'single') { - $rowoptions[] = $mform->createElement('radio', 'rowanswers', '', $anslabel, $anslabel); + $rowoptions[] = $mform->createElement('radio', "rowanswers$anslabel", '', $anslabel); } else { - $rowoptions[] = $mform->createElement('checkbox', "rowanswers$anslabel",'', $anslabel); - //$rowoptions[] = $mform->addElement('advcheckbox', "rowanswers$anslabel",'', $anslabel,"", array(0, 1)); + $rowoptions[] = $mform->createElement('checkbox', "rowanswers$anslabel", '', $anslabel); } } $rowoptions[] = $mform->createElement('editor', 'feedback', @@ -382,6 +356,7 @@ protected function get_per_row_fields(MoodleQuickForm $mform, string $label, arr $repeated[] = $mform->createElement('group', 'rowoptions', $label, $rowoptions, null, false); $mform->setType('rowname', PARAM_RAW); $repeatedoptions['row']['type'] = PARAM_RAW; + //$repeatedoptions['row']['correctanswers'] = PARAM_RAW; $rows = 'rows'; return $repeated; } diff --git a/lang/en/qtype_oumatrix.php b/lang/en/qtype_oumatrix.php index d546218..1059e48 100644 --- a/lang/en/qtype_oumatrix.php +++ b/lang/en/qtype_oumatrix.php @@ -41,7 +41,7 @@ All or nothing: students must get every response correct, otherwise they score zero.'; $string['gradepartialcredit'] = 'Give partial credit'; $string['gradeallornothing'] = 'All-or-nothing'; -$string['notenoughquestions'] = 'This type of question requires at least {$a} word'; +$string['notenoughanswercols'] = 'This type of question requires at least {$a} answers columns'; $string['pluginname'] = 'Matrix'; $string['pluginname_help'] = 'Creating a matrix question requires you to specify column headings (values) to row headings (items). For example, you might ask students to classify an item as animal, vegetable, or mineral using Single Choice. You can use Multiple Response so that several values may apply to an item.'; $string['pluginnameadding'] = 'Adding a Matrix question'; diff --git a/lib.php b/lib.php index a6d1362..018a705 100644 --- a/lib.php +++ b/lib.php @@ -22,8 +22,6 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -defined('MOODLE_INTERNAL') || die(); - /** * Checks file access for oumatrix questions. * diff --git a/question.php b/question.php index a6bf2c4..65831d4 100644 --- a/question.php +++ b/question.php @@ -71,14 +71,8 @@ public function check_file_access($qa, $options, $component, $filearea, $args, $ } public function is_same_response(array $prevresponse, array $newresponse): bool { - foreach ($this->answers as $key => $notused) { - $fieldname = $this->field($key); - if (!question_utils::arrays_same_at_key( - $prevresponse, $newresponse, $fieldname)) { - return false; - } - } - return true; + // TODO: + return false; } /** @@ -118,13 +112,10 @@ public function summarise_response(array $response): ?string { } public function is_complete_response(array $response): bool { - $filteredresponse = $this->remove_blank_words_from_response($response); - return count($this->answers) === count($filteredresponse); } public function is_gradable_response(array $response): bool { - $filteredresponse = $this->remove_blank_words_from_response($response); - return count($filteredresponse) > 0; + } public function get_validation_error(array $response): string { @@ -236,18 +227,6 @@ public function calculate_fraction_for_answer(answer $answer, string $responsewo } } - /** - * Filter out blank words from a response. - * - * @param array $response The answers list. - * @return array The filtered list. - */ - private function remove_blank_words_from_response(array $response): array { - return array_filter($response, function(string $responseword) { - return core_text::strlen(trim(str_replace('_', '', $responseword))) > 0; - }); - } - } /** @@ -260,11 +239,13 @@ public function get_renderer(moodle_page $page) { } public function get_expected_data(): array { - //$rows = new \qtype_oumatrix\oumatirx_info(); + $rows = $this->get_question_summary(); + print_object('get_question_summary() -----------'); + print_object($rows); $response = []; - for ($i = 0; $i < count($this->answers); $i++) { - $response[$this->field($i)] = PARAM_RAW_TRIMMED; - } + //for ($i = 0; $i < count($this->answers); $i++) { + // $response[$this->field($i)] = PARAM_RAW_TRIMMED; + //} return $response; } @@ -279,14 +260,7 @@ public function check_file_access($qa, $options, $component, $filearea, $args, $ } public function is_same_response(array $prevresponse, array $newresponse): bool { - foreach ($this->answers as $key => $notused) { - $fieldname = $this->field($key); - if (!question_utils::arrays_same_at_key( - $prevresponse, $newresponse, $fieldname)) { - return false; - } - } - return true; + return parent::is_same_response($prevresponse, $newresponse); } /** @@ -301,9 +275,9 @@ protected function field(int $key): string { public function get_correct_response(): ?array { $response = []; - for ($i = 0; $i < count($this->answers); $i++) { - $response[$this->field($i)] = $this->answers[$i]->answer; - } + //for ($i = 0; $i < count($this->answers); $i++) { + // $response[$this->field($i)] = $this->answers[$i]->answer; + //} return $response; } @@ -326,13 +300,11 @@ public function summarise_response(array $response): ?string { } public function is_complete_response(array $response): bool { - $filteredresponse = $this->remove_blank_words_from_response($response); - return count($this->answers) === count($filteredresponse); + return false; } public function is_gradable_response(array $response): bool { - $filteredresponse = $this->remove_blank_words_from_response($response); - return count($filteredresponse) > 0; + return true; } public function get_validation_error(array $response): string { @@ -446,18 +418,6 @@ public function calculate_fraction_for_answer(answer $answer, string $responsewo } } } - - /** - * Filter out blank words from a response. - * - * @param array $response The answers list. - * @return array The filtered list. - */ - private function remove_blank_words_from_response(array $response): array { - return array_filter($response, function(string $responseword) { - return core_text::strlen(trim(str_replace('_', '', $responseword))) > 0; - }); - } } /** @@ -471,18 +431,10 @@ public function get_renderer(moodle_page $page) { public function get_expected_data(): array { - //$rows = new \qtype_oumatrix\oumatirx_info(); $response = []; - /*foreach ($this->rows as $key => $row) { - //$newrow = $this->qtype->make_row($row); - for ($i = 0; $i < count($row->correctanswers); $i++) { - $response[$key][$i] = PARAM_INT; - } - //$response[$key][$row->correctAnswers] = PARAM_INT; - }*/ - /*for ($i= 0; $i < count($this->answers); $i++) { - $response[$this->field($i)] = PARAM_RAW_TRIMMED; - }*/ + print_object('get_expected_data() -----------------'); + print_object($this->rows); + foreach ($this->rows as $row) { //$newrow = $this->make_row($row); @@ -519,11 +471,23 @@ public function check_file_access($qa, $options, $component, $filearea, $args, $ } public function is_same_response(array $prevresponse, array $newresponse): bool { - foreach ($this->answers as $key => $notused) { - $fieldname = $this->field($key); - if (!question_utils::arrays_same_at_key( - $prevresponse, $newresponse, $fieldname)) { - return false; + if (!$this->is_complete_response($prevresponse)) { + $prevresponse = []; + } + if (!$this->is_complete_response($newresponse)) { + $newresponse = []; + } + foreach ($this->rows as $k => $row) { + print_object('$row -------------'); + print_object($row); + // TODO: + foreach ($row->correctanswers as $key =>$value) { + $fieldname = $this->field($key); + if (!question_utils::arrays_same_at_key( + $prevresponse, $newresponse, $fieldname)) { + return false; + } + return question_utils::arrays_same_at_key($prevresponse, $newresponse, 'answer'); } } return true; @@ -542,29 +506,44 @@ protected function field(int $key): string { public function get_correct_response(): ?array { - $response = []; - print_object("In get_correct_response^^^^^^^^^^^^^^^^^^^^"); - for ($i = 0; $i < count($this->rows); $i++) { - foreach($this->columns as $key => $column) { - $anslabel = get_string('a', 'qtype_oumatrix', $column->number + 1); - $rowanswerslabel = "rowanswers".$anslabel."_".$i; - //$correctAnswers[$rownumber] = $decodedanswers[$column->name]; - //$rowanswerslabel[$i] = 1; - $response[$rowanswerslabel] = $this->rows[$i]->correctanswers[$column->number]; - //$response->$rowanswerslabel[$i] = $this->rows[$i]->correctanswers[$column->number]; + $correctplaces = []; + foreach ($this->rows as $rkey => $row) { + print_object('$row -------------'); + print_object($row); + foreach ($row->correctanswers as $cakey => $value) { + if ($value == 1) { + $correctplaces[$rkey][$cakey] = $value; + } } - //$response[$this->field($i)] = $this->answers[$i]->answer; } - //for ($i = 0; $i < count($this->answers); $i++) { - // $response[$this->field($i)] = $this->answers[$i]->answer; + print_object('Fill correct responses -------------------------'); + print_object($correctplaces); + // TODO: we get the correct values, but we need to pass it to the checkboxes. + return $correctplaces; + + //print_object("In get_correct_response^^^^^^^^^^^^^^^^^^^^"); + //for ($i = 0; $i < count($this->rows); $i++) { + // foreach($this->columns as $key => $column) { + // $anslabel = get_string('a', 'qtype_oumatrix', $column->number + 1); + // $rowanswerslabel = "rowanswers".$anslabel."_".$i; + // //$correctAnswers[$rownumber] = $decodedanswers[$column->name]; + // //$rowanswerslabel[$i] = 1; + // $response[$rowanswerslabel] = $this->rows[$i]->correctanswers[$column->number]; + // //$response->$rowanswerslabel[$i] = $this->rows[$i]->correctanswers[$column->number]; + // } + // //$response[$this->field($i)] = $this->answers[$i]->answer; //} - print_object($response); - return $response; + ////for ($i = 0; $i < count($this->answers); $i++) { + //// $response[$this->field($i)] = $this->answers[$i]->answer; + ////} + //print_object($response); + //return $response; } public function summarise_response(array $response): ?string { $responsewords = []; - foreach ($this->answers as $key => $answer) { + foreach ($this->rows as $key => $row) { + //TODO: $fieldname = $this->field($key); if (array_key_exists($fieldname, $response)) { $responseword = str_replace('_', ' ', $response[$fieldname]); @@ -581,20 +560,18 @@ public function summarise_response(array $response): ?string { } public function is_complete_response(array $response): bool { - $filteredresponse = $this->remove_blank_words_from_response($response); - return count($this->answers) === count($filteredresponse); + return false; } public function is_gradable_response(array $response): bool { - $filteredresponse = $this->remove_blank_words_from_response($response); - return count($filteredresponse) > 0; + return true; } public function get_validation_error(array $response): string { if ($this->is_complete_response($response)) { return ''; } - return get_string('pleaseananswerallparts', 'qtype_crossword'); + return get_string('pleaseananswerallrows', 'qtype_oumatrix'); } public function grade_response(array $response): array { @@ -681,34 +658,4 @@ public function is_partial_fraction(qtype_crossword\answer $answer, string $resp return $this->accentgradingtype === \qtype_crossword::ACCENT_GRADING_PENALTY && $answer->is_wrong_accents($responseword); } - - /** - * Calculate fraction of answer. - * - * @param answer $answer One of the clues. - * @param string $responseword The the response given to that clue. - * @return float the fraction for that word. - */ - public function calculate_fraction_for_answer(answer $answer, string $responseword): float { - - if ($this->is_full_fraction($answer, $responseword)) { - return 1; - } else if ($this->is_partial_fraction($answer, $responseword)) { - return 1 - $this->accentpenalty; - } else { - return 0; - } - } - - /** - * Filter out blank words from a response. - * - * @param array $response The answers list. - * @return array The filtered list. - */ - private function remove_blank_words_from_response(array $response): array { - return array_filter($response, function(string $responseword) { - return core_text::strlen(trim(str_replace('_', '', $responseword))) > 0; - }); - } } diff --git a/questiontype.php b/questiontype.php index e06bf2f..9b0b80a 100644 --- a/questiontype.php +++ b/questiontype.php @@ -39,18 +39,20 @@ class qtype_oumatrix extends question_type { public function get_question_options($question) { - global $DB; + global $DB, $OUTPUT;; parent::get_question_options($question); - $question->options = $DB->get_record('qtype_oumatrix_options', ['questionid' => $question->id]); - if ($question->options === false) { - // If this has happened, then we have a problem. - // For the user to be able to edit or delete this question, we need options. - debugging("Question ID {$question->id} was missing an options record. Using default.", DEBUG_DEVELOPER); - $question->options = $this->create_default_options($question); + if (!$question->options = $DB->get_record('qtype_oumatrix_options', ['questionid' => $question->id])) { + $question->options = $this->create_default_options($question); } - $question->options->columns = $DB->get_records('qtype_oumatrix_columns', ['questionid' => $question->id]); - $question->options->rows = $DB->get_records('qtype_oumatrix_rows', ['questionid' => $question->id]); - parent::get_question_options($question); + if (!$question->options->columns = $DB->get_records('qtype_oumatrix_columns', ['questionid' => $question->id])) { + echo $OUTPUT->notification('Error: Missing question columns!'); + return false; + } + if (!$question->options->rows = $DB->get_records('qtype_oumatrix_rows', ['questionid' => $question->id])) { + echo $OUTPUT->notification('Error: Missing question rows!'); + return false; + } + return true; } /** @@ -90,31 +92,36 @@ public function save_defaults_for_new_questions(stdClass $fromform): void { public function save_question($question, $form) { $question = parent::save_question($question, $form); - return $question; } public function save_question_options($question) { global $DB; $context = $question->context; - + $result = new stdClass(); $options = $DB->get_record('qtype_oumatrix_options',['questionid' => $question->id]); if (!$options) { + $config = get_config('qtype_oumatrix'); $options = new stdClass(); $options->questionid = $question->id; + $options->inputtype = $config->inputtype; + $options->grademethod = $config->grademethod; + $options->shuffleanswers = $config->shuffleanswers; $options->correctfeedback = ''; $options->partiallycorrectfeedback = ''; $options->incorrectfeedback = ''; + $options->shownumcorrect = 0; $options->id = $DB->insert_record('qtype_oumatrix_options', $options); } + $options->questionid = $question->id; $options->inputtype = $question->inputtype; $options->grademethod = $question->grademethod; $options->shuffleanswers = $question->shuffleanswers; $options = $this->save_combined_feedback_helper($options, $question, $context, true); $DB->update_record('qtype_oumatrix_options', $options); - $this->save_rows($question); $this->save_columns($question); + $this->save_rows($question); $this->save_hints($question, true); } @@ -132,24 +139,24 @@ public function save_columns($formdata) { $answercount++; } } - if ($answercount < 1) { - $result->error = get_string('notenoughquestions', 'qtype_oumatrix', '1'); + if ($answercount < 2) { + $result->error = get_string('notenoughanswercols', 'qtype_oumatrix', '2'); return $result; } - // Insert all the new words. + // Insert column input data. for ($i = 0; $i < $numcolumns; $i++) { if (trim($formdata->columnname[$i]) === '') { continue; } // Update an existing word if possible. - $questioncolumn = array_shift($oldcolumns); - if (!$questioncolumn) { - $questioncolumn = new stdClass(); - $questioncolumn->questionid = $formdata->id; - $questioncolumn->number = $i; - $questioncolumn->name = $formdata->columnname[$i]; - $questioncolumn->id = $DB->insert_record('qtype_oumatrix_columns', $questioncolumn); + $column = array_shift($oldcolumns); + if (!$column) { + $column = new stdClass(); + $column->questionid = $formdata->id; + $column->number = $i; + $column->name = $formdata->columnname[$i]; + $column->id = $DB->insert_record('qtype_oumatrix_columns', $column); } // Remove old columns. @@ -157,7 +164,7 @@ public function save_columns($formdata) { $ids = array_map(function($question) { return $question->id; }, $oldcolumns); - list($idssql, $idsparams) = $DB->get_in_or_equal($ids, SQL_PARAMS_QM); + [$idssql, $idsparams] = $DB->get_in_or_equal($ids); //$fs->delete_area_files_select($context->id, 'qtype_crossword', 'feedback', "id $idssql", $idsparams); //$fs->delete_area_files_select($context->id, 'qtype_crossword', 'clue', "id $idssql", $idsparams); $DB->delete_records_select('qtype_oumatrix_columns', "id $idssql", $idsparams); @@ -166,42 +173,35 @@ public function save_columns($formdata) { } public function save_rows($formdata) { global $DB; - print_object("11111111111111111111111111111111111111111111111"); - print_object($formdata); $context = $formdata->context; $result = new stdClass(); - // Old records. - $oldrowquestions = $DB->get_records('qtype_oumatrix_rows', - ['questionid' => $formdata->id], 'id ASC'); + $oldrows = $DB->get_records('qtype_oumatrix_rows', ['questionid' => $formdata->id], 'id ASC'); - $numquestions = count($formdata->rowname); + $numrows = count($formdata->rowname); - // Insert all the new words. - for ($i = 0; $i < $numquestions; $i++) { + // Insert row input data. + for ($i = 0; $i < $numrows; $i++) { if (trim($formdata->rowname[$i] ?? '') === '') { continue; } // Update an existing word if possible. - $questionrow = array_shift($oldrowquestions); + $questionrow = array_shift($oldrows); if (!$questionrow) { $questionrow = new stdClass(); $questionrow->questionid = $formdata->id; $questionrow->number = $i; $questionrow->name = $formdata->rowname[$i]; // Prepare correct answers. - $json = []; - //$json['answertext'] = $formdata->columnname[$i]; - //$questionrow->correctanswers = json_encode($json); if($formdata->inputtype == 'multiple') { - for ($j = 0; $j < count($formdata->columnname); $j++) { - $anslabel = get_string('a', 'qtype_oumatrix', $j + 1); - $rowanswerslabel = "rowanswers".$anslabel; + for ($c = 0; $c < count($formdata->columnname); $c++) { + $anslabel = get_string('a', 'qtype_oumatrix', $c + 1); + $rowanswerslabel = "rowanswers". $anslabel; if (!array_key_exists($i, $formdata->$rowanswerslabel)) { - $answerslist[$formdata->columnname[$j]] = "0"; + $answerslist[$formdata->columnname[$c]] = "0"; continue; } - $answerslist[$formdata->columnname[$j]] = $formdata->$rowanswerslabel[$i]; + $answerslist[$formdata->columnname[$c]] = $formdata->$rowanswerslabel[$i]; } $questionrow->correctanswers = json_encode($answerslist); } else { @@ -216,11 +216,11 @@ public function save_rows($formdata) { } // Remove old rows. $fs = get_file_storage(); - if ($oldrowquestions) { + if ($oldrows) { $ids = array_map(function($question){ return $question->id; - }, $oldrowquestions); - list($idssql, $idsparams) = $DB->get_in_or_equal($ids, SQL_PARAMS_QM); + }, $oldrows); + [$idssql, $idsparams] = $DB->get_in_or_equal($ids); //$fs->delete_area_files_select($context->id, 'qtype_crossword', 'feedback', "id $idssql", $idsparams); //$fs->delete_area_files_select($context->id, 'qtype_crossword', 'clue', "id $idssql", $idsparams); $DB->delete_records_select('qtype_oumatrix_rows', "id $idssql", $idsparams); @@ -330,10 +330,9 @@ protected function initialise_question_instance(question_definition $question, $ $question->inputtype = $questiondata->options->inputtype; $question->grademethod = $questiondata->options->grademethod; $question->shuffleanswers = $questiondata->options->shuffleanswers; - $this->initialise_question_rows($question, $questiondata); $this->initialise_question_columns($question, $questiondata); + $this->initialise_question_rows($question, $questiondata); $this->initialise_combined_feedback($question, $questiondata, true); - $this->initialise_question_answers($question, $questiondata, false); } public function delete_question($questionid, $contextid) { @@ -424,11 +423,9 @@ protected function initialise_question_rows(question_definition $question, * @param question_definition $question the question_definition we are creating. * @param object $questiondata the question data loaded from the database. */ - protected function initialise_question_columns(question_definition $question, - $questiondata) { + protected function initialise_question_columns(question_definition $question, $questiondata) { if (!empty($questiondata->options->columns)) { foreach ($questiondata->options->columns as $column) { - //$newcolumn = $this->make_column($column); $question->columns[] = $this->make_column($column); } } @@ -600,20 +597,3 @@ public function adjust_display_options(question_display_options $options) { $options->suppressrowfeedback = !$this->showrowfeedback; } } - - - - - - - - - - - - - - - - - diff --git a/renderer.php b/renderer.php index b338b21..6f27702 100644 --- a/renderer.php +++ b/renderer.php @@ -103,11 +103,6 @@ public function formulation_and_controls(question_attempt $qa, $result .= html_writer::start_tag('div', array('class' => 'answer')); - foreach ($question->columns as $key => $value) { - $colname = $value->getName(); - $result .= html_writer::tag('span', $colname); - } - $result .= $this->get_matrix($question); /*$result .= "\n"; $inputtype = $this->get_input_type(); @@ -234,34 +229,33 @@ public function formulation_and_controls(question_attempt $qa, } public function get_matrix($question) { - $columns = ['Copper', 'Gold', 'Iron']; - $rows = ['Is a good electrical', 'Is a good insulator', 'Can be magnetised']; print_object("*******************************************"); print_object($question); $caption = "Matrix question"; $colname[] = null; $table = " - + "; foreach ($question->columns as $key => $value) { $colname[$key] = $value->getName(); - $table .= ""; - } + $table .= ""; + } $table .= " "; $i = 0; foreach ($question->rows as $key => $value) { $rowname = $value->getName(); - $table .= ""; + $rowid = 'row_'. $key; + $table .= ""; for ($j = 0; $j < count($colname); $j++) { if($question->inputtype == 'single') { - $table .= ""; + $table .= ""; } else { - $table .= ""; + $table .= ""; } } $i++; @@ -275,36 +269,6 @@ protected function number_html($qnum) { return $qnum . '. '; } - /** - * @param int $num The number, starting at 0. - * @param string $style The style to render the number in. One of the - * options returned by {@link qtype_multichoice:;get_numbering_styles()}. - * @return string the number $num in the requested style. - */ - protected function number_in_style($num, $style) { - switch($style) { - case 'abc': - $number = chr(ord('a') + $num); - break; - case 'ABCD': - $number = chr(ord('A') + $num); - break; - case '123': - $number = $num + 1; - break; - case 'iii': - $number = question_utils::int_to_roman($num + 1); - break; - case 'IIII': - $number = strtoupper(question_utils::int_to_roman($num + 1)); - break; - case 'none': - return ''; - default: - return 'ERR'; - } - return $this->number_html($number); - } public function specific_feedback(question_attempt $qa) { return $this->combined_feedback($qa); diff --git a/styles.css b/styles.css index c9ca2ee..130936d 100644 --- a/styles.css +++ b/styles.css @@ -1,13 +1,29 @@ /* Styles for oumatrix. */ .que.oumatrix .question_text { - background-color: white; + background-color: lightyellow; } -/* Styles for audio widgets. */ -#fitem_id_Row1 { - width: 100px; - margin: 0; +.que.oumatrix .table_caption { + font-size: medium; + text-align: center; +} + +.que.oumatrix .answer_col { + text-align: center; + margin-left: 2em; } +.que.oumatrix input[type="radio"], +.que.oumatrix input[type="checkbox"] { + box-sizing: border-box; + margin-left: 2.5em; + margin-bottom: 0.5m; +} + +.que.oumatrix .question_row { + text-align: left; + margin-right: 0.1em; +} + /* .que.matrix table { diff --git a/tests/behat/add.feature b/tests/behat/add.feature index e93b654..40b8e32 100644 --- a/tests/behat/add.feature +++ b/tests/behat/add.feature @@ -27,12 +27,12 @@ Feature: Test creating a Matrix question | Answer mode | Single choice | | Marking mode | Give partial credit | | id_columnname_0 | salmon | - | id_rowanswers_0_A1 | 1 | | id_columnname_1 | chicken | - | id_rowanswers_1_A2 | 1 | | id_columnname_2 | lamb | | id_rowname_0 | Is a fish | + | id_rowanswers_0_A1 | 1 | | id_rowname_1 | Is a bird | + | id_rowanswers_1_A2 | 1 | | id_rowname_2 | Is a mammal | | id_rowanswers_2_A3 | 1 | | For any correct response | Correct feedback |
" .$caption. "$caption
$colname[$key]$colname[$key]
$rowname$rowname