|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 // This file is part of Moodle - http://moodle.org/ 00003 // 00004 // Moodle is free software: you can redistribute it and/or modify 00005 // it under the terms of the GNU General Public License as published by 00006 // the Free Software Foundation, either version 3 of the License, or 00007 // (at your option) any later version. 00008 // 00009 // Moodle is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License 00015 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 00016 00027 defined('MOODLE_INTERNAL') || die(); 00028 00029 00063 class qformat_gift extends qformat_default { 00064 00065 public function provide_import() { 00066 return true; 00067 } 00068 00069 public function provide_export() { 00070 return true; 00071 } 00072 00073 public function export_file_extension() { 00074 return '.txt'; 00075 } 00076 00077 protected function answerweightparser(&$answer) { 00078 $answer = substr($answer, 1); // removes initial % 00079 $end_position = strpos($answer, "%"); 00080 $answer_weight = substr($answer, 0, $end_position); // gets weight as integer 00081 $answer_weight = $answer_weight/100; // converts to percent 00082 $answer = substr($answer, $end_position+1); // removes comment from answer 00083 return $answer_weight; 00084 } 00085 00086 protected function commentparser($answer, $defaultformat) { 00087 $bits = explode('#', $answer, 2); 00088 $ans = $this->parse_text_with_format(trim($bits[0]), $defaultformat); 00089 if (count($bits) > 1) { 00090 $feedback = $this->parse_text_with_format(trim($bits[1]), $defaultformat); 00091 } else { 00092 $feedback = array('text' => '', 'format' => $defaultformat, 'files' => array()); 00093 } 00094 return array($ans, $feedback); 00095 } 00096 00097 protected function split_truefalse_comment($answer, $defaultformat) { 00098 $bits = explode('#', $answer, 3); 00099 $ans = $this->parse_text_with_format(trim($bits[0]), $defaultformat); 00100 if (count($bits) > 1) { 00101 $wrongfeedback = $this->parse_text_with_format(trim($bits[1]), $defaultformat); 00102 } else { 00103 $wrongfeedback = array('text' => '', 'format' => $defaultformat, 'files' => array()); 00104 } 00105 if (count($bits) > 2) { 00106 $rightfeedback = $this->parse_text_with_format(trim($bits[2]), $defaultformat); 00107 } else { 00108 $rightfeedback = array('text' => '', 'format' => $defaultformat, 'files' => array()); 00109 } 00110 return array($ans, $wrongfeedback, $rightfeedback); 00111 } 00112 00113 protected function escapedchar_pre($string) { 00114 //Replaces escaped control characters with a placeholder BEFORE processing 00115 00116 $escapedcharacters = array("\\:", "\\#", "\\=", "\\{", "\\}", "\\~", "\\n" ); //dlnsk 00117 $placeholders = array("&&058;", "&&035;", "&&061;", "&&123;", "&&125;", "&&126;", "&&010"); //dlnsk 00118 00119 $string = str_replace("\\\\", "&&092;", $string); 00120 $string = str_replace($escapedcharacters, $placeholders, $string); 00121 $string = str_replace("&&092;", "\\", $string); 00122 return $string; 00123 } 00124 00125 protected function escapedchar_post($string) { 00126 //Replaces placeholders with corresponding character AFTER processing is done 00127 $placeholders = array("&&058;", "&&035;", "&&061;", "&&123;", "&&125;", "&&126;", "&&010"); //dlnsk 00128 $characters = array(":", "#", "=", "{", "}", "~", "\n" ); //dlnsk 00129 $string = str_replace($placeholders, $characters, $string); 00130 return $string; 00131 } 00132 00133 protected function check_answer_count($min, $answers, $text) { 00134 $countanswers = count($answers); 00135 if ($countanswers < $min) { 00136 $this->error(get_string('importminerror', 'qformat_gift'), $text); 00137 return false; 00138 } 00139 00140 return true; 00141 } 00142 00143 protected function parse_text_with_format($text, $defaultformat = FORMAT_MOODLE) { 00144 $result = array( 00145 'text' => $text, 00146 'format' => $defaultformat, 00147 'files' => array(), 00148 ); 00149 if (strpos($text, '[') === 0) { 00150 $formatend = strpos($text, ']'); 00151 $result['format'] = $this->format_name_to_const(substr($text, 1, $formatend - 1)); 00152 if ($result['format'] == -1) { 00153 $result['format'] = $defaultformat; 00154 } else { 00155 $result['text'] = substr($text, $formatend + 1); 00156 } 00157 } 00158 $result['text'] = trim($this->escapedchar_post($result['text'])); 00159 return $result; 00160 } 00161 00162 public function readquestion($lines) { 00163 // Given an array of lines known to define a question in this format, this function 00164 // converts it into a question object suitable for processing and insertion into Moodle. 00165 00166 $question = $this->defaultquestion(); 00167 $comment = NULL; 00168 // define replaced by simple assignment, stop redefine notices 00169 $gift_answerweight_regex = '/^%\-*([0-9]{1,2})\.?([0-9]*)%/'; 00170 00171 // REMOVED COMMENTED LINES and IMPLODE 00172 foreach ($lines as $key => $line) { 00173 $line = trim($line); 00174 if (substr($line, 0, 2) == '//') { 00175 $lines[$key] = ' '; 00176 } 00177 } 00178 00179 $text = trim(implode(' ', $lines)); 00180 00181 if ($text == '') { 00182 return false; 00183 } 00184 00185 // Substitute escaped control characters with placeholders 00186 $text = $this->escapedchar_pre($text); 00187 00188 // Look for category modifier 00189 if (preg_match('~^\$CATEGORY:~', $text)) { 00190 // $newcategory = $matches[1]; 00191 $newcategory = trim(substr($text, 10)); 00192 00193 // build fake question to contain category 00194 $question->qtype = 'category'; 00195 $question->category = $newcategory; 00196 return $question; 00197 } 00198 00199 // QUESTION NAME parser 00200 if (substr($text, 0, 2) == '::') { 00201 $text = substr($text, 2); 00202 00203 $namefinish = strpos($text, '::'); 00204 if ($namefinish === false) { 00205 $question->name = false; 00206 // name will be assigned after processing question text below 00207 } else { 00208 $questionname = substr($text, 0, $namefinish); 00209 $question->name = trim($this->escapedchar_post($questionname)); 00210 $text = trim(substr($text, $namefinish+2)); // Remove name from text 00211 } 00212 } else { 00213 $question->name = false; 00214 } 00215 00216 00217 // FIND ANSWER section 00218 // no answer means its a description 00219 $answerstart = strpos($text, '{'); 00220 $answerfinish = strpos($text, '}'); 00221 00222 $description = false; 00223 if (($answerstart === false) and ($answerfinish === false)) { 00224 $description = true; 00225 $answertext = ''; 00226 $answerlength = 0; 00227 } else if (!(($answerstart !== false) and ($answerfinish !== false))) { 00228 $this->error(get_string('braceerror', 'qformat_gift'), $text); 00229 return false; 00230 } else { 00231 $answerlength = $answerfinish - $answerstart; 00232 $answertext = trim(substr($text, $answerstart + 1, $answerlength - 1)); 00233 } 00234 00235 // Format QUESTION TEXT without answer, inserting "_____" as necessary 00236 if ($description) { 00237 $questiontext = $text; 00238 } else if (substr($text, -1) == "}") { 00239 // no blank line if answers follow question, outside of closing punctuation 00240 $questiontext = substr_replace($text, "", $answerstart, $answerlength+1); 00241 } else { 00242 // inserts blank line for missing word format 00243 $questiontext = substr_replace($text, "_____", $answerstart, $answerlength+1); 00244 } 00245 00246 // Get questiontext format from questiontext 00247 $text = $this->parse_text_with_format($questiontext); 00248 $question->questiontextformat = $text['format']; 00249 $question->generalfeedbackformat = $text['format']; 00250 $question->questiontext = $text['text']; 00251 00252 // set question name if not already set 00253 if ($question->name === false) { 00254 $question->name = $question->questiontext; 00255 } 00256 00257 // ensure name is not longer than 250 characters 00258 $question->name = shorten_text($question->name, 200); 00259 $question->name = strip_tags(substr($question->name, 0, 250)); 00260 00261 // determine QUESTION TYPE 00262 $question->qtype = NULL; 00263 00264 // give plugins first try 00265 // plugins must promise not to intercept standard qtypes 00266 // MDL-12346, this could be called from lesson mod which has its own base class =( 00267 if (method_exists($this, 'try_importing_using_qtypes') && ($try_question = $this->try_importing_using_qtypes($lines, $question, $answertext))) { 00268 return $try_question; 00269 } 00270 00271 if ($description) { 00272 $question->qtype = DESCRIPTION; 00273 00274 } else if ($answertext == '') { 00275 $question->qtype = ESSAY; 00276 00277 } else if ($answertext{0} == '#') { 00278 $question->qtype = NUMERICAL; 00279 00280 } else if (strpos($answertext, '~') !== false) { 00281 // only Multiplechoice questions contain tilde ~ 00282 $question->qtype = MULTICHOICE; 00283 00284 } else if (strpos($answertext, '=') !== false 00285 && strpos($answertext, '->') !== false) { 00286 // only Matching contains both = and -> 00287 $question->qtype = MATCH; 00288 00289 } else { // either TRUEFALSE or SHORTANSWER 00290 00291 // TRUEFALSE question check 00292 $truefalse_check = $answertext; 00293 if (strpos($answertext, '#') > 0) { 00294 // strip comments to check for TrueFalse question 00295 $truefalse_check = trim(substr($answertext, 0, strpos($answertext,"#"))); 00296 } 00297 00298 $valid_tf_answers = array('T', 'TRUE', 'F', 'FALSE'); 00299 if (in_array($truefalse_check, $valid_tf_answers)) { 00300 $question->qtype = TRUEFALSE; 00301 00302 } else { // Must be SHORTANSWER 00303 $question->qtype = SHORTANSWER; 00304 } 00305 } 00306 00307 if (!isset($question->qtype)) { 00308 $giftqtypenotset = get_string('giftqtypenotset', 'qformat_gift'); 00309 $this->error($giftqtypenotset, $text); 00310 return false; 00311 } 00312 00313 switch ($question->qtype) { 00314 case DESCRIPTION: 00315 $question->defaultmark = 0; 00316 $question->length = 0; 00317 return $question; 00318 00319 case ESSAY: 00320 $question->responseformat = 'editor'; 00321 $question->responsefieldlines = 15; 00322 $question->attachments = 0; 00323 $question->graderinfo = array( 00324 'text' => '', 'format' => FORMAT_HTML, 'files' => array()); 00325 return $question; 00326 00327 case MULTICHOICE: 00328 if (strpos($answertext,"=") === false) { 00329 $question->single = 0; // multiple answers are enabled if no single answer is 100% correct 00330 } else { 00331 $question->single = 1; // only one answer allowed (the default) 00332 } 00333 $question = $this->add_blank_combined_feedback($question); 00334 00335 $answertext = str_replace("=", "~=", $answertext); 00336 $answers = explode("~", $answertext); 00337 if (isset($answers[0])) { 00338 $answers[0] = trim($answers[0]); 00339 } 00340 if (empty($answers[0])) { 00341 array_shift($answers); 00342 } 00343 00344 $countanswers = count($answers); 00345 00346 if (!$this->check_answer_count(2, $answers, $text)) { 00347 return false; 00348 } 00349 00350 foreach ($answers as $key => $answer) { 00351 $answer = trim($answer); 00352 00353 // determine answer weight 00354 if ($answer[0] == '=') { 00355 $answer_weight = 1; 00356 $answer = substr($answer, 1); 00357 00358 } else if (preg_match($gift_answerweight_regex, $answer)) { // check for properly formatted answer weight 00359 $answer_weight = $this->answerweightparser($answer); 00360 00361 } else { //default, i.e., wrong anwer 00362 $answer_weight = 0; 00363 } 00364 list($question->answer[$key], $question->feedback[$key]) = 00365 $this->commentparser($answer, $question->questiontextformat); 00366 $question->fraction[$key] = $answer_weight; 00367 } // end foreach answer 00368 00369 return $question; 00370 00371 case MATCH: 00372 $question = $this->add_blank_combined_feedback($question); 00373 00374 $answers = explode('=', $answertext); 00375 if (isset($answers[0])) { 00376 $answers[0] = trim($answers[0]); 00377 } 00378 if (empty($answers[0])) { 00379 array_shift($answers); 00380 } 00381 00382 if (!$this->check_answer_count(2,$answers,$text)) { 00383 return false; 00384 } 00385 00386 foreach ($answers as $key => $answer) { 00387 $answer = trim($answer); 00388 if (strpos($answer, "->") === false) { 00389 $this->error(get_string('giftmatchingformat','qformat_gift'), $answer); 00390 return false; 00391 } 00392 00393 $marker = strpos($answer, '->'); 00394 $question->subquestions[$key] = $this->parse_text_with_format( 00395 substr($answer, 0, $marker), $question->questiontextformat); 00396 $question->subanswers[$key] = trim($this->escapedchar_post( 00397 substr($answer, $marker + 2))); 00398 } 00399 00400 return $question; 00401 00402 case TRUEFALSE: 00403 list($answer, $wrongfeedback, $rightfeedback) = 00404 $this->split_truefalse_comment($answertext, $question->questiontextformat); 00405 00406 if ($answer['text'] == "T" OR $answer['text'] == "TRUE") { 00407 $question->correctanswer = 1; 00408 $question->feedbacktrue = $rightfeedback; 00409 $question->feedbackfalse = $wrongfeedback; 00410 } else { 00411 $question->correctanswer = 0; 00412 $question->feedbacktrue = $wrongfeedback; 00413 $question->feedbackfalse = $rightfeedback; 00414 } 00415 00416 $question->penalty = 1; 00417 00418 return $question; 00419 00420 case SHORTANSWER: 00421 // SHORTANSWER Question 00422 $answers = explode("=", $answertext); 00423 if (isset($answers[0])) { 00424 $answers[0] = trim($answers[0]); 00425 } 00426 if (empty($answers[0])) { 00427 array_shift($answers); 00428 } 00429 00430 if (!$this->check_answer_count(1, $answers, $text)) { 00431 return false; 00432 } 00433 00434 foreach ($answers as $key => $answer) { 00435 $answer = trim($answer); 00436 00437 // Answer weight 00438 if (preg_match($gift_answerweight_regex, $answer)) { // check for properly formatted answer weight 00439 $answer_weight = $this->answerweightparser($answer); 00440 } else { //default, i.e., full-credit anwer 00441 $answer_weight = 1; 00442 } 00443 00444 list($answer, $question->feedback[$key]) = $this->commentparser( 00445 $answer, $question->questiontextformat); 00446 00447 $question->answer[$key] = $answer['text']; 00448 $question->fraction[$key] = $answer_weight; 00449 } 00450 00451 return $question; 00452 00453 case NUMERICAL: 00454 // Note similarities to ShortAnswer 00455 $answertext = substr($answertext, 1); // remove leading "#" 00456 00457 // If there is feedback for a wrong answer, store it for now. 00458 if (($pos = strpos($answertext, '~')) !== false) { 00459 $wrongfeedback = substr($answertext, $pos); 00460 $answertext = substr($answertext, 0, $pos); 00461 } else { 00462 $wrongfeedback = ''; 00463 } 00464 00465 $answers = explode("=", $answertext); 00466 if (isset($answers[0])) { 00467 $answers[0] = trim($answers[0]); 00468 } 00469 if (empty($answers[0])) { 00470 array_shift($answers); 00471 } 00472 00473 if (count($answers) == 0) { 00474 // invalid question 00475 $giftnonumericalanswers = get_string('giftnonumericalanswers','qformat_gift'); 00476 $this->error($giftnonumericalanswers, $text); 00477 return false; 00478 } 00479 00480 foreach ($answers as $key => $answer) { 00481 $answer = trim($answer); 00482 00483 // Answer weight 00484 if (preg_match($gift_answerweight_regex, $answer)) { // check for properly formatted answer weight 00485 $answer_weight = $this->answerweightparser($answer); 00486 } else { //default, i.e., full-credit anwer 00487 $answer_weight = 1; 00488 } 00489 00490 list($answer, $question->feedback[$key]) = $this->commentparser( 00491 $answer, $question->questiontextformat); 00492 $question->fraction[$key] = $answer_weight; 00493 $answer = $answer['text']; 00494 00495 //Calculate Answer and Min/Max values 00496 if (strpos($answer,"..") > 0) { // optional [min]..[max] format 00497 $marker = strpos($answer,".."); 00498 $max = trim(substr($answer, $marker+2)); 00499 $min = trim(substr($answer, 0, $marker)); 00500 $ans = ($max + $min)/2; 00501 $tol = $max - $ans; 00502 } else if (strpos($answer, ':') > 0) { // standard [answer]:[errormargin] format 00503 $marker = strpos($answer, ':'); 00504 $tol = trim(substr($answer, $marker+1)); 00505 $ans = trim(substr($answer, 0, $marker)); 00506 } else { // only one valid answer (zero errormargin) 00507 $tol = 0; 00508 $ans = trim($answer); 00509 } 00510 00511 if (!(is_numeric($ans) || $ans = '*') || !is_numeric($tol)) { 00512 $errornotnumbers = get_string('errornotnumbers'); 00513 $this->error($errornotnumbers, $text); 00514 return false; 00515 } 00516 00517 // store results 00518 $question->answer[$key] = $ans; 00519 $question->tolerance[$key] = $tol; 00520 } 00521 00522 if ($wrongfeedback) { 00523 $key += 1; 00524 $question->fraction[$key] = 0; 00525 list($notused, $question->feedback[$key]) = $this->commentparser( 00526 $wrongfeedback, $question->questiontextformat); 00527 $question->answer[$key] = '*'; 00528 $question->tolerance[$key] = ''; 00529 } 00530 00531 return $question; 00532 00533 default: 00534 $this->error(get_string('giftnovalidquestion', 'qformat_gift'), $text); 00535 return false; 00536 00537 } 00538 } 00539 00540 protected function add_blank_combined_feedback($question) { 00541 $question->correctfeedback['text'] = ''; 00542 $question->correctfeedback['format'] = $question->questiontextformat; 00543 $question->correctfeedback['files'] = array(); 00544 $question->partiallycorrectfeedback['text'] = ''; 00545 $question->partiallycorrectfeedback['format'] = $question->questiontextformat; 00546 $question->partiallycorrectfeedback['files'] = array(); 00547 $question->incorrectfeedback['text'] = ''; 00548 $question->incorrectfeedback['format'] = $question->questiontextformat; 00549 $question->incorrectfeedback['files'] = array(); 00550 return $question; 00551 } 00552 00553 protected function repchar($text, $notused = 0) { 00554 // Escapes 'reserved' characters # = ~ {) : 00555 // Removes new lines 00556 $reserved = array( '#', '=', '~', '{', '}', ':', "\n", "\r"); 00557 $escaped = array('\#','\=','\~','\{','\}','\:', '\n', '' ); 00558 00559 $newtext = str_replace($reserved, $escaped, $text); 00560 return $newtext; 00561 } 00562 00567 protected function format_const_to_name($format) { 00568 if ($format == FORMAT_MOODLE) { 00569 return 'moodle'; 00570 } else if ($format == FORMAT_HTML) { 00571 return 'html'; 00572 } else if ($format == FORMAT_PLAIN) { 00573 return 'plain'; 00574 } else if ($format == FORMAT_MARKDOWN) { 00575 return 'markdown'; 00576 } else { 00577 return 'moodle'; 00578 } 00579 } 00580 00585 protected function format_name_to_const($format) { 00586 if ($format == 'moodle') { 00587 return FORMAT_MOODLE; 00588 } else if ($format == 'html') { 00589 return FORMAT_HTML; 00590 } else if ($format == 'plain') { 00591 return FORMAT_PLAIN; 00592 } else if ($format == 'markdown') { 00593 return FORMAT_MARKDOWN; 00594 } else { 00595 return -1; 00596 } 00597 } 00598 00599 public function write_name($name) { 00600 return '::' . $this->repchar($name) . '::'; 00601 } 00602 00603 public function write_questiontext($text, $format, $defaultformat = FORMAT_MOODLE) { 00604 $output = ''; 00605 if ($text != '' && $format != $defaultformat) { 00606 $output .= '[' . $this->format_const_to_name($format) . ']'; 00607 } 00608 $output .= $this->repchar($text, $format); 00609 return $output; 00610 } 00611 00612 public function writequestion($question) { 00613 global $OUTPUT; 00614 00615 // Start with a comment 00616 $expout = "// question: $question->id name: $question->name\n"; 00617 00618 // output depends on question type 00619 switch($question->qtype) { 00620 00621 case 'category': 00622 // not a real question, used to insert category switch 00623 $expout .= "\$CATEGORY: $question->category\n"; 00624 break; 00625 00626 case DESCRIPTION: 00627 $expout .= $this->write_name($question->name); 00628 $expout .= $this->write_questiontext($question->questiontext, $question->questiontextformat); 00629 break; 00630 00631 case ESSAY: 00632 $expout .= $this->write_name($question->name); 00633 $expout .= $this->write_questiontext($question->questiontext, $question->questiontextformat); 00634 $expout .= "{}\n"; 00635 break; 00636 00637 case TRUEFALSE: 00638 $trueanswer = $question->options->answers[$question->options->trueanswer]; 00639 $falseanswer = $question->options->answers[$question->options->falseanswer]; 00640 if ($trueanswer->fraction == 1) { 00641 $answertext = 'TRUE'; 00642 $rightfeedback = $this->write_questiontext($trueanswer->feedback, 00643 $trueanswer->feedbackformat, $question->questiontextformat); 00644 $wrongfeedback = $this->write_questiontext($falseanswer->feedback, 00645 $falseanswer->feedbackformat, $question->questiontextformat); 00646 } else { 00647 $answertext = 'FALSE'; 00648 $rightfeedback = $this->write_questiontext($falseanswer->feedback, 00649 $falseanswer->feedbackformat, $question->questiontextformat); 00650 $wrongfeedback = $this->write_questiontext($trueanswer->feedback, 00651 $trueanswer->feedbackformat, $question->questiontextformat); 00652 } 00653 00654 $expout .= $this->write_name($question->name); 00655 $expout .= $this->write_questiontext($question->questiontext, $question->questiontextformat); 00656 $expout .= '{' . $this->repchar($answertext); 00657 if ($wrongfeedback) { 00658 $expout .= '#' . $wrongfeedback; 00659 } else if ($rightfeedback) { 00660 $expout .= '#'; 00661 } 00662 if ($rightfeedback) { 00663 $expout .= '#' . $rightfeedback; 00664 } 00665 $expout .= "}\n"; 00666 break; 00667 00668 case MULTICHOICE: 00669 $expout .= $this->write_name($question->name); 00670 $expout .= $this->write_questiontext($question->questiontext, $question->questiontextformat); 00671 $expout .= "{\n"; 00672 foreach($question->options->answers as $answer) { 00673 if ($answer->fraction == 1) { 00674 $answertext = '='; 00675 } else if ($answer->fraction == 0) { 00676 $answertext = '~'; 00677 } else { 00678 $weight = $answer->fraction * 100; 00679 $answertext = '~%' . $weight . '%'; 00680 } 00681 $expout .= "\t" . $answertext . $this->write_questiontext($answer->answer, 00682 $answer->answerformat, $question->questiontextformat); 00683 if ($answer->feedback != '') { 00684 $expout .= '#' . $this->write_questiontext($answer->feedback, 00685 $answer->feedbackformat, $question->questiontextformat); 00686 } 00687 $expout .= "\n"; 00688 } 00689 $expout .= "}\n"; 00690 break; 00691 00692 case SHORTANSWER: 00693 $expout .= $this->write_name($question->name); 00694 $expout .= $this->write_questiontext($question->questiontext, $question->questiontextformat); 00695 $expout .= "{\n"; 00696 foreach($question->options->answers as $answer) { 00697 $weight = 100 * $answer->fraction; 00698 $expout .= "\t=%" . $weight . '%' . $this->repchar($answer->answer) . 00699 '#' . $this->write_questiontext($answer->feedback, 00700 $answer->feedbackformat, $question->questiontextformat) . "\n"; 00701 } 00702 $expout .= "}\n"; 00703 break; 00704 00705 case NUMERICAL: 00706 $expout .= $this->write_name($question->name); 00707 $expout .= $this->write_questiontext($question->questiontext, $question->questiontextformat); 00708 $expout .= "{#\n"; 00709 foreach ($question->options->answers as $answer) { 00710 if ($answer->answer != '' && $answer->answer != '*') { 00711 $weight = 100 * $answer->fraction; 00712 $expout .= "\t=%" . $weight . '%' . $answer->answer . ':' . 00713 (float)$answer->tolerance . '#' . $this->write_questiontext($answer->feedback, 00714 $answer->feedbackformat, $question->questiontextformat) . "\n"; 00715 } else { 00716 $expout .= "\t~#" . $this->write_questiontext($answer->feedback, 00717 $answer->feedbackformat, $question->questiontextformat) . "\n"; 00718 } 00719 } 00720 $expout .= "}\n"; 00721 break; 00722 00723 case MATCH: 00724 $expout .= $this->write_name($question->name); 00725 $expout .= $this->write_questiontext($question->questiontext, $question->questiontextformat); 00726 $expout .= "{\n"; 00727 foreach($question->options->subquestions as $subquestion) { 00728 $expout .= "\t=" . $this->write_questiontext($subquestion->questiontext, 00729 $subquestion->questiontextformat, $question->questiontextformat) . 00730 ' -> ' . $this->repchar($subquestion->answertext) . "\n"; 00731 } 00732 $expout .= "}\n"; 00733 break; 00734 00735 default: 00736 // Check for plugins 00737 if ($out = $this->try_exporting_using_qtypes($question->qtype, $question)) { 00738 $expout .= $out; 00739 } else { 00740 $expout .= "Question type $question->qtype is not supported\n"; 00741 echo $OUTPUT->notification(get_string('nohandler', 'qformat_gift', 00742 question_bank::get_qtype_name($question->qtype))); 00743 } 00744 } 00745 00746 // Add empty line to delimit questions 00747 $expout .= "\n"; 00748 return $expout; 00749 } 00750 }