<div class="answer">
<fieldset class="answer" id="generalheader">
<legend class="ftoggler">
- <?php echo get_string('datasetnumber', 'quiz') ; ?>
+ <?php
+ echo $OUTPUT->help_icon('validnumberformats', 'qtype_numerical', '');
+ echo get_string('datasetnumber', 'quiz') ;
+ ?>
</legend>
<input type="text" class="<?php echo $class; ?>" <?php echo "$readonly $nameanswer $valueanswer"; //
?> size="<?php echo $textlength;?>" />
- <?php echo $feedbackimg; ?>
+ <?php echo $feedbackimg;
+ if(! $answerasterisk && $question->options->unitgradingtype != 0 && $unit_in_numerical_answer){
+ print_string('nonvalidcharactersinnumber', 'qtype_numerical');
+ }
+
+
+ ?>
</fieldset>
</div>
<div class="answer numerical ">
<fieldset class="clearfix" id="generalheader">
<legend class="ftoggler">
- <?php echo get_string('unit', 'quiz'); ?>
+ <?php
+ if ( $question->options->unitgradingtype == 0 ){
+ echo $OUTPUT->help_icon('unitoptional', 'qtype_numerical', '');
+ }else { // unitgradingtype == 1
+ echo $OUTPUT->help_icon('unitmandatory', 'qtype_numerical', '');
+ }
+ echo get_string('unit', 'quiz'); ?>
</legend>
<input type="text" class="<?php echo $classunit; ?>" <?php echo "$readonly $nameunit $valueunit"; //
?> size="<?php echo $textlength;?>"/>
<?php echo $feedbackimgunit;
- if ($options->feedback && $classunitvalue == 0 && ! $answerasterisk ){
- if(isset($question->options->units) && count($question->options->units) > 0){
- $found = 0 ;
- foreach($question->options->units as $key => $unit){
- if($state->responses['unit'] == $unit->unit){
- print_string('unitnotvalid', 'qtype_numerical');
- $found = 1 ;
- break;
+ if ($options->feedback && $question->options->unitgradingtype == 1 && ! $valid_numerical_unit && ! $answerasterisk ){
+ if ( $empty_unit) {
+ print_string('unitmandatory', 'qtype_numerical');
+ }else {
+ if(isset($question->options->units) && count($question->options->units) > 0){
+ $found = 0 ;
+ $valid_unit_found = 0 ;
+ foreach($question->options->units as $key => $unit){
+ if($state->responses['unit'] == $unit->unit){
+ print_string('unitnotvalid', 'qtype_numerical');
+ $valid_unit_found = 1 ;
+ break;
+ }
+ }
+ if ($valid_unit_found == 0) {
+ print_string('unitunknown', 'qtype_numerical');
}
- }
- if ($found == 0) {
- print_string('unitunknown', 'qtype_numerical');
}
}
}
-
?>
</fieldset>
</div>
<div class="answer">
<fieldset class="clearfix" id="generalheader">
<legend class="ftoggler">
- <?php echo get_string('unit', 'quiz');
+ <?php
+ echo get_string('selectunit', 'qtype_numerical');
?>
</legend>
- <!-- <div class="que multichoice clearfix">
- <div class="content"> class="answer"
- <div class="ablock clearfix"> -->
- <table >
+ <table >
<?php
// the order is not shuffled
//however the unitvalue is related to the number value
// if the response/unit->multiplier is true then
// the
-
+ // if(isset($state->responses['unit']) && $state->responses['unit'] != '' ){
+ $valid_numerical_unit_index = -1;
foreach ($question->options->units as $key => $unit) {
- $checked = '';
- $chosen = false;
- $classunitvalue = 0 ;
+ $checked = '';
+ $chosen = false;
+ $classunit = 0 ;
+ $feedbackimgunit = question_get_feedback_image(0);
+ $valid_numerical_unit = false ;
+ $validunit = false ;
$type = 'type="radio"';
- // $nameunit = "name=\"".$question->name_prefix;//."unit\"";
- if ($response != '' && isset($state->responses['unit']) && $state->responses['unit'] != '' ){
- // we have a unit response
- // this unit is the one chosen
- // test if the unit give a valid response
- $testresponse = $response /$unit->multiplier ;
- if($answerasterisk || ($answer->min <= $testresponse && $testresponse <= $answer->max)) {
- $classunitvalue = $answer->fraction ;
- }
- // echo "<p> dans display classunitvalue $classunitvalue response $response $unit->multiplier $unit->unit state <pre>";print_r($answer);echo "</pre></p>";
- if ($state->responses['unit'] == $unit->unit) {
- $checked = 'checked="checked"';
- $chosen = true;
-
+ // echo "<p> boucle unit $key $unit->unit answerfraction $answer->fraction classunit $classunit index $valid_numerical_unit_index $key response $response $unit->multiplier $unit->unit state <pre>";print_r($answer);echo "</pre></p>";
+ if(isset($state->responses['unit']) && $state->responses['unit'] != '' ){
+ // $nameunit = "name=\"".$question->name_prefix;//."unit\"";
+ // if (isset($response->number) && $response->number != false && isset($state->responses['unit']) && $state->responses['unit'] != '' ){
+ // if ($unit->unit == $state->responses['unit']){
+ // test if the numerical value as is or as multiplied by this unit
+ // could give a good response
+ // we need to extract the numerical and apply it with this unit
+ // as if it was used
+ $testresponse = $state->responses['answer']/$unit->multiplier ;
+ /* if(isset($state->responses['unit'])){
+ $testresponse .= $state->responses['unit'] ;
+ } */
+ $response = $this->apply_unit($testresponse, array($question->options->units[$key])) ;
+ $invalid_unit_found = 0 ;
+ if ($response !== false) {
+ $this->get_tolerance_interval($answer);
+ if($answer->min <= $response && $response <= $answer->max){
+ // then it could give a good response
+ // has it been used ?
+ $classunit = 1; // or max response i.e. 1
+ $feedbackimgunit = question_get_feedback_image($rawgrade);
+ $valid_numerical_unit = true ;
+ $validunit = true ;
+
+ $valid_numerical_unit_index = $key ;
+ }
}
- }else if ($key == 0) {
+ }
+ // if ($unit->unit == $state->responses['unit']){
+ // we have a valid unit response
+ if($answerasterisk || $valid_numerical_unit_index == $key ){
+ $classunit = $rawgrade ; //question_get_feedback_class(1) ; // ;
+ }
+ // we have a unit response
+ // this unit is the one chosen
+ // test if the unit give a valid response
+ // $testresponse = $response->number /$unit->multiplier ;
+ // if($answerasterisk || ($answer->min <= $testresponse && $testresponse <= $answer->max)) {
+ // $classunitvalue = $answer->fraction ;
+ // }
+ // echo "<p> dans display $answer->fraction classunit $classunit index $valid_numerical_unit_index $key response $response $unit->multiplier $unit->unit state <pre>";print_r($answer);echo "</pre></p>";
+ // if ($state->responses['unit'] == $unit->unit) {
+ if (isset($state->responses['unit']) && $unit->unit == $state->responses['unit']){
$checked = 'checked="checked"';
$chosen = true;
+ }else {
+ $checked = '';
}
-
- $aid = $question->id ;
- $a = new stdClass;
- $a->id = $question->name_prefix."unit" ;//. "2"
- $a->class = '' ;
- $a->feedbackimg = '';
-
- $a->control = "<input $readonly $nameunit $checked $type value=\"$key\" />";
-
- if ($options->correct_responses && $classunitvalue > 0 ) { //$answer->fraction
- $a->class = question_get_feedback_class($classunitvalue);
- }
- if (($options->feedback && $chosen) || $options->correct_responses) {
- $a->feedbackimg = question_get_feedback_image($classunitvalue, $chosen && $options->feedback);
- }
-
- // Print the control
- // Print the answer text
- $a->text = format_text($unit->unit, FORMAT_MOODLE, $formatoptions, $cmoptions->course);
- $row = 0 ;
-
+
+
+ $aid = $question->id ;
+ $a = new stdClass;
+ $a->id = $question->name_prefix."unit" ;//. "2"
+ $a->class = '' ;
+ $a->feedbackimg = '';
+
+ $a->control = "<input $readonly $nameunit $checked $type value=\"$key\" />";
+
+ if ($options->correct_responses && $classunit > 0 ) { //$answer->fraction
+ $a->class = question_get_feedback_class($classunit);
+ }
+ if (($options->feedback && $chosen) || $options->correct_responses) {
+ $a->feedbackimg = question_get_feedback_image($classunit, $chosen && $options->feedback);
+ }
+
+ // Print the control
+ // Print the answer text
+ $a->text = format_text($unit->unit, FORMAT_MOODLE, $formatoptions, $cmoptions->course);
+ $row = 0 ;
+
?>
<tr class="<?php echo 'r'.$row = $row ? 0 : 1; ?>">
<td class="c0 control " style=" ">
<label for="<?php echo $a->id ?>">
<?php echo $a->text.'<br />'; ?>
<?php echo $a->feedbackimg;
- if ($options->feedback && $classunitvalue == 0 && $chosen && !$answerasterisk){
+ if ($options->feedback && $classunit == 0 && $chosen && !$answerasterisk){
print_string('unitnotvalid', 'qtype_numerical');
+ }else {
+ echo ' ';
}
?>
</label>
</td>
</tr>
<?php } ?>
-
</table>
- <!-- </div>
- </div>
- </div> -->
- </fieldset>
-
-
+ <?php if ($options->feedback && isset($state->responses['answer'])&& $state->responses['answer'] != '' && (!isset($state->responses['unit']) || $state->responses['unit'] == '') && ! $answerasterisk ){
+
+ print_string('unitnotselected', 'qtype_numerical');
+ }
+ ?>
+
+ </fieldset>
</div>
<?php } // end unit choices
// display intructions
<div class="answer">
<fieldset class="clearfix" id="generalheader">
<legend class="ftoggler">
- <?php echo get_string('datasetnumber', 'quiz'); ?>
+ <?php
+ echo $OUTPUT->help_icon('validnumberformats', 'qtype_numerical', '');
+ echo get_string('datasetnumber', 'quiz');
+ ?>
</legend>
<input type="text" class="<?php echo $class; ?>" <?php echo "$readonly $nameanswer $valueanswer"; //
?> size="<?php echo $textlength;?>"/>
</div>
+ <?php if (!empty($question->options->instructions)){?>
<div class="feedback">
<fieldset class="clearfix" id="generalheader">
<legend class="ftoggler">
<?php echo get_string('instructions', 'auth'); ?>
</legend>
- <div class="feedback">
- <fieldset class="clearfix" id="generalheader">
- <legend class="ftoggler">
- <?php echo get_string('validnumberformats', 'qtype_numerical');?>
- </legend>
- <?php echo get_string('validnumbers', 'qtype_numerical');
-
- ?>
-
- </fieldset>
- </div>
- <?php if (!empty($question->options->instructions)){?>
<div>
<?php echo format_text($question->options->instructions, $question->options->instructionsformat, $formatoptions, $cmoptions->course);?>
</div>
- <?php }?>
</fieldset>
</div>
+ <?php }?>
<?php if ($feedback) { ?>
<div class="feedback">
return true;
}
+ function get_numerical_units(&$question) {
+ global $DB;
+ if ($units = $DB->get_records('question_numerical_units', array('question' => $question->id), 'id ASC')) {
+ $units = array_values($units);
+ } else {
+ $units = array();
+ }
+ foreach ($units as $key => $unit) {
+ $units[$key]->multiplier = clean_param($unit->multiplier, PARAM_NUMBER);
+ }
+ $question->options->units = $units;
+ return true;
+ }
+
+ function get_default_numerical_unit(&$question) {
+ if (isset($question->options->units[0])) {
+ foreach ($question->options->units as $unit) {
+ if (abs($unit->multiplier - 1.0) < '1.0e-' . ini_get('precision')) {
+ return $unit;
+ }
+ }
+ }
+ return false;
+ }
+
function get_numerical_options(&$question) {
global $DB;
if (!$options = $DB->get_record('question_numerical_options', array('question' => $question->id))) {
$question->options->unitgradingtype = 0; // total grade
- $question->options->unitpenalty = 0;
+ $question->options->unitpenalty = 0.1; // default for old questions
// the default
if ($defaultunit = $this->get_default_numerical_unit($question)) {
// so units can be graded
$question->options->showunits = NUMERICALQUESTIONUNITTEXTINPUTDISPLAY ;
- $question->options->unitpenalty = 1;
}else {
// only numerical will be graded
$question->options->showunits = NUMERICALQUESTIONUNITNODISPLAY ;
return true;
}
- function get_numerical_units(&$question) {
- global $DB;
- if ($units = $DB->get_records('question_numerical_units', array('question' => $question->id), 'id ASC')) {
- $units = array_values($units);
- } else {
- $units = array();
- }
- foreach ($units as $key => $unit) {
- $units[$key]->multiplier = clean_param($unit->multiplier, PARAM_NUMBER);
- }
- $question->options->units = $units;
- return true;
- }
-
- function get_default_numerical_unit(&$question) {
- if (isset($question->options->units[0])) {
- foreach ($question->options->units as $unit) {
- if (abs($unit->multiplier - 1.0) < '1.0e-' . ini_get('precision')) {
- return $unit;
- }
- }
- }
- return false;
- }
/**
* Save the units and the answers associated with this question.
if (trim($dataanswer) === '*') {
$answer->answer = '*';
} else {
- $answer->answer = $this->apply_unit_old($dataanswer, $units);
+ $answer->answer = $this->apply_unit($dataanswer, $units);
if ($answer->answer === false) {
$result->notice = get_string('invalidnumericanswer', 'quiz');
}
if (trim($question->tolerance[$key]) == '') {
$options->tolerance = '';
} else {
- $options->tolerance = $this->apply_unit_old($question->tolerance[$key], $units);
+ $options->tolerance = $this->apply_unit($question->tolerance[$key], $units);
if ($options->tolerance === false) {
$result->notice = get_string('invalidnumerictolerance', 'quiz');
}
return true;
}
+ /**
+ * The numerical options control the display and the grading of the unit
+ * part of the numerical question and related types (calculateds)
+ * Questions previous to 2,0 do not have this table as multianswer questions
+ * in all versions including 2,0. The default values are set to give the same grade
+ * as old question.
+ *
+ */
function save_numerical_options(&$question) {
global $DB;
+ // echo"<p> ".$question->id."question<pre>";print_r($question) ;echo"</pre></p>";
$result = new stdClass;
// numerical options
$options = new stdClass;
$options->question = $question->id;
}
- if(isset($question->unitgradingtype)){
- $options->unitgradingtype = $question->unitgradingtype;
+ if(isset($question->options->unitgradingtype)){
+ $options->unitgradingtype = $question->options->unitgradingtype;
}else {
$options->unitgradingtype = 0 ;
}
if(isset($question->unitpenalty)){
$options->unitpenalty = $question->unitpenalty;
- }else {
- $options->unitpenalty = 0 ;
+ }else { //so this is 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)){
- if ($question->unitrole == 0 ){
- $options->showunits = $question->showunits0;
- }else {
- $options->showunits = $question->showunits1;
+ 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 ;
}
- }else {
+ } else {
if(isset($question->showunits)){
$options->showunits = $question->showunits;
}else {
if ($defaultunit = $this->get_default_numerical_unit($question)) {
- // so units can be graded
+ // so units can be used
$options->showunits = NUMERICALQUESTIONUNITTEXTINPUTDISPLAY ;
}else {
// only numerical will be graded
$unitalreadyinsert[$question->unit[$i]] = 1 ;
$units[$i] = new stdClass;
$units[$i]->question = $question->id;
- $units[$i]->multiplier = $this->apply_unit_old($question->multiplier[$i], array());
+ $units[$i]->multiplier = $this->apply_unit($question->multiplier[$i], array());
$units[$i]->unit = $question->unit[$i];
$DB->insert_record('question_numerical_units', $units[$i]);
}
* the separate rendering of number and unit
*/
function print_question_formulation_and_controls(&$question, &$state, $cmoptions, $options) {
- global $CFG;
+ global $CFG, $OUTPUT;
+ //echo"<p> ".$question->id."question->options<pre>";print_r($question->options) ;echo"</pre></p>";
+ //echo"<p> ".$question->id."state<pre>";print_r($state) ;echo"</pre></p>";
+
$context = $this->get_context_by_category_id($question->category);
$readonly = empty($options->readonly) ? '' : 'readonly="readonly"';
$formatoptions = new stdClass;
// before i.e. at left or after at rigth of the unit variants.
$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'])){
$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
if (isset($state->responses['answer']) && $state->responses['answer']!='') {
$valueanswer = ' value="'.s($state->responses['answer']).'" ';
} else {
$answerasterisk = false ;
$response = '' ;
$valid_numerical_unit = false ;
+ $valid_numerical_unit_index = -1 ;
+ $unit_in_numerical_answer = false ;
$rawgrade = 0 ;
if ($options->feedback) {
$class = question_get_feedback_class(0);
$feedbackimg = question_get_feedback_image(0);
$feedbackimgunit = question_get_feedback_image(0);
$classunitvalue = 0 ;
+ $valid_numerical_unit_index = -1 ;
+ // if there is unit in answer and unitgradingtype = 0
+ // the grade is 0
//this is OK for the first answer with a good response
// having to test for * so response as long as not empty
- $response = $this->extract_numerical_response($state->responses['answer']);
- $break = 0 ;
+ // $response = $this->extract_numerical_response($state->responses['answer']);
+ // test for a greater than 0 grade
foreach($question->options->answers as $answer) {
- // if * then everything has the $answer->fraction value
- if ($answer->answer !== '*' ) {
- $this->get_tolerance_interval($answer);
- }
-
- $answer->feedback = quiz_rewrite_question_urls($answer->feedback, 'pluginfile.php', $context->id, 'question', 'answerfeedback', array($state->attempt, $state->question), $answer->id);
- if ($answer->answer === '*') {
- $answerasterisk = true ;
- $rawgrade = $answer->fraction ;
+ if ($this->test_response($question, $state, $answer)) {
+ // Answer was correct or partially correct.
+ if ( $answer->answer === '*'){
+ $answerasterisk = true ;
+ }
+ // in all cases
$class = question_get_feedback_class($answer->fraction);
$feedbackimg = question_get_feedback_image($answer->fraction);
- $classunitvalue = $class ;
- $classunit = question_get_feedback_class($answer->fraction);
- $feedbackimgunit = question_get_feedback_image($answer->fraction, $options->feedback);
- if ($answer->feedback) {
- $feedback = format_text($answer->feedback, true, $formatoptions, $cmoptions->course);
- }
- if ( isset($question->options->units))
- {
- $valid_numerical_unit = true ;
- }
- $break = 1 ;
- } else if ($response !== false && isset($question->options->units) && count($question->options->units) > 0) {
- $hasunits = 1 ;
- foreach($question->options->units as $key => $unit){
- // The student did type a number, so check it with tolerances.
- $testresponse = $response /$unit->multiplier ;
- if($answer->min <= $testresponse && $testresponse <= $answer->max) {
- $unittested = $unit->unit ;
- $rawgrade = $answer->fraction ;
- $class = question_get_feedback_class($answer->fraction);
- $feedbackimg = question_get_feedback_image($answer->fraction);
- if ($answer->feedback) {
- $feedback = format_text($answer->feedback, true, $formatoptions, $cmoptions->course);
- }
- if($state->responses['unit'] == $unit->unit){
- $classunitvalue = $answer->fraction ;
+ 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
+ // then number - unit combination has been used to test response
+ // so the unit should have same color
+ $classunit = question_get_feedback_class($answer->fraction);
+ $feedbackimgunit = question_get_feedback_image($answer->fraction);
+ $rawgrade = $answer->fraction ;
+
+
+ }else {
+ // so we need to apply unit grading i.e. to check if the number-unit combination
+ // was the rigth one
+ // on NUMERICALQUESTIONUNITTEXTINPUTDISPLAY we need only to ckeck if applyunit will test OK
+ // with the $state->responses['unit'] value which cannot be empty
+ // if $state->responses['unit']
+ // if apply-unit is true with a specific unit as long as the unit as been written either in the
+ // we need the numerical response and test it with the available units
+ // if the unit used is good then it should be set OK
+ // however the unit could have been put in the number element in this case
+ // the unit penalty should be apllied.
+ // testing apply_unit with no units will get us a false response if there is any text in it
+ // testing apply_unit with a given unit will get a good value if the number is good with this unit
+ // apply unit will return the numerical if
+ // we need to know which conditions let to a good numerical value that were done in the
+ //
+ // echo"<p> unit grading > 0 asterisk <pre>";print_r($answer) ;echo"</pre></p>";
+ $valid_numerical_unit = false ;
+ $validunit = false ;
+ $rawgrade = $answer->fraction ;
+ $valid_numerical_unit_index = -1 ;
+ $invalid_unit_in_numerical_answer = false ;
+ if ( $answerasterisk ) {
+ $classunit = question_get_feedback_class($answer->fraction);
+ $feedbackimgunit = question_get_feedback_image($answer->fraction);
+ $valid_numerical_unit = true ;//everything is true with *
+ //echo"<p> answer asterisk <pre>";print_r($answer) ;echo"</pre></p>";
+ } else {
+ //echo"<p> else after answer asterisk <pre>";print_r($answer) ;echo"</pre></p>";
+ // 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 != ''){
+ $unit_in_numerical_answer = true ;
}else {
- $classunitvalue == 0 ;
+ $unit_in_numerical_answer = false ;
}
- $classunit = question_get_feedback_class($classunitvalue);
- $feedbackimgunit = question_get_feedback_image($classunitvalue, $options->feedback);
- $break = 1 ;
- break;
- }
+
+ // the we let the testing to the two cases either
+ // NUMERICALQUESTIONUNITTEXTINPUTDISPLAY or
+ // NUMERICALQUESTIONUNITMULTICHOICEDISPLAY
+ 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);
+ $feedbackimgunit = question_get_feedback_image(0);
+ $empty_unit = true ;
+ } else {
+ // echo"<p> some unit answer <pre>";print_r($answer) ;echo"</pre></p>";
+ // echo"<p> some unit answer <pre>";print_r($answer) ;echo"</pre></p>";
+ $empty_unit = false ;
+ $valid_numerical_unit = false ;
+
+ foreach ($question->options->units as $key => $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 ;
+ if ($response->number !== false) {
+ //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){
+ //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);
+ $valid_numerical_unit = true ;
+ $validunit = true ;
+ $valid_numerical_unit_index = $key ;
+ break ;
+ }
+ }
+ } // else
+
+ // }
+ }
+ //echo "<p> apres la boucle valid_numerical_unit $valid_numerical_unit valid_numerical_unit_index $valid_numerical_unit_index </p>";
+
+ }
+ }
}
- } else if($response !== false && ($answer->min <= $response && $response <= $answer->max) ) {
- $rawgrade = $answer->fraction ;
- $class = question_get_feedback_class($answer->fraction);
- $feedbackimg = question_get_feedback_image($answer->fraction);
+ // echo "<p> dans valid_numerical_unit_index $valid_numerical_unit_index </p>";
if ($answer->feedback) {
- $feedback = format_text($answer->feedback, $answer->feedbackformat, $formatoptions, $cmoptions->course);
+ $answer->feedback = quiz_rewrite_question_urls($answer->feedback, 'pluginfile.php', $context->id, 'question', 'answerfeedback', array($state->attempt, $state->question), $answer->id);
+ $feedback = format_text($answer->feedback, true, $formatoptions, $cmoptions->course);
}
- $break = 1 ;
- }
- if ($break) {
+
break;
}
}
- }
+
+
+ }
+ // echo "<p> rawgrade $rawgrade classunit $classunit valid_numerical_unit_index $valid_numerical_unit_index ".$feedbackimgunit."</p>";
$state->options->raw_unitpenalty = 0 ;
$raw_unitpenalty = 0 ;
if( $question->options->showunits == NUMERICALQUESTIONUNITNODISPLAY ||
$classunitvalue = 1 ;
}
-
- if($classunitvalue == 0){
+ 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 {
function compare_responses(&$question, $state, $teststate) {
- if ($question->options->showunits == NUMERICALQUESTIONUNITMULTICHOICEDISPLAY && isset($question->options->units) && 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;
};
*/
function test_response(&$question, &$state, $answer ) {
// Deal with the match anything answer.
+ // echo"<p> test_response answer <pre>";print_r($answer) ;echo"</pre></p>";
+ // echo"<p>test_response state <pre>";print_r($state) ;echo"</pre></p>";
if ($answer->answer === '*') {
return true;
}
- /* To be able to test (old) questions that do not have an unit
- * input element the test is done using the $state->responses['']
- * which contains the response which is analyzed by extract_numerical_response()
- * If the data comes from the numerical or calculated display
- * the $state->responses['unit'] comes from either
- * a multichoice radio element NUMERICALQUESTIONUNITMULTICHOICEDISPLAY
- * where the $state->responses['unit'] value is the key => unit object
- * in the the $question->options->units array
- * or an input text element NUMERICALUNITTEXTINPUTDISPLAY
- * which contains the student response
- * for NUMERICALQUESTIONUNITTEXTDISPLAY and NUMERICALQUESTIONUNITNODISPLAY
- *
- */
-
- if (!isset($state->responses['answer']) && isset($state->responses[''])){
- $state->responses['answer'] = $state->responses[''];
- }
- $response = $this->extract_numerical_response($state->responses['answer']);
- if ($response === false) {
- return false; // The student did not type a number.
- }
- // The student did type a number, so check it with tolerances.
- $this->get_tolerance_interval($answer);
- if ($answer->min <= $response && $response <= $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){
- $testresponse = $response /$unit->multiplier ;
- if($answer->min <= $testresponse && $testresponse<= $answer->max) {
- return true;
- }
+ // using old grading process if $question->unitgradingtype == 0
+ // and adding unit1 for the new option NUMERICALQUESTIONUNITTEXTDISPLAY
+ if ($question->options->unitgradingtype == 0 ){
+ // values coming form old question stored in attempts
+ 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(isset($state->responses['unit'])) {
+ $answertotest .= $state->responses['unit'] ;
+ }
+ // 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
+ $response = $this->apply_unit($answertotest, $question->options->units);
+ // echo"<p> dans response apres apply <pre>";print_r($response) ;echo"</pre></p>";
+
+ if ($response === false) {
+ return false; // The student did not type a number.
+ }
+
+ // The student did type a number, so check it with tolerances.
+ $this->get_tolerance_interval($answer);
+ // echo"<p> test_response apres get tolerance interval answer <pre>";print_r($answer) ;echo"</pre></p>";
+ return ($answer->min <= $response && $response <= $answer->max);
+ }else { // $question->options->unitgradingtype > 0
+ /* testing with unitgradingtype $question->options->unitgradingtype > 0
+ * if the response is at least patially true
+ * if the numerical value agree in the interval
+ * if so the only non valid case will be a bad unit and a unity penalty.
+
+ To be able to test (old) questions that do not have an unit
+ * input element the test is done using the $state->responses['']
+ * which contains the response which is analyzed by extract_numerical_response()
+ * If the data comes from the numerical or calculated display
+ * the $state->responses['unit'] comes from either
+ * a multichoice radio element NUMERICALQUESTIONUNITMULTICHOICEDISPLAY
+ * where the $state->responses['unit'] value is the key => unit object
+ * in the the $question->options->units array
+ * or an input text element NUMERICALQUESTIONUNITTEXTINPUTDISPLAY
+ * which contains the student response
+ * for NUMERICALQUESTIONUNITTEXTDISPLAY and NUMERICALQUESTIONUNITNODISPLAY
+ *
+ */
+
+ $response = $this->extract_numerical_response($state->responses['answer']);
+
+ // echo"<p> response <pre>";print_r($response) ;echo"</pre></p>";
+ // echo"<p> response <pre>";print_r($response) ;echo"</pre></p>";
+
+ if ($response->number === false ) {
+ return false; // The student did not type a number.
}
+
+ // 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){
+ // echo"<p> response true <pre>";print_r($response) ;echo"</pre></p>";
+ return true;
+ }
+ // testing for other units
+ if ( isset($question->options->units) && count($question->options->units) > 0) {
+ foreach($question->options->units as $key =>$unit){
+ $testresponse = $response->number /$unit->multiplier ;
+ if($answer->min <= $testresponse && $testresponse<= $answer->max) {
+ return true;
+ }
+ }
+ }
+ return false;
}
return false;
}
* @param object $cmoptions
*/
function grade_responses(&$question, &$state, $cmoptions) {
- if (!isset($state->responses['answer']) && isset($state->responses[''])){
+ // echo"<p>grade question->options<pre>";print_r($question->options) ;echo"</pre></p>";
+ // echo"<p>grade state response<pre>";print_r($state->responses) ;echo"</pre></p>";
+ /* if (!isset($state->responses['answer']) && isset($state->responses[''])){
$state->responses['answer'] = $state->responses[''];
+ }*/
+ 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'] );
}
//to apply the unit penalty we need to analyse the response in a more complex way
//the apply_unit() function analysis could be used to obtain the infos
// however it is used to detect good or bad numbers but also
- // gives false
+ // gives false if there is a unit
$state->raw_grade = 0;
$valid_numerical_unit = false ;
$break = 0 ;
$unittested = '';
$hasunits = 0 ;
- $response = $this->extract_numerical_response($state->responses['answer']);
+ // $response = $this->extract_numerical_response($state->responses['answer']);
$answerasterisk = false ;
$break = 0 ;
foreach($question->options->answers as $answer) {
- if ($answer->answer !== '*' ) {
- // The student did type a number, so check it with tolerances.
- $this->get_tolerance_interval($answer);
- }
-
- // if * then everything is OK even unit
- if ($answer->answer === '*') {
- $state->raw_grade = $answer->fraction;
- if ( isset($question->options->units)){
- $valid_numerical_unit = true ;
- }
- $answerasterisk = true ;
- $break = 1 ;
- }else if ($response !== false && isset($question->options->units) && count($question->options->units) > 0) {
- $hasunits = 1 ;
- foreach($question->options->units as $key => $unit){
- $testresponse = $response /$unit->multiplier ;
-
- if($answer->min <= $testresponse && $testresponse <= $answer->max) {
- $state->raw_grade = $answer->fraction;
- $unittested = $unit->unit ;
- $break = 1 ;
- break;
+ 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 * then unit has the $answer->fraction value
+ // if $question->options->unitgradingtype == 0 everything has been checked
+ // if $question->options->showunits == NUMERICALQUESTIONUNITTEXTINPUTDISPLAY
+ // then number - unit combination has been used to test response
+ // so the unit should have same color
+
+ }else {
+ // so we need to apply unit grading i.e. to check if the number-unit combination
+ // was the rigth one
+ $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'] != '' ){
+ foreach ($question->options->units as $key => $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){
+ $valid_numerical_unit = true ;
+ }
+ }
+ break ;
+ }
+ }
}
}
- }else if ($response !== false) {
- if($this->test_response($question, $state, $answer)) {
- $state->raw_grade = $answer->fraction;
- break;
- }
- }
- if ($break) break;
- } //foreach($question->options
-
- // in all cases the unit should be tested
- if( $question->options->showunits == NUMERICALQUESTIONUNITNODISPLAY ||
- $question->options->showunits == NUMERICALQUESTIONUNITTEXTDISPLAY ) {
- $valid_numerical_unit = true ;
- }else {
- // $valid_numerical_unit means that the grading was done with the unit defined
- //
- if ($hasunits && !$answerasterisk ){
- $valid_numerical_unit = ($state->responses['unit'] == $unittested) ;
- } else {
- $valid_numerical_unit = true ;
- }
+ break ;
+ }
}
-
// apply unit penalty
$raw_unitpenalty = 0 ;
- if(!empty($question->options->unitpenalty)&& $valid_numerical_unit != true ){
+ 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 {
}
$state->raw_grade -= $raw_unitpenalty ;
}
-
+
// Make sure we don't assign negative or too high marks.
$state->raw_grade = min(max((float) $state->raw_grade,
0.0), 1.0) * $question->maxgrade;
-
+
// Update the penalty.
$state->penalty = $question->penalty * $question->maxgrade;
* account as a float.
*/
function extract_numerical_response($rawresponse) {
+ $extractedresponse = new stdClass() ;
$rawresponse = trim($rawresponse) ;
$search = array(' ', ',');
// test if a . is present or there are multiple , (i.e. 2,456,789 ) so that we don't need spaces and ,
if (preg_match('~^([+-]?([0-9]+(\\.[0-9]*)?|\\.[0-9]+)([eE][-+]?[0-9]+)?)([^0-9].*)?$~',
$rawresponse, $responseparts)) {
- return (float)$responseparts[1] ;
+ //return (float)$responseparts[1] ;
+ $extractedresponse->number = (float)$responseparts[1] ;
+ }else {
+ $extractedresponse->number = false ;
+ }
+ if (!empty($responseparts[5])) {
+ $extractedresponse->unit = $responseparts[5] ;
+ }else {
+ $extractedresponse->unit = '';
}
+
// Invalid number. Must be wrong.
- return false;
+ return clone($extractedresponse) ;
}
/**
* Checks if the $rawresponse has a unit and applys it if appropriate.
* @return float The rawresponse with the unit taken into
* account as a float.
*/
- function apply_unit_old($rawresponse, $units) {
+ function apply_unit($rawresponse, $units) {
+ // echo"<p> rawresponse $rawresponse <pre>";print_r($units) ;echo"</pre></p>";
+
// Make units more useful
$tmpunits = array();
foreach ($units as $unit) {
// Apply any unit that is present.
if (ereg('^([+-]?([0-9]+(\\.[0-9]*)?|\\.[0-9]+)([eE][-+]?[0-9]+)?)([^0-9].*)?$',
$rawresponse, $responseparts)) {
+ // echo"<p> responseparts <pre>";print_r($responseparts) ;echo"</pre></p>";
if (!empty($responseparts[5])) {
* numerical, calculated, calculatedsimple
*/
function add_units_options(&$mform, &$that){
- $mform->addElement('header', 'unithandling', get_string('unitshandling', 'qtype_numerical'));
// Units are graded
- $mform->addElement('radio', 'unitrole', get_string('unitgraded1', 'qtype_numerical'), get_string('unitgraded', 'qtype_numerical'),0);
+ $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('header', 'unithandling1', get_string('unitnotgraded', 'qtype_numerical'));
+ $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);
+ /* $showunits1grp = array();
+ $showunits1grp[] = & $mform->createElement('radio', 'showunits1', '', get_string('no', 'moodle'),3);
+ $showunits1grp[] = & $mform->createElement('radio', 'showunits1', '', get_string('yes', 'moodle'),2);*/
+ // $mform->addGroup($showunits1grp, 'showunits1grp', get_string('unitdisplay', 'qtype_numerical'),' ' , false);
+ $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('decfractionofquestiongrade', 'qtype_numerical'), '2' => get_string('decfractionofresponsegrade', 'qtype_numerical'));
- $penaltygrp[] =& $mform->createElement('select', 'unitgradingtype', '' , $unitgradingtypes );
+ $penaltygrp[] =& $mform->createElement('select', 'unitgradingtypes', '' , $unitgradingtypes );
$mform->addGroup($penaltygrp, 'penaltygrp', get_string('unitpenalty', 'qtype_numerical'),' ' , false);
- $showunits0grp = array();
- $showunits0grp[] =& $mform->createElement('radio', 'showunits0', get_string('unitedit', 'qtype_numerical'), get_string('editableunittext', 'qtype_numerical'),0);
- $showunits0grp[] =& $mform->createElement('radio', 'showunits0', get_string('selectunits', 'qtype_numerical') , get_string('unitchoice', 'qtype_numerical'),1);
- $mform->addGroup($showunits0grp, 'showunits0grp', get_string('studentunitanswer', 'qtype_numerical'),' OR ' , 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);
- $mform->addElement('static', 'separator1', '<HR/>', '<HR/>');
+// $mform->addElement('static', 'separator1', '<HR/>', '<HR/>');
// Units are not graded
- $mform->addElement('radio', 'unitrole', get_string('unitnotgraded', 'qtype_numerical'), get_string('onlynumerical', 'qtype_numerical'),1);
$showunits1grp = array();
- $showunits1grp[] = & $mform->createElement('radio', 'showunits1', '', get_string('no', 'moodle'),3);
- $showunits1grp[] = & $mform->createElement('radio', 'showunits1', '', get_string('yes', 'moodle'),2);
- $mform->addGroup($showunits1grp, 'showunits1grp', get_string('unitdisplay', 'qtype_numerical'),' ' , false);
- $unitslefts = array('0' => get_string('rightexample', 'qtype_numerical'),'1' => get_string('leftexample', 'qtype_numerical'));
$mform->addElement('static', 'separator2', '<HR/>', '<HR/>');
- $mform->addElement('select', 'unitsleft', get_string('unitposition', 'qtype_numerical') , $unitslefts );
- $currentgrp1 = array();
$mform->setType('unitpenalty', PARAM_NUMBER);
$mform->setDefault('unitpenalty', 0.1);
- $mform->setDefault('unitgradingtype', 1);
- // $mform->addHelpButton('penaltygrp', 'unitpenalty', 'qtype_numerical'); // TODO help did not exist before MDL-21695
- $mform->setDefault('showunits0', 0);
- $mform->setDefault('showunits1', 3);
+ $mform->setDefault('unitgradingtypes', 1);
+ $mform->addHelpButton('penaltygrp', 'unitpenalty', 'qtype_numerical'); // TODO help did not exist before MDL-21695
+ // $mform->setDefault('multichoicedisplay', 1);
+ // $mform->setDefault('showunits1', 3);
$mform->setDefault('unitsleft', 0);
$mform->setType('instructions', PARAM_RAW);
+ // $mform->addHelpButton('instructions', 'unituses', 'qtype_numerical');
$mform->addHelpButton('instructions', 'numericalinstructions', 'qtype_numerical');
+ $mform->disabledIf('penaltygrp', 'unitrole','eq','0');
$mform->disabledIf('penaltygrp', 'unitrole','eq','1');
- $mform->disabledIf('unitgradingtype', 'unitrole','eq','1');
- $mform->disabledIf('instructions', 'unitrole','eq','1');
- $mform->disabledIf('unitsleft', 'showunits1','eq','3');
- $mform->disabledIf('showunits1','unitrole','eq','0');
- $mform->disabledIf('showunits0','unitrole','eq','1');
+ $mform->disabledIf('penaltygrp', 'unitrole','eq','2');
+ // $mform->disabledIf('unitgradingtype', 'unitrole','eq','1');
+ // $mform->disabledIf('instructions', 'unitrole','eq','1');
+ $mform->disabledIf('unitsleft', 'unitrole','eq','0');
+ // $mform->disabledIf('showunits1','unitrole','eq','0');
+ $mform->disabledIf('multichoicedisplay','unitrole','eq','0');
+ $mform->disabledIf('multichoicedisplay','unitrole','eq','1');
+ $mform->disabledIf('multichoicedisplay','unitrole','eq','2');
}
$context = $this->get_context_by_category_id($categoryid);
if (isset($question->options)){
- $default_values['unitgradingtype'] = $question->options->unitgradingtype ;
+ $default_values['unitgradingtypes'] = 1 ;
+ if ($question->options->unitgradingtype == 2 ) {
+ $default_values['unitgradingtypes'] = 1 ;
+ }
+ if ($question->options->unitgradingtype == 0 ) {
+ $default_values['unitgradingtypes'] = 0 ;
+ }
$default_values['unitpenalty'] = $question->options->unitpenalty ;
switch ($question->options->showunits){
- case 'O' :
- case '1' :
- $default_values['showunits0'] = $question->options->showunits ;
- $default_values['unitrole'] = 0 ;
+ 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' :
- case '3' :
- $default_values['showunits1'] = $question->options->showunits ;
+ case 2 : // NUMERICALQUESTIONUNITTEXTDISPLAY
$default_values['unitrole'] = 1 ;
+ case 3 : // NUMERICALQUESTIONUNITNODISPLAY
+ $default_values['unitrole'] = 0 ;
+ // $default_values['showunits1'] = $question->options->showunits ;
break;
}
$default_values['unitsleft'] = $question->options->unitsleft ;
+ // $question->unitrole = $default_values['unitrole'] ;
// processing files
$component = 'qtype_' . $question->qtype;
function validate_numerical_options(& $data, & $errors){
$units = $data['unit'];
- if ($data['unitrole'] == 0 ){
- $showunits = $data['showunits0'];
- }else {
- $showunits = $data['showunits1'];
- }
+ 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 ) ||
}
}
-
+
function valid_unit($rawresponse, $units) {
// Make units more useful