コード例 #1
0
 public function __construct($submiturl, $question, $category, $contexts, $formeditable = true)
 {
     $this->regenerate = true;
     $this->question = $question;
     $this->qtypeobj = question_bank::get_qtype($this->question->qtype);
     // Get the dataset definitions for this question.
     // Coming here everytime even when using a NoSubmitButton.
     // 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.
     $this->reload = optional_param('reload', false, PARAM_BOOL);
     if (!$this->reload) {
         // Use database data as this is first pass
         // Question->id == 0 so no stored datasets.
         if (!empty($question->id)) {
             $this->datasetdefs = $this->qtypeobj->get_dataset_definitions($question->id, array());
             if (!empty($this->datasetdefs)) {
                 foreach ($this->datasetdefs as $defid => $datasetdef) {
                     // First get the items in case their number does not correspond to itemcount.
                     if (isset($datasetdef->id)) {
                         $this->datasetdefs[$defid]->items = $this->qtypeobj->get_database_dataset_items($datasetdef->id);
                         if ($this->datasetdefs[$defid]->items != '') {
                             $datasetdef->itemcount = count($this->datasetdefs[$defid]->items);
                         } else {
                             $datasetdef->itemcount = 0;
                         }
                     }
                     // Get maxnumber.
                     if ($this->maxnumber == -1 || $datasetdef->itemcount < $this->maxnumber) {
                         $this->maxnumber = $datasetdef->itemcount;
                     }
                 }
             }
             $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. In any case the validation
         // step will warn the user of any error in settings the values.
         // Verification for the specific dataset values as the other parameters
         // units, 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.
         // most of the data.
         $datasettoremove = false;
         $newdatasetvalues = false;
         $newdataset = false;
         $dummyform = new stdClass();
         $mandatorydatasets = array();
         // Should not test on adding a new answer.
         // Should test if there are already olddatasets or if the 'analyzequestion'.
         // submit button has been clicked.
         if (optional_param_array('datasetdef', false, PARAM_BOOL) || optional_param('analyzequestion', false, PARAM_BOOL)) {
             if ($dummyform->answer = optional_param_array('answer', '', PARAM_NOTAGS)) {
                 // There is always at least one answer...
                 $fraction = optional_param_array('fraction', '', PARAM_FLOAT);
                 $tolerance = optional_param_array('tolerance', '', PARAM_FLOAT);
                 $tolerancetype = optional_param_array('tolerancetype', '', PARAM_FLOAT);
                 $correctanswerlength = optional_param_array('correctanswerlength', '', PARAM_INT);
                 $correctanswerformat = optional_param_array('correctanswerformat', '', PARAM_INT);
                 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]->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);
                     }
                 }
             }
             $this->datasetdefs = array();
             // Rebuild datasetdefs from old values.
             if ($olddef = optional_param_array('datasetdef', '', PARAM_RAW)) {
                 $calcmin = optional_param_array('calcmin', '', PARAM_FLOAT);
                 $calclength = optional_param_array('calclength', '', PARAM_INT);
                 $calcmax = optional_param_array('calcmax', '', PARAM_FLOAT);
                 $oldoptions = optional_param_array('defoptions', '', PARAM_RAW);
                 $newdatasetvalues = false;
                 $sizeofolddef = count($olddef);
                 for ($key = 1; $key <= $sizeofolddef; $key++) {
                     $def = $olddef[$key];
                     $this->datasetdefs[$def] = new stdClass();
                     $this->datasetdefs[$def]->type = 1;
                     $this->datasetdefs[$def]->category = 0;
                     $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 (preg_match('~^(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;
                         }
                     }
                     $this->datasetdefs[$def]->options = "uniform:" . $this->datasetdefs[$def]->calcmin . ":" . $this->datasetdefs[$def]->calcmax . ":" . $this->datasetdefs[$def]->calclength;
                 }
             }
             // Detect new datasets.
             $newdataset = false;
             foreach ($mandatorydatasets as $datasetname) {
                 if (!isset($this->datasetdefs["1-0-{$datasetname}"])) {
                     $key = "1-0-{$datasetname}";
                     $this->datasetdefs[$key] = new stdClass();
                     $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;
                 } else {
                     $this->datasetdefs["1-0-{$datasetname}"]->name = $datasetname;
                 }
             }
             // Remove obsolete datasets.
             $datasettoremove = false;
             foreach ($this->datasetdefs as $defkey => $datasetdef) {
                 if (!isset($datasetdef->name)) {
                     $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', false, PARAM_BOOL)) {
         $maxnumber = optional_param('selectadd', '', PARAM_INT);
         // FIXME: sloppy coding.
         foreach ($this->datasetdefs as $defid => $datasetdef) {
             $datasetdef->itemcount = $maxnumber;
             unset($datasetdef->items);
             for ($numberadded = 1; $numberadded <= $maxnumber; $numberadded++) {
                 $datasetitem = new stdClass();
                 $datasetitem->itemnumber = $numberadded;
                 $datasetitem->id = 0;
                 $datasetitem->value = $this->qtypeobj->generate_dataset_item($datasetdef->options);
                 $this->datasetdefs[$defid]->items[$numberadded] = $datasetitem;
             }
         }
         $this->maxnumber = $maxnumber;
     } else {
         // Handle reload dataset items.
         if (optional_param_array('definition', '', PARAM_NOTAGS) && !($datasettoremove || $newdataset || $newdatasetvalues)) {
             $i = 1;
             $fromformdefinition = optional_param_array('definition', '', PARAM_NOTAGS);
             $fromformnumber = optional_param_array('number', '', PARAM_RAW);
             // This parameter will be validated in the form.
             $fromformitemid = optional_param_array('itemid', '', PARAM_INT);
             ksort($fromformdefinition);
             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;
                 }
             }
         }
     }
     parent::__construct($submiturl, $question, $category, $contexts, $formeditable);
 }
コード例 #2
0
 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);
     }
     while (preg_match('~\\{=([^[: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) {
         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');
     }
     /*Here we use the already done the error analysis so that 
      * we could force all wild cards values display if there is an error in values.
      * as using a , in a number */
     $numbers = $data['number'];
     foreach ($numbers as $key => $number) {
         if (!is_numeric($number)) {
             if (stristr($number, ',')) {
                 $errors['number[' . $key . ']'] = get_string('notvalidnumber', 'qtype_datasetdependent');
             } else {
                 $errors['number[' . $key . ']'] = get_string('notvalidnumber', 'qtype_datasetdependent');
             }
         } else {
             if (stristr($number, 'x')) {
                 $errors['number[' . $key . ']'] = get_string('notvalidnumber', 'qtype_datasetdependent');
             } else {
                 if (is_nan($number)) {
                     $errors['number[' . $key . ']'] = get_string('notvalidnumber', 'qtype_datasetdependent');
                 }
             }
         }
     }
     if ($this->noofitems == 0) {
         $errors['warning'] = get_string('warning', 'mnet');
     }
     return $errors;
 }