mirror of
https://github.com/moodle/moodle.git
synced 2025-03-07 01:10:02 +01:00
MDL-20636 Fix the numerical qtype editing form.
This commit is contained in:
parent
397bd29549
commit
1fa3936440
@ -27,7 +27,7 @@
|
||||
<FIELD NAME="instructionsformat" TYPE="int" LENGTH="2" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" PREVIOUS="instructions" NEXT="showunits"/>
|
||||
<FIELD NAME="showunits" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" COMMENT="display units as multichoice" PREVIOUS="instructionsformat" NEXT="unitsleft"/>
|
||||
<FIELD NAME="unitsleft" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" COMMENT="display the unit at left as in $1.00" PREVIOUS="showunits" NEXT="unitgradingtype"/>
|
||||
<FIELD NAME="unitgradingtype" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" COMMENT="0 no penalty, 1 total grade, 2 response grade" PREVIOUS="unitsleft" NEXT="unitpenalty"/>
|
||||
<FIELD NAME="unitgradingtype" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" COMMENT="0 no penalty, 1 response grade, 2 total grade" PREVIOUS="unitsleft" NEXT="unitpenalty"/>
|
||||
<FIELD NAME="unitpenalty" TYPE="number" LENGTH="12" NOTNULL="true" UNSIGNED="true" DEFAULT="0.1" SEQUENCE="false" DECIMALS="7" PREVIOUS="unitgradingtype"/>
|
||||
</FIELDS>
|
||||
<KEYS>
|
||||
|
@ -34,12 +34,22 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @copyright 2007 Jamie Pratt me@jamiep.org
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class question_edit_numerical_form extends question_edit_form {
|
||||
class qtype_numerical_edit_form extends question_edit_form {
|
||||
|
||||
protected function definition_inner($mform) {
|
||||
$creategrades = get_grade_options();
|
||||
$this->add_per_answer_fields($mform, get_string('answerno', 'qtype_numerical', '{no}'),
|
||||
$creategrades->gradeoptions);
|
||||
|
||||
$this->add_units_options($mform);
|
||||
$this->add_units_elements($mform);
|
||||
$this->add_interactive_settings();
|
||||
}
|
||||
|
||||
protected function get_per_answer_fields($mform, $label, $gradeoptions, &$repeatedoptions, &$answersoption) {
|
||||
$repeated = parent::get_per_answer_fields($mform, $label, $gradeoptions, $repeatedoptions, $answersoption);
|
||||
|
||||
$tolerance =& $mform->createElement('text', 'tolerance', get_string('acceptederror', 'qtype_numerical'));
|
||||
$tolerance = $mform->createElement('text', 'tolerance', get_string('acceptederror', 'qtype_numerical'));
|
||||
$repeatedoptions['tolerance']['type'] = PARAM_NUMBER;
|
||||
array_splice($repeated, 3, 0, array($tolerance));
|
||||
$repeated[1]->setSize(10);
|
||||
@ -48,51 +58,176 @@ class question_edit_numerical_form extends question_edit_form {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add question-type specific form fields.
|
||||
*
|
||||
* @param MoodleQuickForm $mform the form being built.
|
||||
* Add the unit handling options to the form.
|
||||
* @param object $mform the form being built.
|
||||
*/
|
||||
protected function definition_inner($mform) {
|
||||
protected function add_units_options($mform) {
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
$creategrades = get_grade_options();
|
||||
$this->add_per_answer_fields($mform, get_string('answerno', 'qtype_numerical', '{no}'),
|
||||
$creategrades->gradeoptions);
|
||||
//------------------------------------------------------------------------------------------
|
||||
question_bank::get_qtype('numerical')->add_units_options($mform, $this);
|
||||
question_bank::get_qtype('numerical')->add_units_elements($mform, $this);
|
||||
$mform->addElement('header', 'unithandling', get_string('unithandling', 'qtype_numerical'));
|
||||
|
||||
$unitoptions = array(
|
||||
qtype_numerical::UNITNONE => get_string('onlynumerical', 'qtype_numerical'),
|
||||
qtype_numerical::UNITDISPLAY => get_string('oneunitshown', 'qtype_numerical'),
|
||||
qtype_numerical::UNITOPTIONAL => get_string('manynumerical', 'qtype_numerical'),
|
||||
qtype_numerical::UNITGRADED => get_string('unitgraded', 'qtype_numerical'),
|
||||
);
|
||||
$mform->addElement('select', 'unitrole', get_string('unithandling', 'qtype_numerical'), $unitoptions);
|
||||
|
||||
$penaltygrp = array();
|
||||
$penaltygrp[] = $mform->createElement('text', 'unitpenalty', get_string('unitpenalty', 'qtype_numerical') ,
|
||||
array('size' => 6));
|
||||
$mform->setType('unitpenalty', PARAM_NUMBER);
|
||||
$mform->setDefault('unitpenalty', 0.1000000);
|
||||
|
||||
$unitgradingtypes = array(
|
||||
qtype_numerical::UNITGRADEDOUTOFMARK => get_string('decfractionofresponsegrade', 'qtype_numerical'),
|
||||
qtype_numerical::UNITGRADEDOUTOFMAX => get_string('decfractionofquestiongrade', 'qtype_numerical'),
|
||||
);
|
||||
$penaltygrp[] = $mform->createElement('select', 'unitgradingtypes', '' , $unitgradingtypes );
|
||||
$mform->setDefault('unitgradingtypes', 1);
|
||||
|
||||
$mform->addGroup($penaltygrp, 'penaltygrp', get_string('unitpenalty', 'qtype_numerical'),' ' , false);
|
||||
$mform->addHelpButton('penaltygrp', 'unitpenalty', 'qtype_numerical');
|
||||
|
||||
$unitinputoptions = array(
|
||||
qtype_numerical::UNITINPUT => get_string('editableunittext', 'qtype_numerical'),
|
||||
qtype_numerical::UNITSELECT => get_string('unitchoice', 'qtype_numerical'),
|
||||
);
|
||||
$mform->addElement('select', 'multichoicedisplay', get_string('studentunitanswer', 'qtype_numerical'), $unitinputoptions);
|
||||
|
||||
$unitslefts = array(
|
||||
0 => get_string('rightexample', 'qtype_numerical'),
|
||||
1 => get_string('leftexample', 'qtype_numerical')
|
||||
);
|
||||
$mform->addElement('select', 'unitsleft', get_string('unitposition', 'qtype_numerical') , $unitslefts );
|
||||
$mform->setDefault('unitsleft', 0);
|
||||
|
||||
$mform->addElement('editor', 'instructions', get_string('instructions', 'qtype_numerical'), null, $this->editoroptions);
|
||||
$mform->setType('instructions', PARAM_RAW);
|
||||
$mform->addHelpButton('instructions', 'numericalinstructions', 'qtype_numerical');
|
||||
|
||||
$mform->disabledIf('penaltygrp', 'unitrole', 'eq', qtype_numerical::UNITNONE);
|
||||
$mform->disabledIf('penaltygrp', 'unitrole', 'eq', qtype_numerical::UNITDISPLAY);
|
||||
$mform->disabledIf('penaltygrp', 'unitrole', 'eq', qtype_numerical::UNITOPTIONAL);
|
||||
|
||||
$mform->disabledIf('unitsleft', 'unitrole', 'eq', qtype_numerical::UNITNONE);
|
||||
|
||||
$mform->disabledIf('multichoicedisplay', 'unitrole', 'eq', qtype_numerical::UNITNONE);
|
||||
$mform->disabledIf('multichoicedisplay', 'unitrole', 'eq', qtype_numerical::UNITDISPLAY);
|
||||
$mform->disabledIf('multichoicedisplay', 'unitrole', 'eq', qtype_numerical::UNITOPTIONAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the input areas for each unit.
|
||||
* @param object $mform the form being built.
|
||||
*/
|
||||
protected function add_units_elements($mform) {
|
||||
$repeated = array(
|
||||
$mform->createElement('header', 'unithdr', get_string('unithdr', 'qtype_numerical', '{no}')),
|
||||
$mform->createElement('text', 'unit', get_string('unit', 'quiz')),
|
||||
$mform->createElement('text', 'multiplier', get_string('multiplier', 'quiz')),
|
||||
);
|
||||
|
||||
$repeatedoptions['unit']['type'] = PARAM_NOTAGS;
|
||||
$repeatedoptions['multiplier']['type'] = PARAM_NUMBER;
|
||||
$repeatedoptions['unit']['disabledif'] = array('unitrole', 'eq', qtype_numerical::UNITNONE);
|
||||
$repeatedoptions['multiplier']['disabledif'] = array('unitrole', 'eq', qtype_numerical::UNITNONE);
|
||||
|
||||
if (isset($this->question->options->units)) {
|
||||
$countunits = count($this->question->options->units);
|
||||
} else {
|
||||
$countunits = 0;
|
||||
}
|
||||
if ($this->question->formoptions->repeatelements) {
|
||||
$repeatsatstart = $countunits + 1;
|
||||
} else {
|
||||
$repeatsatstart = $countunits;
|
||||
}
|
||||
$this->repeat_elements($repeated, $repeatsatstart, $repeatedoptions,
|
||||
'nounits', 'addunits', 2, get_string('addmoreunitblanks', 'qtype_calculated', '{no}'));
|
||||
|
||||
if ($mform->elementExists('multiplier[0]')) {
|
||||
$firstunit = $mform->getElement('multiplier[0]');
|
||||
$firstunit->freeze();
|
||||
$firstunit->setValue('1.0');
|
||||
$firstunit->setPersistantFreeze(true);
|
||||
$mform->addHelpButton('multiplier[0]', 'numericalmultiplier', 'qtype_numerical');
|
||||
}
|
||||
}
|
||||
|
||||
protected function data_preprocessing($question) {
|
||||
if (isset($question->options)){
|
||||
$answers = $question->options->answers;
|
||||
if (count($answers)) {
|
||||
$key = 0;
|
||||
foreach ($answers as $answer){
|
||||
$draftid = file_get_submitted_draft_itemid('feedback['.$key.']');
|
||||
$default_values['answer['.$key.']'] = $answer->answer;
|
||||
$default_values['fraction['.$key.']'] = $answer->fraction;
|
||||
$default_values['tolerance['.$key.']'] = $answer->tolerance;
|
||||
$default_values['feedback['.$key.']'] = array();
|
||||
$default_values['feedback['.$key.']']['format'] = $answer->feedbackformat;
|
||||
$default_values['feedback['.$key.']']['text'] = file_prepare_draft_area(
|
||||
$draftid, // draftid
|
||||
$this->context->id, // context
|
||||
'question', // component
|
||||
'answerfeedback', // filarea
|
||||
!empty($answer->id)?(int)$answer->id:null, // itemid
|
||||
$this->fileoptions, // options
|
||||
$answer->feedback // text
|
||||
);
|
||||
$default_values['feedback['.$key.']']['itemid'] = $draftid;
|
||||
$key++;
|
||||
}
|
||||
}
|
||||
question_bank::get_qtype('numerical')->set_numerical_unit_data($this, $question, $default_values);
|
||||
$question = parent::data_preprocessing($question);
|
||||
$question = $this->data_preprocessing_answers($question);
|
||||
$question = $this->data_preprocessing_hints($question);
|
||||
$question = $this->data_preprocessing_units($question);
|
||||
$question = $this->data_preprocessing_numerical_options($question);
|
||||
return $question;
|
||||
}
|
||||
|
||||
$question = (object)((array)$question + $default_values);
|
||||
protected function data_preprocessing_answers($question) {
|
||||
$question = parent::data_preprocessing_answers($question);
|
||||
if (empty($question->options->answers)) {
|
||||
return $question;
|
||||
}
|
||||
|
||||
$key = 0;
|
||||
foreach ($question->options->answers as $answer) {
|
||||
$question->tolerance[$key] = $answer->tolerance;
|
||||
$key++;
|
||||
}
|
||||
|
||||
return $question;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
function data_preprocessing_units($question) {
|
||||
if (empty($question->options->units)) {
|
||||
return $question;
|
||||
}
|
||||
|
||||
foreach ($question->options->units as $key => $unit) {
|
||||
$question->unit[$key] = $unit->unit;
|
||||
$question->multiplier[$key] = $unit->multiplier;
|
||||
}
|
||||
|
||||
return $question;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
function data_preprocessing_numerical_options($question) {
|
||||
if (empty($question->options)) {
|
||||
return $question;
|
||||
}
|
||||
|
||||
$question->unitpenalty = $question->options->unitpenalty;
|
||||
$question->unitsleft = $question->options->unitsleft;
|
||||
|
||||
if ($question->options->unitgradingtype) {
|
||||
$question->unitgradingtypes = $question->options->unitgradingtype;
|
||||
$question->multichoicedisplay = $question->options->showunits;
|
||||
$question->unitrole = qtype_numerical::UNITGRADED;
|
||||
} else {
|
||||
$question->unitrole = $question->options->showunits;
|
||||
}
|
||||
|
||||
// Instructions field.
|
||||
$draftitemid = file_get_submitted_draft_itemid('instruction');
|
||||
$question->instructions['text'] = file_prepare_draft_area(
|
||||
$draftitemid, // draftid
|
||||
$this->context->id, // context
|
||||
'qtype_' . $this->qtype(), // component
|
||||
'instruction', // filarea
|
||||
!empty($question->id) ? (int) $question->id : null, // itemid
|
||||
$this->fileoptions, // options
|
||||
$question->options->instructions // text
|
||||
);
|
||||
$question->instructions['itemid'] = $draftitemid ;
|
||||
$question->instructions['format'] = $question->options->instructionsformat;
|
||||
|
||||
return $question;
|
||||
}
|
||||
|
||||
@ -124,7 +259,62 @@ class question_edit_numerical_form extends question_edit_form {
|
||||
if ($maxgrade == false) {
|
||||
$errors['fraction[0]'] = get_string('fractionsnomax', 'question');
|
||||
}
|
||||
question_bank::get_qtype('numerical')->validate_numerical_options($data, $errors);
|
||||
|
||||
$errors = $this->validate_numerical_options($data, $errors);
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the unit options.
|
||||
*/
|
||||
function validate_numerical_options($data, $errors) {
|
||||
print_object($data); // DONOTCOMMIT
|
||||
if ($data['unitrole'] != qtype_numerical::UNITNONE && trim($data['unit'][0]) == '') {
|
||||
$errors['unit[0]'] = get_string('unitonerequired', 'qtype_numerical');
|
||||
}
|
||||
|
||||
if (empty($data['unit'])) {
|
||||
return $errors;
|
||||
}
|
||||
|
||||
// Basic unit validation.
|
||||
foreach ($data['unit'] as $key => $unit) {
|
||||
if (is_numeric($unit)) {
|
||||
$errors['unit[' . $key . ']'] =
|
||||
get_string('mustnotbenumeric', 'qtype_calculated');
|
||||
}
|
||||
|
||||
$trimmedunit = trim($unit);
|
||||
if (empty($trimmedunit)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$trimmedmultiplier = trim($data['multiplier'][$key]);
|
||||
if (empty($trimmedmultiplier)) {
|
||||
$errors['multiplier[' . $key . ']'] =
|
||||
get_string('youmustenteramultiplierhere', 'qtype_calculated');
|
||||
} else if (!is_numeric($trimmedmultiplier)) {
|
||||
$errors['multiplier[' . $key . ']'] =
|
||||
get_string('mustbenumeric', 'qtype_calculated');
|
||||
}
|
||||
}
|
||||
|
||||
// Check for repeated units.
|
||||
$alreadyseenunits = array();
|
||||
foreach ($data['unit'] as $key => $unit) {
|
||||
$trimmedunit = trim($unit);
|
||||
if ($trimmedunit == '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (in_array($trimmedunit, $alreadyseenunits)) {
|
||||
$errors['unit[' . $key . ']'] =
|
||||
get_string('errorrepeatedunit', 'qtype_numerical');
|
||||
} else {
|
||||
$alreadyseenunits[] = $trimmedunit;
|
||||
}
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
@ -30,10 +30,10 @@ $string['addmoreanswerblanks'] = 'Blanks for {no} More Answers';
|
||||
$string['addmoreunitblanks'] = 'Blanks for {no} More Units';
|
||||
$string['answermustbenumberorstar'] = 'The answer must be a number, or \'*\'.';
|
||||
$string['answerno'] = 'Answer {$a}';
|
||||
$string['decfractionofquestiongrade'] = 'as decimal fraction (0-1) of question grade';
|
||||
$string['decfractionofresponsegrade'] = 'as decimal fraction (0-1) of response grade';
|
||||
$string['decfractionofquestiongrade'] = 'as a fraction (0-1) of the question grade';
|
||||
$string['decfractionofresponsegrade'] = 'as a fraction (0-1) of the response grade';
|
||||
$string['decimalformat'] = 'decimals';
|
||||
$string['editableunittext'] = 'Text input element';
|
||||
$string['editableunittext'] = 'a text input element';
|
||||
$string['editingnumerical'] = 'Editing a Numerical question';
|
||||
$string['errornomultiplier'] = 'You must specify a multiplier for this unit.';
|
||||
$string['errorrepeatedunit'] = 'You cannot have two units with the same name.';
|
||||
@ -41,7 +41,7 @@ $string['geometric'] = 'Geometric';
|
||||
$string['instructions'] = 'Instructions ';
|
||||
$string['invalidnumericanswer'] = 'One of the answers you entered was not a valid number.';
|
||||
$string['invalidnumerictolerance'] = 'One of the tolerances you entered was not a valid number.';
|
||||
$string['leftexample'] = 'LEFT as $1.00';
|
||||
$string['leftexample'] = 'on the left, for example $1.00 or £1.00';
|
||||
$string['multiplier'] = 'Multiplier';
|
||||
$string['noneditableunittext'] = 'NON editable text of Unit No1';
|
||||
$string['nonvalidcharactersinnumber'] = 'NON valid characters in number';
|
||||
@ -52,10 +52,7 @@ $string['numerical_help'] = 'From the student perspective, a numerical question
|
||||
$string['numerical_link'] = 'question/type/numerical';
|
||||
$string['numericalsummary'] = 'Allows a numerical response, possibly with units, that is graded by comparing against various model answers, possibly with tolerances.';
|
||||
$string['numericalinstructions'] = 'Instructions';
|
||||
$string['numericalinstructions_help'] = 'Specific instructions related to the question as
|
||||
|
||||
* Examples of number formats
|
||||
* Complex units';
|
||||
$string['numericalinstructions_help'] = 'Enter any instructions you would like to give the student about how to complete their response.';
|
||||
$string['numericalmultiplier'] = 'Multiplier';
|
||||
$string['numericalmultiplier_help'] = 'The multiplier is the factor by which the correct numerical response will be multiplied.
|
||||
|
||||
@ -64,24 +61,21 @@ The first unit (Unit 1) has a default multiplier of 1. Thus if the correct numer
|
||||
If you add the unit kW with a multiplier of 0.001, this will add a correct response of 5.5 kW. This means that the answers 5500W or 5.5kW would be marked correct.
|
||||
|
||||
Note that the accepted error is also multiplied, so an allowed error of 100W would become an error of 0.1kW.';
|
||||
$string['manynumerical'] = 'Only the NUMERICAL ANSWER will be graded using optional units ';
|
||||
$string['manynumerical'] = 'Units are optional. If a unit is entered, it is used to convert the reponse to Unit 1 before grading.';
|
||||
$string['nominal'] = 'Nominal';
|
||||
$string['onlynumerical'] = 'Only the NUMERICAL ANSWER will be graded, no units allowed';
|
||||
$string['oneunitshown'] = 'Only the NUMERICAL ANSWER will be graded, Unit1 will be shown';
|
||||
$string['onlynumerical'] = 'Units are not used at all. Only the numerical value is graded.';
|
||||
$string['oneunitshown'] = 'Unit 1 is automatically displayed beside the answer box.';
|
||||
$string['pleaseenterananswer'] = 'Please enter an answer.';
|
||||
$string['relative'] = 'Relative';
|
||||
$string['rightexample'] = 'RIGHT as 1.00cm';
|
||||
$string['rightexample'] = 'on the right, for example 1.00cm or 1.00km';
|
||||
$string['selectunits'] = 'Select units';
|
||||
$string['selectunit'] = 'Select one unit';
|
||||
$string['studentunitanswer'] = 'UNIT ANSWER displayed as a ';
|
||||
$string['studentunitanswer'] = 'Units are input using';
|
||||
$string['tolerancetype'] = 'Tolerance type';
|
||||
$string['unit'] = 'Unit';
|
||||
$string['unitchoice'] = 'Multichoice (radio elements)';
|
||||
$string['unitdisplay'] = '<STRONG>Unit 1 displayed </STRONG>';
|
||||
$string['unitchoice'] = 'a multiple choice selection';
|
||||
$string['unitedit'] = 'Edit unit';
|
||||
$string['unitgraded'] = ' NUMERICAL ANSWER and UNIT ANSWER will be graded ';
|
||||
$string['unitgraded1'] = '<STRONG>UNIT GRADED</STRONG>';
|
||||
$string['unitsused'] = '<STRONG>UNIT USED</STRONG>';
|
||||
$string['unitgraded'] = 'The unit must be given, and will be graded.';
|
||||
$string['unithdr'] = 'Unit {$a}';
|
||||
$string['unitmandatory'] = 'Mandatory';
|
||||
$string['unitmandatory_help'] = '
|
||||
@ -91,32 +85,24 @@ $string['unitmandatory_help'] = '
|
||||
* The unit penalty will be applied if the unit field is empty
|
||||
|
||||
';
|
||||
$string['unitnotgraded'] = '<STRONG>UNIT NOT GRADED</STRONG>';
|
||||
$string['unitnotused'] = '<STRONG>UNIT NOT USED</STRONG>';
|
||||
$string['unitonerequired'] = 'You must enter at least one unit';
|
||||
$string['unitoptional'] = 'Optional unit';
|
||||
$string['unitoptional_help'] = '
|
||||
* If the unit field is not empty, the response will be graded using this unit.
|
||||
|
||||
* If the unit is badly written or unknown, the response will be considered as non valid.
|
||||
';
|
||||
$string['unitused'] = '<STRONG>UNIT USED</STRONG>';
|
||||
$string['unituses'] = 'Unit uses';
|
||||
$string['unituses_help'] = 'The unit(s) are uses as in pre 2,0 Moodle version
|
||||
|
||||
* The student can answer using units predefined by the teacher
|
||||
* in which case the constant will be applied to the student value.
|
||||
* If the student does not add any unit, his numerical answer is used as is.';
|
||||
$string['unitnotvalid'] = ' Unit not valid with this numerical value';
|
||||
$string['unitunknown'] = ' Undefined unit ';
|
||||
$string['unitpenalty'] = 'Unit penalty';
|
||||
$string['unitpenalty_help'] = 'The penalty is applied if
|
||||
|
||||
* An undefined unit name is put in the Unit answer element or
|
||||
* An unit name is put in the Number answer element ';
|
||||
* the wrong unit name is entered into the unit input, or
|
||||
* a unit is entered into the value input box';
|
||||
$string['unitappliedpenalty'] = 'These marks include a penalty of {$a} for bad unit.';
|
||||
$string['unitposition'] = 'Unit position';
|
||||
$string['unitposition'] = 'Units are displayed';
|
||||
$string['unitnotselected'] = 'No unit selected';
|
||||
$string['unitshandling'] = 'Units handling';
|
||||
$string['unithandling'] = 'Unit handling';
|
||||
$string['validnumberformats'] = 'Valid number formats';
|
||||
$string['validnumberformats_help'] = '
|
||||
* regular numbers 13500.67 : 13 500.67 : 13500,67: 13 500,67
|
||||
|
@ -31,20 +31,6 @@ defined('MOODLE_INTERNAL') || die();
|
||||
require_once($CFG->dirroot . '/question/type/numerical/question.php');
|
||||
|
||||
|
||||
if ( ! defined ("NUMERICALQUESTIONUNITTEXTINPUTDISPLAY")) {
|
||||
define("NUMERICALQUESTIONUNITTEXTINPUTDISPLAY", 0);
|
||||
}
|
||||
if ( ! defined ("NUMERICALQUESTIONUNITMULTICHOICEDISPLAY")) {
|
||||
define("NUMERICALQUESTIONUNITMULTICHOICEDISPLAY", 1);
|
||||
}
|
||||
if ( ! defined ("NUMERICALQUESTIONUNITTEXTDISPLAY")) {
|
||||
define("NUMERICALQUESTIONUNITTEXTDISPLAY", 2);
|
||||
}
|
||||
if ( ! defined ("NUMERICALQUESTIONUNITNODISPLAY")) {
|
||||
define("NUMERICALQUESTIONUNITNODISPLAY", 3);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The numerical question type class.
|
||||
*
|
||||
@ -55,6 +41,17 @@ if ( ! defined ("NUMERICALQUESTIONUNITNODISPLAY")) {
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class qtype_numerical extends question_type {
|
||||
const UNITINPUT = 0;
|
||||
const UNITSELECT = 1;
|
||||
|
||||
const UNITNONE = 3;
|
||||
const UNITDISPLAY = 2;
|
||||
const UNITGRADED = 1;
|
||||
const UNITOPTIONAL = 0;
|
||||
|
||||
const UNITGRADEDOUTOFMARK = 1;
|
||||
const UNITGRADEDOUTOFMAX = 2;
|
||||
|
||||
public function has_wildcards_in_responses() {
|
||||
return true;
|
||||
}
|
||||
@ -149,7 +146,7 @@ class qtype_numerical extends question_type {
|
||||
$question->options->showunits = $options->showunits;
|
||||
$question->options->unitsleft = $options->unitsleft;
|
||||
$question->options->instructions = $options->instructions;
|
||||
$question->options->instructionsformat = $options->instructionsformat;
|
||||
$question->options->instructionsformat = $options->instructionsformat;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -244,6 +241,8 @@ class qtype_numerical extends question_type {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$this->save_hints($question);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -269,49 +268,35 @@ class qtype_numerical extends question_type {
|
||||
$options->id = $DB->insert_record('question_numerical_options', $options);
|
||||
}
|
||||
|
||||
if (isset($question->options->unitgradingtype)) {
|
||||
$options->unitgradingtype = $question->options->unitgradingtype;
|
||||
} else {
|
||||
$options->unitgradingtype = 0 ;
|
||||
}
|
||||
if (isset($question->unitpenalty)){
|
||||
if (isset($question->unitpenalty)) {
|
||||
$options->unitpenalty = $question->unitpenalty;
|
||||
} else { //so this is either an old question or a close question type
|
||||
} else {
|
||||
// Either an old question or a close question type.
|
||||
$options->unitpenalty = 1 ;
|
||||
}
|
||||
// if we came from the form then 'unitrole' exists
|
||||
if (isset($question->unitrole)){
|
||||
switch ($question->unitrole){
|
||||
case '0' : $options->showunits = NUMERICALQUESTIONUNITNODISPLAY ;
|
||||
break ;
|
||||
case '1' : $options->showunits = NUMERICALQUESTIONUNITTEXTDISPLAY ;
|
||||
break ;
|
||||
case '2' : $options->showunits = NUMERICALQUESTIONUNITTEXTINPUTDISPLAY ;
|
||||
$options->unitgradingtype = 0 ;
|
||||
break ;
|
||||
case '3' : $options->showunits = $question->multichoicedisplay ;
|
||||
$options->unitgradingtype = $question->unitgradingtypes ;
|
||||
break ;
|
||||
|
||||
$options->unitgradingtype = 0;
|
||||
if (isset($question->unitrole)) {
|
||||
// Saving the editing form.
|
||||
$options->showunits = $question->unitrole;
|
||||
if ($question->unitrole == self::UNITGRADED) {
|
||||
$options->unitgradingtype = $question->unitgradingtypes;
|
||||
}
|
||||
|
||||
} else if (isset($question->showunits)) {
|
||||
// Updated import, e.g. Moodle XML.
|
||||
$options->showunits = $question->showunits;
|
||||
|
||||
} else {
|
||||
if (isset($question->showunits)){
|
||||
$options->showunits = $question->showunits;
|
||||
// Legacy import.
|
||||
if ($defaultunit = $this->get_default_numerical_unit($question)) {
|
||||
$options->showunits = self::UNITINPUT;
|
||||
} else {
|
||||
if ($defaultunit = $this->get_default_numerical_unit($question)) {
|
||||
// so units can be used
|
||||
$options->showunits = NUMERICALQUESTIONUNITTEXTINPUTDISPLAY ;
|
||||
} else {
|
||||
// only numerical will be graded
|
||||
$options->showunits = NUMERICALQUESTIONUNITNODISPLAY ;
|
||||
}
|
||||
$options->showunits = self::UNITNONE;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($question->unitsleft)) {
|
||||
$options->unitsleft = $question->unitsleft;
|
||||
} else {
|
||||
$options->unitsleft = 0 ;
|
||||
}
|
||||
$options->unitsleft = !empty($question->unitsleft);
|
||||
|
||||
$options->instructions = $this->import_or_save_files($question->instructions,
|
||||
$question->context, 'qtype_'.$question->qtype , 'instruction', $question->id);
|
||||
@ -319,8 +304,6 @@ class qtype_numerical extends question_type {
|
||||
|
||||
$DB->update_record('question_numerical_options', $options);
|
||||
|
||||
$this->save_hints($question);
|
||||
|
||||
// Report any problems.
|
||||
if (!empty($result->notice)) {
|
||||
return $result;
|
||||
@ -362,10 +345,10 @@ class qtype_numerical extends question_type {
|
||||
return $result;
|
||||
}
|
||||
|
||||
function find_unit_index(&$question,$value){
|
||||
function find_unit_index($question, $value) {
|
||||
$length = 0;
|
||||
$goodkey = 0 ;
|
||||
foreach ($question->options->units as $key => $unit){
|
||||
foreach ($question->options->units as $key => $unit) {
|
||||
if($unit->unit ==$value ) {
|
||||
return $key ;
|
||||
}
|
||||
@ -424,8 +407,8 @@ class qtype_numerical extends question_type {
|
||||
$formatoptions->noclean = true;
|
||||
$formatoptions->para = false;
|
||||
$nameprefix = $question->name_prefix;
|
||||
$component = 'qtype_' . $question->qtype;
|
||||
// rewrite instructions text
|
||||
$component = 'qtype_' . $question->qtype;
|
||||
// rewrite instructions text
|
||||
$question->options->instructions = quiz_rewrite_question_urls($question->options->instructions, 'pluginfile.php', $context->id, $component, 'instruction', array($state->attempt, $state->question), $question->id);
|
||||
/// Print question text and media
|
||||
|
||||
@ -445,7 +428,7 @@ class qtype_numerical extends question_type {
|
||||
$nameanswer = "name=\"".$question->name_prefix."answer\"";
|
||||
$nameunit = "name=\"".$question->name_prefix."unit\"";
|
||||
// put old answer data in $state->responses['answer'] and $state->responses['unit']
|
||||
if (isset($state->responses['']) && $state->responses[''] != '' && !isset($state->responses['answer'])){
|
||||
if (isset($state->responses['']) && $state->responses[''] != '' && !isset($state->responses['answer'])) {
|
||||
$this->split_old_answer($state->responses[''], $question->options->units, $state->responses['answer'] ,$state->responses['unit'] );
|
||||
}
|
||||
// prepare the values of the input elements to be dispalyed answer i.e. number and unit
|
||||
@ -458,7 +441,7 @@ class qtype_numerical extends question_type {
|
||||
$valueunit = ' value="'.s($state->responses['unit']).'" ';
|
||||
} else {
|
||||
$valueunit = ' value="" ';
|
||||
if ($question->options->showunits == NUMERICALQUESTIONUNITTEXTDISPLAY ){
|
||||
if ($question->options->showunits == NUMERICALQUESTIONUNITTEXTDISPLAY ) {
|
||||
$valueunit = ' value="'.s($question->options->units[0]->unit).'" ';
|
||||
}
|
||||
}
|
||||
@ -491,13 +474,13 @@ class qtype_numerical extends question_type {
|
||||
foreach($question->options->answers as $answer) {
|
||||
if ($this->test_response($question, $state, $answer)) {
|
||||
// Answer was correct or partially correct.
|
||||
if ( $answer->answer === '*'){
|
||||
if ( $answer->answer === '*') {
|
||||
$answerasterisk = true ;
|
||||
}
|
||||
// in all cases
|
||||
$class = question_get_feedback_class($answer->fraction);
|
||||
$feedbackimg = question_get_feedback_image($answer->fraction);
|
||||
if ($question->options->unitgradingtype == 0 || ($question->options->unitgradingtype == 0 && $answer->answer === '*')){
|
||||
if ($question->options->unitgradingtype == 0 || ($question->options->unitgradingtype == 0 && $answer->answer === '*')) {
|
||||
// if * then unit has the $answer->fraction value
|
||||
// if $question->options->unitgradingtype == 0 everything has been checked
|
||||
// if $question->options->showunits == NUMERICALQUESTIONUNITTEXTINPUTDISPLAY
|
||||
@ -533,12 +516,12 @@ class qtype_numerical extends question_type {
|
||||
$feedbackimgunit = question_get_feedback_image($answer->fraction);
|
||||
$valid_numerical_unit = true ;//everything is true with *
|
||||
} else {
|
||||
// if( isset($state->responses['unit']) && $state->responses['unit'] != '' ){// unit should be written in the unit input or checked in multichoice
|
||||
// if( isset($state->responses['unit']) && $state->responses['unit'] != '' ) {// unit should be written in the unit input or checked in multichoice
|
||||
// we need to see if something was written in the answer field that was not in the number
|
||||
// although we cannot actually detect units put before the number which will cause bad numerical.
|
||||
// use extract response
|
||||
$response = $this->extract_numerical_response($state->responses['answer']);
|
||||
if(isset($response->unit ) && $response->unit != ''){
|
||||
if(isset($response->unit ) && $response->unit != '') {
|
||||
$unit_in_numerical_answer = true ;
|
||||
}else {
|
||||
$unit_in_numerical_answer = false ;
|
||||
@ -547,7 +530,7 @@ class qtype_numerical extends question_type {
|
||||
// the we let the testing to the two cases either
|
||||
// NUMERICALQUESTIONUNITTEXTINPUTDISPLAY or
|
||||
// NUMERICALQUESTIONUNITMULTICHOICEDISPLAY
|
||||
if( !isset($state->responses['unit']) || $state->responses['unit'] == '' ){
|
||||
if( !isset($state->responses['unit']) || $state->responses['unit'] == '' ) {
|
||||
// unit should be written in the unit input or checked in multichoice
|
||||
$valid_numerical_unit = false ;
|
||||
$classunit = question_get_feedback_class(0);
|
||||
@ -560,7 +543,7 @@ class qtype_numerical extends question_type {
|
||||
$valid_numerical_unit = false ;
|
||||
|
||||
foreach ($question->options->units as $key => $unit) {
|
||||
if ($unit->unit == $state->responses['unit']){
|
||||
if ($unit->unit == $state->responses['unit']) {
|
||||
// $response = $this->apply_unit($state->responses['answer'].$unit->unit, array($question->options->units[$key])) ;
|
||||
// echo "<p> avant false valid_numerical_unit_index $valid_numerical_unit_index ".$state->responses['answer']."</p>";
|
||||
$invalid_unit_found = 0 ;
|
||||
@ -568,7 +551,7 @@ class qtype_numerical extends question_type {
|
||||
//echo "<p> avanr get valid_numerical_unit_index $valid_numerical_unit_index </p>";
|
||||
// $this->get_tolerance_interval($answer);
|
||||
$testresponse = $response->number /$unit->multiplier ;
|
||||
if($answer->min <= $testresponse && $testresponse <= $answer->max){
|
||||
if($answer->min <= $testresponse && $testresponse <= $answer->max) {
|
||||
//echo "<p> apres min max valid_numerical_unit_index $valid_numerical_unit_index </p>";
|
||||
$classunit = question_get_feedback_class($answer->fraction) ; //question_get_feedback_class(1);
|
||||
$feedbackimgunit = question_get_feedback_image($rawgrade);
|
||||
@ -598,8 +581,8 @@ class qtype_numerical extends question_type {
|
||||
$classunitvalue = 1 ;
|
||||
}
|
||||
|
||||
if(! $answerasterisk && $question->options->unitgradingtype != 0 && (! $valid_numerical_unit || $unit_in_numerical_answer)){
|
||||
if($question->options->unitgradingtype == 1){
|
||||
if(! $answerasterisk && $question->options->unitgradingtype != 0 && (! $valid_numerical_unit || $unit_in_numerical_answer)) {
|
||||
if($question->options->unitgradingtype == 1) {
|
||||
$raw_unitpenalty = $question->options->unitpenalty * $rawgrade ;
|
||||
}else {
|
||||
$raw_unitpenalty = $question->options->unitpenalty ;
|
||||
@ -612,25 +595,25 @@ class qtype_numerical extends question_type {
|
||||
}
|
||||
|
||||
|
||||
function compare_responses(&$question, $state, $teststate) {
|
||||
function compare_responses($question, $state, $teststate) {
|
||||
|
||||
if ($question->options->showunits == NUMERICALQUESTIONUNITMULTICHOICEDISPLAY && isset($question->options->units) && isset($state->responses['unit']) && isset($question->options->units[$state->responses['unit']] )){
|
||||
if ($question->options->showunits == NUMERICALQUESTIONUNITMULTICHOICEDISPLAY && isset($question->options->units) && isset($state->responses['unit']) && isset($question->options->units[$state->responses['unit']] )) {
|
||||
$state->responses['unit']=$question->options->units[$state->responses['unit']]->unit;
|
||||
};
|
||||
|
||||
|
||||
$responses = '';
|
||||
$testresponses = '';
|
||||
if (isset($state->responses['answer'])){
|
||||
if (isset($state->responses['answer'])) {
|
||||
$responses = $state->responses['answer'];
|
||||
}
|
||||
if (isset($state->responses['unit'])){
|
||||
if (isset($state->responses['unit'])) {
|
||||
$responses .= $state->responses['unit'];
|
||||
}
|
||||
if (isset($teststate->responses['answer'])){
|
||||
if (isset($teststate->responses['answer'])) {
|
||||
$testresponses = $teststate->responses['answer'];
|
||||
}
|
||||
if (isset($teststate->responses['unit'])){
|
||||
if (isset($teststate->responses['unit'])) {
|
||||
$testresponses .= $teststate->responses['unit'];
|
||||
}
|
||||
|
||||
@ -655,19 +638,19 @@ class qtype_numerical extends question_type {
|
||||
}
|
||||
// using old grading process if $question->unitgradingtype == 0
|
||||
// and adding unit1 for the new option NUMERICALQUESTIONUNITTEXTDISPLAY
|
||||
if ($question->options->unitgradingtype == 0 ){
|
||||
if ($question->options->unitgradingtype == 0 ) {
|
||||
// values coming form old question stored in attempts
|
||||
if (!isset($state->responses['answer']) && isset($state->responses[''])){
|
||||
if (!isset($state->responses['answer']) && isset($state->responses[''])) {
|
||||
$state->responses['answer'] = $state->responses[''];
|
||||
}
|
||||
$answertotest = $state->responses['answer'];
|
||||
// values coming from NUMERICALQUESTIONUNITTEXTINPUTDISPLAY
|
||||
// or NUMERICALQUESTIONUNITTEXTDISPLAY as unit hidden HTML element
|
||||
|
||||
if($question->options->showunits == NUMERICALQUESTIONUNITTEXTINPUTDISPLAY ){
|
||||
if($question->options->showunits == NUMERICALQUESTIONUNITTEXTINPUTDISPLAY ) {
|
||||
|
||||
$testresponse = $this->extract_numerical_response($state->responses['answer']);
|
||||
if($testresponse->unit != '' || $testresponse->number === false){
|
||||
if($testresponse->unit != '' || $testresponse->number === false) {
|
||||
return false;
|
||||
}
|
||||
$answertotest = $testresponse->number ;
|
||||
@ -675,7 +658,7 @@ class qtype_numerical extends question_type {
|
||||
if(isset($state->responses['unit'])) {
|
||||
$answertotest .= $state->responses['unit'] ;
|
||||
}
|
||||
// if ($question->options->showunits == NUMERICALQUESTIONUNITTEXTDISPLAY && isset($question->options->units[0])){
|
||||
// if ($question->options->showunits == NUMERICALQUESTIONUNITTEXTDISPLAY && isset($question->options->units[0])) {
|
||||
// $answertotest .= $question->options->units[0]->unit ;
|
||||
// }
|
||||
// test OK if only numerical or numerical with known unit names with the unit mltiplier applied
|
||||
@ -717,12 +700,12 @@ class qtype_numerical extends question_type {
|
||||
|
||||
// The student did type a number, so check it with tolerances.
|
||||
$this->get_tolerance_interval($answer);
|
||||
if ($answer->min <= $response->number && $response->number <= $answer->max){
|
||||
if ($answer->min <= $response->number && $response->number <= $answer->max) {
|
||||
return true;
|
||||
}
|
||||
// testing for other units
|
||||
if ( isset($question->options->units) && count($question->options->units) > 0) {
|
||||
foreach($question->options->units as $key =>$unit){
|
||||
foreach($question->options->units as $key =>$unit) {
|
||||
$testresponse = $response->number /$unit->multiplier ;
|
||||
if($answer->min <= $testresponse && $testresponse<= $answer->max) {
|
||||
return true;
|
||||
@ -758,7 +741,7 @@ class qtype_numerical extends question_type {
|
||||
* @param object $cmoptions
|
||||
*/
|
||||
function grade_responses(&$question, &$state, $cmoptions) {
|
||||
if ( isset($state->responses['']) && $state->responses[''] != '' && !isset($state->responses['answer'])){
|
||||
if ( isset($state->responses['']) && $state->responses[''] != '' && !isset($state->responses['answer'])) {
|
||||
$this->split_old_answer($state->responses[''], $question->options->units, $state->responses['answer'] ,$state->responses['unit'] );
|
||||
}
|
||||
|
||||
@ -774,7 +757,7 @@ class qtype_numerical extends question_type {
|
||||
if ($this->test_response($question, $state, $answer)) {
|
||||
// Answer was correct or partially correct.
|
||||
$state->raw_grade = $answer->fraction ;
|
||||
if ($question->options->unitgradingtype == 0 || $answer->answer === '*'){
|
||||
if ($question->options->unitgradingtype == 0 || $answer->answer === '*') {
|
||||
// if * then unit has the $answer->fraction value
|
||||
// if $question->options->unitgradingtype == 0 everything has been checked
|
||||
// if $question->options->showunits == NUMERICALQUESTIONUNITTEXTINPUTDISPLAY
|
||||
@ -787,14 +770,14 @@ class qtype_numerical extends question_type {
|
||||
$valid_numerical_unit = false ;
|
||||
$class = question_get_feedback_class($answer->fraction);
|
||||
$feedbackimg = question_get_feedback_image($answer->fraction);
|
||||
if(isset($state->responses['unit']) && $state->responses['unit'] != '' ){
|
||||
if(isset($state->responses['unit']) && $state->responses['unit'] != '' ) {
|
||||
foreach ($question->options->units as $key => $unit) {
|
||||
if ($unit->unit == $state->responses['unit']){
|
||||
if ($unit->unit == $state->responses['unit']) {
|
||||
|
||||
$response = $this->apply_unit($state->responses['answer'].$state->responses['unit'], array($question->options->units[$key])) ;
|
||||
if ($response !== false) {
|
||||
$this->get_tolerance_interval($answer);
|
||||
if($answer->min <= $response && $response <= $answer->max){
|
||||
if($answer->min <= $response && $response <= $answer->max) {
|
||||
$valid_numerical_unit = true ;
|
||||
}
|
||||
}
|
||||
@ -808,8 +791,8 @@ class qtype_numerical extends question_type {
|
||||
}
|
||||
// apply unit penalty
|
||||
$raw_unitpenalty = 0 ;
|
||||
if($question->options->unitgradingtype != 0 && !empty($question->options->unitpenalty)&& $valid_numerical_unit != true ){
|
||||
if($question->options->unitgradingtype == 1){
|
||||
if($question->options->unitgradingtype != 0 && !empty($question->options->unitpenalty)&& $valid_numerical_unit != true ) {
|
||||
if($question->options->unitgradingtype == 1) {
|
||||
$raw_unitpenalty = $question->options->unitpenalty * $state->raw_grade ;
|
||||
}else {
|
||||
$raw_unitpenalty = $question->options->unitpenalty ;
|
||||
@ -903,9 +886,9 @@ class qtype_numerical extends question_type {
|
||||
case '2': case 'nominal':
|
||||
$tolerance = abs($tolerance); // important - otherwise min and max are swapped
|
||||
// $answer->tolerance 0 or something else
|
||||
if ((float)$answer->tolerance == 0.0 && abs((float)$answer->answer) <= $tolerance ){
|
||||
if ((float)$answer->tolerance == 0.0 && abs((float)$answer->answer) <= $tolerance ) {
|
||||
$tolerance = (float) ("1.0e-".ini_get('precision')) * abs((float)$answer->answer) ; //tiny fraction
|
||||
} else if ((float)$answer->tolerance != 0.0 && abs((float)$answer->tolerance) < abs((float)$answer->answer) && abs((float)$answer->answer) <= $tolerance){
|
||||
} else if ((float)$answer->tolerance != 0.0 && abs((float)$answer->tolerance) < abs((float)$answer->answer) && abs((float)$answer->answer) <= $tolerance) {
|
||||
$tolerance = (1+("1.0e-".ini_get('precision')) )* abs((float) $answer->tolerance) ;//tiny fraction
|
||||
}
|
||||
|
||||
@ -1015,279 +998,6 @@ class qtype_numerical extends question_type {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* function used in function definition_inner()
|
||||
* of edit_..._form.php for
|
||||
* numerical, calculated, calculatedsimple
|
||||
*/
|
||||
protected function add_units_options(&$mform, &$that){
|
||||
// Units are graded
|
||||
$mform->addElement('header', 'unithandling', get_string('unitshandling', 'qtype_numerical'));
|
||||
$mform->addElement('radio', 'unitrole', get_string('unitnotused', 'qtype_numerical'), get_string('onlynumerical', 'qtype_numerical'),0);
|
||||
$mform->addElement('radio', 'unitrole', get_string('unitdisplay', 'qtype_numerical'), get_string('oneunitshown', 'qtype_numerical'),1);
|
||||
$mform->addElement('radio', 'unitrole', get_string('unitsused', 'qtype_numerical'), get_string('manynumerical', 'qtype_numerical'),2);
|
||||
$mform->addElement('static', 'separator2', '', '<HR/>');
|
||||
$mform->addElement('radio', 'unitrole', get_string('unitgraded1', 'qtype_numerical'), get_string('unitgraded', 'qtype_numerical'),3);
|
||||
$penaltygrp = array();
|
||||
$penaltygrp[] =& $mform->createElement('text', 'unitpenalty', get_string('unitpenalty', 'qtype_numerical') ,
|
||||
array('size' => 6));
|
||||
$unitgradingtypes = array('1' => get_string('decfractionofresponsegrade', 'qtype_numerical'), '2' => get_string('decfractionofquestiongrade', 'qtype_numerical'));
|
||||
$penaltygrp[] =& $mform->createElement('select', 'unitgradingtypes', '' , $unitgradingtypes );
|
||||
$mform->addGroup($penaltygrp, 'penaltygrp', get_string('unitpenalty', 'qtype_numerical'),' ' , false);
|
||||
$multichoicedisplaygrp = array();
|
||||
$multichoicedisplaygrp[] =& $mform->createElement('radio', 'multichoicedisplay', get_string('unitedit', 'qtype_numerical'), get_string('editableunittext', 'qtype_numerical'),0);
|
||||
$multichoicedisplaygrp[] =& $mform->createElement('radio', 'multichoicedisplay', get_string('selectunits', 'qtype_numerical') , get_string('unitchoice', 'qtype_numerical'),1);
|
||||
$mform->addGroup($multichoicedisplaygrp, 'multichoicedisplaygrp', get_string('studentunitanswer', 'qtype_numerical'),' OR ' , false);
|
||||
$unitslefts = array('0' => get_string('rightexample', 'qtype_numerical'),'1' => get_string('leftexample', 'qtype_numerical'));
|
||||
$mform->addElement('select', 'unitsleft', get_string('unitposition', 'qtype_numerical') , $unitslefts );
|
||||
|
||||
$mform->addElement('static', 'separator2', '<HR/>', '<HR/>');
|
||||
|
||||
$mform->addElement('editor', 'instructions', get_string('instructions', 'qtype_numerical'), null, $that->editoroptions);
|
||||
$showunits1grp = array();
|
||||
$mform->addElement('static', 'separator2', '<HR/>', '<HR/>');
|
||||
|
||||
$mform->setType('unitpenalty', PARAM_NUMBER);
|
||||
$mform->setDefault('unitpenalty', 0.1);
|
||||
$mform->setDefault('unitgradingtypes', 1);
|
||||
$mform->addHelpButton('penaltygrp', 'unitpenalty', 'qtype_numerical');
|
||||
$mform->setDefault('unitsleft', 0);
|
||||
$mform->setType('instructions', PARAM_RAW);
|
||||
$mform->addHelpButton('instructions', 'numericalinstructions', 'qtype_numerical');
|
||||
$mform->disabledIf('penaltygrp', 'unitrole','eq','0');
|
||||
$mform->disabledIf('penaltygrp', 'unitrole','eq','1');
|
||||
$mform->disabledIf('penaltygrp', 'unitrole','eq','2');
|
||||
$mform->disabledIf('unitsleft', 'unitrole','eq','0');
|
||||
$mform->disabledIf('multichoicedisplay','unitrole','eq','0');
|
||||
$mform->disabledIf('multichoicedisplay','unitrole','eq','1');
|
||||
$mform->disabledIf('multichoicedisplay','unitrole','eq','2');
|
||||
}
|
||||
|
||||
/**
|
||||
* function used in in function definition_inner()
|
||||
* of edit_..._form.php for
|
||||
* numerical, calculated, calculatedsimple
|
||||
*/
|
||||
protected function add_units_elements(& $mform,& $that) {
|
||||
$repeated = array();
|
||||
$repeated[] =& $mform->createElement('header', 'unithdr', get_string('unithdr', 'qtype_numerical', '{no}'));
|
||||
|
||||
$repeated[] =& $mform->createElement('text', 'unit', get_string('unit', 'quiz'));
|
||||
$mform->setType('unit', PARAM_NOTAGS);
|
||||
|
||||
$repeated[] =& $mform->createElement('text', 'multiplier', get_string('multiplier', 'quiz'));
|
||||
$mform->setType('multiplier', PARAM_NUMBER);
|
||||
|
||||
if (isset($that->question->options->units)){
|
||||
$countunits = count($that->question->options->units);
|
||||
} else {
|
||||
$countunits = 0;
|
||||
}
|
||||
if ($that->question->formoptions->repeatelements){
|
||||
$repeatsatstart = $countunits + 1;
|
||||
} else {
|
||||
$repeatsatstart = $countunits;
|
||||
}
|
||||
$that->repeat_elements($repeated, $repeatsatstart, array(), 'nounits', 'addunits', 2, get_string('addmoreunitblanks', 'qtype_calculated', '{no}'));
|
||||
|
||||
if ($mform->elementExists('multiplier[0]')){
|
||||
$firstunit =& $mform->getElement('multiplier[0]');
|
||||
$firstunit->freeze();
|
||||
$firstunit->setValue('1.0');
|
||||
$firstunit->setPersistantFreeze(true);
|
||||
$mform->addHelpButton('multiplier[0]', 'numericalmultiplier', 'qtype_numerical');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* function used in in function data_preprocessing() of edit_numerical_form.php for
|
||||
* numerical, calculated, calculatedsimple
|
||||
*/
|
||||
function set_numerical_unit_data($mform, &$question, &$default_values){
|
||||
|
||||
list($categoryid) = explode(',', $question->category);
|
||||
$context = $this->get_context_by_category_id($categoryid);
|
||||
|
||||
if (isset($question->options)){
|
||||
if (isset($question->options->unitpenalty)){
|
||||
$default_values['unitpenalty'] = $question->options->unitpenalty ;
|
||||
}
|
||||
$default_values['unitgradingtypes'] = 1 ;
|
||||
if (isset($question->options->unitgradingtype )&& isset($question->options->showunits ) ){
|
||||
if ( $question->options->unitgradingtype == 2 ) {
|
||||
$default_values['unitgradingtypes'] = 1 ;
|
||||
}
|
||||
if ( $question->options->unitgradingtype == 0 ) {
|
||||
$default_values['unitgradingtypes'] = 0 ;
|
||||
}
|
||||
switch ($question->options->showunits){
|
||||
case 0 :// NUMERICALQUESTIONUNITTEXTINPUTDISPLAY
|
||||
if($question->options->unitgradingtype == 0 ){
|
||||
$default_values['unitrole'] = 2 ;
|
||||
$default_values['multichoicedisplay'] = 0 ;
|
||||
}else { // 1 or 2
|
||||
$default_values['unitrole'] = 3 ;
|
||||
$default_values['multichoicedisplay'] = 0 ;
|
||||
$default_values['unitgradingtypes'] = $question->options->unitgradingtype ;
|
||||
}
|
||||
break;
|
||||
case 1 : // NUMERICALQUESTIONUNITMULTICHOICEDISPLAY
|
||||
$default_values['unitrole'] = 3 ;
|
||||
$default_values['multichoicedisplay'] = $question->options->unitgradingtype ;
|
||||
$default_values['unitgradingtypes'] = $question->options->unitgradingtype ;
|
||||
break;
|
||||
case 2 : // NUMERICALQUESTIONUNITTEXTDISPLAY
|
||||
$default_values['unitrole'] = 1 ;
|
||||
break;
|
||||
case 3 : // NUMERICALQUESTIONUNITNODISPLAY
|
||||
$default_values['unitrole'] = 0 ;
|
||||
// $default_values['showunits1'] = $question->options->showunits ;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isset($question->options->unitsleft)){
|
||||
$default_values['unitsleft'] = $question->options->unitsleft ;
|
||||
}
|
||||
|
||||
// processing files
|
||||
$component = 'qtype_' . $question->qtype;
|
||||
$draftid = file_get_submitted_draft_itemid('instruction');
|
||||
$default_values['instructions'] = array();
|
||||
if (isset($question->options->instructionsformat) && isset($question->options->instructions)){
|
||||
$default_values['instructions']['format'] = $question->options->instructionsformat;
|
||||
$default_values['instructions']['text'] = file_prepare_draft_area(
|
||||
$draftid, // draftid
|
||||
$context->id, // context
|
||||
$component, // component
|
||||
'instruction', // filarea
|
||||
!empty($question->id)?(int)$question->id:null, // itemid
|
||||
$mform->fileoptions, // options
|
||||
$question->options->instructions // text
|
||||
);
|
||||
}
|
||||
$default_values['instructions']['itemid'] = $draftid ;
|
||||
|
||||
if (isset($question->options->units)) {
|
||||
$units = array_values($question->options->units);
|
||||
if (!empty($units)) {
|
||||
foreach ($units as $key => $unit){
|
||||
$default_values['unit['.$key.']'] = $unit->unit;
|
||||
$default_values['multiplier['.$key.']'] = $unit->multiplier;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* function use in in function validation()
|
||||
* of edit_..._form.php for
|
||||
* numerical, calculated, calculatedsimple
|
||||
*/
|
||||
|
||||
function validate_numerical_options(& $data, & $errors){
|
||||
$units = $data['unit'];
|
||||
switch ($data['unitrole']){
|
||||
case '0' : $showunits = NUMERICALQUESTIONUNITNODISPLAY ;
|
||||
break ;
|
||||
case '1' : $showunits = NUMERICALQUESTIONUNITTEXTDISPLAY ;
|
||||
break ;
|
||||
case '2' : $showunits = NUMERICALQUESTIONUNITTEXTINPUTDISPLAY ;
|
||||
break ;
|
||||
case '3' : $showunits = $data['multichoicedisplay'] ;
|
||||
break ;
|
||||
}
|
||||
|
||||
if (($showunits == NUMERICALQUESTIONUNITTEXTINPUTDISPLAY) ||
|
||||
($showunits == NUMERICALQUESTIONUNITMULTICHOICEDISPLAY ) ||
|
||||
($showunits == NUMERICALQUESTIONUNITTEXTDISPLAY )){
|
||||
if (trim($units[0]) == ''){
|
||||
$errors['unit[0]'] = 'You must set a valid unit name' ;
|
||||
}
|
||||
}
|
||||
if ($showunits == NUMERICALQUESTIONUNITNODISPLAY ){
|
||||
if (count($units)) {
|
||||
foreach ($units as $key => $unit){
|
||||
if ($units[$key] != ''){
|
||||
$errors["unit[$key]"] = 'You must erase this unit name' ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Check double units.
|
||||
$alreadyseenunits = array();
|
||||
if (isset($data['unit'])) {
|
||||
foreach ($data['unit'] as $key => $unit) {
|
||||
$trimmedunit = trim($unit);
|
||||
if ($trimmedunit!='' && in_array($trimmedunit, $alreadyseenunits)) {
|
||||
$errors["unit[$key]"] = get_string('errorrepeatedunit', 'qtype_numerical');
|
||||
if (trim($data['multiplier'][$key]) == '') {
|
||||
$errors["multiplier[$key]"] = get_string('errornomultiplier', 'qtype_numerical');
|
||||
}
|
||||
} elseif($trimmedunit!='') {
|
||||
$alreadyseenunits[] = $trimmedunit;
|
||||
}
|
||||
}
|
||||
}
|
||||
$units = $data['unit'];
|
||||
if (count($units)) {
|
||||
foreach ($units as $key => $unit){
|
||||
if (is_numeric($unit)){
|
||||
$errors['unit['.$key.']'] = get_string('mustnotbenumeric', 'qtype_calculated');
|
||||
}
|
||||
$trimmedunit = trim($unit);
|
||||
$trimmedmultiplier = trim($data['multiplier'][$key]);
|
||||
if (!empty($trimmedunit)){
|
||||
if (empty($trimmedmultiplier)){
|
||||
$errors['multiplier['.$key.']'] = get_string('youmustenteramultiplierhere', 'qtype_calculated');
|
||||
}
|
||||
if (!is_numeric($trimmedmultiplier)){
|
||||
$errors['multiplier['.$key.']'] = get_string('mustbenumeric', 'qtype_calculated');
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function valid_unit($rawresponse, $units) {
|
||||
// Make units more useful
|
||||
$tmpunits = array();
|
||||
foreach ($units as $unit) {
|
||||
$tmpunits[$unit->unit] = $unit->multiplier;
|
||||
}
|
||||
// remove spaces and normalise decimal places.
|
||||
$search = array(' ', ',');
|
||||
$replace = array('', '.');
|
||||
$rawresponse = str_replace($search, $replace, trim($rawresponse));
|
||||
|
||||
// Apply any unit that is present.
|
||||
if (preg_match('~^([+-]?([0-9]+(\\.[0-9]*)?|\\.[0-9]+)([eE][-+]?[0-9]+)?)([^0-9].*)?$~',
|
||||
$rawresponse, $responseparts)) {
|
||||
|
||||
if (!empty($responseparts[5])) {
|
||||
|
||||
if (isset($tmpunits[$responseparts[5]])) {
|
||||
// Valid number with unit.
|
||||
return true ; //(float)$responseparts[1] / $tmpunits[$responseparts[5]];
|
||||
} else {
|
||||
// Valid number with invalid unit. Must be wrong.
|
||||
return false;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Valid number without unit.
|
||||
return false ; //(float)$responseparts[1];
|
||||
}
|
||||
}
|
||||
// Invalid number. Must be wrong.
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs all the code required to set up and save an essay question for testing purposes.
|
||||
* Alternate DB table prefix may be used to facilitate data deletion.
|
||||
@ -1338,7 +1048,7 @@ class qtype_numerical extends question_type {
|
||||
function check_file_access($question, $state, $options, $contextid, $component,
|
||||
$filearea, $args) {
|
||||
$itemid = reset($args);
|
||||
|
||||
|
||||
if ($component == 'question' && $filearea == 'answerfeedback') {
|
||||
$result = $options->feedback && array_key_exists($itemid, $question->options->answers);
|
||||
if (!$result) {
|
||||
@ -1363,7 +1073,6 @@ class qtype_numerical extends question_type {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This class processes numbers with units.
|
||||
*
|
||||
|
@ -46,7 +46,7 @@ class qtype_numerical_test extends UnitTestCase {
|
||||
}
|
||||
|
||||
public function tearDown() {
|
||||
$this->qtype = null;
|
||||
$this->qtype = null;
|
||||
}
|
||||
|
||||
protected function get_test_question_data() {
|
||||
|
@ -214,16 +214,19 @@ class question_type {
|
||||
public function create_editing_form($submiturl, $question, $category,
|
||||
$contexts, $formeditable) {
|
||||
global $CFG;
|
||||
require_once("{$CFG->dirroot}/question/type/edit_question_form.php");
|
||||
$definition_file = $CFG->dirroot . '/question/type/' . $this->name() .
|
||||
require_once($CFG->dirroot . '/question/type/edit_question_form.php');
|
||||
$definitionfile = $CFG->dirroot . '/question/type/' . $this->name() .
|
||||
'/edit_' . $this->name() . '_form.php';
|
||||
if (!(is_readable($definition_file) && is_file($definition_file))) {
|
||||
return null;
|
||||
if (!is_readable($definitionfile) || !is_file($definitionfile)) {
|
||||
throw new coding_exception($this->plugin_name() .
|
||||
' is missing the definition of its editing formin file ' . $definitionfile . '.');
|
||||
}
|
||||
require_once($definition_file);
|
||||
require_once($definitionfile);
|
||||
$classname = $this->plugin_name() . '_edit_form';
|
||||
if (!class_exists($classname)) {
|
||||
return null;
|
||||
throw new coding_exception($this->plugin_name() .
|
||||
' does not define the class ' . $this->plugin_name() .
|
||||
'_edit_form.');
|
||||
}
|
||||
return new $classname($submiturl, $question, $category, $contexts, $formeditable);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user