1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
|
<?PHP // $Id: questiontype.php,v 1.2 2004/07/21 13:01:06 moodler Exp $
/////////////////////
/// RANDOMSAMATCH ///
/////////////////////
/// The use of this question type together with the
/// question type RANDOM within the same quiz can cause
/// a shortanswer question to appear in a RANDOM question
/// as well as one of the matcher questions in a question of this type
/// QUESTION TYPE CLASS //////////////////
class quiz_randomsamatch_qtype extends quiz_match_qtype {
/// Extends MATCH as there are quite a few simularities...
// $catrandoms carries question ids for shortanswer questions
// available as random questios.
// They are sorted by category.
var $catrandoms = array();
function name() {
return 'randomsamatch';
}
function save_question_options($question) {
$options->question = $question->id;
$options->choose = $question->choose;
if ($existing = get_record("quiz_randomsamatch",
"question", $options->question)) {
$options->id = $existing->id;
if (!update_record("quiz_randomsamatch", $options)) {
$result->error = "Could not update quiz randomsamatch options!";
return $result;
}
} else {
if (!insert_record("quiz_randomsamatch", $options)) {
$result->error = "Could not insert quiz randomsamatch options!";
return $result;
}
}
return true;
}
function wrapped_questions($question) {
if (empty($question->response)) {
return false;
} else {
$wrapped = '';
$delimiter = '';
foreach ($question->response as $rkey => $response) {
$wrapped .= $delimiter.$this->extract_response_id($rkey);
$delimiter = ',';
}
return $wrapped;
}
}
function create_response($question, $nameprefix, $questionsinuse) {
// It's for question types like RANDOMSAMATCH and RANDOM that
// the true power of the pattern with this function comes to the surface.
// This implementation will stand even after a possible exclusion of
// the funtions extract_response and convert_to_response_answer_field
if (!isset($this->catrandoms[$question->category])) {
/// Need to fetch the shortanswer question ids for the category:
$saquestions = get_records_select('quiz_questions',
" category='$question->category'
AND qtype='".SHORTANSWER."'
AND id NOT IN ($questionsinuse) ");
$this->catrandoms[$question->category] = array_keys($saquestions);
shuffle($this->catrandoms[$question->category]);
}
/// Access question options to find out how many short-answer
/// questions we are supposed to pick...
if ($options = get_record('quiz_randomsamatch',
'question', $question->id)) {
$questionstopick = $options->choose;
} else {
notify("Error: Missing question options! - Try to pick two shortanswer questions anyway");
$questionstopick = 2;
}
/// Pick the short-answer question ids and create the $response array
$response = array();
while ($questionstopick) {
$said = array_pop($this->catrandoms[$question->category]);
if (!ereg("(^|,)$said(,|$)", $questionsinuse)) {
$response[$nameprefix.$said] = '0';
--$questionstopick;
}
}
if ($questionstopick) {
notify("Error: could not get enough Short-Answer questions!");
$count = count($response);
$wanted = $count + $questionstopick;
notify("Got $count Short-Answer questions, but wanted $wanted.");
}
return $response;
}
function extract_response($rawresponse, $nameprefix) {
/// Simple implementation that does not check with the database
/// and thus - does not bother to check whether there has been
/// any changes to the question options.
$response = array();
$rawitems = explode(',', $rawresponse->answer);
foreach ($rawitems as $rawitem) {
$splits = explode('-', $rawitem, 2);
$response[$nameprefix.$splits[0]] = $splits[1];
}
return $response;
}
function print_question_formulation_and_controls($question,
$quiz, $readonly, $answers, $correctanswers, $nameprefix) {
// Print question formulation
echo format_text($question->questiontext,
$question->questiontextformat, NULL, $quiz->course);
quiz_print_possible_question_image($quiz->id, $question);
// Summarize shortanswer questions answer alternatives:
if (empty($correctanswers)) {
// Get them using the grade_response method
$tempresult = $this->grade_response($question, $nameprefix);
$saanswers = $tempresult->correctanswers;
} else {
$saanswers = $correctanswers;
}
foreach ($saanswers as $key => $saanswer) {
unset($saanswers[$key]); // Unsets the nameprefix occurence
$saanswers[$saanswer->id] = trim($saanswer->answer);
}
$saanswers = draw_rand_array($saanswers, count($saanswers));
// Print the shortanswer questions and input controls:
echo '<table border="0" cellpadding="10">';
foreach ($question->response as $inputname => $response) {
if (!($saquestion = get_record('quiz_questions', 'id',
quiz_extract_posted_id($inputname, $nameprefix)))) {
notify("Error: cannot find shortanswer question for $inputname ");
continue;
}
echo '<tr><td align="left" valign="top">';
echo $saquestion->questiontext;
echo '</td>';
echo '<td align="right" valign="top">';
if (!empty($correctanswers)
&& $correctanswers[$inputname]->id == $response) {
echo '<span="highlight">';
choose_from_menu($saanswers, $inputname, $response);
echo '</span><br />';
} else {
choose_from_menu($saanswers, $inputname, $response);
if ($readonly && $quiz->correctanswers
&& isset($correctanswer[$inputname])) {
quiz_print_correctanswer($correctanswer[$inputname]->answer);
}
}
if ($quiz->feedback && isset($answers[$inputname])
&& $answers[$inputname]->feedback) {
quiz_print_comment($answers[$inputname]->feedback);
}
echo '</td></tr>';
}
echo '</table>';
}
function grade_response($question, $nameprefix) {
global $QUIZ_QTYPES;
$result->answers = array();
$result->correctanswers = array();
$result->grade = 0.0;
foreach ($question->response as $inputname => $subresponse) {
if ($subquestion = get_record('quiz_questions',
'id', quiz_extract_posted_id($inputname, $nameprefix),
// These two query conditions are security checks that prevents cheating...
'qtype', SHORTANSWER,
'category', $question->category)) {
if ($subresponse = get_record('quiz_answers',
'id', $subresponse)) {
$subquestion->response[$inputname] = $subresponse->answer;
} else {
$subquestion->response[$inputname] = '';
}
// Use the shortanswer framework to for grading...
$subresult = $QUIZ_QTYPES[SHORTANSWER]
->grade_response($subquestion, $inputname);
// Summarize shortanswer results
if (isset($subresult->answers[$inputname])) {
$result->answers[$inputname] =
$subresult->answers[$inputname];
$result->grade += $result->answers[$inputname]->fraction;
if ($result->answers[$inputname]->fraction >= 1.0) {
$result->correctanswers[$inputname] =
$result->answers[$inputname];
continue;
}
}
// Pick the first correctanswer:
foreach ($subresult->correctanswers as $correct) {
$result->correctanswers[$inputname] = $correct;
break;
}
}
}
if ($result->grade) {
$result->grade /= count($question->response);
}
return $result;
}
}
//// END OF CLASS ////
//////////////////////////////////////////////////////////////////////////
//// INITIATION - Without this line the question type is not in use... ///
//////////////////////////////////////////////////////////////////////////
$QUIZ_QTYPES[RANDOMSAMATCH]= new quiz_randomsamatch_qtype();
?>
|