more work on the datasetdependent / calculated question creation forms
This commit is contained in:
@@ -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)';
|
||||
?>
|
||||
@@ -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
@@ -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);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
?>
|
||||
Reference in New Issue
Block a user