Note:

If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

Calculated question validating the datasets: Difference between revisions

From MoodleDocs
Line 93: Line 93:
         $this->'''find_all_question_dataset_names'''($question, $mandatorydatasets, $possibledatasets) ;
         $this->'''find_all_question_dataset_names'''($question, $mandatorydatasets, $possibledatasets) ;
a typical output being
a typical output being
 
...


       // get all datasets related to this question datasetdefinitions and datasets infos
       // get all datasets related to this question datasetdefinitions and datasets infos
Line 105: Line 105:
                             {
                             {
a typical output being
a typical output being
...
          
          
(to be continued)
(to be continued)
===Are all the necessary datasets defined===
===Are all the necessary datasets defined===
First checking if all the necessary datasets are defined using the code in datasetdefinitions.php.
First checking if all the necessary datasets are defined using the code in datasetdefinitions.php.

Revision as of 21:15, 17 October 2006

This page contains working notes related to modifying the calculated question code for solving 1.7 bugs related to the handling of datasets and dataitems. They will be "cleaned" when the code proposals will be put in the Moodle code.

Selecting the right dataitem for a question

Actually the code select the dataitem number using the MAX value from the question_dataset_definitions->itemcount. It should choose the MIN so that there is a valid data item for each datasets. so in datasetdependent/abstractype.php line 29

       if(!$maxnumber = (int)get_field_sql(
                           "SELECT MAX(a.itemcount)
                           FROM {$CFG->prefix}question_dataset_definitions a,
                                {$CFG->prefix}question_datasets b
                           WHERE b.question = $question->id
                           AND   a.id = b.datasetdefinition")) {
           error("Couldn't get the specified dataset for a calculated " .
                 "question! (question: {$question->id}");
       }

should be changed to

       if(!$maxnumber = (int)get_field_sql(
                           "SELECT MIN(a.itemcount)
                           FROM {$CFG->prefix}question_dataset_definitions a,
                                {$CFG->prefix}question_datasets b
                           WHERE b.question = $question->id
                           AND   a.id = b.datasetdefinition")) {
           error("Couldn't get the specified dataset for a calculated " .
                 "question! (question: {$question->id}");
       }

But there is a difficulty if there is one question_dataset_definitions->itemcount == 0 there is an error and the question is not working properly. This could happen if question has been moved or the 3 steps of creation or edition process not completed. So I propose that we first validate the datasets BEFORE asking for $maxnumber

Validation of the datasets where?

If there is a problem when creating a calculated question for a quiz or a preview, this is because the test had not been done before i.e. when quiz or preview call calculated->get_question_options(); If calculated question validate its question options before there will be no problems. But what options should be extracted from calculated->get_question_options();

  • the answers (already done)
  • the units (already done)
  • the datasetdefs not done but can simplify the validation, there are some other functions to do this
  • the dataitems this could be large but useful, there are some other functions to do this

We have to choose. I will come back later A new function should be created to validate the datasets.

function datasets_validation()

Validate the datasets: How to

  1. Get all the datasets {a..} present in the question text (possible) and in the answers (mandatory)
    1. define a new function find_all_question_dataset_names($question, $mandatorydatasets, $possibledatasets) ;
  2. Get all the datasets {a..} present in the mdl_question_datasetdef using the datasets table
  3. Examine and validate all those question_dataset_names
    1. if the name IS NOT ALREADY in the datasets list, generate a local dataset (category = 0) and a link to it.
    2. if the name IS ALREADY in the list use the following rules
      1. if it is a local dataset (category = 0) use it without modifications
      2. if it is a category dataset (category > 0)
        1. if the $dataset->category == $question->category use it without modifications
        2. if the $dataset->category != $question->category (has been moved)
          1. if there is NO category dataset with the same name in the $question->category
            1. if NO other questions are using this category dataset in the initial $dataset->category move it to $question->category by just changing the category, there is already a link and possibly datatitems.
            2. if YES other questions are using it, generate a new category dataset in the $question->category , a link to it and add a copy of the data items already defined in the preceeding $dataset->category
          2. if there is A category dataset with the same name
            1. and YES the same options use it by making a link to it and add a copy of the data items already defined in $dataset->category that outnumber those already in $question->category (>itemnumber)(in this way you accept the values already defined using the same rules and don't modify the values already there.This will solve the situation were more than one question has been moved to another category.
            2. and NOT the same option, copy as local dataset (category = 0) add a link to it add a copy of the data items already defined in $dataset->category
  4. Verify the the itemcount of each datasedef
    1. If itemcount > 0 do nothing
    2. If itemcount == 0 generate one default using the datasetdef->options and
      1. Here we have a choice
        1. We store it in the database and it can be used by any other quiz functions needing it. the user is unaware of this but the question will at least not generate an error.
        2. We store it in $question and checked everywhere that it will be find when needed.
      2. In a first solution the default will be stored in the database.
  5. Every dataset name has valid parameters so we return.

Doing this we are also correcting the problems associate with the actual code for moving the questions.

function validate_datasets(&$question)

The function will be placed in abstractype.php so to be general to all datasetdependent typs although actually there is only calculated question using it.

We need supplementary functions to supply calculated carateristics so they are coded in calculated/questiontype.php

   function get_default_dataset_options() {
       
     return  'uniform:1.0:10.0:1'; 
   }    
   function get_default_dataset_type_value() {
       
     return  1 ; 
   }    
   function get_default_dataset_type_litteral() {
       
     return  'litteral' ; 
   }    
   function validate_datasets(&$question) {
       // try to set a general solution so take care to choose the right type and options
       // this is not a real problem because actually the calculated question is the only
       // one using datasetdependenttype
       global $CFG;
       $mandatorydatasets = array();
       $possibledatasets =array();
       $this->find_all_question_dataset_names($question, $mandatorydatasets, $possibledatasets) ;

a typical output being

...
      // get all datasets related to this question datasetdefinitions and datasets infos
        if(!$databasedatasets= get_records_sql(
                           "SELECT  a.name,a.category,a.type, a.options, a.itemcount,  b.id, b.datasetdefinition
                           FROM {$CFG->prefix}question_dataset_definitions a,
                                {$CFG->prefix}question_datasets b
                           WHERE b.question = $question->id
                           AND   a.id = b.datasetdefinition
                           ")) 
                           {

a typical output being

...
       

(to be continued)

Are all the necessary datasets defined

First checking if all the necessary datasets are defined using the code in datasetdefinitions.php.

// Determine possible and mandatory datasets...
$possibledatasets = $this->find_dataset_names($form->questiontext);
$mandatorydatasets = array();
foreach ($form->answers as $answer) {
    $mandatorydatasets += $this
            ->find_dataset_names($answer);
}

but this is a good occasion to create a new function

$this->find_all_dataset_names