Skip to content

Commit

Permalink
merging small modifications from head mostly for calculated questions
Browse files Browse the repository at this point in the history
  • Loading branch information
pichetp committed May 15, 2007
1 parent c0bea40 commit edaaa46
Showing 1 changed file with 108 additions and 119 deletions.
227 changes: 108 additions & 119 deletions question/format/webct/format.php
Expand Up @@ -27,6 +27,10 @@
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////


// Based on format.php, included by ../../import.php // Based on format.php, included by ../../import.php
/**
* @package questionbank
* @subpackage importexport
*/


function unhtmlentities($string){ function unhtmlentities($string){
$search = array ("'<script[?>]*?>.*?</script>'si", // remove javascript $search = array ("'<script[?>]*?>.*?</script>'si", // remove javascript
Expand Down Expand Up @@ -58,91 +62,7 @@ function unhtmlentities($string){
return preg_replace ($search, $replace, $string); return preg_replace ($search, $replace, $string);
} }


class qformat_webct_modified_calculated_qtype extends question_calculated_qtype {
// We need to make a modification of this qtype so that
// it will be able to save webct style calculated questions
// The difference between webct and Moodle is that webct
// pass the individual data items as part of the question
// while Moodle core treat them separately


function save_question_options($question, $options = false) {

if (false !== $options) {
// function is called from save_question...
return parent::save_question_options($question, $options);
}

// function is called from format.php...

$datasetdatas = $question->datasets;

// Set dataset
$form->dataset = array();
foreach ($datasetdatas as $datasetname => $notimportant) {
// Literal - question local - name
$form->dataset[] = "1-0-$datasetname";
}

$subtypeoptions->answers = $question->answers;
$subtypeoptions->units = $question->units;

unset($question->datasets);
unset($question->answers);
unset($question->units);

$this->save_question($question, $form, 'not used', $subtypeoptions);

// Save dataset options and items...

// Get datasetdefinitions
global $CFG;
$datasetdefs = get_records_sql(
"SELECT a.*
FROM {$CFG->prefix}question_dataset_definitions a,
{$CFG->prefix}question_datasets b
WHERE a.id = b.datasetdefinition
AND b.question = '$question->id' ");

foreach ($datasetdefs as $datasetdef) {
$datasetdata = $datasetdatas[$datasetdef->name];

// Set items and retrieve ->itemcout
$item->definition = $datasetdef->id;
for ($item->itemnumber=1 ; isset($datasetdata->items["$item->itemnumber"]) ; ++$item->itemnumber) {
$item->value = $datasetdata->items["$item->itemnumber"];
if (!insert_record('question_dataset_items', $item)) {
error("Unable to insert dataset item $item->itemnumber with $item->value for $datasetdef->name");
}
}
$datasetdef->itemcount = $item->itemnumber - 1;

// Retrieve ->options
if (is_numeric($datasetdata->min) && is_numeric($datasetdata->max)
&& $datasetdata->min <= $datasetdata->max) {
if (is_numeric($datasetdata->dec)) {
$dec = max(0, ceil($datasetdata->dec));
} else {
$dec = 1; // A try
}

$datasetdef->options = "uniform:$datasetdata->min:$datasetdata->max:$dec";
} else {
$datasetdef->options = '';
}

// Save definition
if ($datasetdef->itemcount || $datasetdef->options) {
if (!update_record('question_dataset_definitions', $datasetdef)) {
error("Unable to update dataset definition $datasetdef->name on question $question->id");
}
}
}

// Done
return true;
}
}
$QTYPES[CALCULATED] = new qformat_webct_modified_calculated_qtype();


function qformat_webct_convert_formula($formula) { function qformat_webct_convert_formula($formula) {


Expand Down Expand Up @@ -246,7 +166,8 @@ function provide_import() {
} }


function readquestions ($lines) { function readquestions ($lines) {
$qtypecalculated = new qformat_webct_modified_calculated_qtype(); global $QTYPES ;
// $qtypecalculated = new qformat_webct_modified_calculated_qtype();
$webctnumberregex = $webctnumberregex =
'[+-]?([0-9]+(\\.[0-9]*)?|\\.[0-9]+)((e|E|\\*10\\*\\*)([+-]?[0-9]+|\\([+-]?[0-9]+\\)))?'; '[+-]?([0-9]+(\\.[0-9]*)?|\\.[0-9]+)((e|E|\\*10\\*\\*)([+-]?[0-9]+|\\([+-]?[0-9]+\\)))?';


Expand Down Expand Up @@ -305,7 +226,7 @@ function readquestions ($lines) {


if (isset($feedbacktext) and is_string($feedbacktext)) { if (isset($feedbacktext) and is_string($feedbacktext)) {
if (ereg("^:",$line)) { if (ereg("^:",$line)) {
$question->feedback[$currentchoice] = addslashes(trim($feedbacktext)); $question->feedback[$currentchoice] = addslashes(trim($feedbacktext));
unset($feedbacktext); unset($feedbacktext);
} }
else { else {
Expand All @@ -314,6 +235,17 @@ function readquestions ($lines) {
} }
} }


if (isset($generalfeedbacktext) and is_string($generalfeedbacktext)) {
if (ereg("^:",$line)) {
$question->tempgeneralfeedback= addslashes(trim($generalfeedbacktext));
unset($generalfeedbacktext);
}
else {
$generalfeedbacktext .= str_replace('\:', ':', $line);
continue;
}
}

$line = trim($line); $line = trim($line);


if (eregi("^:(TYPE|EOF):",$line)) { if (eregi("^:(TYPE|EOF):",$line)) {
Expand Down Expand Up @@ -346,11 +278,26 @@ function readquestions ($lines) {
$QuestionOK = FALSE; $QuestionOK = FALSE;
} }
else { else {
// Create empty feedback array // Create empty feedback array
$question->feedback = array();
foreach ($question->answer as $key => $dataanswer) { foreach ($question->answer as $key => $dataanswer) {
$question->feedback[$key] = ''; if(!isset( $question->feedback[$key])){
$question->feedback[$key] = '';
}
} }
// this tempgeneralfeedback allows the code to work with versions from 1.6 to 1.9
// when question->generalfeedback is undefined, the webct feedback is added to each answer feedback
if (isset($question->tempgeneralfeedback)){
if (isset($question->generalfeedback)) {
$question->generalfeedback = $question->tempgeneralfeedback;
} else {
foreach ($question->answer as $key => $dataanswer) {
if ($question->tempgeneralfeedback !=''){
$question->feedback[$key] = $question->tempgeneralfeedback.'<br/>'.$question->feedback[$key];
}
}
}
unset($question->tempgeneralfeedback);
}
$maxfraction = -1; $maxfraction = -1;
$totalfraction = 0; $totalfraction = 0;
foreach($question->fraction as $fraction) { foreach($question->fraction as $fraction) {
Expand Down Expand Up @@ -379,8 +326,7 @@ function readquestions ($lines) {
} }
} else { } else {
$totalfraction = round($totalfraction,2); $totalfraction = round($totalfraction,2);
if ($totalfraction != 1) { if ($totalfraction != 1) {
echo "<p>$totalfraction</p>";
$totalfraction = $totalfraction * 100; $totalfraction = $totalfraction * 100;
$errors[] = "'$question->name': ".get_string("wronggrade", "quiz", $nLineCounter).' '.get_string("fractionsaddwrong", "quiz", $totalfraction); $errors[] = "'$question->name': ".get_string("wronggrade", "quiz", $nLineCounter).' '.get_string("fractionsaddwrong", "quiz", $totalfraction);
$QuestionOK = FALSE; $QuestionOK = FALSE;
Expand All @@ -390,20 +336,36 @@ function readquestions ($lines) {


case CALCULATED: case CALCULATED:
foreach ($question->answers as $answer) { foreach ($question->answers as $answer) {
if ($formulaerror =qtype_calculated_find_formula_errors($answer->answer)) { if ($formulaerror =qtype_calculated_find_formula_errors($answer)) { //$QTYPES['calculated']->
$warnings[] = "'$question->name': ". $formulaerror; $warnings[] = "'$question->name': ". $formulaerror;
$QuestionOK = FALSE; $QuestionOK = FALSE;
} }
} }
foreach ($question->dataset as $dataset) {
$dataset->itemcount=count($dataset->datasetitem);
}
$question->import_process=TRUE ;
unset($question->answer); //not used in calculated question
break;
case MATCH:
if (count($question->answer) < 3){
// add a dummy missing question
$question->name = 'Dummy question added '.$question->name ;
$question->answer[] = 'dummy';
$question->subanswers[] = 'dummy';
$question->subquestions[] = 'dummy';
$question->fraction[] = '0.0';
$question->feedback[] = '';
}
break; break;


default: default:
// No problemo // No problemo
} }
} }


if ($QuestionOK) { if ($QuestionOK) {
// $question->feedback = array(); // echo "<pre>"; print_r ($question);
$questions[] = $question; // store it $questions[] = $question; // store it
unset($question); // and prepare a new one unset($question); // and prepare a new one
$question = $this->defaultquestion(); $question = $this->defaultquestion();
Expand All @@ -417,6 +379,7 @@ function readquestions ($lines) {
if (eregi("^:TYPE:MC:1(.*)",$line,$webct_options)) { if (eregi("^:TYPE:MC:1(.*)",$line,$webct_options)) {
// Multiple Choice Question with only one good answer // Multiple Choice Question with only one good answer
$question = $this->defaultquestion(); $question = $this->defaultquestion();
$question->feedback = array();
$question->qtype = MULTICHOICE; $question->qtype = MULTICHOICE;
$question->single = 1; // Only one answer is allowed $question->single = 1; // Only one answer is allowed
$ignore_rest_of_question = FALSE; $ignore_rest_of_question = FALSE;
Expand All @@ -426,6 +389,7 @@ function readquestions ($lines) {
if (eregi("^:TYPE:MC:N(.*)",$line,$webct_options)) { if (eregi("^:TYPE:MC:N(.*)",$line,$webct_options)) {
// Multiple Choice Question with several good answers // Multiple Choice Question with several good answers
$question = $this->defaultquestion(); $question = $this->defaultquestion();
$question->feedback = array();
$question->qtype = MULTICHOICE; $question->qtype = MULTICHOICE;
$question->single = 0; // Many answers allowed $question->single = 0; // Many answers allowed
$ignore_rest_of_question = FALSE; $ignore_rest_of_question = FALSE;
Expand All @@ -435,6 +399,7 @@ function readquestions ($lines) {
if (eregi("^:TYPE:S",$line)) { if (eregi("^:TYPE:S",$line)) {
// Short Answer Question // Short Answer Question
$question = $this->defaultquestion(); $question = $this->defaultquestion();
$question->feedback = array();
$question->qtype = SHORTANSWER; $question->qtype = SHORTANSWER;
$question->usecase = 0; // Ignore case $question->usecase = 0; // Ignore case
$ignore_rest_of_question = FALSE; $ignore_rest_of_question = FALSE;
Expand All @@ -443,27 +408,31 @@ function readquestions ($lines) {


if (eregi("^:TYPE:C",$line)) { if (eregi("^:TYPE:C",$line)) {
// Calculated Question // Calculated Question
$warnings[] = get_string("calculatedquestion", "quiz", $nLineCounter); /* $warnings[] = get_string("calculatedquestion", "quiz", $nLineCounter);
unset($question); unset($question);
$ignore_rest_of_question = TRUE; // Question Type not handled by Moodle $ignore_rest_of_question = TRUE; // Question Type not handled by Moodle
/* $question->qtype = CALCULATED; */
$question = $this->defaultquestion();
$question->qtype = CALCULATED;
$question->answers = array(); // No problem as they go as :FORMULA: from webct $question->answers = array(); // No problem as they go as :FORMULA: from webct
$question->units = array(); $question->units = array();
$question->datasets = array(); $question->dataset = array();


// To make us pass the end-of-question sanity checks // To make us pass the end-of-question sanity checks
$question->answer = array('dummy'); $question->answer = array('dummy');
$question->fraction = array('1.0'); $question->fraction = array('1.0');
$question->feedback = array();


$currentchoice = -1; $currentchoice = -1;
$ignore_rest_of_question = FALSE;*/ $ignore_rest_of_question = FALSE;
continue; continue;
} }


if (eregi("^:TYPE:M",$line)) { if (eregi("^:TYPE:M",$line)) {
// Match Question // Match Question
$question = $this->defaultquestion(); $question = $this->defaultquestion();
$question->qtype = MATCH; $question->qtype = MATCH;
$question->feedback = array();
$ignore_rest_of_question = FALSE; // match question processing is not debugged $ignore_rest_of_question = FALSE; // match question processing is not debugged
continue; continue;
} }
Expand Down Expand Up @@ -517,18 +486,20 @@ function readquestions ($lines) {
$datasetvalue = qformat_webct_convert_formula($webct_options[4]); $datasetvalue = qformat_webct_convert_formula($webct_options[4]);
switch ($webct_options[2]) { switch ($webct_options[2]) {
case 'MIN': case 'MIN':
$question->datasets[$datasetname]->min = $datasetvalue; $question->dataset[$datasetname]->min = $datasetvalue;
break; break;
case 'MAX': case 'MAX':
$question->datasets[$datasetname]->max = $datasetvalue; $question->dataset[$datasetname]->max = $datasetvalue;
break; break;
case 'DEC': case 'DEC':
$datasetvalue = floor($datasetvalue); // int only! $datasetvalue = floor($datasetvalue); // int only!
$question->datasets[$datasetname]->dec = max(0, $datasetvalue); $question->dataset[$datasetname]->length = max(0, $datasetvalue);
break; break;
default: default:
// The VAL case: // The VAL case:
$question->datasets[$datasetname]->items[$webct_options[3]] = $datasetvalue; $question->dataset[$datasetname]->datasetitem[$webct_options[3]] = new stdClass();
$question->dataset[$datasetname]->datasetitem[$webct_options[3]]->itemnumber = $webct_options[3];
$question->dataset[$datasetname]->datasetitem[$webct_options[3]]->value = $datasetvalue;
break; break;
} }
continue; continue;
Expand Down Expand Up @@ -558,19 +529,23 @@ function readquestions ($lines) {
if (eregi('^:FORMULA:(.*)', $line, $webct_options)) { if (eregi('^:FORMULA:(.*)', $line, $webct_options)) {
// Answer for a CALCULATED question // Answer for a CALCULATED question
++$currentchoice; ++$currentchoice;
$question->answers[$currentchoice]->answer = $question->answers[$currentchoice] =
qformat_webct_convert_formula($webct_options[1]); qformat_webct_convert_formula($webct_options[1]);


// Default settings: // Default settings:
$question->answers[$currentchoice]->fraction = 1.0; $question->fraction[$currentchoice] = 1.0;
$question->answers[$currentchoice]->tolerance = 0.0; $question->tolerance[$currentchoice] = 0.0;
$question->answers[$currentchoice]->tolerancetype = 2; // nominal (units in webct) $question->tolerancetype[$currentchoice] = 2; // nominal (units in webct)
$question->answers[$currentchoice]->feedback = ''; $question->feedback[$currentchoice] = '';
$question->answers[$currentchoice]->correctanswerlength = 4; $question->correctanswerlength[$currentchoice] = 4;


$datasetnames = $qtypecalculated->find_dataset_names($webct_options[1]); $datasetnames = $QTYPES[CALCULATED]->find_dataset_names($webct_options[1]);
foreach ($datasetnames as $datasetname) { foreach ($datasetnames as $datasetname) {
$question->datasets[$datasetname]->items = array(); $question->dataset[$datasetname] = new stdClass();
$question->dataset[$datasetname]->datesetitem = array();
$question->dataset[$datasetname]->name = $datasetname ;
$question->dataset[$datasetname]->distribution = 'uniform';
$question->dataset[$datasetname]->status ='private';
} }
continue; continue;
} }
Expand All @@ -593,24 +568,38 @@ function readquestions ($lines) {
$currentchoice=$webct_options[1]; $currentchoice=$webct_options[1];
continue; continue;
} }
if (eregi("^:FEEDBACK([0-9]+):?",$line,$webct_options)) {
$generalfeedbacktext=""; // Start gathering next lines
$currentchoice=$webct_options[1];
continue;
}
if (eregi('^:FEEDBACK:(.*)',$line,$webct_options)) {
$generalfeedbacktext=""; // Start gathering next lines
continue;
}
if (eregi('^:LAYOUT:(.*)',$line,$webct_options)) {
// ignore since layout in question_multichoice is no more used in moodle
// $webct_options[1] contains either vertical or horizontal ;
continue;
}


if (isset($question->qtype ) && CALCULATED == $question->qtype && eregi('^:ANS-DEC:([1-9][0-9]*)', $line, $webct_options)) { if (isset($question->qtype ) && CALCULATED == $question->qtype && eregi('^:ANS-DEC:([1-9][0-9]*)', $line, $webct_options)) {
// We can but hope that this always appear before the ANSTYPE property // We can but hope that this always appear before the ANSTYPE property
$question->answers[$currentchoice]->correctanswerlength = $webct_options[1]; $question->correctanswerlength[$currentchoice] = $webct_options[1];
continue; continue;
} }


if (isset($question->qtype )&& CALCULATED == $question->qtype && eregi("^:TOL:($webctnumberregex)", $line, $webct_options)) { if (isset($question->qtype )&& CALCULATED == $question->qtype && eregi("^:TOL:($webctnumberregex)", $line, $webct_options)) {
// We can but hope that this always appear before the TOL property // We can but hope that this always appear before the TOL property
$question->answers[$currentchoice]->tolerance = $question->tolerance[$currentchoice] =
qformat_webct_convert_formula($webct_options[1]); qformat_webct_convert_formula($webct_options[1]);
continue; continue;
} }


if (isset($question->qtype )&& CALCULATED == $question->qtype && eregi('^:TOLTYPE:percent', $line)) { if (isset($question->qtype )&& CALCULATED == $question->qtype && eregi('^:TOLTYPE:percent', $line)) {
// Percentage case is handled as relative in Moodle: // Percentage case is handled as relative in Moodle:
$question->answers[$currentchoice]->tolerance /= 100; $question->tolerance[$currentchoice] /= 100;
$question->answers[$currentchoice]->tolerancetype = 1; // Relative $question->tolerancetype[$currentchoice] = 1; // Relative
continue; continue;
} }


Expand Down Expand Up @@ -643,11 +632,11 @@ function readquestions ($lines) {
} }


if (isset($question->qtype )&& CALCULATED == $question->qtype && eregi('^:ANSTYPE:dec', $line)) { if (isset($question->qtype )&& CALCULATED == $question->qtype && eregi('^:ANSTYPE:dec', $line)) {
// Houston - we have a problem $question->correctanswerformat[$currentchoice]='1';
// Moodle does not support this - we try something defensively by continue;
// setting the correct answer length to 5, it shoud be enough for }
// most cases if (isset($question->qtype )&& CALCULATED == $question->qtype && eregi('^:ANSTYPE:sig', $line)) {
$question->answers[$currentchoice]->correctanswerlength = 5; $question->correctanswerformat[$currentchoice]='2';
continue; continue;
} }
} }
Expand Down

0 comments on commit edaaa46

Please sign in to comment.