MDL-24503 recoding unit grading options
authorPierre Pichet <pichet.pierre@uqam.ca>
Sat, 30 Oct 2010 15:14:57 +0000 (15:14 +0000)
committerPierre Pichet <pichet.pierre@uqam.ca>
Sat, 30 Oct 2010 15:14:57 +0000 (15:14 +0000)
question/type/numerical/display.html
question/type/numerical/edit_numerical_form.php
question/type/numerical/lang/en/qtype_numerical.php
question/type/numerical/questiontype.php

index c81bd1e..953f27f 100644 (file)
   <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 '&nbsp;&nbsp;&nbsp;';
                         }
 ?>
                                 </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">
index 8ed3aff..ff56c24 100644 (file)
@@ -86,15 +86,6 @@ class question_edit_numerical_form extends question_edit_form {
             }
             $QTYPES['numerical']->set_numerical_unit_data($this, $question, $default_values);
 
-          /*  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;
-                    }
-                }
-            }*/
             $question = (object)((array)$question + $default_values);
         }
         return $question;
index f6dd723..642a971 100644 (file)
@@ -37,6 +37,7 @@ $string['errorrepeatedunit'] = 'You cannot have two units with the same name.';
 $string['instructions'] = 'Instructions ';
 $string['leftexample'] = 'LEFT as $1.00';
 $string['noneditableunittext'] = 'NON editable text of Unit No1';
+$string['nonvalidcharactersinnumber'] = 'NON valid characters in number';
 $string['notenoughanswers'] = 'You must enter at least one answer.';
 $string['nounitdisplay'] = 'No unit grading';
 $string['numerical'] = 'Numerical';
@@ -56,22 +57,62 @@ 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['onlynumerical'] = 'Only NUMERICAL ANSWER will be graded';
+$string['manynumerical'] = 'Only the NUMERICAL ANSWER will be graded using optional units ';
+$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['rightexample'] = 'RIGHT as 1.00cm';
 $string['selectunits'] = 'Select units';
+$string['selectunit'] = 'Select one unit';
 $string['studentunitanswer'] = 'UNIT ANSWER displayed as a ';
 $string['unitchoice'] = 'Multichoice (radio elements)';
-$string['unitdisplay'] = 'Display Unit1';
+$string['unitdisplay'] = '<STRONG>Unit 1 displayed </STRONG>';
 $string['unitedit'] = 'Edit unit';
-$string['unitgraded'] = ' NUMERICAL  ANSWER and UNIT ANSWER will be graded ';
+$string['unitgraded'] = ' NUMERICAL ANSWER and UNIT ANSWER will be graded ';
 $string['unitgraded1'] = '<STRONG>UNIT GRADED</STRONG>';
+$string['unitsused'] = '<STRONG>UNIT USED</STRONG>';
 $string['unithdr'] = 'Unit {$a}';
+$string['unitmandatory'] = 'Mandatory';
+$string['unitmandatory_help'] = '
+
+* The response will be graded using the unit written.  
+
+* 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['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'] = 'Penalty for bad 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 ';
 $string['unitappliedpenalty'] = 'These marks include a penalty of {$a} for bad unit.';
 $string['unitposition'] = 'Unit position';
+$string['unitnotselected'] = 'No unit selected';
 $string['unitshandling'] = 'Units handling';
 $string['validnumberformats'] = 'Valid number formats';
+$string['validnumberformats_help'] = '
+* regular numbers  13500.67 : 13 500.67 : 13500,67: 13 500,67
+
+* if you use , as thousand separator *always* put the decimal . as in 
+ 13,500.67 : 13,500.
+* for exponent form, say 1.350067 * 10<sup>4</sup>, use  
+ 1.350067 E4 : 1.350067 E04 ';
+
 $string['validnumbers'] = ' 13500.67 : 13 500.67 : 13,500.67 : 13500,67: 13 500,67 : 1.350067 E4 : 1.350067 E04 ';
index 02ec82c..89cf396 100644 (file)
@@ -87,16 +87,40 @@ class question_numerical_qtype extends question_shortanswer_qtype {
 
         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 ;
@@ -116,30 +140,6 @@ class question_numerical_qtype extends question_shortanswer_qtype {
         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.
@@ -178,7 +178,7 @@ class question_numerical_qtype extends question_shortanswer_qtype {
             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');
                 }
@@ -212,7 +212,7 @@ class question_numerical_qtype extends question_shortanswer_qtype {
             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');
                 }
@@ -249,8 +249,17 @@ class question_numerical_qtype extends question_shortanswer_qtype {
         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
@@ -261,29 +270,36 @@ class question_numerical_qtype extends question_shortanswer_qtype {
             $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
@@ -342,7 +358,7 @@ class question_numerical_qtype extends question_shortanswer_qtype {
                 $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]);
             }
@@ -438,7 +454,10 @@ class question_numerical_qtype extends question_shortanswer_qtype {
     * 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;
@@ -466,9 +485,11 @@ class question_numerical_qtype extends question_shortanswer_qtype {
         // 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 {
@@ -492,6 +513,8 @@ class question_numerical_qtype extends question_shortanswer_qtype {
         $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);
@@ -499,71 +522,129 @@ class question_numerical_qtype extends question_shortanswer_qtype {
             $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 ||
@@ -571,8 +652,7 @@ class question_numerical_qtype extends question_shortanswer_qtype {
                     $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 {
@@ -588,7 +668,7 @@ class question_numerical_qtype extends question_shortanswer_qtype {
 
     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;
         };
 
@@ -624,43 +704,84 @@ class question_numerical_qtype extends question_shortanswer_qtype {
      */
     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;
     }
@@ -689,75 +810,67 @@ class question_numerical_qtype extends question_shortanswer_qtype {
     * @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 {
@@ -765,11 +878,11 @@ class question_numerical_qtype extends question_shortanswer_qtype {
             }
             $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;
 
@@ -892,6 +1005,7 @@ class question_numerical_qtype extends question_shortanswer_qtype {
      *                             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 ,
@@ -904,10 +1018,19 @@ class question_numerical_qtype extends question_shortanswer_qtype {
 
          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.
@@ -918,7 +1041,9 @@ class question_numerical_qtype extends question_shortanswer_qtype {
      * @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) {
@@ -939,6 +1064,7 @@ class question_numerical_qtype extends question_shortanswer_qtype {
         // 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])) {
 
@@ -965,47 +1091,63 @@ class question_numerical_qtype extends question_shortanswer_qtype {
     * 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');
 
 
     }
@@ -1056,21 +1198,39 @@ class question_numerical_qtype extends question_shortanswer_qtype {
         $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;
@@ -1108,11 +1268,16 @@ class question_numerical_qtype extends question_shortanswer_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 ) ||
@@ -1168,7 +1333,7 @@ class question_numerical_qtype extends question_shortanswer_qtype {
             }
 
     }
-
 
     function valid_unit($rawresponse, $units) {
         // Make units more useful