📄 questiontype.php
字号:
if ($question) { if ($in_first) { $sequence_field .= $question->new_id; $in_first = false; } else { $sequence_field .= ",".$question->new_id; } } //check for next $tok = strtok(","); } //We have the answers field recoded to its new ids $multianswer->sequence = $sequence_field; //The structure is equal to the db, so insert the question_multianswer $newid = insert_record("question_multianswer", $multianswer); //Save ids in backup_ids if ($newid) { backup_putid($restore->backup_unique_code,"question_multianswer", $oldid, $newid); } //Do some output if (($i+1) % 50 == 0) { if (!defined('RESTORE_SILENTLY')) { echo "."; if (($i+1) % 1000 == 0) { echo "<br />"; } } backup_flush(300); } } return $status; } function restore_map($old_question_id,$new_question_id,$info,$restore) { $status = true; //Get the multianswers array $multianswers = $info['#']['MULTIANSWERS']['0']['#']['MULTIANSWER']; //Iterate over multianswers for($i = 0; $i < sizeof($multianswers); $i++) { $mul_info = $multianswers[$i]; //We need this later $oldid = backup_todb($mul_info['#']['ID']['0']['#']); //Now, build the question_multianswer record structure $multianswer->question = $new_question_id; $multianswer->answers = backup_todb($mul_info['#']['ANSWERS']['0']['#']); $multianswer->positionkey = backup_todb($mul_info['#']['POSITIONKEY']['0']['#']); $multianswer->answertype = backup_todb($mul_info['#']['ANSWERTYPE']['0']['#']); $multianswer->norm = backup_todb($mul_info['#']['NORM']['0']['#']); //If we are in this method is because the question exists in DB, so its //multianswer must exist too. //Now, we are going to look for that multianswer in DB and to create the //mappings in backup_ids to use them later where restoring states (user level). //Get the multianswer from DB (by question and positionkey) $db_multianswer = get_record ("question_multianswer","question",$new_question_id, "positionkey",$multianswer->positionkey); //Do some output if (($i+1) % 50 == 0) { if (!defined('RESTORE_SILENTLY')) { echo "."; if (($i+1) % 1000 == 0) { echo "<br />"; } } backup_flush(300); } //We have the database multianswer, so update backup_ids if ($db_multianswer) { //We have the newid, update backup_ids backup_putid($restore->backup_unique_code,"question_multianswer",$oldid, $db_multianswer->id); } else { $status = false; } } return $status; } function restore_recode_answer($state, $restore) { //The answer is a comma separated list of hypen separated sequence number and answers. We may have to recode the answers $answer_field = ""; $in_first = true; $tok = strtok($state->answer,","); while ($tok) { //Extract the multianswer_id and the answer $exploded = explode("-",$tok); $seqnum = $exploded[0]; $answer = $exploded[1]; // $sequence is an ordered array of the question ids. if (!$sequence = get_field('question_multianswer', 'sequence', 'question', $state->question)) { print_error('missingoption', 'question', '', $state->question); } $sequence = explode(',', $sequence); // The id of the current question. $wrappedquestionid = $sequence[$seqnum-1]; // now we can find the question if (!$wrappedquestion = get_record('question', 'id', $wrappedquestionid)) { notify("Can't find the subquestion $wrappedquestionid that is used as part $seqnum in cloze question $state->question"); } // For multichoice question we need to recode the answer if ($answer and $wrappedquestion->qtype == 'multichoice') { //The answer is an answer_id, look for it in backup_ids if (!$ans = backup_getid($restore->backup_unique_code,"question_answers",$answer)) { echo 'Could not recode cloze multichoice answer '.$answer.'<br />'; } $answer = $ans->new_id; } //build the new answer field for each pair if ($in_first) { $answer_field .= $seqnum."-".$answer; $in_first = false; } else { $answer_field .= ",".$seqnum."-".$answer; } //check for next $tok = strtok(","); } return $answer_field; } /** * Runs all the code required to set up and save an essay question for testing purposes. * Alternate DB table prefix may be used to facilitate data deletion. */ function generate_test($name, $courseid = null) { list($form, $question) = parent::generate_test($name, $courseid); $question->category = $form->category; $form->questiontext = "This question consists of some text with an answer embedded right here {1:MULTICHOICE:Wrong answer#Feedback for this wrong answer~Another wrong answer#Feedback for the other wrong answer~=Correct answer#Feedback for correct answer~%50%Answer that gives half the credit#Feedback for half credit answer} and right after that you will have to deal with this short answer {1:SHORTANSWER:Wrong answer#Feedback for this wrong answer~=Correct answer#Feedback for correct answer~%50%Answer that gives half the credit#Feedback for half credit answer} and finally we have a floating point number {2:NUMERICAL:=23.8:0.1#Feedback for correct answer 23.8~%50%23.8:2#Feedback for half credit answer in the nearby region of the correct answer}.Note that addresses like www.moodle.org and smileys :-) all work as normal: a) How good is this? {:MULTICHOICE:=Yes#Correct~No#We have a different opinion} b) What grade would you give it? {3:NUMERICAL:=3:2}Good luck!"; $form->feedback = "feedback"; $form->generalfeedback = "General feedback"; $form->fraction = 0; $form->penalty = 0.1; $form->versioning = 0; if ($courseid) { $course = get_record('course', 'id', $courseid); } return $this->save_question($question, $form, $course); }}//// END OF CLASS ////////////////////////////////////////////////////////////////////////////////// INITIATION - Without this line the question type is not in use... /////////////////////////////////////////////////////////////////////////////question_register_questiontype(new embedded_cloze_qtype());///////////////////////////////////////////////////////////////// ADDITIONAL FUNCTIONS//// The functions below deal exclusivly with editing//// of questions with question type 'multianswer'.//// Therefore they are kept in this file.//// They are not in the class as they are not//// likely to be subject for overriding./////////////////////////////////////////////////////////////// ANSWER_ALTERNATIVE regexesdefine("ANSWER_ALTERNATIVE_FRACTION_REGEX", '=|%(-?[0-9]+)%');// for the syntax '(?<!' see http://www.perl.com/doc/manual/html/pod/perlre.html#item_Cdefine("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_REGEXdefine("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_ANSWERdefine("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_REGEXdefine("NUMERICAL_CORRECT_ANSWER", 1);define("NUMERICAL_ABS_ERROR_MARGIN", 6);// Remaining ANSWER regexesdefine("ANSWER_TYPE_DEF_REGEX", '(NUMERICAL|NM)|(MULTICHOICE|MC)|(MULTICHOICE_V|MCV)|(MULTICHOICE_H|MCH)|(SHORTANSWER|SA|MW)|(SHORTANSWER_C|SAC|MWC)');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_REGEXdefine("ANSWER_REGEX_NORM", 1);define("ANSWER_REGEX_ANSWER_TYPE_NUMERICAL", 3);define("ANSWER_REGEX_ANSWER_TYPE_MULTICHOICE", 4);define("ANSWER_REGEX_ANSWER_TYPE_MULTICHOICE_REGULAR", 5);define("ANSWER_REGEX_ANSWER_TYPE_MULTICHOICE_HORIZONTAL", 6);define("ANSWER_REGEX_ANSWER_TYPE_SHORTANSWER", 7);define("ANSWER_REGEX_ANSWER_TYPE_SHORTANSWER_C", 8);define("ANSWER_REGEX_ALTERNATIVES", 9);function qtype_multianswer_extract_question($text) { $question = new stdClass; $question->qtype = 'multianswer'; $question->questiontext = $text; $question->options->questions = array(); $question->defaultgrade = 0; // Will be increased for each answer norm for ($positionkey=1 ; preg_match('/'.ANSWER_REGEX.'/', $question->questiontext, $answerregs) ; ++$positionkey ) { $wrapped = new stdClass; $wrapped->defaultgrade = $answerregs[ANSWER_REGEX_NORM] or $wrapped->defaultgrade = '1'; if (!empty($answerregs[ANSWER_REGEX_ANSWER_TYPE_NUMERICAL])) { $wrapped->qtype = 'numerical'; $wrapped->multiplier = array(); $wrapped->units = array(); } else if(!empty($answerregs[ANSWER_REGEX_ANSWER_TYPE_SHORTANSWER])) { $wrapped->qtype = 'shortanswer'; $wrapped->usecase = 0; } else if(!empty($answerregs[ANSWER_REGEX_ANSWER_TYPE_SHORTANSWER_C])) { $wrapped->qtype = 'shortanswer'; $wrapped->usecase = 1; } else if(!empty($answerregs[ANSWER_REGEX_ANSWER_TYPE_MULTICHOICE])) { $wrapped->qtype = 'multichoice'; $wrapped->single = 1; $wrapped->answernumbering = 0; $wrapped->correctfeedback = ''; $wrapped->partiallycorrectfeedback = ''; $wrapped->incorrectfeedback = ''; $wrapped->layout = 0; } else if(!empty($answerregs[ANSWER_REGEX_ANSWER_TYPE_MULTICHOICE_REGULAR])) { $wrapped->qtype = 'multichoice'; $wrapped->single = 1; $wrapped->answernumbering = 0; $wrapped->correctfeedback = ''; $wrapped->partiallycorrectfeedback = ''; $wrapped->incorrectfeedback = ''; $wrapped->layout = 1; } else if(!empty($answerregs[ANSWER_REGEX_ANSWER_TYPE_MULTICHOICE_HORIZONTAL])) { $wrapped->qtype = 'multichoice'; $wrapped->single = 1; $wrapped->answernumbering = 0; $wrapped->correctfeedback = ''; $wrapped->partiallycorrectfeedback = ''; $wrapped->incorrectfeedback = ''; $wrapped->layout = 2; } else { print_error('unknownquestiontype', 'question', '', $answerregs[2]); return false; } // Each $wrapped simulates a $form that can be processed by the // respective save_question and save_question_options methods of the // wrapped questiontypes $wrapped->answer = array(); $wrapped->fraction = array(); $wrapped->feedback = array(); $wrapped->shuffleanswers = 1; $wrapped->questiontext = $answerregs[0]; $wrapped->questiontextformat = 0; $remainingalts = $answerregs[ANSWER_REGEX_ALTERNATIVES]; while (preg_match('/~?'.ANSWER_ALTERNATIVE_REGEX.'/', $remainingalts, $altregs)) { if ('=' == $altregs[ANSWER_ALTERNATIVE_REGEX_FRACTION]) { $wrapped->fraction[] = '1'; } else if ($percentile = $altregs[ANSWER_ALTERNATIVE_REGEX_PERCENTILE_FRACTION]){ $wrapped->fraction[] = .01 * $percentile; } else { $wrapped->fraction[] = '0'; } if (isset($altregs[ANSWER_ALTERNATIVE_REGEX_FEEDBACK])) { $feedback = html_entity_decode($altregs[ANSWER_ALTERNATIVE_REGEX_FEEDBACK], ENT_QUOTES, 'UTF-8'); $feedback = str_replace('\}', '}', $feedback); $wrapped->feedback[] = str_replace('\#', '#', $feedback); } else { $wrapped->feedback[] = ''; } if (!empty($answerregs[ANSWER_REGEX_ANSWER_TYPE_NUMERICAL]) && ereg(NUMERICAL_ALTERNATIVE_REGEX, $altregs[ANSWER_ALTERNATIVE_REGEX_ANSWER], $numregs)) { $wrapped->answer[] = $numregs[NUMERICAL_CORRECT_ANSWER]; if ($numregs[NUMERICAL_ABS_ERROR_MARGIN]) { $wrapped->tolerance[] = $numregs[NUMERICAL_ABS_ERROR_MARGIN]; } else { $wrapped->tolerance[] = 0; } } else { // Tolerance can stay undefined for non numerical questions // Undo quoting done by the HTML editor. $answer = html_entity_decode($altregs[ANSWER_ALTERNATIVE_REGEX_ANSWER], ENT_QUOTES, 'UTF-8'); $answer = str_replace('\}', '}', $answer); $wrapped->answer[] = str_replace('\#', '#', $answer); } $tmp = explode($altregs[0], $remainingalts, 2); $remainingalts = $tmp[1]; } $question->defaultgrade += $wrapped->defaultgrade; $question->options->questions[$positionkey] = clone($wrapped); $question->questiontext = implode("{#$positionkey}", explode($answerregs[0], $question->questiontext, 2)); } $question->questiontext = $question->questiontext; return $question;}?>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -