-// EXAMPLE QUESTIONS for the GIFT import filter\r// by Paul Tsuchido Shew, January 2004.\r\r//-----------------------------------------//\r// EXAMPLES FROM DESCRIPTION\r//-----------------------------------------//\r\rWho's buried in Grant's tomb?{~Grant ~Jefferson =no one}\r\rGrant is {~buried =entombed ~living} in Grant's tomb.\r\rGrant is buried in Grant's tomb.{FALSE}\r\rWho's buried in Grant's tomb?{=no one =nobody}\r\rWhen was Ulysses S. Grant born?{#1822:1}\r\r\r//-----------------------------------------//\r// EXAMPLES FROM DOCUMENTATION\r//-----------------------------------------//\r\r// ===Multiple Choice===\r\rWho's buried in Grant's tomb?{~Grant ~Jefferson =no one}\r\rGrant is {~buried =entombed ~living} in Grant's tomb.\r\rThe American holiday of Thanksgiving is celebrated on the {\r ~second\r ~third\r =fourth\r} Thursday of November.\r\rJapanese characters originally came from what country? {\r ~India\r =China\r ~Korea\r ~Egypt}\r\r// ===Short Answer===\r\rWho's buried in Grant's tomb?{=no one =nobody}\r\rTwo plus two equals {=four =4}.\r\r// ===True-False===\r\rGrant is buried in Grant's tomb.{F}\r\rThe sun rises in the east.{T}\r\r// ===Numerical===\r\rWhen was Ulysses S. Grant born? {#1822}\r\rWhat is the value of pi (to 3 decimal places)? {#3.1415:0.0005}.\r\rWhat is the value of pi (to 3 decimal places)? {#3.141..3.142}.\r\rWhen was Ulysses S. Grant born? {#\r =1822:0\r =%50%1822:2}\r\r// OPTIONS \r\r// ===Inline Comments===\r\r// Subheading: Numerical questions below\rWhat's 2 plus 2? {#4}\r\r\r// ===Question Name===\r\r::Kanji Origins::Japanese characters originally\rcame from what country? {=China}\r\r::Thanksgiving Date::The American holiday of Thanksgiving is \rcelebrated on the {~second ~third =fourth} Thursday of November.\r\r// ===Feedback===\r\rWhat's the answer to this multiple-choice question?{\r~wrong answer#feedback comment on the wrong answer\r~another wrong answer#feedback comment on this wrong answer\r=right answer#Very good!}\r \rWho's buried in Grant's tomb?{\r=no one#excellent answer!\r=nobody#excellent answer!}\r\r// ===Percentage Answer Weights===\rGrant is buried in Grant's tomb.{FALSE#No one is buried in Grant's tomb.}\r\rDifficult question.{~wrong answer ~%50%half credit answer =full credit answer}\r \r::Jesus' hometown::Jesus Christ was from {\r ~Jerusalem#This was an important city, but the wrong answer.\r ~%25%Bethlehem#He was born here, but not raised here.\r ~%50%Galilee#You need to be more specific.\r =Nazareth#Yes! That's right!}.\r \r::Jesus' hometown:: Jesus Christ was from {\r =Nazareth#Yes! That's right!\r =%75%Nazereth#Right, but misspelled.\r =%25%Bethlehem#He was born here, but not raised here.}\r\r// ===Multiple Answers===\r\rWhat two people are entombed in Grant's tomb? {\r ~No one\r ~%50%Grant\r ~%50%Grant's wife\r ~Grant's father }\r\rWhat two people are entombed in Grant's tomb? {\r ~%-50%No one\r ~%50%Grant\r ~%50%Grant's wife\r ~%-50%Grant's father }\r\r//-----------------------------------------//\r// EXAMPLES FROM gift/format.php\r//-----------------------------------------//\r\r::Grant's Tomb::Grant is {\r ~buried#No one is buried there.\r =entombed#Right answer!\r ~living#We hope not!\r} in Grant's tomb.\r\rDifficult multiple choice question.{\r ~wrong answer #comment on wrong answer\r ~%50%half credit answer #comment on answer\r =full credit answer #well done!}\r\r::Jesus' hometown (Short answer ex.):: Jesus Christ was from {\r =Nazareth#Yes! That's right!\r =%75%Nazereth#Right, but misspelled.\r =%25%Bethlehem#He was born here, but not raised here.\r}.\r\r//this comment will be ignored by the filter\r::Numerical example::\rWhen was Ulysses S. Grant born? {#\r =1822:0 #Correct! 100% credit\r =%50%1822:2 #He was born in 1822.\r You get 50% credit for being close.\r}
\ No newline at end of file
+// EXAMPLE QUESTIONS for the GIFT import filter
+// by Paul Tsuchido Shew, January 2004.
+
+//-----------------------------------------//
+// EXAMPLES FROM DESCRIPTION
+//-----------------------------------------//
+
+Who's buried in Grant's tomb?{~Grant ~Jefferson =no one}
+
+Grant is {~buried =entombed ~living} in Grant's tomb.
+
+Grant is buried in Grant's tomb.{FALSE}
+
+Who's buried in Grant's tomb?{=no one =nobody}
+
+When was Ulysses S. Grant born?{#1822:1}
+
+
+//-----------------------------------------//
+// EXAMPLES FROM DOCUMENTATION
+//-----------------------------------------//
+
+// ===Multiple Choice===
+
+Who's buried in Grant's tomb?{~Grant ~Jefferson =no one}
+
+Grant is {~buried =entombed ~living} in Grant's tomb.
+
+The American holiday of Thanksgiving is celebrated on the {
+ ~second
+ ~third
+ =fourth
+} Thursday of November.
+
+Japanese characters originally came from what country? {
+ ~India
+ =China
+ ~Korea
+ ~Egypt}
+
+// ===Short Answer===
+
+Who's buried in Grant's tomb?{=no one =nobody}
+
+Two plus two equals {=four =4}.
+
+// ===True-False===
+
+Grant is buried in Grant's tomb.{F}
+
+The sun rises in the east.{T}
+
+// ===Numerical===
+
+When was Ulysses S. Grant born? {#1822}
+
+What is the value of pi (to 3 decimal places)? {#3.1415:0.0005}.
+
+What is the value of pi (to 3 decimal places)? {#3.141..3.142}.
+
+When was Ulysses S. Grant born? {#
+ =1822:0
+ =%50%1822:2}
+
+// OPTIONS
+
+// ===Inline Comments===
+
+// Subheading: Numerical questions below
+What's 2 plus 2? {#4}
+
+
+// ===Question Name===
+
+::Kanji Origins::Japanese characters originally
+came from what country? {=China}
+
+::Thanksgiving Date::The American holiday of Thanksgiving is
+celebrated on the {~second ~third =fourth} Thursday of November.
+
+// ===Feedback===
+
+What's the answer to this multiple-choice question?{
+~wrong answer#feedback comment on the wrong answer
+~another wrong answer#feedback comment on this wrong answer
+=right answer#Very good!}
+
+Who's buried in Grant's tomb?{
+=no one#excellent answer!
+=nobody#excellent answer!}
+
+// ===Percentage Answer Weights===
+Grant is buried in Grant's tomb.{FALSE#No one is buried in Grant's tomb.}
+
+Difficult question.{~wrong answer ~%50%half credit answer =full credit answer}
+
+::Jesus' hometown::Jesus Christ was from {
+ ~Jerusalem#This was an important city, but the wrong answer.
+ ~%25%Bethlehem#He was born here, but not raised here.
+ ~%50%Galilee#You need to be more specific.
+ =Nazareth#Yes! That's right!}.
+
+::Jesus' hometown:: Jesus Christ was from {
+ =Nazareth#Yes! That's right!
+ =%75%Nazereth#Right, but misspelled.
+ =%25%Bethlehem#He was born here, but not raised here.}
+
+// ===Multiple Answers===
+
+What two people are entombed in Grant's tomb? {
+ ~No one
+ ~%50%Grant
+ ~%50%Grant's wife
+ ~Grant's father }
+
+What two people are entombed in Grant's tomb? {
+ ~%-50%No one
+ ~%50%Grant
+ ~%50%Grant's wife
+ ~%-50%Grant's father }
+
+//-----------------------------------------//
+// EXAMPLES FROM gift/format.php
+//-----------------------------------------//
+
+::Grant's Tomb::Grant is {
+ ~buried#No one is buried there.
+ =entombed#Right answer!
+ ~living#We hope not!
+} in Grant's tomb.
+
+Difficult multiple choice question.{
+ ~wrong answer #comment on wrong answer
+ ~%50%half credit answer #comment on answer
+ =full credit answer #well done!}
+
+::Jesus' hometown (Short answer ex.):: Jesus Christ was from {
+ =Nazareth#Yes! That's right!
+ =%75%Nazereth#Right, but misspelled.
+ =%25%Bethlehem#He was born here, but not raised here.
+}.
+
+//this comment will be ignored by the filter
+::Numerical example::
+When was Ulysses S. Grant born? {#
+ =1822:0 #Correct! 100% credit
+ =%50%1822:2 #He was born in 1822.
+ You get 50% credit for being close.
+}
\ No newline at end of file
-<?php // $Id$\r//\r///////////////////////////////////////////////////////////////\r// GIFT\r//\r// The GIFT import filter is an easy to use method for teachers \r// writing questions as a text file. It supports true-false, \r// short answer, multiple-choice and numerical questions, as well \r// as insertion of a blank line for the missing word format.\r//\r// Multiple Choice / Missing Word\r// Who's buried in Grant's tomb?{~Grant ~Jefferson =no one}\r// Grant is {~buried =entombed ~living} in Grant's tomb.\r// True-False:\r// Grant is buried in Grant's tomb.{FALSE}\r// Short-Answer.\r// Who's buried in Grant's tomb?{=no one =nobody}\r// Numerical\r// When was Ulysses S. Grant born?{#1822:5}\r//\r// Comment lines start with a double backslash (//). \r// Optional question names are enclosed in double colon(::). \r// Answer feedback is indicated with hash mark (#).\r// Percentage answer weights immediately follow the tilde (for\r// multiple choice) or equal sign (for short answer and numerical),\r// and are enclosed in percent signs (% %). Below are more\r// complicated examples with various options and formatting styles.\r// \r// ::Grant's Tomb::Grant is {\r// ~buried#No one is buried there.\r// =entombed#Right answer!\r// ~living#We hope not!\r// } in Grant's tomb.\r//\r// Difficult multiple choice question.{\r// ~wrong answer #comment on wrong answer\r// ~%50%half credit answer #comment on answer\r// =full credit answer #well done!}\r//\r// ::Jesus' hometown (Short answer ex.):: Jesus Christ was from {\r// =Nazareth#Yes! That's right!\r// =%75%Nazereth#Right, but misspelled.\r// =%25%Bethlehem#He was born here, but not raised here.\r// }.\r//\r// //this inline comment will be ignored by the filter\r// ::Numerical example::\r// When was Ulysses S. Grant born? {#\r// =1822:0 #Correct! 100% credit\r// =%50%1982:2 #He was born in 1822.\r// You get 50% credit for being close.\r// }\r// \r// This filter was written through the collaboration of numerous \r// members of the Moodle community. It was originally based on \r// the missingword format, which included code from Thomas Robb\r// and others. Paul Tsuchido Shew wrote this filter in December 2003.\r//////////////////////////////////////////////////////////////////////////\r// Based on default.php, included by ../import.php\r\rclass quiz_file_format extends quiz_default_format {\r\r function answerweightparser(&$answer) {\r $answer = substr($answer, 1); // removes initial %\r $end_position = strpos($answer, "%");\r $answer_weight = substr($answer, 0, $end_position); // gets weight as integer\r $answer_weight = $answer_weight/100; // converts to percent\r $answer = substr($answer, $end_position+1); // removes comment from answer\r return $answer_weight;\r }\r\r\r function commentparser(&$answer) {\r if (strpos($answer,"#") > 0){\r $hashpos = strpos($answer,"#");\r $comment = addslashes(substr($answer, $hashpos+1));\r $answer = substr($answer, 0, $hashpos);\r } else {\r $comment = " ";\r }\r return $comment;\r }\r \r\r function readquestion($lines) {\r // Given an array of lines known to define a question in this format, this function\r // converts it into a question object suitable for processing and insertion into Moodle.\r\r $question = NULL;\r $comment = NULL;\r define("GIFT_ANSWERWEIGHT_REGEX", "^%\-*([0-9]{1,2})\.?([0-9]*)%"); \r\r // REMOVED COMMENTED LINES and IMPLODE\r foreach ($lines as $key => $line) {\r $line = trim($line);\r if (substr($line, 0, 2) == "//") {\r // echo "Commented line removed.<br />";\r $lines[$key] = " ";\r }\r }\r\r $text = trim(implode(" ", $lines));\r\r if ($text == "") {\r // echo "<p>Empty line.</p>";\r return false;\r }\r\r // QUESTION NAME parser\r if (substr($text, 0, 2) == "::") {\r $text = substr($text, 2);\r\r $namefinish = strpos($text, "::");\r if ($namefinish === false) {\r $question->name = false;\r // name will be assigned after processing question text below\r } else {\r $question->name = addslashes(trim(substr($text, 0, $namefinish)));\r $text = trim(substr($text, $namefinish+2)); // Remove name from text\r }\r } else {\r $question->name = false;\r }\r\r\r // FIND ANSWER section\r $answerstart = strpos($text, "{");\r if ($answerstart === false) {\r if ($this->displayerrors) {\r echo "<P>$text<P>Could not find a {";\r }\r return false;\r }\r\r $answerfinish = strpos($text, "}");\r if ($answerfinish === false) {\r if ($this->displayerrors) {\r echo "<P>$text<P>Could not find a }";\r }\r return false;\r }\r\r $answerlength = $answerfinish - $answerstart;\r $answertext = trim(substr($text, $answerstart + 1, $answerlength - 1));\r\r // Format QUESTION TEXT without answer, inserting "_____" as necessary\r if (substr($text, -1) == "}") {\r // no blank line if answers follow question, outside of closing punctuation\r $question->questiontext = addslashes(trim(substr_replace($text, "", $answerstart, $answerlength+1)));\r } else {\r // inserts blank line for missing word format\r $question->questiontext = addslashes(trim(substr_replace($text, "_____", $answerstart, $answerlength+1)));\r }\r\r // set question name if not already set\r if ($question->name === false) {\r $question->name = $question->questiontext;\r }\r\r\r // determine QUESTION TYPE\r $question->qtype = NULL;\r\r if ($answertext{0} == "#"){\r $question->qtype = NUMERICAL;\r\r } elseif (strstr($answertext, "~") !== false) {\r // only Multiplechoice questions contain tilde ~\r $question->qtype = MULTICHOICE;\r \r } else { // either TRUEFALSE or SHORTANSWER\r \r // TRUEFALSE question check\r $truefalse_check = $answertext;\r if (strpos($answertext,"#") > 0){ \r // strip comments to check for TrueFalse question\r $truefalse_check = trim(substr($answertext, 0, strpos($answertext,"#")));\r }\r\r $valid_tf_answers = array("T", "TRUE", "F", "FALSE");\r if (in_array($truefalse_check, $valid_tf_answers)) {\r $question->qtype = TRUEFALSE;\r\r } else { // Must be SHORTANSWER\r $question->qtype = SHORTANSWER;\r }\r }\r\r if (!isset($question->qtype)) {\r if ($this->displayerrors) {\r echo "<P>$text<P>Question type not set.";\r }\r return false;\r }\r\r switch ($question->qtype) {\r case MULTICHOICE:\r if (strpos($answertext,"=") === false) {\r $question->single = 0; // multiple answers are enabled if no single answer is 100% correct \r } else {\r $question->single = 1; // only one answer allowed (the default)\r }\r\r $answertext = str_replace("=", "~=", $answertext);\r $answers = explode("~", $answertext);\r if (isset($answers[0])) {\r $answers[0] = trim($answers[0]);\r }\r if (empty($answers[0])) {\r array_shift($answers);\r }\r \r $countanswers = count($answers);\r if ($countanswers < 2) {\r if ($this->displayerrors) {\r echo "<P>$text<P>Found tilde for multiple choice, \r but too few answers for Multiple Choice.<br />\r Found <u>$countanswers</u> answers in answertext.";\r }\r return false;\r break;\r }\r \r foreach ($answers as $key => $answer) {\r $answer = trim($answer);\r\r // determine answer weight\r if ($answer[0] == "=") {\r $answer_weight = 1;\r $answer = substr($answer, 1);\r \r } elseif (ereg(GIFT_ANSWERWEIGHT_REGEX, $answer)) { // check for properly formatted answer weight\r $answer_weight = $this->answerweightparser($answer);\r \r } else { //default, i.e., wrong anwer\r $answer_weight = 0;\r }\r $question->fraction[$key] = $answer_weight;\r $question->feedback[$key] = $this->commentparser($answer); // commentparser also removes comment from $answer\r $question->answer[$key] = addslashes($answer); \r } // end foreach answer\r \r $question->defaultgrade = 1;\r $question->image = ""; // No images with this format\r return $question;\r break;\r \r case TRUEFALSE:\r $answer = $answertext;\r $comment = $this->commentparser($answer); // commentparser also removes comment from $answer\r\r if ($answer == "T" OR $answer == "TRUE") {\r $question->answer = 1;\r $question->feedbackfalse = $comment; //feedback if answer is wrong\r } else {\r $question->answer = 0;\r $question->feedbacktrue = $comment; //feedback if answer is wrong\r }\r $question->defaultgrade = 1;\r $question->image = ""; // No images with this format\r return $question;\r break;\r \r case SHORTANSWER:\r // SHORTANSWER Question\r $answers = explode("=", $answertext);\r if (isset($answers[0])) {\r $answers[0] = trim($answers[0]);\r }\r if (empty($answers[0])) {\r array_shift($answers);\r }\r \r if (count($answers) == 0) {\r // invalid question\r if ($this->displayerrors) {\r echo "<P>$text<P>Found equals=, but no answers in answertext";\r }\r return false;\r break;\r }\r\r foreach ($answers as $key => $answer) {\r $answer = trim($answer);\r\r // Answer Weight\r if (ereg(GIFT_ANSWERWEIGHT_REGEX, $answer)) { // check for properly formatted answer weight\r $answer_weight = $this->answerweightparser($answer);\r } else { //default, i.e., full-credit anwer\r $answer_weight = 1;\r }\r $question->fraction[$key] = $answer_weight;\r $question->feedback[$key] = $this->commentparser($answer); //commentparser also removes comment from $answer\r $question->answer[$key] = addslashes($answer);\r } // end foreach\r\r $question->usecase = 0; // Ignore case\r $question->defaultgrade = 1;\r $question->image = ""; // No images with this format\r return $question;\r break;\r\r case NUMERICAL:\r // Note similarities to ShortAnswer\r $answertext = substr($answertext, 1); // remove leading "#"\r\r $answers = explode("=", $answertext);\r if (isset($answers[0])) {\r $answers[0] = trim($answers[0]);\r }\r if (empty($answers[0])) {\r array_shift($answers);\r }\r \r if (count($answers) == 0) {\r // invalid question\r if ($this->displayerrors) {\r echo "<P>$text<P>No answers found in answertext (Numerical answer)";\r }\r return false;\r break;\r }\r\r foreach ($answers as $key => $answer) {\r $answer = trim($answer);\r\r // Answer weight\r if (ereg(GIFT_ANSWERWEIGHT_REGEX, $answer)) { // check for properly formatted answer weight\r $answer_weight = $this->answerweightparser($answer);\r } else { //default, i.e., full-credit anwer\r $answer_weight = 1;\r }\r $question->fraction[$key] = $answer_weight;\r $question->feedback[$key] = $this->commentparser($answer); //commentparser also removes comment from $answer\r\r //Calculate Answer and Min/Max values\r if (strpos($answer,"..") > 0) { // optional [min]..[max] format\r $marker = strpos($answer,"..");\r $question->max[$key] = trim(substr($answer, $marker+2));\r $question->min[$key] = trim(substr($answer, 0, $marker));\r $question->answer[$key] = ($question->max[$key] + $question->min[$key])/2;\r\r } elseif (strpos($answer,":") > 0){ // standard [answer]:[errormargin] format\r $marker = strpos($answer,":");\r $errormargin = trim(substr($answer, $marker+1));\r $question->answer[$key] = trim(substr($answer, 0, $marker));\r $question->max[$key] = $question->answer[$key] + $errormargin;\r $question->min[$key] = $question->answer[$key] - $errormargin;\r\r } else { // only one valid answer (zero errormargin)\r $errormargin = 0;\r $question->answer[$key] = trim($answer);\r $question->max[$key] = $question->answer[$key] + $errormargin;\r $question->min[$key] = $question->answer[$key] - $errormargin;\r }\r \r if (!is_numeric($question->answer[$key]) \r OR !is_numeric($question->max[$key])\r OR !is_numeric($question->max[$key])) {\r if ($this->displayerrors) {\r echo "<P>$text<P>For numerical questions, answer must be numbers.\r <P>Answer: <u>$answer</u><P>ErrorMargin: <u>$errormargin</u> .";\r }\r return false;\r break;\r }\r\r } // end foreach\r\r $question->defaultgrade = 1;\r $question->image = ""; // No images with this format\r return $question;\r break;\r\r default:\r if ($this->displayerrors) {\r echo "<P>$text<P> No valid question type. Error in switch(question->qtype)";\r }\r return false;\r break; \r \r } // end switch ($question->qtype)\r\r } // end function readquestion($lines)\r}\r\r?>\r
\ No newline at end of file
+<?php // $Id$
+//
+///////////////////////////////////////////////////////////////
+// GIFT
+//
+// The GIFT import filter is an easy to use method for teachers
+// writing questions as a text file. It supports true-false,
+// short answer, multiple-choice and numerical questions, as well
+// as insertion of a blank line for the missing word format.
+//
+// Multiple Choice / Missing Word
+// Who's buried in Grant's tomb?{~Grant ~Jefferson =no one}
+// Grant is {~buried =entombed ~living} in Grant's tomb.
+// True-False:
+// Grant is buried in Grant's tomb.{FALSE}
+// Short-Answer.
+// Who's buried in Grant's tomb?{=no one =nobody}
+// Numerical
+// When was Ulysses S. Grant born?{#1822:5}
+//
+// Comment lines start with a double backslash (//).
+// Optional question names are enclosed in double colon(::).
+// Answer feedback is indicated with hash mark (#).
+// Percentage answer weights immediately follow the tilde (for
+// multiple choice) or equal sign (for short answer and numerical),
+// and are enclosed in percent signs (% %). Below are more
+// complicated examples with various options and formatting styles.
+//
+// ::Grant's Tomb::Grant is {
+// ~buried#No one is buried there.
+// =entombed#Right answer!
+// ~living#We hope not!
+// } in Grant's tomb.
+//
+// Difficult multiple choice question.{
+// ~wrong answer #comment on wrong answer
+// ~%50%half credit answer #comment on answer
+// =full credit answer #well done!}
+//
+// ::Jesus' hometown (Short answer ex.):: Jesus Christ was from {
+// =Nazareth#Yes! That's right!
+// =%75%Nazereth#Right, but misspelled.
+// =%25%Bethlehem#He was born here, but not raised here.
+// }.
+//
+// //this inline comment will be ignored by the filter
+// ::Numerical example::
+// When was Ulysses S. Grant born? {#
+// =1822:0 #Correct! 100% credit
+// =%50%1982:2 #He was born in 1822.
+// You get 50% credit for being close.
+// }
+//
+// This filter was written through the collaboration of numerous
+// members of the Moodle community. It was originally based on
+// the missingword format, which included code from Thomas Robb
+// and others. Paul Tsuchido Shew wrote this filter in December 2003.
+//////////////////////////////////////////////////////////////////////////
+// Based on default.php, included by ../import.php
+
+class quiz_file_format extends quiz_default_format {
+
+ function answerweightparser(&$answer) {
+ $answer = substr($answer, 1); // removes initial %
+ $end_position = strpos($answer, "%");
+ $answer_weight = substr($answer, 0, $end_position); // gets weight as integer
+ $answer_weight = $answer_weight/100; // converts to percent
+ $answer = substr($answer, $end_position+1); // removes comment from answer
+ return $answer_weight;
+ }
+
+
+ function commentparser(&$answer) {
+ if (strpos($answer,"#") > 0){
+ $hashpos = strpos($answer,"#");
+ $comment = addslashes(substr($answer, $hashpos+1));
+ $answer = substr($answer, 0, $hashpos);
+ } else {
+ $comment = " ";
+ }
+ return $comment;
+ }
+
+
+ function readquestion($lines) {
+ // Given an array of lines known to define a question in this format, this function
+ // converts it into a question object suitable for processing and insertion into Moodle.
+
+ $question = NULL;
+ $comment = NULL;
+ define("GIFT_ANSWERWEIGHT_REGEX", "^%\-*([0-9]{1,2})\.?([0-9]*)%");
+
+ // REMOVED COMMENTED LINES and IMPLODE
+ foreach ($lines as $key => $line) {
+ $line = trim($line);
+ if (substr($line, 0, 2) == "//") {
+ // echo "Commented line removed.<br />";
+ $lines[$key] = " ";
+ }
+ }
+
+ $text = trim(implode(" ", $lines));
+
+ if ($text == "") {
+ // echo "<p>Empty line.</p>";
+ return false;
+ }
+
+ // QUESTION NAME parser
+ if (substr($text, 0, 2) == "::") {
+ $text = substr($text, 2);
+
+ $namefinish = strpos($text, "::");
+ if ($namefinish === false) {
+ $question->name = false;
+ // name will be assigned after processing question text below
+ } else {
+ $question->name = addslashes(trim(substr($text, 0, $namefinish)));
+ $text = trim(substr($text, $namefinish+2)); // Remove name from text
+ }
+ } else {
+ $question->name = false;
+ }
+
+
+ // FIND ANSWER section
+ $answerstart = strpos($text, "{");
+ if ($answerstart === false) {
+ if ($this->displayerrors) {
+ echo "<P>$text<P>Could not find a {";
+ }
+ return false;
+ }
+
+ $answerfinish = strpos($text, "}");
+ if ($answerfinish === false) {
+ if ($this->displayerrors) {
+ echo "<P>$text<P>Could not find a }";
+ }
+ return false;
+ }
+
+ $answerlength = $answerfinish - $answerstart;
+ $answertext = trim(substr($text, $answerstart + 1, $answerlength - 1));
+
+ // Format QUESTION TEXT without answer, inserting "_____" as necessary
+ if (substr($text, -1) == "}") {
+ // no blank line if answers follow question, outside of closing punctuation
+ $question->questiontext = addslashes(trim(substr_replace($text, "", $answerstart, $answerlength+1)));
+ } else {
+ // inserts blank line for missing word format
+ $question->questiontext = addslashes(trim(substr_replace($text, "_____", $answerstart, $answerlength+1)));
+ }
+
+ // set question name if not already set
+ if ($question->name === false) {
+ $question->name = $question->questiontext;
+ }
+
+
+ // determine QUESTION TYPE
+ $question->qtype = NULL;
+
+ if ($answertext{0} == "#"){
+ $question->qtype = NUMERICAL;
+
+ } elseif (strstr($answertext, "~") !== false) {
+ // only Multiplechoice questions contain tilde ~
+ $question->qtype = MULTICHOICE;
+
+ } else { // either TRUEFALSE or SHORTANSWER
+
+ // TRUEFALSE question check
+ $truefalse_check = $answertext;
+ if (strpos($answertext,"#") > 0){
+ // strip comments to check for TrueFalse question
+ $truefalse_check = trim(substr($answertext, 0, strpos($answertext,"#")));
+ }
+
+ $valid_tf_answers = array("T", "TRUE", "F", "FALSE");
+ if (in_array($truefalse_check, $valid_tf_answers)) {
+ $question->qtype = TRUEFALSE;
+
+ } else { // Must be SHORTANSWER
+ $question->qtype = SHORTANSWER;
+ }
+ }
+
+ if (!isset($question->qtype)) {
+ if ($this->displayerrors) {
+ echo "<P>$text<P>Question type not set.";
+ }
+ return false;
+ }
+
+ switch ($question->qtype) {
+ case MULTICHOICE:
+ if (strpos($answertext,"=") === false) {
+ $question->single = 0; // multiple answers are enabled if no single answer is 100% correct
+ } else {
+ $question->single = 1; // only one answer allowed (the default)
+ }
+
+ $answertext = str_replace("=", "~=", $answertext);
+ $answers = explode("~", $answertext);
+ if (isset($answers[0])) {
+ $answers[0] = trim($answers[0]);
+ }
+ if (empty($answers[0])) {
+ array_shift($answers);
+ }
+
+ $countanswers = count($answers);
+ if ($countanswers < 2) {
+ if ($this->displayerrors) {
+ echo "<P>$text<P>Found tilde for multiple choice,
+ but too few answers for Multiple Choice.<br />
+ Found <u>$countanswers</u> answers in answertext.";
+ }
+ return false;
+ break;
+ }
+
+ foreach ($answers as $key => $answer) {
+ $answer = trim($answer);
+
+ // determine answer weight
+ if ($answer[0] == "=") {
+ $answer_weight = 1;
+ $answer = substr($answer, 1);
+
+ } elseif (ereg(GIFT_ANSWERWEIGHT_REGEX, $answer)) { // check for properly formatted answer weight
+ $answer_weight = $this->answerweightparser($answer);
+
+ } else { //default, i.e., wrong anwer
+ $answer_weight = 0;
+ }
+ $question->fraction[$key] = $answer_weight;
+ $question->feedback[$key] = $this->commentparser($answer); // commentparser also removes comment from $answer
+ $question->answer[$key] = addslashes($answer);
+ } // end foreach answer
+
+ $question->defaultgrade = 1;
+ $question->image = ""; // No images with this format
+ return $question;
+ break;
+
+ case TRUEFALSE:
+ $answer = $answertext;
+ $comment = $this->commentparser($answer); // commentparser also removes comment from $answer
+
+ if ($answer == "T" OR $answer == "TRUE") {
+ $question->answer = 1;
+ $question->feedbackfalse = $comment; //feedback if answer is wrong
+ } else {
+ $question->answer = 0;
+ $question->feedbacktrue = $comment; //feedback if answer is wrong
+ }
+ $question->defaultgrade = 1;
+ $question->image = ""; // No images with this format
+ return $question;
+ break;
+
+ case SHORTANSWER:
+ // SHORTANSWER Question
+ $answers = explode("=", $answertext);
+ if (isset($answers[0])) {
+ $answers[0] = trim($answers[0]);
+ }
+ if (empty($answers[0])) {
+ array_shift($answers);
+ }
+
+ if (count($answers) == 0) {
+ // invalid question
+ if ($this->displayerrors) {
+ echo "<P>$text<P>Found equals=, but no answers in answertext";
+ }
+ return false;
+ break;
+ }
+
+ foreach ($answers as $key => $answer) {
+ $answer = trim($answer);
+
+ // Answer Weight
+ if (ereg(GIFT_ANSWERWEIGHT_REGEX, $answer)) { // check for properly formatted answer weight
+ $answer_weight = $this->answerweightparser($answer);
+ } else { //default, i.e., full-credit anwer
+ $answer_weight = 1;
+ }
+ $question->fraction[$key] = $answer_weight;
+ $question->feedback[$key] = $this->commentparser($answer); //commentparser also removes comment from $answer
+ $question->answer[$key] = addslashes($answer);
+ } // end foreach
+
+ $question->usecase = 0; // Ignore case
+ $question->defaultgrade = 1;
+ $question->image = ""; // No images with this format
+ return $question;
+ break;
+
+ case NUMERICAL:
+ // Note similarities to ShortAnswer
+ $answertext = substr($answertext, 1); // remove leading "#"
+
+ $answers = explode("=", $answertext);
+ if (isset($answers[0])) {
+ $answers[0] = trim($answers[0]);
+ }
+ if (empty($answers[0])) {
+ array_shift($answers);
+ }
+
+ if (count($answers) == 0) {
+ // invalid question
+ if ($this->displayerrors) {
+ echo "<P>$text<P>No answers found in answertext (Numerical answer)";
+ }
+ return false;
+ break;
+ }
+
+ foreach ($answers as $key => $answer) {
+ $answer = trim($answer);
+
+ // Answer weight
+ if (ereg(GIFT_ANSWERWEIGHT_REGEX, $answer)) { // check for properly formatted answer weight
+ $answer_weight = $this->answerweightparser($answer);
+ } else { //default, i.e., full-credit anwer
+ $answer_weight = 1;
+ }
+ $question->fraction[$key] = $answer_weight;
+ $question->feedback[$key] = $this->commentparser($answer); //commentparser also removes comment from $answer
+
+ //Calculate Answer and Min/Max values
+ if (strpos($answer,"..") > 0) { // optional [min]..[max] format
+ $marker = strpos($answer,"..");
+ $question->max[$key] = trim(substr($answer, $marker+2));
+ $question->min[$key] = trim(substr($answer, 0, $marker));
+ $question->answer[$key] = ($question->max[$key] + $question->min[$key])/2;
+
+ } elseif (strpos($answer,":") > 0){ // standard [answer]:[errormargin] format
+ $marker = strpos($answer,":");
+ $errormargin = trim(substr($answer, $marker+1));
+ $question->answer[$key] = trim(substr($answer, 0, $marker));
+ $question->max[$key] = $question->answer[$key] + $errormargin;
+ $question->min[$key] = $question->answer[$key] - $errormargin;
+
+ } else { // only one valid answer (zero errormargin)
+ $errormargin = 0;
+ $question->answer[$key] = trim($answer);
+ $question->max[$key] = $question->answer[$key] + $errormargin;
+ $question->min[$key] = $question->answer[$key] - $errormargin;
+ }
+
+ if (!is_numeric($question->answer[$key])
+ OR !is_numeric($question->max[$key])
+ OR !is_numeric($question->max[$key])) {
+ if ($this->displayerrors) {
+ echo "<P>$text<P>For numerical questions, answer must be numbers.
+ <P>Answer: <u>$answer</u><P>ErrorMargin: <u>$errormargin</u> .";
+ }
+ return false;
+ break;
+ }
+
+ } // end foreach
+
+ $question->defaultgrade = 1;
+ $question->image = ""; // No images with this format
+ return $question;
+ break;
+
+ default:
+ if ($this->displayerrors) {
+ echo "<P>$text<P> No valid question type. Error in switch(question->qtype)";
+ }
+ return false;
+ break;
+
+ } // end switch ($question->qtype)
+
+ } // end function readquestion($lines)
+}
+
+?>