Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Adding various improvements (MDL-8565, MDL-9496, MDL10070 etc.)to cal…

…culated question
  • Loading branch information...
commit 009d136f7248e61377325d5cf25fd987fd9c06ea 1 parent 719ef5f
pichetp authored
View
97 question/type/calculated/editquestion.html
@@ -80,24 +80,31 @@
<?php if (isset($err["penalty"])) formerr($err["penalty"]); ?>
</td>
</tr>
+<?php
+// Answers.
+ for ($i=1; $i<=count($answers); $i++) {
+ $answer = $answers[$i-1];
+?>
<tr valign="top">
<td align="right"><b><?php print_string("correctanswerformula", "quiz") ?>:</b></td>
<td align="left">
- <input align="left" type="text" id="formula0" name="answers[]" size="20" value="<?php p($answers[0]->answer) ?>" alt="<?php print_string("correctanswerformula", "quiz") ?>" />&nbsp;&nbsp;
- <input type="hidden" name="fraction[]" value="1.0" />
+ <input align="left" type="text" id="formula0" name="answers[]" size="20" value="<?php p($answer->answer) ?>" alt="<?php print_string("correctanswerformula", "quiz") ?>" />&nbsp;&nbsp;
+ <?php print_string("grade");
+ echo ":&nbsp;";
+ choose_from_menu($gradeoptions, "fraction[]", $answer->fraction,""); ?>
</td>
</tr>
<tr valign="top">
<td align="right"><b><?php print_string("tolerance", "quiz"); ?>:</b></td>
<td align="left">
- <input align="left" type="text" id="tolerance0" name="tolerance[]" size="15" value="<?php p($answers[0]->tolerance) ?>" alt="<?php print_string("tolerance", "quiz"); ?>" />&plusmn;
+ <input align="left" type="text" id="tolerance0" name="tolerance[]" size="15" value="<?php p($answer->tolerance) ?>" alt="<?php print_string("tolerance", "quiz"); ?>" />&plusmn;
</td>
</tr>
<tr valign="top">
<td align="right"><b><?php print_string("tolerancetype", "quiz"); ?>:</b></td>
<td align="left">
<?php choose_from_menu($qtypeobj->tolerance_types(),
- 'tolerancetype[]', $answers[0]->tolerancetype, false); ?>
+ 'tolerancetype[]', $answer->tolerancetype, false); ?>
</td>
</tr>
<tr valign="top">
@@ -108,17 +115,27 @@
'4' => ' 4 ', '5' => ' 5 ', '6' => ' 6 ',
'7' => ' 7 ', '8' => ' 8 ', '9' => ' 9 '),
'correctanswerlength[]',
- $answers[0]->correctanswerlength, false); ?>
+ $answer->correctanswerlength, false); ?>
<?php choose_from_menu(array('1' => get_string('decimalformat', 'quiz'),
'2' => get_string('significantfiguresformat', 'quiz')),
'correctanswerformat[]',
- $answers[0]->correctanswerformat, false); ?>
+ $answer->correctanswerformat, false); ?>
</td>
</tr>
<tr valign="top">
<td align="right"><b><?php print_string("feedback", "quiz") ?>:</b></td>
<td align="left">
- <textarea name="feedback[]" rows="2" cols="50"><?php p($answers[0]->feedback) ?></textarea>
+ <textarea name="feedback[]" rows="2" cols="50"><?php p($answer->feedback) ?></textarea>
+ </td>
+</tr>
+<?php
+ }
+// Units.
+$addmoreanswerblanks=get_string('addmoreanswerblanks', 'qtype_calculated');
+?>
+<tr valign="top">
+ <td align="center" colspan="2">
+ <input name ='addanswers' type="submit" value="<?php p($addmoreanswerblanks) ?>" />
</td>
</tr>
<tr valign="top">
@@ -157,40 +174,40 @@
</tr>
<?php
} /// END for
+$addmoreanswerblanks=get_string('addmoreunitblanks', 'qtype_calculated');
?>
+<tr valign="top">
+ <td align="center" colspan="2">
+ <input name ='addunits' type="submit" value="<?php p($addmoreanswerblanks) ?>" />
+ </td>
+</tr>
+ <tr valign="top">
+ <td colspan="2" align="center">
+ <input type="submit" value="<?php print_string('nextpage', 'qtype_calculated') ?>" />
+ <?php
+ if ($question->id) {
+ ?>
+ <input type="submit" name="makecopy" value="<?php print_string('makecopynextpage', 'qtype_calculated')?>" />
+ <?php
+ }
+ ?>
+ <input type="submit" name="cancel" value="<?php print_string("cancel") ?>" />
+ <input type="hidden" name="sesskey" value="<?php p($USER->sesskey) ?>" />
+ <input type="hidden" name="id" value="<?php p($question->id) ?>" />
+ <input type="hidden" name="qtype" value="<?php p($question->qtype) ?>" />
+ <input type="hidden" name="wizardpage" value="question" />
+ <input type="hidden" name="inpopup" value="<?php echo optional_param('inpopup', 0, PARAM_INT) ?>" />
+ <?php
+
+
+ // The following hidden field indicates that the versioning code should be turned on, i.e.,
+ // that old versions should be kept if necessary
+ ?>
+ <input type="hidden" name="versioning" value="on" />
+ </td>
+ </tr>
</table>
-<input type="hidden" name="sesskey" value="<?php echo $USER->sesskey; ?>" />
-<input type="hidden" name="id" value="<?php p($question->id) ?>" />
-<input type="hidden" name="qtype" value="<?php p($question->qtype) ?>" />
-<input type="hidden" name="wizardpage" value="question" />
-<input type="submit" onclick="return determineMinAndMax();" value="<?php print_string("savechanges") ?>" />
+</center>
+</form></table>
</center>
</form>
-<script language="javascript" type="text/javascript">
-function determineMinAndMax() {
- // This client-side script will determine the values for min and max
- // based on the input for answer and acceptederror.
- with(document.theform) {
- if (formula0.value=='') {
- alert('<?php print_string("missingformula","quiz") ?>');
- return false;
- /* It could perhaps be an idea to parse the formula here
- * but as it is necessary at the server anyway, we can
- * it leave like this for the moment. */
-
- } else if (''!=defaultunit.value && !isNaN(defaultunit.value)) {
- alert('<?php print_string("unitmustnotbenumeric","quiz") ?>');
- return false;
- } else if (isNaN(tolerance0.value)) {
- alert('<?php print_string("tolerancemustbenumeric","quiz") ?>');
- return false;
- } else if ('2' == document.theform['correctanswerformat[]'].value
- && '0' == document.theform['correctanswerlength[]'].value) {
- alert('<?php print_string("zerosignificantfiguresnotallowed","quiz") ?>');
- return false;
- } else {
- return true;
- }
- }
-}
-</script>
View
61 question/type/calculated/editquestion.php
@@ -3,7 +3,7 @@
// Get a handle to the question type we are dealing with here
$qtypeobj = $QTYPES['calculated'];
-if (empty($form)) {
+if (empty($form)|| isset($form->addanswers) || isset($form->addunits)) {
/****************************************************************/
/***** First page in question wizard - editquestion.html.html! **/
/****************************************************************/
@@ -14,7 +14,7 @@
// However, the code behind supports up to six formulas
// and the database store and attempt/review framework
// does not have any limit.
- $answers= array();
+/* $answers= array();
for ($i=0; $i<6; $i++) {
// Make answer slots with default values
$answers[$i]->answer = "";
@@ -38,15 +38,52 @@
}
}
}
+ */
+ $emptyanswer = new stdClass;
+ $emptyanswer->answer = '';
+ $emptyanswer->feedback = "";
+ $emptyanswer->fraction = "1.0";
+ $emptyanswer->tolerance = "0.01";
+ $emptyanswer->tolerancetype = "1";
+ $emptyanswer->correctanswerlength = "2"; // Defaults to two ...
+ $emptyanswer->correctanswerformat = "1"; // ... decimals
+
+ if (!empty($question->id) && isset($question->qtype) &&
+ $QTYPES[$question->qtype]->get_question_options($question)) {
+
+ $answers = array_values($question->options->answers);
+ /* $units = array_values($question->options->units);
+ usort($units, create_function('$a, $b', // make sure the default unit is at index 0
+ 'if (1.0 === (float)$a->multiplier) { return -1; } else '.
+ 'if (1.0 === (float)$b->multiplier) { return 1; } else { return 0; }'));
+ */
+ } else {
+ $answers = array();
+ $answers[] = $emptyanswer;
+ // $units = array();
+ }
+
+ // Add blank answers to make the number up to QUESTION_NUMANS
+ // or one more than current, if there are already lots.
+ $emptyanswer = new stdClass;
+ $emptyanswer->answer = '';
+ $emptyanswer->feedback = "";
+ $emptyanswer->fraction = "1.0";
+ $emptyanswer->tolerance = "0.01";
+ $emptyanswer->tolerancetype = "1";
+ $emptyanswer->correctanswerlength = "2"; // Defaults to two ...
+ $emptyanswer->correctanswerformat = "1"; // ... decimals
+ // $i = count($answers);
+ // $limit = QUESTION_NUMANS;
+// $limit = $limit <= $i ? $i+1 : $limit;
+// for (; $i < $limit; $i++) {
+ $answers[] = $emptyanswer;
+ // }
// Units are handled the same way
// as for numerical questions
$units = array();
- for ($i=0 ; $i<6 ; $i++) {
- // Make unit slots, default as blank...
- $units[$i]->multiplier = '';
- $units[$i]->unit = '';
- }
+
if (!empty($question->id) and $unitsraw = get_records(
'question_numerical_units', 'question', $question->id)) {
/// Find default unit and have it put in the zero slot
@@ -70,8 +107,9 @@
}
} else {
$units[0]->multiplier = 1.0;
+ $units[0]->unit= '';
}
-
+
// Strip trailing zeros from multipliers
foreach ($units as $i => $unit) {
if (ereg('^(.*\\..(.*[^0])?)0+$', $unit->multiplier, $regs1)) {
@@ -82,6 +120,13 @@
}
}
}
+ if (isset($form->addunits)){
+ $emptyunit = new stdClass;
+ $emptyunit->multiplier = '';
+ $emptyunit->unit = '';
+ $units[]=$emptyunit;
+ $units[]=$emptyunit;
+ }
print_heading_with_help(get_string("editingcalculated", "quiz"), "calculated", "quiz");
require("$CFG->dirroot/question/type/calculated/editquestion.html");
} else { // $form is not empty
View
268 question/type/calculated/questiontype.php
@@ -195,11 +195,136 @@ function save_question_options($question) {
delete_records('question_calculated', 'id', $oo->id);
}
}
+ // validating data but not on import
+ if( !isset($question->import_process)){
+ $mandatorydatasets = array();
+ foreach ($question->answers as $answer) {
+ $mandatorydatasets += $this->find_dataset_names($answer);
+ }
+ // do not proceed further if no mandatorydataset
+ if (count($mandatorydatasets) < 1) { // check there are at lest 2 answers for multiple choice
+ $result->notice = get_string('atleastonewildcard', 'qtype_datasetdependent');//get_string("notenoughanswers", "qtype_multichoice", "2");
+ return $result;
+ }
+ $calculatedmessages = array();
+ //evaluate the equations i.e {=5+4) eval(
+ $qtext = "";
+ $qtextremaining = $question->questiontext ;
+ $possibledatasets = $this->find_dataset_names($question->questiontext);
+ foreach ($possibledatasets as $name => $value) {
+ $qtextremaining = str_replace('{'.$name.'}', '1', $qtextremaining);
+ }
+ // echo "numericalquestion qtextremaining <pre>";print_r($possibledatasets);
+
+// echo "test<pre>";print_r($numericalquestion);
+ while (ereg('\{=([^[:space:]}]*)}', $qtextremaining, $regs1)) {
+ $qtextsplits = explode($regs1[0], $qtextremaining, 2);
+ $qtext =$qtext.$qtextsplits[0];
+ $qtextremaining = $qtextsplits[1];
+ // echo "testsplit0".$qtextsplits[0]."<br/>";
+ // echo "test".$regs1[0]."<br/>";
+ // echo "qtext".$qtext."<br/>";
+ // echo "test<pre>";print_r($regs1);
+ if (empty($regs1[1])) {
+ $str = '';
+ } else {
+ // could put here an equation verification
+ if ($formulaerrors =
+ qtype_calculated_find_formula_errors($regs1[1])) {
+ $calculatedmessages[] = $formulaerrors;
+ $str = '';
+ }
+ }
+ }
+ // import from 1.8 to be tested
+ $answercount=0 ;
+ $maxgrade = false;
+ $mandatorydatasets = array();
+ foreach ($question->answers as $key => $answer){
+ $mandatorydatasets += $this->find_dataset_names($answer);
+ }
+ if ( count($mandatorydatasets )==0){
+ // $errors['questiontext']=get_string('atleastonewildcard', 'qtype_datasetdependent');
+ // foreach ($answers as $key => $answer){
+ $calculatedmessages[] = get_string('atleastonewildcard', 'qtype_datasetdependent');
+// }
+ }
+ foreach ($question->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){
+ $calculatedmessages[] = $eqerror.":".$answer;
+ }
+ }
+
+ 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++;
+ }
+ }
+ if ($answercount == 0) {
+ $calculatedmessages[]=get_string('atleastoneanswer', 'qtype_calculated');
+ }
+ /* $calculatedmessages = array();
+ if (empty($form->name)) {
+ $calculatedmessages[] = get_string('missingname', 'quiz');
+ }
+ if (empty($form->questiontext)) {
+ $calculatedmessages[] = get_string('missingquestiontext', 'quiz');
+ }
+ // Verify formulas
+ foreach ($form->answers as $key => $answer) {
+ if ('' === trim($answer)) {
+ $calculatedmessages[] =
+ get_string('missingformula', 'quiz');
+ }
+ if ($formulaerrors =
+ qtype_calculated_find_formula_errors($answer)) {
+ $calculatedmessages[] = $formulaerrors;
+ }
+ if (! isset($form->tolerance[$key])) {
+ $form->tolerance[$key] = 0.0;
+ }
+ if (! is_numeric($form->tolerance[$key])) {
+ $calculatedmessages[] =
+ get_string('tolerancemustbenumeric', 'quiz');
+ }
+ }
+ if (!empty($calculatedmessages)) {
+ $errorstring = "The following errors were found:<br />";
+ foreach ($calculatedmessages as $msg) {
+ $errorstring .= $msg . '<br />';
+ }
+ error($errorstring);
+ }
+ */
+ }
if( isset($question->import_process)&&$question->import_process){
$this->import_datasets($question);
}
+ if (!empty($calculatedmessages)) {
+ $errorstring = "The following errors were found:<br />";
+ foreach ($calculatedmessages as $msg) {
+ $errorstring .= $msg . '<br />';
+ }
+ $result->notice=$errorstring;
+ }
+
// Report any problems.
if (!empty($result->notice)) {
return $result;
@@ -261,7 +386,7 @@ function import_datasets($question){
$datasetitem->number = $dataitem->itemnumber ;
$datasetitem->value = $dataitem->value ;
if (!insert_record('question_dataset_items', $datasetitem)) {
- error("Unable to insert dataset item $item->itemnumber with $item->value for $datasetdef->name");
+ error("Unable to insert dataset item $datasetitem->number with $item->value for $datasetdef->name");
}
}
}
@@ -273,6 +398,7 @@ function create_runtime_question($question, $form) {
$question->options->answers = array();
foreach ($form->answers as $key => $answer) {
$a->answer = trim($form->answer[$key]);
+ $a->fraction = $form->fraction[$key];//new
$a->tolerance = $form->tolerance[$key];
$a->tolerancetype = $form->tolerancetype[$key];
$a->correctanswerlength = $form->correctanswerlength[$key];
@@ -365,6 +491,25 @@ function print_question_formulation_and_controls(&$question, &$state, $cmoptions
}
$numericalquestion->questiontext = parent::substitute_variables(
$numericalquestion->questiontext, $state->options->dataset);
+ //evaluate the equations i.e {=5+4)
+ $qtext = "";
+ $qtextremaining = $numericalquestion->questiontext ;
+ while (ereg('\{=([^[:space:]}]*)}', $qtextremaining, $regs1)) {
+ $qtextsplits = explode($regs1[0], $qtextremaining, 2);
+ $qtext =$qtext.$qtextsplits[0];
+ $qtextremaining = $qtextsplits[1];
+ if (empty($regs1[1])) {
+ $str = '';
+ } else {
+ if( $formulaerrors = qtype_calculated_find_formula_errors($regs1[1])){
+ $str=$formulaerrors ;
+ }else {
+ eval('$str = '.$regs1[1].';');
+ }
+ }
+ $qtext = $qtext.$str ;
+ }
+ $numericalquestion->questiontext = $qtext.$qtextremaining ; // end replace equations
$virtualqtype->print_question_formulation_and_controls($numericalquestion, $state, $cmoptions, $options);
}
@@ -590,7 +735,7 @@ function generate_dataset_item($options) {
function comment_header($question) {
//$this->get_question_options($question);
global $SESSION;
- $strheader = '';
+ $strheader = Array();
$delimiter = '';
if (empty($question->id)) {
$answers = $SESSION->datasetdependent->questionform->answers;
@@ -599,9 +744,9 @@ function comment_header($question) {
}
foreach ($answers as $answer) {
if (is_string($answer)) {
- $strheader .= $delimiter.$answer;
+ $strheader[] = $answer;
} else {
- $strheader .= $delimiter.$answer->answer;
+ $strheader[]= $answer->answer;
}
$delimiter = ',';
}
@@ -624,6 +769,7 @@ function comment_on_datasetitems($question, $data, $number) {
$errors = '';
$delimiter = ': ';
$virtualqtype = $this->get_virtual_qtype();
+ $column =Array();
foreach ($answers as $answer) {
$calculated = qtype_calculated_calculate_answer(
$answer->answer, $data, $answer->tolerance,
@@ -639,12 +785,13 @@ function comment_on_datasetitems($question, $data, $number) {
$errors .= " -$calculated->answer";
$stranswers .= $delimiter;
} else {
- $stranswers .= $delimiter.$calculated->answer;
- $strmin .= $delimiter.$calculated->min;
- $strmax .= $delimiter.$calculated->max;
+ // $stranswers .= $delimiter.$calculated->answer;
+ // $strmin .= $delimiter.$calculated->min;
+ // $strmax .= $delimiter.$calculated->max;
+ $column[]=$stranswers.$delimiter.$calculated->answer.'<br/>'.$strmin.$delimiter.$calculated->min.'<br/>'.$strmax.$delimiter.$calculated->max ;
}
}
- return "$stranswers<br/>$strmin<br/>$strmax<br/>$errors";
+ return $column;
}
function tolerance_types() {
@@ -653,18 +800,25 @@ function tolerance_types() {
'3' => get_string('geometric', 'quiz'));
}
- function dataset_options($form, $name, $renameabledatasets=false) {
+ function dataset_options($form, $name, $mandatory=true,$renameabledatasets=false) {
// Takes datasets from the parent implementation but
// filters options that are currently not accepted by calculated
// It also determines a default selection...
- list($options, $selected) = parent::dataset_options($form, $name);
+ //$renameabledatasets not implemented anmywhere
+ list($options, $selected) = parent::dataset_options($form, $name,'','qtype_calculated');
+ // list($options, $selected) = $this->dataset_optionsa($form, $name);
+
foreach ($options as $key => $whatever) {
if (!ereg('^'.LITERAL.'-', $key) && $key != '0') {
unset($options[$key]);
}
}
if (!$selected) {
+ if ($mandatory){
$selected = LITERAL . "-0-$name"; // Default
+ }else {
+ $selected = "0"; // Default
+ }
}
return array($options, $selected);
}
@@ -721,6 +875,100 @@ function substitute_variables($str, $dataset) {
return $str;
}
+ /**
+ * This function retrieve the item count of the available category shareable
+ * wild cards that is added as a comment displayed when a wild card with
+ * the same name is displayed in datasetdefinitions_form.php
+ */
+ function get_dataset_definitions_category($form) {
+ global $CFG;
+ $datasetdefs = array();
+ $lnamemax = 30;
+ if (!empty($form->category)) {
+ $sql = "SELECT i.*,d.*
+ FROM {$CFG->prefix}question_datasets d,
+ {$CFG->prefix}question_dataset_definitions i
+ WHERE i.id = d.datasetdefinition
+ AND i.category = '$form->category'
+ ;
+ ";
+ if ($records = get_records_sql($sql)) {
+ foreach ($records as $r) {
+ if ( !isset ($datasetdefs["$r->name"])) $datasetdefs["$r->name"] = $r->itemcount;
+ }
+ }
+ }
+ return $datasetdefs ;
+ }
+
+ /**
+ * This function build a table showing the available category shareable
+ * wild cards, their name, their definition (Min, Max, Decimal) , the item count
+ * and the name of the question where they are used.
+ * This table is intended to be add before the question text to help the user use
+ * these wild cards
+ */
+
+ function print_dataset_definitions_category($form) {
+ global $CFG;
+ $datasetdefs = array();
+ $lnamemax = 22;
+ $namestr =get_string('name', 'quiz');
+ $minstr=get_string('min', 'quiz');
+ $maxstr=get_string('max', 'quiz');
+ $rangeofvaluestr=get_string('minmax','qtype_datasetdependent');
+ $questionusingstr = get_string('usedinquestion','qtype_calculated');
+ $wildcardstr = get_string('wildcard', 'qtype_calculated');
+ $itemscountstr = get_string('itemscount','qtype_datasetdependent');
+ $text ='';
+ if (!empty($form->category)) {
+ $sql = "SELECT i.*,d.*
+ FROM {$CFG->prefix}question_datasets d,
+ {$CFG->prefix}question_dataset_definitions i
+ WHERE i.id = d.datasetdefinition
+ AND i.category = '$form->category';
+ " ;
+ if ($records = get_records_sql($sql)) {
+ foreach ($records as $r) {
+ $sql1 = "SELECT q.*
+ FROM {$CFG->prefix}question q
+ WHERE q.id = $r->question
+ ";
+ if ( !isset ($datasetdefs["$r->type-$r->category-$r->name"])){
+ $datasetdefs["$r->type-$r->category-$r->name"]= $r;
+ }
+ if ($questionb = get_records_sql($sql1)) {
+ $datasetdefs["$r->type-$r->category-$r->name"]->questions[$r->question]->name =$questionb[$r->question]->name ;
+ }
+ }
+ }
+ }
+ if (!empty ($datasetdefs)){
+
+ $text ="<table width=\"100%\" border=\"1\"><tr><th style=\"white-space:nowrap;\" class=\"header\" scope=\"col\" >$namestr</th><th style=\"white-space:nowrap;\" class=\"header\" scope=\"col\">$rangeofvaluestr</th><th style=\"white-space:nowrap;\" class=\"header\" scope=\"col\">$itemscountstr</th><th style=\"white-space:nowrap;\" class=\"header\" scope=\"col\">$questionusingstr</th></tr>";
+ foreach ($datasetdefs as $datasetdef){
+ list($distribution, $min, $max,$dec) = explode(':', $datasetdef->options, 4);
+ $text .="<tr><td valign=\"top\" align=\"center\"> $datasetdef->name </td><td align=\"center\" valign=\"top\"> $min <strong>-</strong> $max </td><td align=\"right\" valign=\"top\">$datasetdef->itemcount&nbsp;&nbsp;</td><td align=\"left\">";
+ foreach ($datasetdef->questions as $qu) {
+ //limit the name length displayed
+ if (!empty($qu->name)) {
+ $qu->name = (strlen($qu->name) > $lnamemax) ?
+ substr($qu->name, 0, $lnamemax).'...' : $qu->name;
+ } else {
+ $qu->name = '';
+ }
+ $text .=" &nbsp;&nbsp; $qu->name <br/>";
+ }
+ $text .="</td></tr>";
+ }
+ $text .="</table>";
+ }else{
+ $text .=get_string('nosharedwildcard', 'qtype_calculated');
+ }
+ return $text ;
+ }
+
+
/// BACKUP FUNCTIONS ////////////////////////////
/*
View
341 question/type/datasetdependent/abstractqtype.php
@@ -27,7 +27,7 @@ function create_session_and_responses(&$question, &$state, $cmoptions, $attempt)
// Find out how many datasets are available
global $CFG;
if(!$maxnumber = (int)get_field_sql(
- "SELECT MAX(a.itemcount)
+ "SELECT MIN(a.itemcount)
FROM {$CFG->prefix}question_dataset_definitions a,
{$CFG->prefix}question_datasets b
WHERE b.question = $question->id
@@ -76,42 +76,6 @@ function save_session_and_responses(&$question, &$state) {
return true;
}
- 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();
- $unit = $virtualqtype->get_default_numerical_unit($question);
- foreach ($question->options->answers as $answer) {
- $answer->answer = $this->substitute_variables($answer->answer,
- $state->options->dataset);
- }
- $question->questiontext = $this->substitute_variables(
- $question->questiontext, $state->options->dataset);
- $virtualqtype->print_question_formulation_and_controls($question,
- $state, $cmoptions, $options);
- }
-
- function grade_responses(&$question, &$state, $cmoptions) {
- // Forward the grading to the virtual qtype
- foreach ($question->options->answers as $answer) {
- $answer->answer = $this->substitute_variables($answer->answer,
- $state->options->dataset);
- }
- $virtualqtype = $this->get_virtual_qtype();
- return $virtualqtype->grade_responses($question, $state, $cmoptions) ;
- }
-
- // ULPGC ecastro
- function check_response(&$question, &$state) {
- // Forward the checking to the virtual qtype
- foreach ($question->options->answers as $answer) {
- $answer->answer = $this->substitute_variables($answer->answer,
- $state->options->dataset);
- }
- $virtualqtype = $this->get_virtual_qtype();
- return $virtualqtype->check_response($question, $state) ;
- }
function substitute_variables($str, $dataset) {
foreach ($dataset as $name => $value) {
@@ -156,7 +120,11 @@ function print_next_wizard_page(&$question, &$form, $course) {
// See where we're coming from
switch($form->wizardpage) {
case 'question':
+ if (!isset($form->addanswers)) {
require("$CFG->dirroot/question/type/datasetdependent/datasetdefinitions.php");
+ // require("$CFG->dirroot/question/type/datasetdependent/datasetdefinitions_form.php");
+ // $mform =& new question_dataset_dependent_definitions_form("question.php?wizardnow=datasetdefinitions", $question);
+ }
break;
case 'datasetdefinitions':
case 'datasetitems':
@@ -168,6 +136,80 @@ function print_next_wizard_page(&$question, &$form, $course) {
}
}
+ /**
+ * This method prepare the $datasets in a format similar to dadatesetdefinitions_form.php
+ * so that they can be saved
+ * using the function save_dataset_definitions($form)
+ * when creating a new calculated question or
+ * whenediting an already existing calculated question
+ * or by function save_as_new_dataset_definitions($form, $initialid)
+ * when saving as new an already existing calculated question
+ *
+ * @param object $form
+ * @param int $questionfromid default = '0'
+ */
+ function preparedatasets($form , $questionfromid='0'){
+ // the dataset names present in the edit_question_form and edit_calculated_form are retrieved
+ $possibledatasets = $this->find_dataset_names($form->questiontext);
+ $mandatorydatasets = array();
+ foreach ($form->answers as $answer) {
+ $mandatorydatasets += $this->find_dataset_names($answer);
+ }
+ // if there are identical datasetdefs already saved in the original question.
+ // either when editing a question or saving as new
+ // they are retrieved using $questionfromid
+ if ($questionfromid!='0'){
+ $form->id = $questionfromid ;
+ }
+ $datasets = array();
+ $key = 0 ;
+ // always prepare the mandatorydatasets present in the answers
+ // the $options are not used here
+ foreach ($mandatorydatasets as $datasetname) {
+ if (!isset($datasets[$datasetname])) {
+ list($options, $selected) =
+ $this->dataset_options($form, $datasetname);
+ $datasets[$datasetname]='';
+ $form->dataset[$key]=$selected ;
+ $key++;
+ }
+ }
+ // do not prepare possibledatasets when creating a question
+ // they will defined and stored with datasetdefinitions_form.php
+ // the $options are not used here
+ if ($questionfromid!='0'){
+
+ foreach ($possibledatasets as $datasetname) {
+ if (!isset($datasets[$datasetname])) {
+ list($options, $selected) =
+ $this->dataset_options($form, $datasetname,false);
+ $datasets[$datasetname]='';
+ $form->dataset[$key]=$selected ;
+ $key++;
+ }
+ }
+ }
+ return $datasets ;
+ }
+ /**
+ * this version save the available data at the different steps of the question editing process
+ * without using global $SESSION as storage between steps
+ * at the first step $wizardnow = 'question'
+ * when creating a new question
+ * when modifying a question
+ * when copying as a new question
+ * the general parameters and answers are saved using parent::save_question
+ * then the datasets are prepared and saved
+ * at the second step $wizardnow = 'datasetdefinitions'
+ * the datadefs final type are defined as private, category or not a datadef
+ * at the third step $wizardnow = 'datasetitems'
+ * the datadefs parameters and the data items are created or defined
+ *
+ * @param object question
+ * @param object $form
+ * @param int $course
+ * @param PARAM_ALPHA $wizardnow should be added as we are coming from question2.php
+ */
function save_question($question, &$form, $course) {
// For dataset dependent questions a wizard is used for editing
// questions. Therefore saving the question is delayed until
@@ -181,35 +223,34 @@ function save_question($question, &$form, $course) {
// See where we're coming from
switch($form->wizardpage) {
+ case '' :
case 'question': // coming from the first page, creating the second
- if (empty($form->id)) {
- $SESSION->datasetdependent = new stdClass;
- $SESSION->datasetdependent->questionform = $form;
- } else {
+ if (empty($form->id)) { // for a new question $form->id is empty
$question = parent::save_question($question, $form, $course);
+ //prepare the datasets using default $questionfromid
+ $form->datasets = $this->preparedatasets($form);
+ $form->id = $question->id;
+ $this->save_dataset_definitions($form);
+ } else if (!empty($form->makecopy)){
+ $questionfromid = $form->id ;
+ $question = parent::save_question($question, $form, $course);
+ //prepare the datasets
+ $form->datasets = $this->preparedatasets($form,$questionfromid);
+ $form->id = $question->id;
+ $this->save_as_new_dataset_definitions($form,$questionfromid );
+ } else {// editing a question
+ $question = parent::save_question($question, $form, $course);
+ //prepare the datasets
+ $form->datasets = $this->preparedatasets($form,$question->id);
+ $form->id = $question->id;
+ $this->save_dataset_definitions($form);
}
break;
case 'datasetdefinitions':
- if (empty($form->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}");
- }
- } else {
$this->save_dataset_definitions($form);
- }
break;
case 'datasetitems':
- if (empty($form->id) && isset($form->addbutton)) {
- $question = parent::save_question($question,
- $SESSION->datasetdependent->questionform, $course);
- $SESSION->datasetdependent->definitionform->id = $form->id = $question->id;
- $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!');
@@ -218,14 +259,19 @@ function save_question($question, &$form, $course) {
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)) {
@@ -235,20 +281,20 @@ function get_dataset_definitions($form) {
}
}
- $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);
}
}
@@ -257,7 +303,7 @@ function get_dataset_definitions($form) {
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) {
@@ -334,7 +380,122 @@ function save_dataset_definitions($form) {
}
}
}
+ /** This function create a copy of the datasets ( definition and dataitems)
+ * from the preceding question if they remain in the new question
+ * otherwise its create the datasets that have been added as in the
+ * save_dataset_definitions()
+ */
+ function save_as_new_dataset_definitions($form, $initialid) {
+ global $CFG ;
+ // Get the datasets from the intial question
+ $datasetdefinitions = $this->get_dataset_definitions($initialid, $form->dataset);
+ // $tmpdatasets contains those of the new question
+ $tmpdatasets = array_flip($form->dataset);
+ $defids = array_keys($datasetdefinitions);// new datasets
+ foreach ($defids as $defid) {
+ $datasetdef = &$datasetdefinitions[$defid];
+ if (isset($datasetdef->id)) {
+ // This dataset exist in the initial question
+ if (!isset($tmpdatasets[$defid])) {
+ // do not exist in the new question so ignore
+ unset($datasetdefinitions[$defid]);
+ continue;
+ }
+ // create a copy but not for category one
+ if (0 == $datasetdef->category) {
+ $olddatasetid = $datasetdef->id ;
+ $olditemcount = $datasetdef->itemcount ;
+ $datasetdef->itemcount =0;
+ if (!$datasetdef->id = insert_record(
+ 'question_dataset_definitions', $datasetdef)) {
+ error("Unable to create dataset $defid");
+ }
+ //copy the dataitems
+ $olditems = get_records_sql( // Use number as key!!
+ " SELECT number, value
+ FROM {$CFG->prefix}question_dataset_items
+ WHERE definition = $olddatasetid ");
+ if (count($olditems) > 0 ) {
+ $itemcount = 0;
+ foreach($olditems as $item ){
+ $item->definition = $datasetdef->id;
+ if (!insert_record('question_dataset_items', $item)) {
+ error("Unable to insert dataset item $item->number with $item->value for $datasetdef->name");
+ }
+ $itemcount++;
+ }
+ //update item count
+ $datasetdef->itemcount =$itemcount;
+ update_record('question_dataset_definitions', $datasetdef);
+ } // end of copy the dataitems
+ }// end of copy the datasetdef
+ // Create relation to the new question with this
+ // copy as new datasetdef from the initial question
+ $questiondataset = new stdClass;
+ $questiondataset->question = $form->id;
+ $questiondataset->datasetdefinition = $datasetdef->id;
+ if (!insert_record('question_datasets',
+ $questiondataset)) {
+ error("Unable to create relation to dataset $name");
+ }
+ unset($datasetdefinitions[$defid]);
+ continue;
+ }// end of datasetdefs from the initial question
+ // really new one code similar to save_dataset_definitions()
+ if (!$datasetdef->id = insert_record(
+ 'question_dataset_definitions', $datasetdef)) {
+ error("Unable to create dataset $defid");
+ }
+
+ if (0 != $datasetdef->category) {
+ // We need to look for already existing
+ // datasets in the category.
+ // By first creating the datasetdefinition above we
+ // can manage to automatically take care of
+ // some possible realtime concurrence
+ if ($olderdatasetdefs = get_records_select(
+ 'question_dataset_definitions',
+ "type = '$datasetdef->type'
+ AND name = '$datasetdef->name'
+ AND category = '$datasetdef->category'
+ AND id < $datasetdef->id
+ ORDER BY id DESC")) {
+
+ while ($olderdatasetdef = array_shift($olderdatasetdefs)) {
+ delete_records('question_dataset_definitions',
+ 'id', $datasetdef->id);
+ $datasetdef = $olderdatasetdef;
+ }
+ }
+ }
+
+ // Create relation to this dataset:
+ $questiondataset = new stdClass;
+ $questiondataset->question = $form->id;
+ $questiondataset->datasetdefinition = $datasetdef->id;
+ if (!insert_record('question_datasets',
+ $questiondataset)) {
+ error("Unable to create relation to dataset $name");
+ }
+ unset($datasetdefinitions[$defid]);
+ }
+ // Remove local obsolete datasets as well as relations
+ // to datasets in other categories:
+ if (!empty($datasetdefinitions)) {
+ foreach ($datasetdefinitions as $def) {
+ delete_records('question_datasets',
+ 'question', $form->id,
+ 'datasetdefinition', $def->id);
+
+ if ($def->category == 0) { // Question local dataset
+ delete_records('question_dataset_definitions', 'id', $def->id);
+ delete_records('question_dataset_items',
+ 'definition', $def->id);
+ }
+ }
+ }
+ }
/*
@@ -395,58 +556,8 @@ function save_question($question, &$form, $course) {
*/
-/*
- function create_runtime_question($question, $form) {
- $question->name = trim($form->name);
- $question->questiontext = trim($form->questiontext);
- $question->questiontextformat = $form->questiontextformat;
- $question->parent = isset($form->parent)? $form->parent : 0;
- $question->length = $this->actual_number_of_questions($question);
- $question->penalty = isset($form->penalty) ? $form->penalty : 0;
-
- if (empty($form->image)) {
- $question->image = "";
- } else {
- $question->image = $form->image;
- }
- if (empty($question->name)) {
- $question->name = strip_tags($question->questiontext);
- if (empty($question->name)) {
- $question->name = '-';
- }
- }
-
- if ($question->penalty > 1 or $question->penalty < 0) {
- $question->errors['penalty'] = get_string('invalidpenalty', 'quiz');
- }
-
- if (isset($form->defaultgrade)) {
- $question->defaultgrade = $form->defaultgrade;
- }
- return $question;
- }
-*/
-/*
- function validate_form($form) {
- switch($form->wizardpage) {
- case 'question':
- error('Validation for the wizardpage "question" needs to be ' .
- 'defined in the inheriting questiontype.');
- case 'datasetdefinitions':
- // Nothing to validate
- $SESSION->datasetdependent->datasetdefinitions = $form;
- break;
- case 'datasets':
- break;
- default:
- error('Incorrect or no wizard page specified!');
- break;
- }
- return true;
- }
-*/
/// Dataset functionality
function pick_question_dataset($question, $datasetitem) {
// Select a dataset in the following format:
View
112 question/type/datasetdependent/datasetitems.php
@@ -1,6 +1,7 @@
<?php // $Id$
// Allows a teacher to create, edit and delete datasets
-
+// max datasets = 100 items
+ $max100 = 100 ;
// Set up strings
$strdatasetnumber = get_string("datasetnumber", "quiz");
$strnumberinfo = get_string("categoryinfo", "quiz");
@@ -19,6 +20,8 @@
$strforceregeneration = get_string('forceregeneration', 'quiz');
$strdataitemneed = get_string('dataitemneed', 'quiz');
+ $strcondensedtable =get_string('switchtocondensedtable', 'qtype_datasetdependent');
+ $strnormaltable =get_string('switchtonormaltable', 'qtype_datasetdependent');
if (empty($question->id)) {
$datasetdefs = $this->get_dataset_definitions(
$SESSION->datasetdependent->definitionform);
@@ -26,7 +29,7 @@
if (empty($question->options)) {
$this->get_question_options($question);
}
- $datasetdefs = $this->get_dataset_definitions($form);
+ $datasetdefs = $this->get_dataset_definitions($question->id, array());
}
// Handle generator options...
@@ -55,8 +58,21 @@
$addeditem->definition = $datasetdefs[$defid]->id;
$addeditem->value = $form->value[$key];
if ($form->itemid[$key]) {
- // Reuse an previously used record
$addeditem->id = $form->itemid[$key];
+ // Reuse an previously used record
+ if (empty($form->forceregeneration) && (
+ isset($form->regenerateddefid) &&
+ $form->regenerateddefid != $defid ||
+ isset($form->deletebutton))) {
+ // echo "<p>Reuse an previously used record un".$addeditem->id."</p>";
+ } else {
+ if ($this->supports_dataset_item_generation()) {
+ $addeditem->value = $this->generate_dataset_item($datasetdefs[$defid]->options);
+ } else {
+ $addeditem->value = '';
+ }
+ }
+ //echo "<p>update le dataset_items".$addeditem->id."</p>";
if (!update_record('question_dataset_items', $addeditem)) {
error("Error: Unable to update dataset item");
}
@@ -66,31 +82,79 @@
error("Error: Unable to insert dataset item");
}
}
-
+ }
+ $maxnumber = $addeditem->number;
+ $numbertoadd =0;
+ if ($form->selectadd > 1 && $maxnumber < $max100 ) {
+ $numbertoadd =$form->selectadd-1 ;
+ if ( $max100 - $maxnumber < $numbertoadd ) {
+ $numbertoadd = $max100 - $maxnumber ;
+ }
+ //add the other items.
+ // tout d'abord le définit
+ // Generate a new dataset item (or reuse an old one)
+ foreach ($datasetdefs as $defid => $datasetdef) {
+ if (isset($datasetdef->id)) {
+ $datasetdefs[$defid]->items = get_records_sql( // Use number as key!!
+ " SELECT number, definition, id, value
+ FROM {$CFG->prefix}question_dataset_items
+ WHERE definition = $datasetdef->id ORDER BY number");
+ }
+ // echo "<pre>"; print_r($datasetdefs[$defid]->items);
+ for ($numberadded =$maxnumber+1 ; $numberadded <= $maxnumber+$numbertoadd ; $numberadded++){
+ if (isset($datasetdefs[$defid]->items[$numberadded]) && (
+ empty($form->forceregeneration)
+ // && isset($form->regenerateddefid) &&
+ // $form->regenerateddefid != $defid || no
+ || isset($form->deletebutton))) {
+ // echo "<p>Reuse an previously used record".$numberadded."id".$datasetdef->id."</p>";
+ } else {
+ $datasetitem = new stdClass;
+ $datasetitem->definition = $datasetdef->id ;
+ $datasetitem->number = $numberadded;
+ if ($this->supports_dataset_item_generation()) {
+ $datasetitem->value = $this->generate_dataset_item($datasetdef->options);
+ } else {
+ $datasetitem->value = '';
+ }
+ //pp echo "<pre>"; print_r( $datasetitem );
+ //insere le nouveau
+ if (!insert_record('question_dataset_items', $datasetitem)) {
+ error("Error: Unable to insert new dataset item");
+ }
+ $datasetdefs[$defid]->items[$numberadded] = clone($datasetitem);
+ }
+ }//for number added
+ }// datasetsdefs end
+ }
+ $maxnumber += $numbertoadd ;
foreach ($datasetdefs as $key => $newdef) {
if (isset($newdef->id) && $newdef->itemcount <= $maxnumber) {
- $newdef->itemcount = $maxnumber+1;
+ $newdef->itemcount = $maxnumber;
// Save the new value for options
update_record('question_dataset_definitions', $newdef);
}
}
- }
- // else Success:
- $maxnumber = $addeditem->number;
+ //} // if select >
+
} else if (isset($form->deletebutton)
&& $maxnumber == $form->numbertodelete) {
// Simply decrease itemcount where == $maxnumber
+ // selectedelete<p align="center"></p>
+ if(isset($form->selectdelete)) $newmaxnumber = $maxnumber-$form->selectdelete ;
+ else $newmaxnumber = $maxnumber-1 ;
+ if ($newmaxnumber < 0 ) $newmaxnumber = 0 ;
foreach ($datasetdefs as $datasetdef) {
if ($datasetdef->itemcount == $maxnumber) {
- $datasetdef->itemcount--;
+ $datasetdef->itemcount= $newmaxnumber ; //pp--;
if (!update_record('question_dataset_definitions',
$datasetdef)) {
error("Error: Unable to update itemcount");
}
}
}
- --$maxnumber;
+ $maxnumber= $newmaxnumber;
}
make_upload_directory("$course->id"); // Just in case
@@ -160,13 +224,17 @@
. '<br/><input type="radio" name="forceregeneration" value="1" '
. $force . ' />' . $strforceregeneration;
}
+ //pp limit
+ if ($maxnumber < $max100) {
$addline[] = '<input type="hidden" name="numbertoadd" value="'.
($maxnumber+1).'"/><input type="submit" name="addbutton" '.
- 'value="'.$stradd.'"/>'.$forceregeneration;
+ 'value="'.$stradd.'"/>'.'<select name="selectadd"><option value="1" selected>1</option><option value="10">10</option><option value="20">20</option><option value="30">30</option><option value="40">40</option><option value="50">50</option><option value="100">100</option></select>' .$forceregeneration;
$addline[] = $maxnumber+1;
-
-
+ } else {
+ $addline[] ='<input type="hidden" name="numbertoadd" value="'.($maxnumber+1).'"/>';
+ $addline[] = "&gt;".$max100;
+ }
foreach ($datasetdefs as $defid => $datasetdef) {
if ($datasetdef->name) {
$table->head[] = $datasetdef->name;
@@ -197,8 +265,10 @@
}
if ($strquestionheader) {
- $table->head[] = $strquestionheader;
- $addtable->head[] = $strquestionheader;
+ foreach($strquestionheader as $header){
+ $table->head[] = $header;
+ $addtable->head[] = $header;
+ }
if (empty($question->id) &&
isset($SESSION->datasetdependent->questionform)) {
$tmp = &$SESSION->datasetdependent->questionform;
@@ -212,7 +282,10 @@
}
$question->options->answers = $answers;
}
- $addline[] = $this->comment_on_datasetitems($question, $data, $maxnumber + 1);
+ $comment =$this->comment_on_datasetitems($question, $data, $maxnumber + 1);
+ foreach($comment as $comm){
+ $addline[] = $comm ;
+ }
}
// Set up the table showing existing datasets
@@ -223,7 +296,7 @@
if ($maxnumber == $number) {
$columns[] =
"<input type=\"hidden\" name=\"numbertodelete\" value=\"$number\"/>
- <input type=\"submit\" name=\"deletebutton\" value=\"$strdelete\"/>";
+ <input type=\"submit\" name=\"deletebutton\" value=\"$strdelete\"/>".'<select name="selectdelete"><option value="1" selected>1</option><option value="10">10</option><option value="20">20</option><option value="30">30</option><option value="40">40</option><option value="50">50</option><option value="100">100</option></select>';
} else {
$columns[] = '';
}
@@ -237,7 +310,10 @@
($data[$datasetdef->name] = $datasetdef->items[$number]->value) ;
}
if ($strquestionheader) {
- $columns[] = $this->comment_on_datasetitems($question, $data, $number);
+ $comment =$this->comment_on_datasetitems($question, $data, $number);
+ foreach($comment as $comm){
+ $columns[] = $comm ;
+ }
}
$table->data[] = $columns;
}
Please sign in to comment.
Something went wrong with that request. Please try again.