From b05659dde46897721711a805d63a9fb431cf30a3 Mon Sep 17 00:00:00 2001 From: ppichet Date: Fri, 18 Jan 2013 10:00:34 -0500 Subject: [PATCH] MDL-29691 Improve numerical format in multianswer Allow the use of , as decsep in multianswer numerical subquestions --- .../multianswer/edit_multianswer_form.php | 49 +++++++++++++------ question/type/multianswer/renderer.php | 2 +- 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/question/type/multianswer/edit_multianswer_form.php b/question/type/multianswer/edit_multianswer_form.php index f2cc2bfa486..9ea6c7b2ecf 100644 --- a/question/type/multianswer/edit_multianswer_form.php +++ b/question/type/multianswer/edit_multianswer_form.php @@ -26,6 +26,8 @@ defined('MOODLE_INTERNAL') || die(); +require_once($CFG->dirroot . '/question/type/numerical/questiontype.php'); + /** * Form for editing multi-answer questions. @@ -35,11 +37,11 @@ defined('MOODLE_INTERNAL') || die(); */ class qtype_multianswer_edit_form extends question_edit_form { - // $questiondisplay will contain the qtype_multianswer_extract_question from - // the questiontext + // The variable $questiondisplay will contain the qtype_multianswer_extract_question from + // the questiontext. public $questiondisplay; - // $savedquestiondisplay will contain the qtype_multianswer_extract_question - // from the questiontext in database + // The variable $savedquestiondisplay will contain the qtype_multianswer_extract_question + // from the questiontext in database. public $savedquestion; public $savedquestiondisplay; public $used_in_quiz = false; @@ -49,6 +51,9 @@ class qtype_multianswer_edit_form extends question_edit_form { public $nb_of_attempts = 0; public $confirm = 0; public $reload = false; + /** @var qtype_numerical_answer_processor used when validating numerical answers. */ + protected $ap = null; + public function __construct($submiturl, $question, $category, $contexts, $formeditable = true) { global $SESSION, $CFG, $DB; @@ -86,14 +91,14 @@ class qtype_multianswer_edit_form extends question_edit_form { // Make questiontext a required field for this question type. $mform->addRule('questiontext', null, 'required', null, 'client'); - // display the questions from questiontext; + // Display the questions from questiontext. if ($questiontext = optional_param_array('questiontext', false, PARAM_RAW)) { $this->questiondisplay = fullclone(qtype_multianswer_extract_question($questiontext)); } else { if (!$this->reload && !empty($this->savedquestiondisplay->id)) { - // use database data as this is first pass - // question->id == 0 so no stored datasets + // Use database data as this is first pass + // question->id == 0 so no stored datasets. $this->questiondisplay = fullclone($this->savedquestiondisplay); foreach ($this->questiondisplay->options->questions as $subquestion) { if (!empty($subquestion)) { @@ -261,7 +266,7 @@ class qtype_multianswer_edit_form extends question_edit_form { foreach ($question->options->questions as $key => $wrapped) { if (!empty($wrapped)) { // The old way of restoring the definitions is kept to gradually - // update all multianswer questions + // update all multianswer questions. if (empty($wrapped->questiontext)) { $parsableanswerdef = '{' . $wrapped->defaultmark . ':'; switch ($wrapped->qtype) { @@ -288,7 +293,7 @@ class qtype_multianswer_edit_form extends question_edit_form { $parsableanswerdef .= $subanswer->answer; } if (!empty($wrapped->options->tolerance)) { - // Special for numerical answers: + // Special for numerical answers. $parsableanswerdef .= ":{$wrapped->options->tolerance}"; // We only want tolerance for the first alternative, it will // be applied to all of the alternatives. @@ -300,7 +305,7 @@ class qtype_multianswer_edit_form extends question_edit_form { $separator = '~'; } $parsableanswerdef .= '}'; - // Fix the questiontext fields of old questions + // Fix the questiontext fields of old questions. $DB->set_field('question', 'questiontext', $parsableanswerdef, array('id' => $wrapped->id)); } else { @@ -312,7 +317,7 @@ class qtype_multianswer_edit_form extends question_edit_form { } } - // set default to $questiondisplay questions elements + // Set default to $questiondisplay questions elements. if ($this->reload) { if (isset($this->questiondisplay->options->questions)) { $subquestions = fullclone($this->questiondisplay->options->questions); @@ -321,7 +326,7 @@ class qtype_multianswer_edit_form extends question_edit_form { foreach ($subquestions as $subquestion) { $prefix = 'sub_'.$sub.'_'; - // validate parameters + // Validate parameters. $answercount = 0; $maxgrade = false; $maxfraction = -1; @@ -370,7 +375,7 @@ class qtype_multianswer_edit_form extends question_edit_form { if ($trimmedanswer !== '') { $answercount++; if ($subquestion->qtype == 'numerical' && - !(is_numeric($trimmedanswer) || $trimmedanswer == '*')) { + !($this->is_valid_number($trimmedanswer) || $trimmedanswer == '*')) { $this->_form->setElementError($prefix.'answer['.$key.']', get_string('answermustbenumberorstar', 'qtype_numerical')); @@ -423,6 +428,22 @@ class qtype_multianswer_edit_form extends question_edit_form { parent::set_data($question); } + /** + * Validate that a string is a nubmer formatted correctly for the current locale. + * @param string $x a string + * @return bool whether $x is a number that the numerical question type can interpret. + */ + protected function is_valid_number($x) { + if (is_null($this->ap)) { + $this->ap = new qtype_numerical_answer_processor(array()); + } + + list($value, $unit) = $this->ap->apply_units($x); + + return !is_null($value) && !$unit; + } + + public function validation($data, $files) { $errors = parent::validation($data, $files); @@ -451,7 +472,7 @@ class qtype_multianswer_edit_form extends question_edit_form { if ($trimmedanswer !== '') { $answercount++; if ($subquestion->qtype == 'numerical' && - !(is_numeric($trimmedanswer) || $trimmedanswer == '*')) { + !($this->is_valid_number($trimmedanswer) || $trimmedanswer == '*')) { $errors[$prefix.'answer['.$key.']'] = get_string('answermustbenumberorstar', 'qtype_numerical'); } diff --git a/question/type/multianswer/renderer.php b/question/type/multianswer/renderer.php index a24a4fd0006..a959080ebf0 100644 --- a/question/type/multianswer/renderer.php +++ b/question/type/multianswer/renderer.php @@ -194,7 +194,7 @@ class qtype_multianswer_textfield_renderer extends qtype_multianswer_subq_render $size = max($size, strlen(trim($ans->answer))); } $size = min(60, round($size + rand(0, $size*0.15))); - // The rand bit is to make guessing harder + // The rand bit is to make guessing harder. $inputattributes = array( 'type' => 'text', -- 2.43.0