]> git.mjollnir.org Git - moodle.git/commitdiff
MDL-17366 adding the calculatedsimple questiontype
authorpichetp <pichetp>
Fri, 29 May 2009 22:42:22 +0000 (22:42 +0000)
committerpichetp <pichetp>
Fri, 29 May 2009 22:42:22 +0000 (22:42 +0000)
lang/en_utf8/qtype_calculatedsimple.php [new file with mode: 0644]
question/type/calculatedsimple/edit_calculatedsimple_form.php [new file with mode: 0644]
question/type/calculatedsimple/icon.gif [new file with mode: 0644]
question/type/calculatedsimple/questiontype.php [new file with mode: 0644]

diff --git a/lang/en_utf8/qtype_calculatedsimple.php b/lang/en_utf8/qtype_calculatedsimple.php
new file mode 100644 (file)
index 0000000..4fd496f
--- /dev/null
@@ -0,0 +1,15 @@
+<?php
+$string['addingcalculatedsimple'] = 'Adding a Simple Calculated question';
+$string['calculatedsimple'] = 'Calculated Simple ';
+$string['calculatedsimplesummary'] = 'A simpler version of calculated questions which are like numerical questions but with the numbers used selected randomly from a set when the quiz is taken.';
+$string['converttocalculated'] = 'Save as a new regular calculated question';
+$string['editingcalculatedsimple'] = 'Editing a Simple Calculated question';
+$string['findwildcards']='Find the wild cards {x..} present in the correct answer formulas';
+$string['generatenewitemsset'] = 'Generate a new set of ';
+$string['mustbenumeric'] = 'You must enter a number here.';
+$string['mustnotbenumeric'] = 'This can\'t be a number.';
+$string['wildcarditems']= 'Items generated';
+$string['wildcardrole']= ' The wild cards <strong>{x..}</strong> will be substituted by a numerical value from the generated values';
+$string['wildcardparam']= 'Wild cards parameters used to generate the items ';
+$string['willconverttocalculated']= 'If set, the <strong>Save as new question</strong> will save as a new calculated question';
+?>
\ No newline at end of file
diff --git a/question/type/calculatedsimple/edit_calculatedsimple_form.php b/question/type/calculatedsimple/edit_calculatedsimple_form.php
new file mode 100644 (file)
index 0000000..c2be49a
--- /dev/null
@@ -0,0 +1,715 @@
+<?php  // $Id$
+/**
+ * Defines the editing form for the calculated simplequestion type.
+ *
+ * @copyright &copy; 2007 Jamie Pratt
+ * @author Jamie Pratt me@jamiep.org
+ * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
+ * @package questionbank
+ * @subpackage questiontypes
+ */
+
+/**
+ * calculatedsimple editing form definition.
+ */
+class question_edit_calculatedsimple_form extends question_edit_form {
+    /**
+     * Handle to the question type for this question.
+     *
+     * @var question_calculatedsimple_qtype
+     */
+    var $qtypeobj;
+    var $wildcarddisplay ;
+//    public $qtypeobj;
+    //  $questiondisplay will contain the question from the form
+    var $questiondisplay ;
+
+    public $datasetdefs;
+
+    public $reload = false ;
+    
+    public $maxnumber = -1;
+
+    public $regenerate = true;
+
+    public $noofitems;
+    
+    public $outsidelimit = false ;
+    
+    public $commentanswer = array(); 
+    
+    public $answer = array();
+
+    public $nonemptyanswer = array();
+     
+
+    function question_edit_calculatedsimple_form(&$submiturl, &$question, &$category, &$contexts, $formeditable = true){
+        global $QTYPES, $SESSION, $CFG, $DB;
+    //     echo "<p> QTYPES  <pre>";print_r($QTYPES);echo"</pre></p>";
+    //     echo "<p> session  <pre>";print_r($SESSION);echo"</pre></p>";
+    //     echo "<p> question <pre>";print_r($question);echo"</pre></p>";
+        $this->regenerate = true;
+        $this->question = $question;
+        $this->qtypeobj =& $QTYPES[$this->question->qtype];
+        //get the dataset definitions for this question
+        //coming here everytime even when using a NoSubmitButton
+        //so this will only set the values to the actual question database content which is not what we want
+        //so this should be removed from here
+        // get priority to paramdatasets
+        
+        // question->id == 0 so no stored datasets
+        // else get datasets 
+        if  (  "1" == optional_param('reload','', PARAM_INT )) {
+     //       echo "<p> optional reload exist </p>";
+            $this->reload = true ;
+        }else {
+            $this->reload = false ;
+        }
+        if(!$this->reload ){ // use database data as this is first pass 
+            if ( !empty($question->id)) {
+                if (empty($question->options)) {
+                    $this->get_question_options($question);
+                }
+                $this->datasetdefs = $this->qtypeobj->get_dataset_definitions($question->id, array());
+            
+                if(!empty($this->datasetdefs)){
+                    foreach ($this->datasetdefs as $datasetdef) {        
+                        // Get maxnumber
+                        if ($this->maxnumber == -1 || $datasetdef->itemcount < $this->maxnumber) {
+                            $this->maxnumber = $datasetdef->itemcount;
+                        }
+                    }
+                    foreach ($this->datasetdefs as $defid => $datasetdef) {
+                        if (isset($datasetdef->id)) {
+                            $this->datasetdefs[$defid]->items = $DB->get_records_sql( // Use number as key!!
+                                    " SELECT itemnumber, definition, id, value
+                                      FROM {question_dataset_items}
+                                      WHERE definition = ? ", array($datasetdef->id));
+                        }
+                    }
+                }
+                $i = 0 ;
+                foreach($this->question->options->answers as $answer){
+                     $this->answer[$i] = $answer ;
+                     $i++;
+                } 
+                $this->nonemptyanswer = $this->answer ;
+            }        
+            $datasettoremove = false;
+            $newdatasetvalues = false ; 
+            $newdataset = false ; 
+        }else { 
+            // handle reload to get values from the form-elements
+            // answers, datasetdefs and data_items
+            // verify for the specific dataset values as the other parameters 
+            // unints, feeedback etc are handled elsewhere
+            // handle request buttons :
+            //    'analyzequestion' (Identify the wild cards {x..} present in answers) 
+            //    'addbutton' (create new set of datatitems)
+            //    'updatedatasets' is handled automatically on each reload
+            // The analyzequestion is done every time on reload  
+            // to detect any new wild cards so that the current display reflects
+            // the mandatory (i.e. in answers) datasets
+            //  to implement : don't do any changes if the question is used in a quiz.
+            // If new datadef, new properties should erase items. 
+                $dummyform = new stdClass();
+                $mandatorydatasets = array();
+
+            if  (  $dummyform->answer =optional_param('answer')) { // there is always at least one answer...
+                $fraction = optional_param('fraction') ;
+                $feedback = optional_param('feedback') ;
+                $tolerance = optional_param('tolerance') ;
+                $tolerancetype = optional_param('tolerancetype') ;
+                $correctanswerlength = optional_param('correctanswerlength') ;
+                $correctanswerformat = optional_param('correctanswerformat') ;
+                
+                foreach( $dummyform->answer as $key => $answer ) {
+                    if(trim($answer) != ''){  // just look for non-empty 
+                        $this->answer[$key]=new stdClass();
+                        $this->answer[$key]->answer = $answer;
+                        $this->answer[$key]->fraction = $fraction[$key];
+                        $this->answer[$key]->feedback = $feedback[$key];
+                        $this->answer[$key]->tolerance = $tolerance[$key];
+                        $this->answer[$key]->tolerancetype = $tolerancetype[$key];
+                        $this->answer[$key]->correctanswerlength = $correctanswerlength[$key];
+                        $this->answer[$key]->correctanswerformat = $correctanswerformat[$key];
+                        $this->nonemptyanswer[]= $this->answer[$key];
+                        $mandatorydatasets +=$this->qtypeobj->find_dataset_names($answer);
+                        }
+                }
+            }
+       //   echo "<p>this->answer  <pre>";print_r($this->answer);echo"</pre></p>";
+       //   echo "<p>this->answer  <pre>";print_r($this->nonemptyanswer);echo"</pre></p>";
+            $this->datasetdefs = array();
+            // rebuild datasetdefs from old values
+            $olddef  = optional_param('datasetdef');
+            $oldoptions  = optional_param('defoptions');
+            $calcmin = optional_param('calcmin') ;
+            $calclength = optional_param('calclength') ;
+            $calcmax = optional_param('calcmax') ;
+       /*   echo "<p> calcmin  <pre>";print_r(optional_param('calcmin'));echo"</pre></p>";
+          echo "<p> calcmax  <pre>";print_r(optional_param('calcmax'));echo"</pre></p>";
+          echo "<p> calclength  <pre>";print_r(optional_param('calclength'));echo"</pre></p>";*/
+            $newdatasetvalues = false ; 
+       //   echo "<p> olddef  <pre>";print_r(optional_param('datasetdef'));echo"</pre></p>";
+
+            for($key = 1 ; $key <= sizeof($olddef) ; $key++) {
+                $def = $olddef[$key] ;
+                $this->datasetdefs[$def]= new stdClass ;
+                    $this->datasetdefs[$def]->type = 1;
+                    $this->datasetdefs[$def]->category = 0;
+                  //  $this->datasets[$key]->name = $datasetname;
+                    $this->datasetdefs[$def]->options = $oldoptions[$key] ;
+                    $this->datasetdefs[$def]->calcmin = $calcmin[$key] ;
+                    $this->datasetdefs[$def]->calcmax = $calcmax[$key] ;
+                    $this->datasetdefs[$def]->calclength = $calclength[$key] ;
+                    //then compare with new values
+                    if (ereg('^(uniform|loguniform):([^:]*):([^:]*):([0-9]*)$', $this->datasetdefs[$def]->options, $regs)) {
+                       if( $this->datasetdefs[$def]->calcmin != $regs[2]||
+                        $this->datasetdefs[$def]->calcmax != $regs[3] ||
+                        $this->datasetdefs[$def]->calclength != $regs[4]){
+                                     $newdatasetvalues = true ;
+                                //     echo "<p> new datasetdefs  values ".$regs[2]."xx". $regs[3]."xx".$regs[4]."</p>";  
+                        }
+                        
+                    }
+                    $this->datasetdefs[$def]->options="uniform:".$this->datasetdefs[$def]->calcmin.":".$this->datasetdefs[$def]->calcmax.":".$this->datasetdefs[$def]->calclength;
+            }
+            
+     //       echo "<p>this  datasetdefs   <pre>";print_r($this->datasetdefs);echo"</pre></p>";
+            // detect new datasets        
+            $newdataset = false ; 
+            foreach ($mandatorydatasets as $datasetname) {
+                if (!isset($this->datasetdefs["1-0-$datasetname"])) {
+               //     list($options, $selected) =
+              //              $this->dataset_options($form, $datasetname);
+                    $key = "1-0-$datasetname";
+                    $this->datasetdefs[$key]=new stdClass ;//"1-0-$datasetname";
+                    $this->datasetdefs[$key]->type = 1;
+                    $this->datasetdefs[$key]->category = 0;
+                    $this->datasetdefs[$key]->name = $datasetname;
+                    $this->datasetdefs[$key]->options = "uniform:1.0:10.0:1";
+                    $newdataset = true ;     
+                     //            echo "<p> new datasetdefs $datasetname  </p>";  
+               //      $form->dataset[$key]=$selected ;
+                    //$key++;
+                }else {
+                    $this->datasetdefs["1-0-$datasetname"]->name = $datasetname ;
+                }
+            }
+            // remove obsolete datasets        
+            $datasettoremove = false;
+            foreach ($this->datasetdefs as $defkey => $datasetdef){
+                if(!isset($datasetdef->name )){
+                  //  echo "<p> dataset $defkey to remove   </p>";
+                    $datasettoremove = true;
+                    unset($this->datasetdefs[$defkey]);
+                }
+            }         
+         
+           
+        } // handle reload
+        // create items if  $newdataset and noofitems > 0 and !$newdatasetvalues
+        // eliminate any items if $newdatasetvalues
+        // eliminate any items if $datasettoremove, $newdataset, $newdatasetvalues
+        if ($datasettoremove ||$newdataset ||$newdatasetvalues ) {
+            foreach ($this->datasetdefs as $defkey => $datasetdef){
+                $datasetdef->itemcount = 0;
+                unset($datasetdef->items);
+            }
+        }
+        $maxnumber = -1 ;
+        if  (  "" !=optional_param('addbutton')){
+            $maxnumber = optional_param('selectadd') ;                             
+            foreach ($this->datasetdefs as $defid => $datasetdef) {
+                $datasetdef->itemcount = $maxnumber;
+                unset($datasetdef->items);
+                for ($numberadded =1 ; $numberadded <= $maxnumber; $numberadded++){
+                    $datasetitem = new stdClass;
+                   // $datasetitem->definition = $datasetdef->id ;
+                    $datasetitem->itemnumber = $numberadded;
+                    $datasetitem->id = 0;
+                    $datasetitem->value = $this->qtypeobj->generate_dataset_item($datasetdef->options);
+                    $this->datasetdefs[$defid]->items[$numberadded]=$datasetitem ;
+                /*    if (!$DB->insert_record('question_dataset_items', $datasetitem)) {
+                        print_error('cannotinsert', 'question');
+                    }*/
+                }//for number added
+            }// datasetsdefs end
+            $this->maxnumber = $maxnumber ;
+             //   echo"<p> using create new items $this->maxnumber </p>";
+        }else {
+                    // Handle reload dataset items
+                //    echo"<p> using optional to build </p>";
+            if  (  "" !=optional_param('definition')&& !($datasettoremove ||$newdataset ||$newdatasetvalues )){              
+                $i = 1;
+                $fromformdefinition = optional_param('definition');
+                $fromformnumber = optional_param('number');
+                $fromformitemid = optional_param('itemid');
+                ksort($fromformdefinition);
+              //    echo "<p> fromformdefinition   <pre>";print_r($fromformdefinition);echo"</pre></p>";
+               //   echo "<p> fromformnumber   <pre>";print_r($fromformnumber);echo"</pre></p>";
+              
+                foreach($fromformdefinition as $key => $defid) {
+                    $addeditem = new stdClass();
+                    $addeditem->id = $fromformitemid[$i]  ;
+                    $addeditem->value = $fromformnumber[$i];
+                    $addeditem->itemnumber = ceil($i / count($this->datasetdefs));
+                    $this->datasetdefs[$defid]->items[$addeditem->itemnumber]=$addeditem ;
+                    $this->datasetdefs[$defid]->itemcount = $i ;
+                    $i++;
+                }
+            }
+            if (isset($addeditem->itemnumber) && $this->maxnumber < $addeditem->itemnumber){
+                $this->maxnumber = $addeditem->itemnumber;
+                if(!empty($this->datasetdefs)){                        
+                    foreach ($this->datasetdefs as $datasetdef) {
+                            $datasetdef->itemcount = $this->maxnumber ;
+                    }
+                }
+            }
+        }
+
+           //     echo "<p>line 443 datasetdefs   <pre>";print_r($this->datasetdefs);echo"</pre></p>";
+        //$key = 0 ;
+   //    if  (  "" !=optional_param('answer')) echo "<p> optional answer exist </p>";
+    //   if  (  "" !=optional_param('answer['.$key.']','', PARAM_NOTAGS)) echo "<p> optional $key exist </p>";
+    //   if  (  "" !=optional_param('noanswer','', PARAM_INT )) echo "<p> optional noanswer exist </p>";
+
+        parent::question_edit_form($submiturl, $question, $category, $contexts, $formeditable);
+    }
+
+    function get_per_answer_fields(&$mform, $label, $gradeoptions, &$repeatedoptions, &$answersoption) {
+        $repeated = parent::get_per_answer_fields(&$mform, $label, $gradeoptions, $repeatedoptions, $answersoption);
+        $mform->setType('answer', PARAM_NOTAGS);
+        $addrepeated = array();
+        $addrepeated[] =& $mform->createElement('text', 'tolerance', get_string('tolerance', 'qtype_calculated'));
+        $repeatedoptions['tolerance']['type'] = PARAM_NUMBER;
+        $repeatedoptions['tolerance']['default'] = 0.01;
+        $addrepeated[] =& $mform->createElement('select', 'tolerancetype', get_string('tolerancetype', 'quiz'), $this->qtypeobj->tolerance_types());
+        $addrepeated[] =&  $mform->createElement('select', 'correctanswerlength', get_string('correctanswershows', 'qtype_calculated'), range(0, 9));
+        $repeatedoptions['correctanswerlength']['default'] = 2;
+
+        $answerlengthformats = array('1' => get_string('decimalformat', 'quiz'), '2' => get_string('significantfiguresformat', 'quiz'));
+        $addrepeated[] =&  $mform->createElement('select', 'correctanswerformat', get_string('correctanswershowsformat', 'qtype_calculated'), $answerlengthformats);
+        array_splice($repeated, 3, 0, $addrepeated);
+        $repeated[1]->setLabel(get_string('correctanswerformula', 'quiz').'=');
+
+        return $repeated;
+    }
+
+    /**
+     * Add question-type specific form fields.
+     *
+     * @param MoodleQuickForm $mform the form being built.
+     */
+    function definition_inner(&$mform) {
+        global $QTYPES;
+        $this->qtypeobj =& $QTYPES[$this->qtype()];
+        $strquestionlabel = $this->qtypeobj->comment_header($this->nonemptyanswer);
+         $label = get_string("sharedwildcards", "qtype_datasetdependent");
+        $mform->addElement('hidden', 'initialcategory', 1);
+        $mform->addElement('hidden', 'reload', 1);
+//        $html2 = $this->qtypeobj->print_dataset_definitions_category($this->question);
+//        $mform->insertElementBefore($mform->createElement('static','listcategory',$label,$html2),'name');
+        $addfieldsname='updatecategory';
+        $addstring=get_string("updatecategory", "qtype_calculated");
+                $mform->registerNoSubmitButton($addfieldsname);
+
+//        $mform->insertElementBefore(    $mform->createElement('submit', $addfieldsname, $addstring),'listcategory');
+
+        $creategrades = get_grade_options();
+        $this->add_per_answer_fields($mform, get_string('answerhdr', 'qtype_calculated', '{no}'),
+                $creategrades->gradeoptions, 1, 1);
+
+        $repeated = array();
+        $repeated[] =& $mform->createElement('header', 'unithdr', get_string('unithdr', 'qtype_numerical', '{no}'));
+
+        $repeated[] =& $mform->createElement('text', 'unit', get_string('unit', 'quiz'));
+        $mform->setType('unit', PARAM_NOTAGS);
+
+        $repeated[] =& $mform->createElement('text', 'multiplier', get_string('multiplier', 'quiz'));
+        $mform->setType('multiplier', PARAM_NUMBER);
+
+        if (isset($this->question->options)){
+            $countunits = count($this->question->options->units);
+        } else {
+            $countunits = 0;
+        }
+        if ($this->question->formoptions->repeatelements){
+            $repeatsatstart = $countunits + 1;
+        } else {
+            $repeatsatstart = $countunits;
+        }
+        $this->repeat_elements($repeated, $repeatsatstart, array(), 'nounits', 'addunits', 2, get_string('addmoreunitblanks', 'qtype_calculated', '{no}'));
+
+        if ($mform->elementExists('multiplier[0]')){
+            $firstunit =& $mform->getElement('multiplier[0]');
+            $firstunit->freeze();
+            $firstunit->setValue('1.0');
+            $firstunit->setPersistantFreeze(true);
+        }
+        //hidden elements
+   //     $mform->addElement('hidden', 'wizard', 'datasetdefinitions');
+   //     $mform->setType('wizard', PARAM_ALPHA);
+     //   $mform->addElement('header', '', '');
+        $label = "<div class='mdl-align'></div><div class='mdl-align'>".get_string('wildcardrole', 'qtype_calculatedsimple')."</div>";
+        $mform->addElement('html', "<div class='mdl-align'>&nbsp;</div>");
+        $mform->addElement('html', $label);// explaining the role of datasets so other strings can be shortened
+
+        $mform->addElement('submit', 'analyzequestion', get_string('findwildcards','qtype_calculatedsimple'));
+        $mform->registerNoSubmitButton('analyzequestion');
+        $mform->closeHeaderBefore('analyzequestion');
+        if  (  "" != optional_param('analyzequestion','', PARAM_RAW)) {
+
+            $this->wizarddisplay = true;
+    //     echo "<p> session answer <pre>";print_r($SESSION);echo"</pre></p>";
+ //        echo "<p> session answer <pre>";print_r($SESSION->calculated->questionform->answers);echo"</pre></p>";
+           
+
+        }else {
+            $this->wizwarddisplay = false;
+        }
+        if ($this->maxnumber != -1){
+            $this->noofitems = $this->maxnumber;
+        } else {
+            $this->noofitems = 0;
+        }
+        if(!empty($this->datasetdefs)){
+
+        $key = 0;
+         $mform->addElement('header', 'additemhdr', get_string('wildcardparam', 'qtype_calculatedsimple'));
+        $idx = 1;
+        if(!empty($this->datasetdefs)){
+            $j = (($this->noofitems) * count($this->datasetdefs))+1;//
+            foreach ($this->datasetdefs as $defkey => $datasetdef){
+                $mform->addElement('static', "na[$j]", get_string('param', 'qtype_datasetdependent', $datasetdef->name));
+                $this->qtypeobj->custom_generator_tools_part($mform, $idx, $j);
+                $mform->addElement('hidden', "datasetdef[$idx]");
+                $mform->setType("datasetdef[$idx]", PARAM_RAW);
+                $idx++;
+                $mform->addElement('static', "divider[$j]", '', '<hr />');
+                $j++;
+            }
+        }       
+        $addoptions = Array();
+        $addoptions['1']='1';
+        for ($i=10; $i<=100 ; $i+=10){
+             $addoptions["$i"]="$i";
+        }
+        $mform->closeHeaderBefore('additemhdr');
+        $addgrp = array();
+        $addgrp[] =& $mform->createElement('submit', 'addbutton', get_string('generatenewitemsset', 'qtype_calculatedsimple'));
+        $addgrp[] =& $mform->createElement('select', "selectadd", get_string('additem', 'qtype_datasetdependent'), $addoptions);
+        $addgrp[] = & $mform->createElement('static',"stat","Items",get_string('item(s)', 'qtype_datasetdependent'));
+        $mform->addGroup($addgrp, 'addgrp', '', '   ', false);
+        $mform->registerNoSubmitButton('addbutton');
+        $mform->closeHeaderBefore('addgrp');
+        $mform->addElement('static', "divideradd", '', '');
+        if ($this->noofitems == 0) {
+           $mform->addElement('static','warningnoitems','','<span class="error">'.get_string('youmustaddatleastoneitem', 'qtype_datasetdependent').'</span>');
+        $mform->closeHeaderBefore('warningnoitems');
+        }else {
+        $mform->addElement('header', 'additemhdr1', get_string('wildcarditems', 'qtype_calculatedsimple'));
+        $mform->closeHeaderBefore('additemhdr1');
+         //   $mform->addElement('header', '', get_string('itemno', 'qtype_datasetdependent', ""));
+         //           $mform->addElement('submit', 'updatedatasets', get_string('updatedatasetparam', 'qtype_datasetdependent'));
+     //   $mform->registerNoSubmitButton('updatedatasets');
+     //   $mform->setAdvanced("updatedatasets",true);
+
+//------------------------------------------------------------------------------------------------------------------------------
+        $j = $this->noofitems * count($this->datasetdefs);
+        for ($i = $this->noofitems; $i >= 1 ; $i--){
+            foreach ($this->datasetdefs as $defkey => $datasetdef){
+                $mform->addElement('text', "number[$j]", get_string('param', 'qtype_datasetdependent', $datasetdef->name));
+                $mform->setType("number[$j]", PARAM_NUMBER);
+                $mform->setAdvanced("number[$j]",true);
+                $mform->addElement('hidden', "itemid[$j]");
+                $mform->setType("itemid[$j]", PARAM_INT);
+
+                $mform->addElement('hidden', "definition[$j]");
+                $mform->setType("definition[$j]", PARAM_NOTAGS);
+
+                $j--;
+            }
+            if (!empty( $strquestionlabel)){
+                $repeated[] =& $mform->addElement('static', "answercomment[$i]", "<b>".get_string('itemno', 'qtype_datasetdependent', $i)."</b>&nbsp;&nbsp;".$strquestionlabel);
+            }
+                            $mform->addElement('static', "divider1[$j]", '', '<hr />');
+
+        }
+    }
+      //  if ($this->outsidelimit){
+         //   $mform->addElement('static','outsidelimit','','');
+      //  }
+    }else {
+        $mform->addElement('static','warningnowildcards','','<span class="error">'.get_string('atleastonewildcard', 'qtype_calculatedsimple').'</span>');
+        $mform->closeHeaderBefore('warningnowildcards');
+    }
+
+//------------------------------------------------------------------------------------------------------------------------------
+        //non standard name for button element needed so not using add_action_buttons
+        //hidden elements
+
+        $mform->addElement('hidden', 'id');
+        $mform->setType('id', PARAM_INT);
+
+        $mform->addElement('hidden', 'courseid');
+        $mform->setType('courseid', PARAM_INT);
+        $mform->setDefault('courseid', 0);
+
+        $mform->addElement('hidden', 'cmid');
+        $mform->setType('cmid', PARAM_INT);
+        $mform->setDefault('cmid', 0);
+        if (!empty($this->question->id)){
+            if ($this->question->formoptions->cansaveasnew){
+        $mform->addElement('header', 'additemhdr', get_string('converttocalculated', 'qtype_calculatedsimple'));
+        $mform->closeHeaderBefore('additemhdr');
+               
+                $mform->addElement('checkbox', 'convert','' ,get_string('willconverttocalculated', 'qtype_calculatedsimple'));
+                                $mform->setDefault('convert', 0);
+
+              }
+            }
+   //     $mform->addElement('hidden', 'wizard', 'edit_calculatedsimple');
+   //     $mform->setType('wizard', PARAM_ALPHA);
+/*
+        $mform->addElement('hidden', 'returnurl');
+        $mform->setType('returnurl', PARAM_LOCALURL);
+        $mform->setDefault('returnurl', 0);
+
+*/
+    }
+
+    function set_data($question) {
+            $answer = $this->answer;
+        $default_values = array();
+            if (count($answer)) {
+                $key = 0;
+                foreach ($answer as $answer){
+                    $default_values['answer['.$key.']'] = $answer->answer;
+                    $default_values['fraction['.$key.']'] = $answer->fraction;
+                    $default_values['tolerance['.$key.']'] = $answer->tolerance;
+                    $default_values['tolerancetype['.$key.']'] = $answer->tolerancetype;
+                    $default_values['correctanswerlength['.$key.']'] = $answer->correctanswerlength;
+                    $default_values['correctanswerformat['.$key.']'] = $answer->correctanswerformat;
+                    $default_values['feedback['.$key.']'] = $answer->feedback;
+                    $key++;
+                }
+            }
+            if (isset($question->options)){
+                $units  = array_values($question->options->units);
+                // make sure the default unit is at index 0
+                usort($units, create_function('$a, $b',
+                'if (1.0 === (float)$a->multiplier) { return -1; } else '.
+                'if (1.0 === (float)$b->multiplier) { return 1; } else { return 0; }'));
+                if (count($units)) {
+                    $key = 0;
+                    foreach ($units as $unit){
+                        $default_values['unit['.$key.']'] = $unit->unit;
+                        $default_values['multiplier['.$key.']'] = $unit->multiplier;
+                        $key++;
+                    }
+                }
+            }
+                      $key = 0 ;
+    //                    echo "<p> mandatorydatasets $key xx".optional_param("answer[0]",'', PARAM_NOTAGS)."YY".$this->_form->getElementValue('answer['.$key.']')."xx<p>";
+
+        $formdata = array();
+        $fromform = new stdClass();
+        //fill out all data sets and also the fields for the next item to add.
+        if(!empty($this->datasetdefs)){
+        $j = $this->noofitems * count($this->datasetdefs);
+         for ($itemnumber = $this->noofitems; $itemnumber >= 1; $itemnumber--){
+            $data = array();
+            foreach ($this->datasetdefs as $defid => $datasetdef){
+                if (isset($datasetdef->items[$itemnumber])){
+                    $formdata["number[$j]"] = $datasetdef->items[$itemnumber]->value;
+                    $formdata["definition[$j]"] = $defid;
+                    $formdata["itemid[$j]"] = $datasetdef->items[$itemnumber]->id;
+                    $data[$datasetdef->name] = $datasetdef->items[$itemnumber]->value;
+                }
+                $j--;
+            }
+    //                 echo "<p>answers avant  comment <pre>";print_r($answer);echo"</pre></p>";
+    //                 echo "<p>data avant  comment <pre>";print_r($data);echo"</pre></p>";
+                     
+            if($this->noofitems != 0 ) {
+                if(!isset($question->id)) $question->id = 0 ;
+            $comment = $this->qtypeobj->comment_on_datasetitems($question->id,$this->nonemptyanswer, $data, $itemnumber);//$this->
+             if ($comment->outsidelimit) {
+                 $this->outsidelimit=$comment->outsidelimit ;
+            }
+            $totalcomment='';
+       //              echo "<p> comment <pre>";print_r($comment);echo"</pre></p>";
+
+            foreach ($this->nonemptyanswer as $key => $answer) {
+                $totalcomment .= $comment->stranswers[$key].'<br/>';
+            }
+
+            $formdata['answercomment['.$itemnumber.']'] = $totalcomment ;
+        }
+        }
+    //    $formdata['reload'] = '1';
+      //  $formdata['nextpageparam[forceregeneration]'] = $this->regenerate;
+        $formdata['selectdelete'] = '1';
+        $formdata['selectadd'] = '1';
+        $j = $this->noofitems * count($this->datasetdefs)+1;
+        $data = array(); // data for comment_on_datasetitems later
+           $idx =1 ;
+            foreach ($this->datasetdefs as $defid => $datasetdef){
+               $formdata["datasetdef[$idx]"] = $defid;
+                $idx++;
+            }
+        $formdata = $this->qtypeobj->custom_generator_set_data($this->datasetdefs, $formdata);
+    }
+        $question = (object)((array)$question + $default_values+$formdata );
+      //                   echo "<p> question data <pre>";print_r($question);echo"</pre></p>";
+
+        parent::set_data($question);
+    }
+
+    function qtype() {
+        return 'calculatedsimple';
+    }
+
+    function validation($data, $files) {
+        $errors = parent::validation($data, $files);
+        //verifying for errors in {=...} in question text;
+        $qtext = "";
+        $qtextremaining = $data['questiontext'] ;
+        $possibledatasets = $this->qtypeobj->find_dataset_names($data['questiontext']);
+            foreach ($possibledatasets as $name => $value) {
+            $qtextremaining = str_replace('{'.$name.'}', '1', $qtextremaining);
+        }
+    //     echo "numericalquestion qtextremaining <pre>";print_r($possibledatasets);
+        while  (ereg('\{=([^[:space:]}]*)}', $qtextremaining, $regs1)) {
+            $qtextsplits = explode($regs1[0], $qtextremaining, 2);
+            $qtext =$qtext.$qtextsplits[0];
+            $qtextremaining = $qtextsplits[1];
+            if (!empty($regs1[1]) && $formulaerrors = qtype_calculated_find_formula_errors($regs1[1])) {
+                if(!isset($errors['questiontext'])){
+                    $errors['questiontext'] = $formulaerrors.':'.$regs1[1] ;
+                }else {
+                    $errors['questiontext'] .= '<br/>'.$formulaerrors.':'.$regs1[1];
+                }
+            }
+        }
+        $answers = $data['answer'];
+        $answercount = 0;
+        $maxgrade = false;
+        $possibledatasets = $this->qtypeobj->find_dataset_names($data['questiontext']);
+        $mandatorydatasets = array();
+        foreach ($answers as $key => $answer){
+            $mandatorydatasets += $this->qtypeobj->find_dataset_names($answer);
+        }
+        if ( count($mandatorydatasets )==0){
+          //  $errors['questiontext']=get_string('atleastonewildcard', 'qtype_datasetdependent');
+            foreach ($answers as $key => $answer){
+                $errors['answer['.$key.']'] = get_string('atleastonewildcard', 'qtype_datasetdependent');
+            }
+        }
+        foreach ($answers as $key => $answer){
+            //check no of choices
+            // the * for everykind of answer not actually implemented
+            $trimmedanswer = trim($answer);
+            if (($trimmedanswer!='')||$answercount==0){
+                $eqerror = qtype_calculated_find_formula_errors($trimmedanswer);
+                if (FALSE !== $eqerror){
+                    $errors['answer['.$key.']'] = $eqerror;
+                }
+            }
+            if ($trimmedanswer!=''){
+                if ('2' == $data['correctanswerformat'][$key]
+                        && '0' == $data['correctanswerlength'][$key]) {
+                    $errors['correctanswerlength['.$key.']'] = get_string('zerosignificantfiguresnotallowed','quiz');
+                }
+                if (!is_numeric($data['tolerance'][$key])){
+                    $errors['tolerance['.$key.']'] = get_string('mustbenumeric', 'qtype_calculated');
+                }
+                if ($data['fraction'][$key] == 1) {
+                   $maxgrade = true;
+                }
+
+                $answercount++;
+            }
+            //check grades
+
+            //TODO how should grade checking work here??
+            /*if ($answer != '') {
+                if ($data['fraction'][$key] > 0) {
+                    $totalfraction += $data['fraction'][$key];
+                }
+                if ($data['fraction'][$key] > $maxfraction) {
+                    $maxfraction = $data['fraction'][$key];
+                }
+            }*/
+        }
+        //grade checking :
+        /// Perform sanity checks on fractional grades
+        /*if ( ) {
+            if ($maxfraction != 1) {
+                $maxfraction = $maxfraction * 100;
+                $errors['fraction[0]'] = get_string('errfractionsnomax', 'qtype_multichoice', $maxfraction);
+            }
+        } else {
+            $totalfraction = round($totalfraction,2);
+            if ($totalfraction != 1) {
+                $totalfraction = $totalfraction * 100;
+                $errors['fraction[0]'] = get_string('errfractionsaddwrong', 'qtype_multichoice', $totalfraction);
+            }
+        }*/
+        $units  = $data['unit'];
+        if (count($units)) {
+            foreach ($units as $key => $unit){
+                if (is_numeric($unit)){
+                    $errors['unit['.$key.']'] = get_string('mustnotbenumeric', 'qtype_calculated');
+                }
+                $trimmedunit = trim($unit);
+                $trimmedmultiplier = trim($data['multiplier'][$key]);
+                if (!empty($trimmedunit)){
+                    if (empty($trimmedmultiplier)){
+                        $errors['multiplier['.$key.']'] = get_string('youmustenteramultiplierhere', 'qtype_calculated');
+                    }
+                    if (!is_numeric($trimmedmultiplier)){
+                        $errors['multiplier['.$key.']'] = get_string('mustbenumeric', 'qtype_calculated');
+                    }
+
+                }
+            }
+        }
+        if ($answercount==0){
+            $errors['answer[0]'] = get_string('atleastoneanswer', 'qtype_calculated');
+        }
+        if ($maxgrade == false) {
+            $errors['fraction[0]'] = get_string('fractionsnomax', 'question');
+        }
+        if (isset($data['backtoquiz']) && ($this->noofitems==0) ){
+            $errors['warning'] = get_string('warning', 'mnet');
+        } 
+        if ($this->outsidelimit){
+         //   if(!isset($errors['warning'])) $errors['warning']=' ';
+           $errors['outsidelimits'] = get_string('oneanswertrueansweroutsidelimits','qtype_calculated');
+        }
+        $numbers = $data['number'];
+        foreach ($numbers as $key => $number){
+            if(! is_numeric($number)){
+                if (stristr($number,',')){
+                    $errors['number['.$key.']'] = get_string('The , cannot be used, use . as in 0.013 or 1.3e-2', 'qtype_datasetdependent');
+                }else {    
+                    $errors['number['.$key.']'] = get_string('This is not a valid number', 'qtype_datasetdependent');
+                }
+            }else if( stristr($number,'x')){
+                $errors['number['.$key.']'] = get_string('Hexadecimal format (i.e. 0X12d) is not allowed', 'qtype_datasetdependent');
+            } else if( is_nan($number)){
+                $errors['number['.$key.']'] = get_string('is a NAN number', 'qtype_datasetdependent');
+            }        
+        }
+        if ( $this->noofitems==0  ){
+            $errors['warning'] = get_string('warning', 'mnet');
+        }
+
+        return $errors;
+    }
+}
+?>
\ No newline at end of file
diff --git a/question/type/calculatedsimple/icon.gif b/question/type/calculatedsimple/icon.gif
new file mode 100644 (file)
index 0000000..e3d60df
Binary files /dev/null and b/question/type/calculatedsimple/icon.gif differ
diff --git a/question/type/calculatedsimple/questiontype.php b/question/type/calculatedsimple/questiontype.php
new file mode 100644 (file)
index 0000000..7eedba4
--- /dev/null
@@ -0,0 +1,434 @@
+<?php  // $Id$
+
+/////////////////
+// CALCULATED ///
+/////////////////
+
+/// QUESTION TYPE CLASS //////////////////
+
+
+
+class question_calculatedsimple_qtype extends question_calculated_qtype {
+
+    // Used by the function custom_generator_tools:
+    var $calcgenerateidhasbeenadded = false;
+    public $virtualqtype = false;
+
+    function name() {
+        return 'calculatedsimple';
+    }
+
+
+
+
+    function save_question_options($question) {
+        //$options = $question->subtypeoptions;
+        // Get old answers:
+        global $CFG, $DB;
+
+        if (isset($question->answer) && !isset($question->answers)) {
+            $question->answers = $question->answer;
+        }
+
+        // Get old versions of the objects
+        if (!$oldanswers = $DB->get_records('question_answers', array('question' => $question->id), 'id ASC')) {
+            $oldanswers = array();
+        }
+
+        if (!$oldoptions = $DB->get_records('question_calculated', array('question' => $question->id), 'answer ASC')) {
+            $oldoptions = array();
+        }
+
+        // Save the units.
+        $virtualqtype = $this->get_virtual_qtype();
+        $result = $virtualqtype->save_numerical_units($question);
+        if (isset($result->error)) {
+            return $result;
+        } else {
+            $units = &$result->units;
+        }
+        // Insert all the new answers
+        if (isset($question->answer) && !isset($question->answers)) {
+            $question->answers=$question->answer;
+        }
+        foreach ($question->answers as $key => $dataanswer) {
+            if (  trim($dataanswer) != '' ) {
+                $answer = new stdClass;
+                $answer->question = $question->id;
+                $answer->answer = trim($dataanswer);
+                $answer->fraction = $question->fraction[$key];
+                $answer->feedback = trim($question->feedback[$key]);
+
+                if ($oldanswer = array_shift($oldanswers)) {  // Existing answer, so reuse it
+                    $answer->id = $oldanswer->id;
+                    if (! $DB->update_record("question_answers", $answer)) {
+                        $result->error = get_string('errorupdatinganswer','question',$answer->id);
+                        return $result;
+                    }
+                } else { // This is a completely new answer
+                    if (! $answer->id = $DB->insert_record("question_answers", $answer)) {
+                        $result->error = get_string('errorinsertinganswer','question');
+                        return $result;
+                    }
+                }
+
+                // Set up the options object
+                if (!$options = array_shift($oldoptions)) {
+                    $options = new stdClass;
+                }
+                $options->question  = $question->id;
+                $options->answer    = $answer->id;
+                $options->tolerance = trim($question->tolerance[$key]);
+                $options->tolerancetype  = trim($question->tolerancetype[$key]);
+                $options->correctanswerlength  = trim($question->correctanswerlength[$key]);
+                $options->correctanswerformat  = trim($question->correctanswerformat[$key]);
+
+                // Save options
+                if (isset($options->id)) { // reusing existing record
+                    if (! $DB->update_record('question_calculated', $options)) {
+                        $mess->name = $this->name();
+                        $mess->id = $options->id ;
+                        $result->error = get_string('errorupdatingoptions','question',$mess);
+                    //    $result->error = "Could not update question calculated options! (id=$options->id)";
+                        return $result;
+                    }
+                } else { // new options
+                    if (! $DB->insert_record('question_calculated', $options)) {
+                        $result->error = "Could not insert question  calculated options!";
+                        return $result;
+                    }
+                }
+            }
+        }
+        // delete old answer records
+        if (!empty($oldanswers)) {
+            foreach($oldanswers as $oa) {
+                $DB->delete_records('question_answers', array('id' => $oa->id));
+            }
+        }
+
+        // delete old answer records
+        if (!empty($oldoptions)) {
+            foreach($oldoptions as $oo) {
+                $DB->delete_records('question_calculated', array('id' => $oo->id));
+            }
+        }
+
+
+        if( isset($question->import_process)&&$question->import_process){
+            $this->import_datasets($question);
+         }else {
+            //save datasets and datatitems from form i.e in question
+          //  $datasetdefs = $this->get_dataset_definitions($question->id, array());
+          $question->dataset = $question->datasetdef ;
+     //       $this->save_dataset_definitions($question);
+        // Save datasets
+        $datasetdefinitions = $this->get_dataset_definitions($question->id, $question->dataset);
+        $tmpdatasets = array_flip($question->dataset);
+        $defids = array_keys($datasetdefinitions);
+        $datasetdefs = array();
+        foreach ($defids as $defid) {
+            $datasetdef = &$datasetdefinitions[$defid];
+            if (isset($datasetdef->id)) {
+                if (!isset($tmpdatasets[$defid])) {
+                // This dataset is not used any more, delete it
+                    $DB->delete_records('question_datasets', array('question' => $question->id, 'datasetdefinition' => $datasetdef->id));
+                   // if ($datasetdef->category == 0) { // Question local dataset
+                        $DB->delete_records('question_dataset_definitions', array('id' => $datasetdef->id));
+                        $DB->delete_records('question_dataset_items', array('definition' => $datasetdef->id));
+                   // }
+         }
+                // This has already been saved or just got deleted
+                unset($datasetdefinitions[$defid]);
+                continue;
+            }
+            if (!$datasetdef->id = $DB->insert_record('question_dataset_definitions', $datasetdef)) {
+                print_error("cannotcreatedataset", 'question', '', $defid);
+            }
+            $datasetdefs[]= clone($datasetdef);
+            $questiondataset = new stdClass;
+            $questiondataset->question = $question->id;
+            $questiondataset->datasetdefinition = $datasetdef->id;
+            if (!$DB->insert_record('question_datasets', $questiondataset)) {
+                print_error('cannotcreaterelation', 'question', '', $name);
+            }
+            unset($datasetdefinitions[$defid]);
+        }
+        // Remove local obsolete datasets as well as relations
+        // to datasets in other categories:
+        if (!empty($datasetdefinitions)) {
+            foreach ($datasetdefinitions as $def) {
+                $DB->delete_records('question_datasets', array('question' => $question->id, 'datasetdefinition' => $def->id));
+                if ($def->category == 0) { // Question local dataset
+                    $DB->delete_records('question_dataset_definitions', array('id' => $def->id));
+                    $DB->delete_records('question_dataset_items', array('definition' => $def->id));
+                }
+            }
+        }
+        $datasetdefs = $this->get_dataset_definitions($question->id, $question->dataset);
+              //         echo "<p> datasetdefs  save  <pre>";print_r($datasetdefs);echo"</pre></p>";
+                    // Handle adding and removing of dataset items
+       $i = 1;
+        ksort($question->definition);
+        foreach ($question->definition as $key => $defid) {
+            $addeditem = new stdClass();
+            $addeditem->definition = $datasetdefs[$defid]->id;
+            $addeditem->value = $question->number[$i];
+            $addeditem->itemnumber = ceil($i / count($datasetdefs));
+            if (empty($question->makecopy) && $question->itemid[$i]) {
+                // Reuse any previously used record
+                $addeditem->id = $question->itemid[$i];
+                if (!$DB->update_record('question_dataset_items', $addeditem)) {
+                    print_error('cannotupdateitem', 'question');
+                }
+            } else {
+                if (!$DB->insert_record('question_dataset_items', $addeditem)) {
+                    print_error('cannotinsert', 'question');
+                }
+            }
+            $i++;
+        }
+        if (isset($addeditem->itemnumber) && $maxnumber < $addeditem->itemnumber){
+            $maxnumber = $addeditem->itemnumber;
+            foreach ($datasetdefs as $key => $newdef) {
+                if (isset($newdef->id) && $newdef->itemcount <= $maxnumber) {
+                    $newdef->itemcount = $maxnumber;
+                    // Save the new value for options
+                    $DB->update_record('question_dataset_definitions', $newdef);
+                }
+            }
+        }
+         }   
+        // Report any problems.
+        //convert to calculated
+        if(!empty($question->makecopy) && !empty($question->convert) ){
+        //     echo "<p> question  save  <pre>";print_r($question);echo"</pre></p>";
+                       if (!$DB->set_field('question', 'qtype', 'calculated', array('id'=> $question->id))) {
+                               print_error('cannotupdateitem', 'question');
+                       }
+    }
+        if (!empty($result->notice)) {
+            return $result;
+        }
+        return true;
+    }
+   function finished_edit_wizard(&$form) {
+        return true ; //isset($form->backtoquiz);
+    }
+
+
+
+
+    /**
+    * this version save the available data at the different steps of the question editing process
+    * without using global $SESSION as storage between steps
+    * at the first step $wizardnow = 'question'
+    *  when creating a new question
+    *  when modifying a question
+    *  when copying as a new question
+    *  the general parameters and answers are saved using parent::save_question
+    *  then the datasets are prepared and saved
+    * at the second step $wizardnow = 'datasetdefinitions'
+    *  the datadefs final type are defined as private, category or not a datadef
+    * at the third step $wizardnow = 'datasetitems'
+    *  the datadefs parameters and the data items are created or defined
+    *
+    * @param object question
+    * @param object $form
+    * @param int $course
+    * @param PARAM_ALPHA $wizardnow should be added as we are coming from question2.php
+    */
+    function save_question($question, $form, $course) {
+       
+        $question = default_questiontype::save_question($question, $form, $course);
+        return $question;
+    }
+
+
+    function response_summary($question, $state, $length=80, $formatting=true) {
+        // The actual response is the bit after the hyphen
+        return substr($state->answer, strpos($state->answer, '-')+1, $length);
+    }
+
+    function custom_generator_tools_part(&$mform, $idx, $j){
+
+        $minmaxgrp = array();
+        $minmaxgrp[] =& $mform->createElement('text', "calcmin[$idx]", get_string('calcmin', 'qtype_datasetdependent'));
+        $minmaxgrp[] =& $mform->createElement('text', "calcmax[$idx]", get_string('calcmax', 'qtype_datasetdependent'));
+        $mform->addGroup($minmaxgrp, 'minmaxgrp', get_string('minmax', 'qtype_datasetdependent'), ' - ', false);
+        $mform->setType("calcmin[$idx]", PARAM_NUMBER);
+        $mform->setType("calcmax[$idx]", PARAM_NUMBER);
+
+        $precisionoptions = range(0, 10);
+        $mform->addElement('select', "calclength[$idx]", get_string('calclength', 'qtype_datasetdependent'), $precisionoptions);
+
+        $distriboptions = array('uniform' => get_string('uniform', 'qtype_datasetdependent'), 'loguniform' => get_string('loguniform', 'qtype_datasetdependent'));
+        $mform->addElement('hidden', "calcdistribution[$idx]", 'uniform');
+
+
+    }
+    function comment_header($answers) {
+        //$this->get_question_options($question);
+        $strheader = "";
+        $delimiter = '';
+
+       // $answers = $question->options->answers;
+        //  echo "<p>comments header answers  <pre>";print_r($answers);echo"</pre></p>";
+
+        foreach ($answers as $key => $answer) {
+         /*   if (is_string($answer)) {
+                $strheader .= $delimiter.$answer;
+            } else {*/
+                $strheader .= $delimiter.$answer->answer;
+           // }
+            $delimiter = '<br/><br/><br/>';
+        }
+        return $strheader;
+    }
+
+    function comment_on_datasetitems($questionid, $answers,$data, $number) {
+        global $DB;
+        $comment = new stdClass;
+        $comment->stranswers = array();
+        $comment->outsidelimit = false ;
+        $comment->answers = array();
+        /// Find a default unit:
+        if (!empty($questionid) && $unit = $DB->get_record('question_numerical_units', array('question'=> $questionid, 'multiplier' => 1.0))) {
+            $unit = $unit->unit;
+        } else {
+            $unit = '';
+        }
+
+        $answers = fullclone($answers);
+        $strmin = get_string('min', 'quiz');
+        $strmax = get_string('max', 'quiz');
+        $errors = '';
+        $delimiter = ': ';
+        $virtualqtype = $this->get_virtual_qtype();
+        foreach ($answers as $key => $answer) {
+            $formula = $this->substitute_variables($answer->answer,$data);
+            $formattedanswer = qtype_calculated_calculate_answer(
+                    $answer->answer, $data, $answer->tolerance,
+                    $answer->tolerancetype, $answer->correctanswerlength,
+                    $answer->correctanswerformat, $unit);
+                    if ( $formula === '*'){
+                        $answer->min = ' ';
+                        $formattedanswer->answer = $answer->answer ;
+                    }else {
+                        eval('$answer->answer = '.$formula.';') ;
+                        $virtualqtype->get_tolerance_interval($answer);
+                    } 
+            if ($answer->min === '') {
+                // This should mean that something is wrong
+                $comment->stranswers[$key] = " $formattedanswer->answer".'<br/><br/>';
+            } else if ($formula === '*'){
+                $comment->stranswers[$key] = $formula.' = '.get_string('anyvalue','qtype_calculated').'<br/><br/>';
+            }else{
+                $comment->stranswers[$key]= $formula.' = '.$formattedanswer->answer.'' ;
+                $comment->stranswers[$key] .= "<br/>".$strmin. $delimiter.$answer->min.'---';
+                $comment->stranswers[$key] .= $strmax.$delimiter.$answer->max;
+                $comment->stranswers[$key] .='<br/>';
+                $correcttrue->correct = $formattedanswer->answer ;
+                $correcttrue->true = $answer->answer ;
+                if ($formattedanswer->answer < $answer->min || $formattedanswer->answer > $answer->max){
+                    $comment->outsidelimit = true ;
+                    $comment->answers[$key] = $key;
+                    $comment->stranswers[$key] .=get_string('trueansweroutsidelimits','qtype_calculated',$correcttrue);//<span class="error">ERROR True answer '..' outside limits</span>';
+                }else {
+                    $comment->stranswers[$key] .=get_string('trueanswerinsidelimits','qtype_calculated',$correcttrue);//' True answer :'.$calculated->trueanswer.' inside limits';
+                }
+                $comment->stranswers[$key] .='';
+            }
+        }
+        return fullclone($comment);
+    }
+
+    function tolerance_types() {
+        return array('1'  => get_string('relative', 'quiz'),
+                     '2'  => get_string('nominal', 'quiz'),
+             //        '3'  => get_string('geometric', 'quiz')
+             );
+    }
+
+    function dataset_options($form, $name, $mandatory=true,$renameabledatasets=false) {
+    // Takes datasets from the parent implementation but
+    // filters options that are currently not accepted by calculated
+    // It also determines a default selection...
+    //$renameabledatasets not implemented anmywhere
+        list($options, $selected) = $this->dataset_options_from_database($form, $name,'','qtype_calculated');
+  //  list($options, $selected) = $this->dataset_optionsa($form, $name);
+
+        foreach ($options as $key => $whatever) {
+            if (!ereg('^1-', $key) && $key != '0') {
+                unset($options[$key]);
+            }
+        }
+        if (!$selected) {
+            if ($mandatory){
+            $selected =  "1-0-$name"; // Default
+            }else {
+                $selected = "0"; // Default
+            }
+        }
+        return array($options, $selected);
+    }
+
+
+/**
+   * Runs all the code required to set up and save an essay question for testing purposes.
+   * Alternate DB table prefix may be used to facilitate data deletion.
+   */
+  function generate_test($name, $courseid = null) {
+      global $DB;
+      list($form, $question) = parent::generate_test($name, $courseid);
+      $form->feedback = 1;
+      $form->multiplier = array(1, 1);
+      $form->shuffleanswers = 1;
+      $form->noanswers = 1;
+      $form->qtype ='calculatedsimple';
+      $question->qtype ='calculatedsimple';
+      $form->answers = array('{a} + {b}');
+      $form->fraction = array(1);
+      $form->tolerance = array(0.01);
+      $form->tolerancetype = array(1);
+      $form->correctanswerlength = array(2);
+      $form->correctanswerformat = array(1);
+      $form->questiontext = "What is {a} + {b}?";
+
+      if ($courseid) {
+          $course = $DB->get_record('course', array('id'=> $courseid));
+      }
+
+      $new_question = $this->save_question($question, $form, $course);
+
+      $dataset_form = new stdClass();
+      $dataset_form->nextpageparam["forceregeneration"]= 1;
+      $dataset_form->calcmin = array(1 => 1.0, 2 => 1.0);
+      $dataset_form->calcmax = array(1 => 10.0, 2 => 10.0);
+      $dataset_form->calclength = array(1 => 1, 2 => 1);
+      $dataset_form->number = array(1 => 5.4 , 2 => 4.9);
+      $dataset_form->itemid = array(1 => '' , 2 => '');
+      $dataset_form->calcdistribution = array(1 => 'uniform', 2 => 'uniform');
+      $dataset_form->definition = array(1 => "1-0-a",
+                                        2 => "1-0-b");
+      $dataset_form->nextpageparam = array('forceregeneration' => false);
+      $dataset_form->addbutton = 1;
+      $dataset_form->selectadd = 1;
+      $dataset_form->courseid = $courseid;
+      $dataset_form->cmid = 0;
+      $dataset_form->id = $new_question->id;
+      $this->save_dataset_items($new_question, $dataset_form);
+
+      return $new_question;
+  }
+}
+//// END OF CLASS ////
+
+//////////////////////////////////////////////////////////////////////////
+//// INITIATION - Without this line the question type is not in use... ///
+//////////////////////////////////////////////////////////////////////////
+question_register_questiontype(new question_calculatedsimple_qtype());
+
+
+?>