moodler 43bf9fc2d7 Reworking of the plug-in format for import/export files.
Each format is now in it's own subdirectory, which allows the
format to have as many files as it likes.  The formats are now
detected automatically (no need to edit lib.php anymore) and
the parent class is now in mod/quiz/format.php

Lastly, I added Paul Shew's new GIFT format.
2003-12-12 07:35:55 +00:00

163 lines
5.9 KiB
PHP

<?PHP // $Id$
////////////////////////////////////////////////////////////////////////////
/// MULTIANSWER FORMAT
///
/// Created by Henrik Kaipe
///
////////////////////////////////////////////////////////////////////////////
// Based on format.php, included by ../../import.php
// REGULAR EXPRESSION CONSTANTS
// I do not know any way to make this easier
// Regexes are always awkard when defined but more comprehensible
// when used as constants in the executive code
// ANSWER_ALTERNATIVE regexes
define("ANSWER_ALTERNATIVE_FRACTION_REGEX",
'=|%(-?[0-9]+)%');
define("ANSWER_ALTERNATIVE_ANSWER_REGEX",
'[^~#}]+');
define("ANSWER_ALTERNATIVE_FEEDBACK_REGEX",
'[^~}]*');
define("ANSWER_ALTERNATIVE_REGEX",
'(' . ANSWER_ALTERNATIVE_FRACTION_REGEX .')?'
. '(' . ANSWER_ALTERNATIVE_ANSWER_REGEX . ')'
. '(#(' . ANSWER_ALTERNATIVE_FEEDBACK_REGEX .'))?');
// Parenthesis positions for ANSWER_ALTERNATIVE_REGEX
define("ANSWER_ALTERNATIVE_REGEX_PERCENTILE_FRACTION", 2);
define("ANSWER_ALTERNATIVE_REGEX_FRACTION", 1);
define("ANSWER_ALTERNATIVE_REGEX_ANSWER", 3);
define("ANSWER_ALTERNATIVE_REGEX_FEEDBACK", 5);
// NUMBER_FORMATED_ALTERNATIVE_ANSWER_REGEX is used
// for identifying numerical answers in ANSWER_ALTERNATIVE_REGEX_ANSWER
define("NUMBER_REGEX",
'-?(([0-9]+[.,]?[0-9]*|[.,][0-9]+)([eE][-+]?[0-9]+)?)');
define("NUMERICAL_ALTERNATIVE_REGEX",
'^(' . NUMBER_REGEX . ')(:' . NUMBER_REGEX . ')?$');
// Parenthesis positions for NUMERICAL_FORMATED_ALTERNATIVE_ANSWER_REGEX
define("NUMERICAL_CORRECT_ANSWER", 1);
define("NUMERICAL_ABS_ERROR_MARGIN", 6);
// Remaining ANSWER regexes
define("ANSWER_TYPE_DEF_REGEX",
'(NUMERICAL|NM)|(MULTICHOICE|MC)|(SHORTANSWER|SA|MW)');
define("ANSWER_START_REGEX",
'\{([0-9]*):(' . ANSWER_TYPE_DEF_REGEX . '):');
define("ANSWER_REGEX",
ANSWER_START_REGEX
. '(' . ANSWER_ALTERNATIVE_REGEX
. '(~'
. ANSWER_ALTERNATIVE_REGEX
. ')*)}' );
// Parenthesis positions for singulars in ANSWER_REGEX
define("ANSWER_REGEX_NORM", 1);
define("ANSWER_REGEX_ANSWER_TYPE_NUMERICAL", 3);
define("ANSWER_REGEX_ANSWER_TYPE_MULTICHOICE", 4);
define("ANSWER_REGEX_ANSWER_TYPE_SHORTANSWER", 5);
define("ANSWER_REGEX_ALTERNATIVES", 6);
function extractMultiAnswerQuestion($text) {
$question = NULL;
$question->qtype= MULTIANSWER;
$question->questiontext= $text;
$question->answers= array();
$question->defaultgrade = 0; // Will be increased for each answer norm
for ($positionkey=1
; ereg(ANSWER_REGEX, $question->questiontext, $answerregs)
; ++$positionkey )
{
unset($multianswer);
$multianswer->positionkey = $positionkey;
$multianswer->norm = $answerregs[ANSWER_REGEX_NORM]
or $multianswer->norm = '1';
if ($answerregs[ANSWER_REGEX_ANSWER_TYPE_NUMERICAL]) {
$multianswer->answertype = NUMERICAL;
} else if($answerregs[ANSWER_REGEX_ANSWER_TYPE_SHORTANSWER]) {
$multianswer->answertype = SHORTANSWER;
} else if($answerregs[ANSWER_REGEX_ANSWER_TYPE_MULTICHOICE]){
$multianswer->answertype = MULTICHOICE;
} else {
error("Cannot identify answertype $answerregs[2]");
return false;
}
$multianswer->alternatives= array();
$remainingalts = $answerregs[ANSWER_REGEX_ALTERNATIVES];
while (ereg(ANSWER_ALTERNATIVE_REGEX, $remainingalts, $altregs)) {
unset($alternative);
if ('=' == $altregs[ANSWER_ALTERNATIVE_REGEX_FRACTION]) {
$alternative->fraction = '1';
} else {
$alternative->fraction = .01 *
$altregs[ANSWER_ALTERNATIVE_REGEX_PERCENTILE_FRACTION]
or $alternative->fraction = '0';
}
$alternative->feedback = $altregs[ANSWER_ALTERNATIVE_REGEX_FEEDBACK];
if ($answerregs[ANSWER_REGEX_ANSWER_TYPE_NUMERICAL]
&& ereg(NUMERICAL_ALTERNATIVE_REGEX,
$altregs[ANSWER_ALTERNATIVE_REGEX_ANSWER],
$numregs) )
{
$alternative->answer = $numregs[NUMERICAL_CORRECT_ANSWER];
if ($numregs[NUMERICAL_ABS_ERROR_MARGIN]) {
$alternative->min = $numregs[NUMERICAL_CORRECT_ANSWER]
- $numregs[NUMERICAL_ABS_ERROR_MARGIN];
$alternative->max = $numregs[NUMERICAL_CORRECT_ANSWER]
+ $numregs[NUMERICAL_ABS_ERROR_MARGIN];
} else {
$alternative->min = $numregs[NUMERICAL_CORRECT_ANSWER];
$alternative->max = $numregs[NUMERICAL_CORRECT_ANSWER];
}
} else { // Min and max must stay undefined...
$alternative->answer =
$altregs[ANSWER_ALTERNATIVE_REGEX_ANSWER];
}
$multianswer->alternatives[] = $alternative;
$tmp = explode($altregs[0], $remainingalts, 2);
$remainingalts = $tmp[1];
}
$question->defaultgrade += $multianswer->norm;
$question->answers[] = $multianswer;
$question->questiontext = implode("{#$positionkey}",
explode($answerregs[0], $question->questiontext, 2));
}
return $question;
}
class quiz_file_format extends quiz_default_format {
function readquestions($lines) {
/// Parses an array of lines into an array of questions.
/// For this class the method has been simplified as
/// there can never be more than one question for a
/// multianswer import
$questions= array();
$thequestion= extractMultiAnswerQuestion(implode('',$lines));
if (!empty($thequestion)) {
$thequestion->name = $lines[0];
$questions[] = $thequestion;
}
return $questions;
}
}
?>