more work on the datasetdependent / calculated question creation forms

This commit is contained in:
jamiesensei
2007-01-17 18:28:51 +00:00
parent 4f390427d5
commit 60b5ecd3cf
8 changed files with 407 additions and 122 deletions
+1
View File
@@ -10,5 +10,6 @@ $string['mustbenumeric'] = 'You must enter a number here.';
$string['mustnotbenumeric'] = 'This can\'t be a number.';
$string['youmustenteramultiplierhere'] = 'You must enter a multiplier here.';
$string['nextpage'] = 'Next Page';
$string['nextitemtoadd'] = 'Next \'Item to Add\'';
$string['makecopynextpage'] = 'Next Page (new question)';
?>
+7 -2
View File
@@ -2,13 +2,18 @@
$string['itemno'] = 'Item $a';
$string['param'] = 'Param {<strong>$a</strong>}';
$string['additem'] = 'Add Item';
$string['deletelastitem'] = 'Delete Last Item';
$string['itemtoadd'] = 'Item To Add';
$string['calclength'] = 'Significant Figures';
$string['calclength'] = 'Decimal Places';
$string['calcdistribution'] = 'Distribution';
$string['uniform'] = 'Uniform';
$string['loguniform'] = 'Loguniform';
$string['generate'] = 'Generate';
$string['calcmin'] = 'Minimum';
$string['calcmax'] = 'Maximum';
$string['minmax'] = 'Range of Values';
$string['replacewithrandom'] = 'Replace with a random value';
$string['getnextnow'] = 'Get New \'Item to Add\' Now';
$string['forceregeneration'] = 'force regeneration';
$string['reuseifpossible'] = 'reuse previous value if available';
$string['youmustaddatleastoneitem'] = 'You must add at least one dataset item before you can save this question.';
?>
+25 -13
View File
@@ -24,20 +24,18 @@ if (!$returnurl && isset($SESSION->fromurl)) {
$id = optional_param('id', 0, PARAM_INT); // question id
$qtype = optional_param('qtype', '', PARAM_FILE);
$categoryid = optional_param('category', 0, PARAM_INT);
$wizard = optional_param('wizard', '', PARAM_ALPHA);
$wizardnow = optional_param('wizardnow', '', PARAM_ALPHA);
// Validate the URL parameters.
if ($id = optional_param('id', 0, PARAM_INT)) {
if (!$question = get_record("question", "id", $id)) {
if ($id) {
if (!$question = get_record('question', 'id', $id)) {
print_error('questiondoesnotexist', 'question', $returnurl);
}
get_question_options($question);
$submiturl = "question2.php?id=$id&returnurl=" . urlencode($returnurl).'&wizard='.$wizard;
} else if ($categoryid && $qtype) { // only for creating new questions
$question = new stdClass;
$question->category = $categoryid;
$question->qtype = $qtype;
$submiturl = "question2.php?category=$categoryid&qtype=$qtype&returnurl=" . urlencode($returnurl).'&wizard='.$wizard;
} else {
print_error('notenoughdatatoeditaquestion', 'question', $returnurl);
}
@@ -63,30 +61,32 @@ $coursecontext = get_context_instance(CONTEXT_COURSE, $category->course);
require_capability('moodle/question:manage', $coursecontext);
// Create the question editing form.
if ($wizard!==''){
if ($wizardnow!==''){
if (!method_exists($QTYPES[$question->qtype], 'next_wizard_form')){
print_error('missingimportantcode', 'question', $returnurl, 'wizard form definition');
} else {
$mform = $QTYPES[$question->qtype]->next_wizard_form($submiturl, $question, $wizard);
$mform = $QTYPES[$question->qtype]->next_wizard_form('question2.php', $question, $wizardnow);
}
} else {
$mform = $QTYPES[$question->qtype]->create_editing_form($submiturl, $question, $category->course);
$mform = $QTYPES[$question->qtype]->create_editing_form('question2.php', $question, $category->course);
}
if ($mform === null) {
print_error('missingimportantcode', 'question', $returnurl, 'question editing form definition');
}
$mform->set_data($question);
$toform = $question; // send the question object and a few more parameters to the form
$toform->returnurl = $returnurl;
$mform->set_data($toform);
if ($mform->is_cancelled()){
redirect($returnurl);
} else if ($data = $mform->get_data()){
} elseif ($data = $mform->get_data()){
if (!empty($data->makecopy)) {
$question->id = 0; // causes a new question to be created.
$question->hidden = 0; // Copies should not be hidden
}
$question = $QTYPES[$qtype]->save_question($question, $data, $COURSE);
if ($QTYPES[$qtype]->finished_edit_wizard($question)){
$question = $QTYPES[$question->qtype]->save_question($question, $data, $COURSE, $wizardnow);
if ($QTYPES[$qtype]->finished_edit_wizard($data)){
if (optional_param('inpopup', 0, PARAM_BOOL)) {
notify(get_string('changessaved'), '');
close_window(3);
@@ -95,7 +95,19 @@ if ($mform->is_cancelled()){
}
die;
} else {
redirect($submiturl.'&wizard='.$data->wizardpage);
//useful for passing data to the next page which is not saved in the database
$queryappend = '';
if (isset($data->nextpageparam)){
foreach ($data->nextpageparam as $key => $param){
$queryappend .= "&".urlencode($key).'='.urlencode($param);
}
}
if ($question->id) {
$nexturl = "question2.php?id=$question->id&returnurl=" . urlencode($returnurl);
} else { // only for creating new questions
$nexturl = "question2.php?category=$question->category&qtype=$question->qtype&returnurl=".urlencode($returnurl);
}
redirect($nexturl.'&wizardnow='.$data->wizard.$queryappend, '', 20);
}
} else {
// Display the question editing form
@@ -118,8 +118,8 @@ class question_edit_calculated_form extends question_edit_form {
$firstunit->setPersistantFreeze(true);
//hidden elements
$mform->addElement('hidden', 'wizardpage', 'question');
$mform->setType('wizardpage', PARAM_ALPHA);
$mform->addElement('hidden', 'wizard', 'datasetdefinitions');
$mform->setType('wizard', PARAM_ALPHA);
}
+131 -22
View File
@@ -216,8 +216,7 @@ class question_calculated_qtype extends question_dataset_dependent_questiontype
return true;
}
function print_question_formulation_and_controls(&$question, &$state, $cmoptions,
$options) {
function print_question_formulation_and_controls(&$question, &$state, $cmoptions, $options) {
// Substitute variables in questiontext before giving the data to the
// virtual type for printing
$virtualqtype = $this->get_virtual_qtype();
@@ -239,8 +238,7 @@ class question_calculated_qtype extends question_dataset_dependent_questiontype
}
$numericalquestion->questiontext = parent::substitute_variables(
$numericalquestion->questiontext, $state->options->dataset);
$virtualqtype->print_question_formulation_and_controls($numericalquestion,
$state, $cmoptions, $options);
$virtualqtype->print_question_formulation_and_controls($numericalquestion, $state, $cmoptions, $options);
}
function grade_responses(&$question, &$state, $cmoptions) {
@@ -326,6 +324,40 @@ class question_calculated_qtype extends question_dataset_dependent_questiontype
// Calcualted support generation of randomly distributed number data
return true;
}
function custom_generator_tools_part(&$mform, $idx, $j){
$minmaxgrp = array();
$minmaxgrp[] =& $mform->createElement('text', "calcmin[$idx]", get_string('calcmin', 'qtype_datasetdependent'), 'size="3"');
$minmaxgrp[] =& $mform->createElement('text', "calcmax[$idx]", get_string('calcmax', 'qtype_datasetdependent'), 'size="3"');
$mform->addGroup($minmaxgrp, 'minmaxgrp', get_string('minmax', 'qtype_datasetdependent'), ' - ', false);
$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('select', "calcdistribution[$idx]", get_string('calcdistribution', 'qtype_datasetdependent'), $distriboptions);
$mform->addElement('hidden', "definition[$j]");
$mform->addElement('hidden', "itemid[$j]");
}
function custom_generator_set_data($datasetdefs, $formdata){
$idx = 1;
foreach ($datasetdefs as $datasetdef){
if (ereg('^(uniform|loguniform):([^:]*):([^:]*):([0-9]*)$', $datasetdef->options, $regs)) {
$defid = "$datasetdef->type-$datasetdef->category-$datasetdef->name";
$formdata["calcdistribution[$idx]"] = $regs[1];
$formdata["calcmin[$idx]"] = $regs[2];
$formdata["calcmax[$idx]"] = $regs[3];
$formdata["calclength[$idx]"] = $regs[4];
}
$idx++;
}
return $formdata;
}
function custom_generator_tools($datasetdef) {
if (ereg('^(uniform|loguniform):([^:]*):([^:]*):([0-9]*)$',
@@ -355,6 +387,7 @@ class question_calculated_qtype extends question_dataset_dependent_questiontype
}
}
function update_dataset_options($datasetdefs, $form) {
// Do we have informatin about new options???
if (empty($form->definition) || empty($form->calcmin)
@@ -364,21 +397,22 @@ class question_calculated_qtype extends question_dataset_dependent_questiontype
} else {
// Looks like we just could have some new information here
foreach ($form->definition as $key => $defid) {
$uniquedefs = array_values(array_unique($form->definition));
foreach ($uniquedefs as $key => $defid) {
if (isset($datasetdefs[$defid])
&& is_numeric($form->calcmin[$key])
&& is_numeric($form->calcmax[$key])
&& is_numeric($form->calclength[$key])) {
switch ($form->calcdistribution[$key]) {
&& is_numeric($form->calcmin[$key+1])
&& is_numeric($form->calcmax[$key+1])
&& is_numeric($form->calclength[$key+1])) {
switch ($form->calcdistribution[$key+1]) {
case 'uniform': case 'loguniform':
$datasetdefs[$defid]->options =
$form->calcdistribution[$key] . ':'
. $form->calcmin[$key] . ':'
. $form->calcmax[$key] . ':'
. $form->calclength[$key];
$form->calcdistribution[$key+1] . ':'
. $form->calcmin[$key+1] . ':'
. $form->calcmax[$key+1] . ':'
. $form->calclength[$key+1];
break;
default:
notify("Unexpected distribution $form->calcdistribution[$key]");
notify("Unexpected distribution ".$form->calcdistribution[$key+1]);
}
}
}
@@ -393,6 +427,79 @@ class question_calculated_qtype extends question_dataset_dependent_questiontype
return $datasetdefs;
}
function save_dataset_items($question, $fromform){
if (empty($question->options)) {
$this->get_question_options($question);
}
//get the old datasets for this question
$datasetdefs = $this->get_dataset_definitions($question->id, array());
// Handle generator options...
$olddatasetdefs = fullclone($datasetdefs);
$datasetdefs = $this->update_dataset_options($datasetdefs, $fromform);
$maxnumber = -1;
foreach ($datasetdefs as $defid => $datasetdef) {
if (isset($datasetdef->id)
&& $datasetdef->options != $olddatasetdefs[$defid]->options) {
// Save the new value for options
update_record('question_dataset_definitions', $datasetdef);
}
// Get maxnumber
if ($maxnumber == -1 || $datasetdef->itemcount < $maxnumber) {
$maxnumber = $datasetdef->itemcount;
}
}
// Handle adding and removing of dataset items
$i = 1;
foreach ($fromform->definition as $key => $defid) {
//if the delete button has not been pressed then skip the datasetitems
//in the 'add item' part of the form.
if ((!isset($fromform->addbutton)) && ($i > (count($datasetdefs)*$maxnumber))) {
break;
}
$addeditem = new stdClass();
$addeditem->definition = $datasetdefs[$defid]->id;
$addeditem->value = $fromform->number[$i];
$addeditem->itemnumber = ceil($i / count($datasetdefs));
if ($fromform->itemid[$i]) {
// Reuse any previously used record
$addeditem->id = $fromform->itemid[$i];
if (!update_record('question_dataset_items', $addeditem)) {
error("Error: Unable to update dataset item");
}
} else {
if (!insert_record('question_dataset_items', $addeditem)) {
error("Error: Unable to insert dataset item");
}
}
$i++;
}
if ($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
update_record('question_dataset_definitions', $newdef);
}
}
}
if (isset($fromform->deletebutton)) {
// Simply decrease itemcount where == $maxnumber
foreach ($datasetdefs as $datasetdef) {
if ($datasetdef->itemcount == $maxnumber) {
$datasetdef->itemcount--;
if (!update_record('question_dataset_definitions',
$datasetdef)) {
error("Error: Unable to update itemcount");
}
}
}
--$maxnumber;
}
}
function generate_dataset_item($options) {
if (!ereg('^(uniform|loguniform):([^:]*):([^:]*):([0-9]*)$',
$options, $regs)) {
@@ -469,11 +576,9 @@ class question_calculated_qtype extends question_dataset_dependent_questiontype
global $SESSION;
$strheader = '';
$delimiter = '';
if (empty($question->id)) {
$answers = $SESSION->datasetdependent->questionform->answers;
} else {
$answers = $question->options->answers;
}
$answers = $question->options->answers;
foreach ($answers as $answer) {
if (is_string($answer)) {
$strheader .= $delimiter.$answer;
@@ -495,13 +600,17 @@ class question_calculated_qtype extends question_dataset_dependent_questiontype
}
$answers = $question->options->answers;
$stranswers = get_string('answer', 'quiz');
$stranswers = '';
$strmin = get_string('min', 'quiz');
$strmax = get_string('max', 'quiz');
$errors = '';
$delimiter = ': ';
$virtualqtype = $this->get_virtual_qtype();
foreach ($answers as $answer) {
$formula = $answer->answer;
foreach ($data as $name => $value) {
$formula = str_replace('{'.$name.'}', $value, $formula);
}
$calculated = qtype_calculated_calculate_answer(
$answer->answer, $data, $answer->tolerance,
$answer->tolerancetype, $answer->correctanswerlength,
@@ -516,12 +625,12 @@ class question_calculated_qtype extends question_dataset_dependent_questiontype
$errors .= " -$calculated->answer";
$stranswers .= $delimiter;
} else {
$stranswers .= $delimiter.$calculated->answer;
$stranswers .= $formula.' = '.$calculated->answer. '<br/>';
$strmin .= $delimiter.$calculated->min;
$strmax .= $delimiter.$calculated->max;
}
}
return "$stranswers<br/>$strmin<br/>$strmax<br/>$errors";
return "$stranswers$strmin<br/>$strmax<br/>$errors";
}
function tolerance_types() {
@@ -146,11 +146,11 @@ class question_dataset_dependent_questiontype extends default_questiontype {
// This gets called by editquestion.php after the standard question is saved
function print_next_wizard_page(&$question, &$form, $course) {
global $CFG, $USER, $SESSION;
global $CFG, $USER, $SESSION, $COURSE;
// Catch invalid navigation & reloads
if (empty($question->id) && empty($SESSION->datasetdependent)) {
redirect('edit.php', 'The page you are loading has expired.', 3);
redirect('edit.php?courseid='.$COURSE->id, 'The page you are loading has expired.', 3);
}
// See where we're coming from
@@ -169,28 +169,28 @@ class question_dataset_dependent_questiontype extends default_questiontype {
}
// This gets called by question2.php after the standard question is saved
function &next_wizard_form($submiturl, $question, $wizard){
global $CFG, $SESSION;
function &next_wizard_form($submiturl, $question, $wizardnow){
global $CFG, $SESSION, $COURSE;
// Catch invalid navigation & reloads
if (empty($question->id) && empty($SESSION->datasetdependent)) {
redirect('edit.php', 'The page you are loading has expired.', 3);
redirect('edit.php?courseid='.$COURSE->id, 'The page you are loading has expired. Cannot get next wizard form.', 3);
}
if (!isset($question->id)){
if (empty($question->id)){
$question =& $SESSION->datasetdependent->questionform;
}
// See where we're coming from
switch($wizard) {
case 'question':
switch($wizardnow) {
case 'datasetdefinitions':
require("$CFG->dirroot/question/type/datasetdependent/datasetdefinitions_form.php");
$mform =& new question_dataset_dependent_definitions_form($submiturl, $question);
$mform =& new question_dataset_dependent_definitions_form("$submiturl?wizardnow=datasetdefinitions", $question);
$mform->heading = print_heading_with_help(get_string("choosedatasetproperties", "quiz"), "questiondatasets", "quiz", '', true);
break;
case 'datasetdefinitions':
case 'datasetitems':
require("$CFG->dirroot/question/type/datasetdependent/datasetitems_form.php");
$mform =& new question_dataset_dependent_items_form($submiturl, $question);
$regenerate = optional_param('forceregeneration', 0, PARAM_BOOL);
$mform =& new question_dataset_dependent_items_form("$submiturl?wizardnow=datasetitems", $question, $regenerate);
$streditdatasets = get_string("editdatasets", "quiz");
$mform->heading = print_heading_with_help($streditdatasets, 'questiondatasets', "quiz", '', true);
break;
@@ -201,21 +201,35 @@ class question_dataset_dependent_questiontype extends default_questiontype {
return $mform;
}
function save_question($question, &$form, $course) {
function save_question($question, $form, $course) {
// For dataset dependent questions a wizard is used for editing
// questions. Therefore saving the question is delayed until
// we're through with the whole wizard.
global $SESSION;
// $this->validate_form($form);
$wizardnow = optional_param('wizardnow', '', PARAM_ALPHA);
// We need to return a valid question object (incl. id) if we're in the
// edit case. If it is a new question we don't necessarily need to
// return a valid question object
// See where we're coming from
switch($form->wizardpage) {
switch($wizardnow) {
case '' :
case 'question': // coming from the first page, creating the second
if (empty($form->id)) {
$form->options = new stdClass;
$form->options->answers = array();
foreach (array_keys($form->answers) as $i){
$form->options->answers[$i] = new stdClass;
$form->options->answers[$i]->answer = $form->answers[$i];
$form->options->answers[$i]->tolerance = $form->tolerance[$i];
$form->options->answers[$i]->tolerancetype = $form->tolerancetype[$i];
$form->options->answers[$i]->correctanswerlength = $form->correctanswerlength[$i];
$form->options->answers[$i]->correctanswerformat = $form->correctanswerformat[$i];
$form->options->answers[$i]->feedback = $form->feedback[$i];
}
$SESSION->datasetdependent = new stdClass;
$SESSION->datasetdependent->questionform = $form;
} else {
@@ -223,12 +237,12 @@ class question_dataset_dependent_questiontype extends default_questiontype {
}
break;
case 'datasetdefinitions':
if (empty($form->id)) {
if (empty($question->id)) {
if (isset($SESSION->datasetdependent->questionform)) {
$SESSION->datasetdependent->definitionform = $form;
} else {
// Something went wrong, go back to the first page
redirect("question.php?category={$question->category}" ."&qtype={$question->qtype}");
redirect("question2.php?category={$question->category}" ."&qtype={$question->qtype}");
}
} else {
$this->save_dataset_definitions($form);
@@ -241,6 +255,7 @@ class question_dataset_dependent_questiontype extends default_questiontype {
$this->save_dataset_definitions($SESSION->datasetdependent->definitionform);
unset($SESSION->datasetdependent);
}
$this->save_dataset_items($question, $form);
break;
default:
error('Incorrect or no wizard page specified!');
@@ -249,14 +264,19 @@ class question_dataset_dependent_questiontype extends default_questiontype {
return $question;
}
function get_dataset_definitions($form) {
function save_dataset_items($question, $fromform){
//overridden in child classes
}
function get_dataset_definitions($questionid, $newdatasets) {
//get the existing datasets for this question
$datasetdefs = array();
if (!empty($form->id)) {
if (!empty($questionid)) {
global $CFG;
$sql = "SELECT i.*
FROM {$CFG->prefix}question_datasets d,
{$CFG->prefix}question_dataset_definitions i
WHERE d.question = '$form->id'
WHERE d.question = '$questionid'
AND d.datasetdefinition = i.id
";
if ($records = get_records_sql($sql)) {
@@ -266,20 +286,20 @@ class question_dataset_dependent_questiontype extends default_questiontype {
}
}
$datasets = empty($form->dataset) ? $form->definition : $form->dataset;
foreach ($datasets as $dataset) {
foreach ($newdatasets as $dataset) {
if (!$dataset) {
continue; // The no dataset case...
}
if (!isset($datasetdefs[$dataset])) {
//make new datasetdef
list($type, $category, $name) = explode('-', $dataset, 3);
$datasetdef = new stdClass;
$datasetdef->type = $type;
$datasetdef->name = $name;
$datasetdef->category = $category;
$datasetdef->itemcount = 0;
$datasetdef->options = '';
$datasetdef->options = 'uniform:1.0:10.0:1';
$datasetdefs[$dataset] = clone($datasetdef);
}
}
@@ -288,7 +308,7 @@ class question_dataset_dependent_questiontype extends default_questiontype {
function save_dataset_definitions($form) {
// Save datasets
$datasetdefinitions = $this->get_dataset_definitions($form);
$datasetdefinitions = $this->get_dataset_definitions($form->id, $form->dataset);
$tmpdatasets = array_flip($form->dataset);
$defids = array_keys($datasetdefinitions);
foreach ($defids as $defid) {
@@ -26,13 +26,21 @@ class question_dataset_dependent_definitions_form extends moodleform {
parent::moodleform($submiturl);
}
function definition() {
global $SESSION;
$mform =& $this->_form;
$possibledatasets = $this->qtypeobj->find_dataset_names($this->question->questiontext);
$mandatorydatasets = array();
foreach ($this->question->answers as $answer) {
$mandatorydatasets += $this->qtypeobj->find_dataset_names($answer);
if (isset($this->question->options->answers)){
foreach ($this->question->options->answers as $answer) {
$mandatorydatasets += $this->qtypeobj->find_dataset_names($answer->answer);
}
}else{
foreach ($SESSION->datasetdependent->questionform->answers as $answer){
$mandatorydatasets += $this->qtypeobj->find_dataset_names($answer);
}
}
$key = 0;
$datasetmenus = array();
foreach ($mandatorydatasets as $datasetname) {
@@ -58,10 +66,20 @@ class question_dataset_dependent_definitions_form extends moodleform {
$key++;
}
}
//hidden elements
$mform->addElement('hidden', 'wizardpage', 'datasetdefinitions');
$mform->setType('wizardpage', PARAM_ALPHA);
$this->add_action_buttons(true, get_string('nextpage', 'qtype_calculated'));
//hidden elements
$mform->addElement('hidden', 'returnurl');
$mform->setType('returnurl', PARAM_URL);
$mform->addElement('hidden', 'qtype');
$mform->setType('qtype', PARAM_ALPHA);
$mform->addElement('hidden', 'category');
$mform->setType('category', PARAM_INT);
$mform->addElement('hidden', 'id');
$mform->setType('id', PARAM_INT);
$mform->addElement('hidden', 'wizard', 'datasetitems');
$mform->setType('wizard', PARAM_ALPHA);
}
}
@@ -14,84 +14,204 @@ class question_dataset_dependent_items_form extends moodleform {
* @var question_dataset_dependent_questiontype
*/
var $qtypeobj;
var $datasetdefs;
var $maxnumber = -1;
var $regenerate;
var $noofitems;
/**
* Add question-type specific form fields.
*
* @param MoodleQuickForm $mform the form being built.
*/
function question_dataset_dependent_items_form($submiturl, $question){
global $QTYPES;
function question_dataset_dependent_items_form($submiturl, $question, $regenerate){
global $QTYPES, $SESSION, $CFG;
$this->regenerate = $regenerate;
$this->question = $question;
$this->qtypeobj =& $QTYPES[$this->question->qtype];
//get the dataset defintions for this question
if (empty($question->id)) {
$this->datasetdefs = $this->qtypeobj->get_dataset_definitions($question->id, $SESSION->datasetdependent->definitionform->dataset);
} else {
if (empty($question->options)) {
$this->get_question_options($question);
}
$this->datasetdefs = $this->qtypeobj->get_dataset_definitions($question->id, array());
}
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 = get_records_sql( // Use number as key!!
" SELECT itemnumber, definition, id, value
FROM {$CFG->prefix}question_dataset_items
WHERE definition = $datasetdef->id ");
}
}
parent::moodleform($submiturl);
}
function definition() {
$mform =& $this->_form;
$strquestionlabel = $this->qtypeobj->comment_header($this->question);
$repeated = array();
$repeatedoptions = array();
$repeated[] =& $mform->createElement('header', 'itemhdr', get_string('itemno', 'qtype_datasetdependent', '{no}'));
$params = array('a', 'b', 'c');
foreach ($params as $paramno => $param){
$idx = $paramno +1;
$repeated[] =& $mform->createElement('text', "number[$idx]", get_string('param', 'qtype_datasetdependent', $param));
$repeated[] =& $mform->createElement('hidden', "itemid[$idx]");
$repeated[] =& $mform->createElement('hidden', "definition[$idx]");
$repeatedoptions["number[$idx]"]['type'] = PARAM_NUMBER;
//$repeatedoptions["number[$idx]"]['rule'] = 'numeric';
$repeatedoptions["itemid[$idx]"]['type'] = PARAM_INT;
$repeatedoptions["definition[$idx]"]['type'] = PARAM_NOTAGS;
}
/*if (isset($this->question->options)){
$countanswers = count($this->question->options->answers);
//------------------------------------------------------------------------------------------------------------------------------
if ($this->maxnumber != -1){
$this->noofitems = $this->maxnumber;
} else {
$countanswers = 0;
$this->noofitems = 0;
}
$repeatsatstart = (QUESTION_NUMANS_START > ($countanswers + QUESTION_NUMANS_ADD))?
QUESTION_NUMANS_START : ($countanswers + QUESTION_NUMANS_ADD);
*/
$repeatsatstart = 3;
$this->repeat_elements($repeated, $repeatsatstart, $repeatedoptions, 'itemsno', 'itemsadd', 1, get_string('additem', 'qtype_datasetdependent'));
$j = 1;
for ($i=1; $i <= $this->noofitems; $i++){
$mform->addElement('header', 'itemhdr', get_string('itemno', 'qtype_datasetdependent', $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->addElement('hidden', "itemid[$j]");
$mform->addElement('hidden', "definition[$j]");
$j++;
}
if ('' != $strquestionlabel){
$repeated[] =& $mform->addElement('static', "answercomment[$i]", $strquestionlabel);
}
if ($i == $this->noofitems) {//last item
$mform->addElement('submit', 'deletebutton', get_string('deletelastitem', 'qtype_datasetdependent'));
}
}
$mform->setType("itemid", PARAM_INT);
$mform->setType("definition", PARAM_NOTAGS);
$mform->addElement('submit', 'addbutton', get_string('additem', 'qtype_datasetdependent'));
$mform->closeHeaderBefore('addbutton');
//------------------------------------------------------------------------------------------------------------------------------
$mform->addElement('header', 'additemhdr', get_string('itemtoadd', 'qtype_datasetdependent'));
$idx = 1;
foreach ($this->datasetdefs as $defkey => $datasetdef){
$mform->addElement('text', "number[$j]", get_string('param', 'qtype_datasetdependent', $datasetdef->name));
$this->qtypeobj->custom_generator_tools_part(&$mform, $idx, $j);
$idx++;
$j++;
$mform->addElement('static', "divider[$j]", '', '<hr />');
}
if ('' != $strquestionlabel){
$mform->addElement('static', 'answercomment['.($this->noofitems+1).']', $strquestionlabel);
}
$mform->closeHeaderBefore('forceregenerationgrp');
if ($this->qtypeobj->supports_dataset_item_generation()){
$radiogrp = array();
$radiogrp[] =& $mform->createElement('radio', "forceregeneration", 0, get_string('reuseifpossible', 'quiz'));
$radiogrp[] =& $mform->createElement('radio', "forceregeneration", 1, get_string('forceregeneration', 'quiz'));
$mform->addGroup($radiogrp, 'forceregenerationgrp', '', null, false);
$radiogrp[] =& $mform->createElement('radio', 'nextpageparam[forceregeneration]', null, get_string('reuseifpossible', 'qtype_datasetdependent'), 0);
$radiogrp[] =& $mform->createElement('radio', 'nextpageparam[forceregeneration]', null, get_string('forceregeneration', 'qtype_datasetdependent'), 1);
$mform->addGroup($radiogrp, 'forceregenerationgrp', get_string('nextitemtoadd', 'qtype_calculated'), null, false);
$mform->setDefault('nextpageparam[forceregeneration]', 0);
}
$mform->addElement('header', 'additemhdr', get_string('itemtoadd', 'qtype_datasetdependent'));
foreach ($params as $paramno => $param){
$idx = $paramno +1;
$mform->addElement('text', "numbertoadd[$idx]", get_string('param', 'qtype_datasetdependent', $param));
$mform->addElement('submit', 'getnextbutton', get_string('getnextnow', 'qtype_datasetdependent'));
$minmaxgrp = array();
$minmaxgrp[] =& $mform->createElement('text', "calcmin[$idx]", get_string('calcmin', 'qtype_datasetdependent'), 'size="3"');
$minmaxgrp[] =& $mform->createElement('text', "calcmax[$idx]", get_string('calcmax', 'qtype_datasetdependent'), 'size="3"');
$mform->addGroup($minmaxgrp, 'minmaxgrp', get_string('minmax', 'qtype_datasetdependent'), ' - ', false);
//non standard name for button element needed so not using add_action_buttons
$buttonarray=array();
$buttonarray[] = &$mform->createElement('submit', 'backtoquiz', get_string('savechanges'));
$buttonarray[] = &$mform->createElement('cancel');
$mform->addGroup($buttonarray, 'buttonar', '', array(' '), false);
$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('select', "calcdistribution[$idx]", get_string('calcdistribution', 'qtype_datasetdependent'), $distriboptions);
$mform->addElement('submit', "generate[$idx]", get_string('generate', 'qtype_datasetdependent'));
$mform->addElement('hidden', "definition[$idx]");
$repeatedoptions["number[$idx]"]['type'] = PARAM_NUMBER;
//$repeatedoptions["number[$idx]"]['rule'] = 'numeric';
$repeatedoptions["itemid[$idx]"]['type'] = PARAM_INT;
$repeatedoptions["definition[$idx]"]['type'] = PARAM_NOTAGS;
}
$mform->addElement('hidden', 'wizardpage', 'datasetitems');
$mform->setType('wizardpage', PARAM_ALPHA);
$this->add_action_buttons(true);
//hidden elements
$mform->addElement('hidden', 'returnurl');
$mform->setType('returnurl', PARAM_URL);
$mform->addElement('hidden', 'qtype');
$mform->setType('qtype', PARAM_ALPHA);
$mform->addElement('hidden', 'category');
$mform->setType('category', PARAM_INT);
$mform->addElement('hidden', 'id');
$mform->setType('id', PARAM_INT);
$mform->addElement('hidden', 'wizard', 'datasetitems');
$mform->setType('wizard', PARAM_ALPHA);
}
function set_data($question){
$formdata = array();
//fill out all data sets and also the fields for the next item to add.
$j = 1;
for ($itemnumber = 1; $itemnumber <= $this->noofitems; $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++;
}
$formdata['answercomment['.$itemnumber.']'] = $this->qtypeobj->comment_on_datasetitems($this->question, $data, $itemnumber);
}
$formdata['nextpageparam[forceregeneration]'] = $this->regenerate;
$savej = $j;
$data = array(); // data for comment_on_datasetitems later
//dataset generation dafaults
if ($this->qtypeobj->supports_dataset_item_generation()) {
$itemnumber = $this->noofitems+1;
foreach ($this->datasetdefs as $defid => $datasetdef){
$formdata["number[$j]"] = $this->qtypeobj->generate_dataset_item($datasetdef->options);
$formdata["definition[$j]"] = $defid;
$formdata["itemid[$j]"] =
isset($datasetdef->items[$itemnumber])?$datasetdef->items[$itemnumber]->id:0;
$data[$datasetdef->name] = $formdata["number[$j]"];
$j++;
}
}
//existing records override generated data depending on radio element
$j = $savej;
if (!$this->regenerate){
$idx = 1;
$itemnumber = $this->noofitems+1;
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++;
}
}
//default answercomment will get ignored if answer element is not in the form.
$formdata['answercomment['.($this->noofitems+1).']'] = $this->qtypeobj->comment_on_datasetitems($this->question, $data, ($this->noofitems+1));
$formdata = $this->qtypeobj->custom_generator_set_data($this->datasetdefs, $formdata);
parent::set_data((object)($formdata + (array)$question));
}
function validation($data){
$errors = array();
if (isset($data['backtoquiz'])){
$errors['addbutton'] = get_string('youmustaddatleastoneitem', 'qtype_datasetdependent');
}
return $errors;
}
}
?>