merging from head so that calculated questions can be imported and other improvments
This commit is contained in:
+127
-131
@@ -27,6 +27,10 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Based on format.php, included by ../../import.php
|
||||
/**
|
||||
* @package questionbank
|
||||
* @subpackage importexport
|
||||
*/
|
||||
|
||||
function unhtmlentities($string){
|
||||
$search = array ("'<script[?>]*?>.*?</script>'si", // remove javascript
|
||||
@@ -58,91 +62,7 @@ function unhtmlentities($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->number=1 ; isset($datasetdata->items["$item->number"]) ; ++$item->number) {
|
||||
$item->value = $datasetdata->items["$item->number"];
|
||||
if (!insert_record('question_dataset_items', $item)) {
|
||||
error("Unable to insert dataset item $item->number with $item->value for $datasetdef->name");
|
||||
}
|
||||
}
|
||||
$datasetdef->itemcount = $item->number - 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) {
|
||||
|
||||
@@ -246,8 +166,8 @@ class qformat_webct extends qformat_default {
|
||||
}
|
||||
|
||||
function readquestions ($lines) {
|
||||
|
||||
$qtypecalculated = new qformat_webct_modified_calculated_qtype();
|
||||
global $QTYPES ;
|
||||
// $qtypecalculated = new qformat_webct_modified_calculated_qtype();
|
||||
$webctnumberregex =
|
||||
'[+-]?([0-9]+(\\.[0-9]*)?|\\.[0-9]+)((e|E|\\*10\\*\\*)([+-]?[0-9]+|\\([+-]?[0-9]+\\)))?';
|
||||
|
||||
@@ -262,11 +182,11 @@ class qformat_webct extends qformat_default {
|
||||
$nQuestionStartLine = 0;
|
||||
$bIsHTMLText = FALSE;
|
||||
$lines[] = ":EOF:"; // for an easiest processing of the last line
|
||||
$question = $this->defaultquestion();
|
||||
// $question = $this->defaultquestion();
|
||||
|
||||
foreach ($lines as $line) {
|
||||
$nLineCounter++;
|
||||
|
||||
$line = iconv("Windows-1252","UTF-8",$line);
|
||||
// Processing multiples lines strings
|
||||
|
||||
if (isset($questiontext) and is_string($questiontext)) {
|
||||
@@ -306,7 +226,7 @@ class qformat_webct extends qformat_default {
|
||||
|
||||
if (isset($feedbacktext) and is_string($feedbacktext)) {
|
||||
if (ereg("^:",$line)) {
|
||||
$question->feedback[$currentchoice] = addslashes(trim($feedbacktext));
|
||||
$question->feedback[$currentchoice] = addslashes(trim($feedbacktext));
|
||||
unset($feedbacktext);
|
||||
}
|
||||
else {
|
||||
@@ -315,6 +235,17 @@ class qformat_webct extends qformat_default {
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (eregi("^:(TYPE|EOF):",$line)) {
|
||||
@@ -347,11 +278,26 @@ class qformat_webct extends qformat_default {
|
||||
$QuestionOK = FALSE;
|
||||
}
|
||||
else {
|
||||
// Create empty feedback array
|
||||
$question->feedback = array();
|
||||
// Create empty feedback array
|
||||
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;
|
||||
$totalfraction = 0;
|
||||
foreach($question->fraction as $fraction) {
|
||||
@@ -366,7 +312,7 @@ class qformat_webct extends qformat_default {
|
||||
case SHORTANSWER:
|
||||
if ($maxfraction != 1) {
|
||||
$maxfraction = $maxfraction * 100;
|
||||
$errors[] = "'$question->name': ".get_string("wronggrade", "quiz", $nLineCounter).get_string("fractionsnomax", "quiz", $maxfraction);
|
||||
$errors[] = "'$question->name': ".get_string("wronggrade", "quiz", $nLineCounter).' '.get_string("fractionsnomax", "quiz", $maxfraction);
|
||||
$QuestionOK = FALSE;
|
||||
}
|
||||
break;
|
||||
@@ -375,15 +321,14 @@ class qformat_webct extends qformat_default {
|
||||
if ($question->single) {
|
||||
if ($maxfraction != 1) {
|
||||
$maxfraction = $maxfraction * 100;
|
||||
$errors[] = "'$question->name': ".get_string("wronggrade", "quiz", $nLineCounter).get_string("fractionsnomax", "quiz", $maxfraction);
|
||||
$errors[] = "'$question->name': ".get_string("wronggrade", "quiz", $nLineCounter).' '.get_string("fractionsnomax", "quiz", $maxfraction);
|
||||
$QuestionOK = FALSE;
|
||||
}
|
||||
} else {
|
||||
$totalfraction = round($totalfraction,2);
|
||||
if ($totalfraction != 1) {
|
||||
echo "<p>$totalfraction</p>";
|
||||
if ($totalfraction != 1) {
|
||||
$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;
|
||||
}
|
||||
}
|
||||
@@ -391,20 +336,35 @@ class qformat_webct extends qformat_default {
|
||||
|
||||
case CALCULATED:
|
||||
foreach ($question->answers as $answer) {
|
||||
if ($formulaerror = quiz_qtype_calculated_find_formula_errors($answer->answer)) {
|
||||
if ($formulaerror =qtype_calculated_find_formula_errors($answer)) { //$QTYPES['calculated']->
|
||||
$warnings[] = "'$question->name': ". $formulaerror;
|
||||
$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;
|
||||
default:
|
||||
// No problemo
|
||||
}
|
||||
}
|
||||
|
||||
if ($QuestionOK) {
|
||||
// $question->feedback = array();
|
||||
if ($QuestionOK) {
|
||||
// echo "<pre>"; print_r ($question);
|
||||
$questions[] = $question; // store it
|
||||
unset($question); // and prepare a new one
|
||||
$question = $this->defaultquestion();
|
||||
@@ -417,6 +377,8 @@ class qformat_webct extends qformat_default {
|
||||
|
||||
if (eregi("^:TYPE:MC:1(.*)",$line,$webct_options)) {
|
||||
// Multiple Choice Question with only one good answer
|
||||
$question = $this->defaultquestion();
|
||||
$question->feedback = array();
|
||||
$question->qtype = MULTICHOICE;
|
||||
$question->single = 1; // Only one answer is allowed
|
||||
$ignore_rest_of_question = FALSE;
|
||||
@@ -425,6 +387,8 @@ class qformat_webct extends qformat_default {
|
||||
|
||||
if (eregi("^:TYPE:MC:N(.*)",$line,$webct_options)) {
|
||||
// Multiple Choice Question with several good answers
|
||||
$question = $this->defaultquestion();
|
||||
$question->feedback = array();
|
||||
$question->qtype = MULTICHOICE;
|
||||
$question->single = 0; // Many answers allowed
|
||||
$ignore_rest_of_question = FALSE;
|
||||
@@ -433,6 +397,8 @@ class qformat_webct extends qformat_default {
|
||||
|
||||
if (eregi("^:TYPE:S",$line)) {
|
||||
// Short Answer Question
|
||||
$question = $this->defaultquestion();
|
||||
$question->feedback = array();
|
||||
$question->qtype = SHORTANSWER;
|
||||
$question->usecase = 0; // Ignore case
|
||||
$ignore_rest_of_question = FALSE;
|
||||
@@ -441,14 +407,20 @@ class qformat_webct extends qformat_default {
|
||||
|
||||
if (eregi("^:TYPE:C",$line)) {
|
||||
// Calculated Question
|
||||
/* $warnings[] = get_string("calculatedquestion", "quiz", $nLineCounter);
|
||||
unset($question);
|
||||
$ignore_rest_of_question = TRUE; // Question Type not handled by Moodle
|
||||
*/
|
||||
$question = $this->defaultquestion();
|
||||
$question->qtype = CALCULATED;
|
||||
$question->answers = array(); // No problem as they go as :FORMULA: from webct
|
||||
$question->units = array();
|
||||
$question->datasets = array();
|
||||
$question->dataset = array();
|
||||
|
||||
// To make us pass the end-of-question sanity checks
|
||||
$question->answer = array('dummy');
|
||||
$question->fraction = array('1.0');
|
||||
$question->feedback = array();
|
||||
|
||||
$currentchoice = -1;
|
||||
$ignore_rest_of_question = FALSE;
|
||||
@@ -457,7 +429,9 @@ class qformat_webct extends qformat_default {
|
||||
|
||||
if (eregi("^:TYPE:M",$line)) {
|
||||
// Match Question
|
||||
$question = $this->defaultquestion();
|
||||
$question->qtype = MATCH;
|
||||
$question->feedback = array();
|
||||
$ignore_rest_of_question = FALSE; // match question processing is not debugged
|
||||
continue;
|
||||
}
|
||||
@@ -465,6 +439,7 @@ class qformat_webct extends qformat_default {
|
||||
if (eregi("^:TYPE:P",$line)) {
|
||||
// Paragraph Question
|
||||
$warnings[] = get_string("paragraphquestion", "quiz", $nLineCounter);
|
||||
unset($question);
|
||||
$ignore_rest_of_question = TRUE; // Question Type not handled by Moodle
|
||||
continue;
|
||||
}
|
||||
@@ -472,6 +447,7 @@ class qformat_webct extends qformat_default {
|
||||
if (eregi("^:TYPE:",$line)) {
|
||||
// Unknow Question
|
||||
$warnings[] = get_string("unknowntype", "quiz", $nLineCounter);
|
||||
unset($question);
|
||||
$ignore_rest_of_question = TRUE; // Question Type not handled by Moodle
|
||||
continue;
|
||||
}
|
||||
@@ -502,25 +478,27 @@ class qformat_webct extends qformat_default {
|
||||
// if question isn't defined yet there is nothing to do here (avoid notices)
|
||||
if (!isset($question)) {
|
||||
continue;
|
||||
}
|
||||
if (CALCULATED == $question->qtype && ereg(
|
||||
}
|
||||
if (isset($question->qtype ) && CALCULATED == $question->qtype && ereg(
|
||||
"^:([[:lower:]].*|::.*)-(MIN|MAX|DEC|VAL([0-9]+))::?:?($webctnumberregex)", $line, $webct_options)) {
|
||||
$datasetname = ereg_replace('^::', '', $webct_options[1]);
|
||||
$datasetvalue = qformat_webct_convert_formula($webct_options[4]);
|
||||
switch ($webct_options[2]) {
|
||||
case 'MIN':
|
||||
$question->datasets[$datasetname]->min = $datasetvalue;
|
||||
$question->dataset[$datasetname]->min = $datasetvalue;
|
||||
break;
|
||||
case 'MAX':
|
||||
$question->datasets[$datasetname]->max = $datasetvalue;
|
||||
$question->dataset[$datasetname]->max = $datasetvalue;
|
||||
break;
|
||||
case 'DEC':
|
||||
$datasetvalue = floor($datasetvalue); // int only!
|
||||
$question->datasets[$datasetname]->dec = max(0, $datasetvalue);
|
||||
$question->dataset[$datasetname]->length = max(0, $datasetvalue);
|
||||
break;
|
||||
default:
|
||||
// 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;
|
||||
}
|
||||
continue;
|
||||
@@ -550,19 +528,23 @@ class qformat_webct extends qformat_default {
|
||||
if (eregi('^:FORMULA:(.*)', $line, $webct_options)) {
|
||||
// Answer for a CALCULATED question
|
||||
++$currentchoice;
|
||||
$question->answers[$currentchoice]->answer =
|
||||
$question->answers[$currentchoice] =
|
||||
qformat_webct_convert_formula($webct_options[1]);
|
||||
|
||||
// Default settings:
|
||||
$question->answers[$currentchoice]->fraction = 1.0;
|
||||
$question->answers[$currentchoice]->tolerance = 0.0;
|
||||
$question->answers[$currentchoice]->tolerancetype = 2; // nominal (units in webct)
|
||||
$question->answers[$currentchoice]->feedback = '';
|
||||
$question->answers[$currentchoice]->correctanswerlength = 4;
|
||||
$question->fraction[$currentchoice] = 1.0;
|
||||
$question->tolerance[$currentchoice] = 0.0;
|
||||
$question->tolerancetype[$currentchoice] = 2; // nominal (units in webct)
|
||||
$question->feedback[$currentchoice] = '';
|
||||
$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) {
|
||||
$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;
|
||||
}
|
||||
@@ -585,24 +567,38 @@ class qformat_webct extends qformat_default {
|
||||
$currentchoice=$webct_options[1];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (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
|
||||
$question->answers[$currentchoice]->correctanswerlength = $webct_options[1];
|
||||
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 (CALCULATED == $question->qtype && eregi("^:TOL:($webctnumberregex)", $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
|
||||
$question->correctanswerlength[$currentchoice] = $webct_options[1];
|
||||
continue;
|
||||
}
|
||||
|
||||
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
|
||||
$question->answers[$currentchoice]->tolerance =
|
||||
$question->tolerance[$currentchoice] =
|
||||
qformat_webct_convert_formula($webct_options[1]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (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:
|
||||
$question->answers[$currentchoice]->tolerance /= 100;
|
||||
$question->answers[$currentchoice]->tolerancetype = 1; // Relative
|
||||
$question->tolerance[$currentchoice] /= 100;
|
||||
$question->tolerancetype[$currentchoice] = 1; // Relative
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -634,12 +630,12 @@ class qformat_webct extends qformat_default {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (CALCULATED == $question->qtype && eregi('^:ANSTYPE:dec', $line)) {
|
||||
// Houston - we have a problem
|
||||
// Moodle does not support this - we try something defensively by
|
||||
// setting the correct answer length to 5, it shoud be enough for
|
||||
// most cases
|
||||
$question->answers[$currentchoice]->correctanswerlength = 5;
|
||||
if (isset($question->qtype )&& CALCULATED == $question->qtype && eregi('^:ANSTYPE:dec', $line)) {
|
||||
$question->correctanswerformat[$currentchoice]='1';
|
||||
continue;
|
||||
}
|
||||
if (isset($question->qtype )&& CALCULATED == $question->qtype && eregi('^:ANSTYPE:sig', $line)) {
|
||||
$question->correctanswerformat[$currentchoice]='2';
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
+177
-10
@@ -5,7 +5,10 @@
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Based on default.php, included by ../import.php
|
||||
|
||||
/**
|
||||
* @package questionbank
|
||||
* @subpackage importexport
|
||||
*/
|
||||
require_once( "$CFG->libdir/xmlize.php" );
|
||||
|
||||
class qformat_xml extends qformat_default {
|
||||
@@ -20,11 +23,11 @@ class qformat_xml extends qformat_default {
|
||||
|
||||
// IMPORT FUNCTIONS START HERE
|
||||
|
||||
/*
|
||||
/**
|
||||
* Translate human readable format name
|
||||
* into internal Moodle code number
|
||||
* @PARAM string name format name from xml file
|
||||
* @RETURN int Moodle format code
|
||||
* @param string name format name from xml file
|
||||
* @return int Moodle format code
|
||||
*/
|
||||
function trans_format( $name ) {
|
||||
$name = trim($name);
|
||||
@@ -53,8 +56,8 @@ class qformat_xml extends qformat_default {
|
||||
/*
|
||||
* Translate human readable single answer option
|
||||
* to internal code number
|
||||
* @PARAM string name true/false
|
||||
* @RETURN int internal code number
|
||||
* @param string name true/false
|
||||
* @return int internal code number
|
||||
*/
|
||||
function trans_single( $name ) {
|
||||
$name = trim($name);
|
||||
@@ -65,14 +68,17 @@ class qformat_xml extends qformat_default {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* process text string from xml file
|
||||
* @PARAM array text bit of xml tree after ['text']
|
||||
* @RETURN string processed text
|
||||
*/
|
||||
function import_text( $text ) {
|
||||
// quick sanity check
|
||||
if (empty($text)) {
|
||||
return '';
|
||||
}
|
||||
$data = $text[0]['#'];
|
||||
$data = html_entity_decode( $data );
|
||||
return addslashes(trim( $data ));
|
||||
}
|
||||
|
||||
@@ -381,8 +387,102 @@ class qformat_xml extends qformat_default {
|
||||
// get feedback
|
||||
$qo->feedback = $this->import_text( $question['#']['answer'][0]['#']['feedback'][0]['#']['text'] );
|
||||
|
||||
// get fraction
|
||||
$qo->fraction = $question['#']['answer'][0]['#']['fraction'][0]['#'];
|
||||
// handle answer
|
||||
$answer = $question['#']['answer'][0];
|
||||
|
||||
// get fraction - <fraction> tag is deprecated
|
||||
if (!empty($answer['#']['fraction'][0]['#'])) {
|
||||
$qo->fraction = $answer['#']['fraction'][0]['#'];
|
||||
}
|
||||
else {
|
||||
$qo->fraction = $answer['@']['fraction'] / 100;
|
||||
}
|
||||
|
||||
return $qo;
|
||||
}
|
||||
|
||||
function import_calculated( $question ) {
|
||||
// import numerical question
|
||||
|
||||
// get common parts
|
||||
$qo = $this->import_headers( $question );
|
||||
|
||||
// header parts particular to numerical
|
||||
$qo->qtype = CALCULATED ;//CALCULATED;
|
||||
// get answers array
|
||||
$answers = $question['#']['answer'];
|
||||
$qo->answers = array();
|
||||
$qo->feedback = array();
|
||||
$qo->fraction = array();
|
||||
$qo->tolerance = array();
|
||||
$qo->tolerancetype = array();
|
||||
$qo->correctanswerformat = array();
|
||||
$qo->correctanswerlength = array();
|
||||
$qo->feedback = array();
|
||||
foreach ($answers as $answer) {
|
||||
// answer outside of <text> is deprecated
|
||||
if (!empty( $answer['#']['text'] )) {
|
||||
$answertext = $this->import_text( $answer['#']['text'] );
|
||||
}
|
||||
else {
|
||||
$answertext = trim($answer['#'][0]);
|
||||
}
|
||||
if ($answertext == '') {
|
||||
$qo->answers[] = '*';
|
||||
} else {
|
||||
$qo->answers[] = $answertext;
|
||||
}
|
||||
$qo->feedback[] = $this->import_text( $answer['#']['feedback'][0]['#']['text'] );
|
||||
$qo->tolerance[] = $answer['#']['tolerance'][0]['#'];
|
||||
// fraction as a tag is deprecated
|
||||
if (!empty($answer['#']['fraction'][0]['#'])) {
|
||||
$qo->fraction[] = $answer['#']['fraction'][0]['#'];
|
||||
}
|
||||
else {
|
||||
$qo->fraction[] = $answer['@']['fraction'] / 100;
|
||||
}
|
||||
$qo->tolerancetype[] = $answer['#']['tolerancetype'][0]['#'];
|
||||
$qo->correctanswerformat[] = $answer['#']['correctanswerformat'][0]['#'];
|
||||
$qo->correctanswerlength[] = $answer['#']['correctanswerlength'][0]['#'];
|
||||
}
|
||||
// get units array
|
||||
$qo->unit = array();
|
||||
if (isset($question['#']['units'][0]['#']['unit'])) {
|
||||
$units = $question['#']['units'][0]['#']['unit'];
|
||||
$qo->multiplier = array();
|
||||
foreach ($units as $unit) {
|
||||
$qo->multiplier[] = $unit['#']['multiplier'][0]['#'];
|
||||
$qo->unit[] = $unit['#']['unit_name'][0]['#'];
|
||||
}
|
||||
}
|
||||
$datasets = $question['#']['dataset_definitions'][0]['#']['dataset_definition'];
|
||||
$qo->dataset = array();
|
||||
$qo->datasetindex= 0 ;
|
||||
foreach ($datasets as $dataset) {
|
||||
$qo->datasetindex++;
|
||||
$qo->dataset[$qo->datasetindex] = new stdClass();
|
||||
$qo->dataset[$qo->datasetindex]->status = $this->import_text( $dataset['#']['status'][0]['#']['text']);
|
||||
$qo->dataset[$qo->datasetindex]->name = $this->import_text( $dataset['#']['name'][0]['#']['text']);
|
||||
$qo->dataset[$qo->datasetindex]->type = $dataset['#']['type'][0]['#'];
|
||||
$qo->dataset[$qo->datasetindex]->distribution = $this->import_text( $dataset['#']['distribution'][0]['#']['text']);
|
||||
$qo->dataset[$qo->datasetindex]->max = $this->import_text( $dataset['#']['maximum'][0]['#']['text']);
|
||||
$qo->dataset[$qo->datasetindex]->min = $this->import_text( $dataset['#']['minimum'][0]['#']['text']);
|
||||
$qo->dataset[$qo->datasetindex]->length = $this->import_text( $dataset['#']['decimals'][0]['#']['text']);
|
||||
$qo->dataset[$qo->datasetindex]->distribution = $this->import_text( $dataset['#']['distribution'][0]['#']['text']);
|
||||
$qo->dataset[$qo->datasetindex]->itemcount = $dataset['#']['itemcount'][0]['#'];
|
||||
$qo->dataset[$qo->datasetindex]->datasetitem = array();
|
||||
$qo->dataset[$qo->datasetindex]->itemindex = 0;
|
||||
$qo->dataset[$qo->datasetindex]->number_of_items=$dataset['#']['number_of_items'][0]['#'];
|
||||
$datasetitems = $dataset['#']['dataset_items'][0]['#']['dataset_item'];
|
||||
foreach ($datasetitems as $datasetitem) {
|
||||
$qo->dataset[$qo->datasetindex]->itemindex++;
|
||||
$qo->dataset[$qo->datasetindex]->datasetitem[$qo->dataset[$qo->datasetindex]->itemindex] = new stdClass();
|
||||
$qo->dataset[$qo->datasetindex]->datasetitem[$qo->dataset[$qo->datasetindex]->itemindex]->itemnumber = $datasetitem['#']['number'][0]['#']; //[0]['#']['number'][0]['#'] ; // [0]['numberitems'] ;//['#']['number'][0]['#'];// $datasetitems['#']['number'][0]['#'];
|
||||
$qo->dataset[$qo->datasetindex]->datasetitem[$qo->dataset[$qo->datasetindex]->itemindex]->value = $datasetitem['#']['value'][0]['#'] ;//$datasetitem['#']['value'][0]['#'];
|
||||
}
|
||||
}
|
||||
|
||||
// echo "<pre>loaded qo";print_r($qo);echo "</pre>";
|
||||
|
||||
return $qo;
|
||||
}
|
||||
@@ -439,6 +539,9 @@ class qformat_xml extends qformat_default {
|
||||
elseif ($question_type=='essay') {
|
||||
$qo = $this->import_essay( $question );
|
||||
}
|
||||
elseif ($question_type=='calculated') {
|
||||
$qo = $this->import_calculated( $question );
|
||||
}
|
||||
else {
|
||||
$notsupported = get_string( 'xmltypeunsupported','quiz',$question_type );
|
||||
echo "<p>$notsupported</p>";
|
||||
@@ -499,6 +602,9 @@ class qformat_xml extends qformat_default {
|
||||
case ESSAY:
|
||||
$name = 'essay';
|
||||
break;
|
||||
case CALCULATED:
|
||||
$name = 'calculated';
|
||||
break;
|
||||
default:
|
||||
$name = 'unknown';
|
||||
}
|
||||
@@ -764,6 +870,67 @@ class qformat_xml extends qformat_default {
|
||||
$expout .= "</answer>\n";
|
||||
}
|
||||
|
||||
break;
|
||||
case CALCULATED:
|
||||
foreach ($question->options->answers as $answer) {
|
||||
$tolerance = $answer->tolerance;
|
||||
$tolerancetype = $answer->tolerancetype;
|
||||
$correctanswerlength= $answer->correctanswerlength ;
|
||||
$correctanswerformat= $answer->correctanswerformat;
|
||||
$percent = 100 * $answer->fraction;
|
||||
$expout .= "<answer fraction=\"$percent\">\n";
|
||||
// "<text/>" tags are an added feature, old files won't have them
|
||||
$expout .= " <text>{$answer->answer}</text>\n";
|
||||
$expout .= " <tolerance>$tolerance</tolerance>\n";
|
||||
$expout .= " <tolerancetype>$tolerancetype</tolerancetype>\n";
|
||||
$expout .= " <correctanswerformat>$correctanswerformat</correctanswerformat>\n";
|
||||
$expout .= " <correctanswerlength>$correctanswerformat</correctanswerlength>\n";
|
||||
$expout .= " <feedback>".$this->writetext( $answer->feedback )."</feedback>\n";
|
||||
$expout .= "</answer>\n";
|
||||
}
|
||||
$units = $question->options->units;
|
||||
if (count($units)) {
|
||||
$expout .= "<units>\n";
|
||||
foreach ($units as $unit) {
|
||||
$expout .= " <unit>\n";
|
||||
$expout .= " <multiplier>{$unit->multiplier}</multiplier>\n";
|
||||
$expout .= " <unit_name>{$unit->unit}</unit_name>\n";
|
||||
$expout .= " </unit>\n";
|
||||
}
|
||||
$expout .= "</units>\n";
|
||||
}
|
||||
//echo "<pre> question calc";print_r($question);echo "</pre>";
|
||||
//First, we a new function to get all the data itmes in the database
|
||||
// $question_datasetdefs =$QTYPES['calculated']->get_datasets_for_export ($question);
|
||||
// echo "<pre> question defs";print_r($question_datasetdefs);echo "</pre>";
|
||||
//If there are question_datasets
|
||||
if( isset($question->options->datasets)&&count($question->options->datasets)){// there should be
|
||||
$expout .= "<dataset_definitions>\n";
|
||||
foreach ($question->options->datasets as $def) {
|
||||
$expout .= "<dataset_definition>\n";
|
||||
$expout .= " <status>".$this->writetext($def->status)."</status>\n";
|
||||
$expout .= " <name>".$this->writetext($def->name)."</name>\n";
|
||||
$expout .= " <type>calculated</type>\n";
|
||||
$expout .= " <distribution>".$this->writetext($def->distribution)."</distribution>\n";
|
||||
$expout .= " <minimum>".$this->writetext($def->minimum)."</minimum>\n";
|
||||
$expout .= " <maximum>".$this->writetext($def->maximum)."</maximum>\n";
|
||||
$expout .= " <decimals>".$this->writetext($def->decimals)."</decimals>\n";
|
||||
$expout .= " <itemcount>$def->itemcount</itemcount>\n";
|
||||
if ($def->itemcount > 0 ) {
|
||||
$expout .= " <dataset_items>\n";
|
||||
foreach ($def->items as $item ){
|
||||
$expout .= " <dataset_item>\n";
|
||||
$expout .= " <number>".$item->itemnumber."</number>\n";
|
||||
$expout .= " <value>".$item->value."</value>\n";
|
||||
$expout .= " </dataset_item>\n";
|
||||
}
|
||||
$expout .= " </dataset_items>\n";
|
||||
$expout .= " <number_of_items>".$def-> number_of_items."</number_of_items>\n";
|
||||
}
|
||||
$expout .= "</dataset_definition>\n";
|
||||
}
|
||||
$expout .= "</dataset_definitions>\n";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$expout .= "<!-- Question type is unknown or not supported (Type=$question->qtype) -->\n";
|
||||
|
||||
Reference in New Issue
Block a user