From: moodler Date: Sun, 30 Mar 2003 16:46:50 +0000 (+0000) Subject: First cut at adding new "fixed" Match question type, which is manually X-Git-Url: http://git.mjollnir.org/gw?a=commitdiff_plain;h=54a67a59218c7c5242a1398e5f3d08f23c9974d2;p=moodle.git First cut at adding new "fixed" Match question type, which is manually created. Works OK after limited testing. I've also renamed some strings to do with "Random Match", so that this question type is now called "Random Short-Answer Match". Later there will be a new 'Random Match' which randomly selects one of the existing "Match" questions. --- diff --git a/lang/en/help/quiz/match.html b/lang/en/help/quiz/match.html new file mode 100644 index 0000000000..3a016d7689 --- /dev/null +++ b/lang/en/help/quiz/match.html @@ -0,0 +1,11 @@ +

Matching questions

+ +

After an optional introduction, the respondent is presented with + several sub-questions and several jumbled answers. There is one + correct answer for each question. + +

The respondent must select an answer to match each sub-question. + +

Each sub-question is equally weighted to contibute towards the + grade for the total question. + diff --git a/lang/en/help/quiz/randommatch.html b/lang/en/help/quiz/randomsamatch.html similarity index 89% rename from lang/en/help/quiz/randommatch.html rename to lang/en/help/quiz/randomsamatch.html index 9009e81198..31c10eb516 100644 --- a/lang/en/help/quiz/randommatch.html +++ b/lang/en/help/quiz/randomsamatch.html @@ -1,4 +1,4 @@ -

Random Matching questions

+

Random Short-Answer Matching questions

After an optional introduction, the respondent is presented with several sub-questions and several jumbled answers. There is one diff --git a/lang/en/quiz.php b/lang/en/quiz.php index cd516aced7..14bb344e5e 100644 --- a/lang/en/quiz.php +++ b/lang/en/quiz.php @@ -42,16 +42,18 @@ $string['default'] = "Default"; $string['defaultinfo'] = "The default category for questions."; $string['deletequestioncheck'] = "Are you absolutely sure you want to delete '\$a'?"; $string['editcategories'] = "Edit categories"; +$string['editingmatch'] = "Editing a matching question"; +$string['editingmultichoice'] = "Editing a multiple choice question"; $string['editingquiz'] = "Editing quiz"; $string['editingquestion'] = "Editing a question"; +$string['editingrandomsamatch'] = "Editing a random short-answer matching question"; $string['editingshortanswer'] = "Editing a short answer question"; $string['editingtruefalse'] = "Editing a true/false question"; -$string['editingmultichoice'] = "Editing a multiple choice question"; -$string['editingrandommatch'] = "Editing a random matching question"; $string['false'] = "False"; $string['feedback'] = "Feedback"; $string['filloutoneanswer'] = "You must fill out at least one possible answer. Answers left blank will not be used."; $string['fillouttwochoices'] = "You must fill out at least two choices. Choices left blank will not be used."; +$string['filloutthreequestions'] = "You must fill out at least three questions. Questions left blank will not be used."; $string['fileformat'] = "File format"; $string['fractionsaddwrong'] = "The positive grades you have chosen do not add up to 100%%
Instead, they add up to \$a%% @@ -67,6 +69,8 @@ $string['imagedisplay'] = "Image to display"; $string['importquestions'] = "Import questions from file"; $string['introduction'] = "Introduction"; $string['marks'] = "Marks"; +$string['match'] = "Matching"; +$string['matchanswer'] = "Matching answer"; $string['missingname'] = "Missing question name"; $string['missingquestiontext'] = "Missing question text"; $string['missingword'] = "Missing word format"; @@ -77,6 +81,8 @@ $string['nomoreattempts'] = "No more attempts are allowed"; $string['noquestions'] = "No questions have been added yet"; $string['noreview'] = "You are not allowed to review this quiz"; $string['noreviewuntil'] = "You are not allowed to review this quiz until \$a"; +$string['notenoughsubquestions'] = "Not enough sub-questions have been defined!
+Do you want to go back and fix this question?"; $string['publish'] = "Publish"; $string['qti'] = "IMS QTI format"; $string['question'] = "Question"; @@ -89,10 +95,10 @@ $string['quizclosed'] = "This quiz closed on \$a"; $string['quizopen'] = "Open the quiz"; $string['quiznotavailable'] = "The quiz will not be available until: \$a"; $string['random'] = "Random set"; -$string['randommatch'] = "Random Match"; -$string['randommatchcreate'] = "Create Random Match questions"; -$string['randommatchintro'] = "For each of the following questions, select the matching answer from the menu."; -$string['randommatchnumber'] = "Number of questions to select"; +$string['randomsamatch'] = "Random Short-Answer Matching"; +$string['randomsamatchcreate'] = "Create Random Short-Answer Matching questions"; +$string['randomsamatchintro'] = "For each of the following questions, select the matching answer from the menu."; +$string['randomsamatchnumber'] = "Number of questions to select"; $string['readytosend'] = "You are about to send your whole quiz to be graded. Are you sure you want to continue?"; $string['regrade'] = "Regrade all attempts"; $string['regradecomplete'] = "All attempts have been regraded"; diff --git a/mod/quiz/db/mysql.php b/mod/quiz/db/mysql.php index 6073f8be5e..b73b912de1 100644 --- a/mod/quiz/db/mysql.php +++ b/mod/quiz/db/mysql.php @@ -66,6 +66,26 @@ function quiz_upgrade($oldversion) { execute_sql(" ALTER TABLE `{$CFG->prefix}quiz_responses` ADD INDEX(question) "); } + if ($oldversion < 2003033100) { + modify_database ("", "ALTER TABLE prefix_quiz_randommatch RENAME prefix_quiz_randomsamatch "); + modify_database ("", "CREATE TABLE `prefix_quiz_match` ( + `id` int(10) unsigned NOT NULL auto_increment, + `question` int(10) unsigned NOT NULL default '0', + `subquestions` varchar(255) NOT NULL default '', + PRIMARY KEY (`id`), + KEY `question` (`question`) + );"); + + modify_database ("", "CREATE TABLE `prefix_quiz_match_sub` ( + `id` int(10) unsigned NOT NULL auto_increment, + `question` int(10) unsigned NOT NULL default '0', + `questiontext` text NOT NULL, + `answertext` varchar(255) NOT NULL default '', + PRIMARY KEY (`id`), + KEY `question` (`question`) + );"); + } + return true; } diff --git a/mod/quiz/db/mysql.sql b/mod/quiz/db/mysql.sql index ca2e7dd7e0..90030d04c0 100644 --- a/mod/quiz/db/mysql.sql +++ b/mod/quiz/db/mysql.sql @@ -98,6 +98,33 @@ CREATE TABLE `prefix_quiz_grades` ( ) TYPE=MyISAM COMMENT='Final quiz grade (may be best of several attempts)'; # -------------------------------------------------------- +# +# Table structure for table `quiz_match` +# + +CREATE TABLE `prefix_quiz_match` ( + `id` int(10) unsigned NOT NULL auto_increment, + `question` int(10) unsigned NOT NULL default '0', + `subquestions` varchar(255) NOT NULL default '', + PRIMARY KEY (`id`), + KEY `question` (`question`) +) TYPE=MyISAM COMMENT='Defines fixed matching questions'; +# -------------------------------------------------------- + +# +# Table structure for table `quiz_match_sub` +# + +CREATE TABLE `prefix_quiz_match_sub` ( + `id` int(10) unsigned NOT NULL auto_increment, + `question` int(10) unsigned NOT NULL default '0', + `questiontext` text NOT NULL, + `answertext` varchar(255) NOT NULL default '', + PRIMARY KEY (`id`), + KEY `question` (`question`) +) TYPE=MyISAM COMMENT='Defines the subquestions that make up a matching question'; +# -------------------------------------------------------- + # # Table structure for table `quiz_multichoice` # @@ -128,18 +155,6 @@ CREATE TABLE `prefix_quiz_question_grades` ( ) TYPE=MyISAM COMMENT='The grade for a question in a quiz'; # -------------------------------------------------------- -# -# Table structure for table `quiz_randommatch` -# - -CREATE TABLE `prefix_quiz_randommatch` ( - `id` int(10) unsigned NOT NULL auto_increment, - `question` int(10) unsigned NOT NULL default '0', - `choose` INT UNSIGNED DEFAULT '4' NOT NULL, - PRIMARY KEY ( `id` ), - KEY `question` (`question`) -) TYPE=MyISAM COMMENT='Info about a random matching question'; - # # Table structure for table `quiz_questions` # @@ -156,6 +171,19 @@ CREATE TABLE `prefix_quiz_questions` ( ) TYPE=MyISAM COMMENT='The quiz questions themselves'; # -------------------------------------------------------- +# +# Table structure for table `quiz_randomsamatch` +# + +CREATE TABLE `prefix_quiz_randomsamatch` ( + `id` int(10) unsigned NOT NULL auto_increment, + `question` int(10) unsigned NOT NULL default '0', + `choose` INT UNSIGNED DEFAULT '4' NOT NULL, + PRIMARY KEY ( `id` ), + KEY `question` (`question`) +) TYPE=MyISAM COMMENT='Info about a random short-answer matching question'; +# -------------------------------------------------------- + # # Table structure for table `quiz_responses` # diff --git a/mod/quiz/db/postgres7.php b/mod/quiz/db/postgres7.php index 7a0bafd265..eac41b021b 100644 --- a/mod/quiz/db/postgres7.php +++ b/mod/quiz/db/postgres7.php @@ -27,6 +27,26 @@ function quiz_upgrade($oldversion) { table_column("quiz_questions", "", "defaultgrade", "INTEGER", "6", "UNSIGNED", "1", "NOT NULL", "image"); } + if ($oldversion < 2003033100) { + modify_database ("", "ALTER TABLE prefix_quiz_randommatch RENAME prefix_quiz_randomsamatch "); + modify_database ("", "CREATE TABLE `prefix_quiz_match_sub` ( + id SERIAL PRIMARY KEY, + question integer NOT NULL default '0', + questiontext text NOT NULL default '', + answertext varchar(255) NOT NULL default '' + );"); + modify_database ("", "CREATE INDEX question_prefix_quiz_match_sub_idx ON prefix_quiz_match_sub (question);"); + + modify_database ("", "CREATE TABLE prefix_quiz_multichoice ( + id SERIAL PRIMARY KEY, + question integer NOT NULL default '0', + layout integer NOT NULL default '0', + answers varchar(255) NOT NULL default '', + single integer NOT NULL default '0' + );"); + modify_database ("", "CREATE INDEX question_quiz_multichoice_idx ON prefix_quiz_multichoice (question);"); + } + return true; } diff --git a/mod/quiz/db/postgres7.sql b/mod/quiz/db/postgres7.sql index 7d49ec4a5e..e6fd3d8641 100644 --- a/mod/quiz/db/postgres7.sql +++ b/mod/quiz/db/postgres7.sql @@ -88,6 +88,31 @@ CREATE TABLE prefix_quiz_grades ( ); # -------------------------------------------------------- +# +# Table structure for table quiz_match +# + +CREATE TABLE prefix_quiz_match ( + id SERIAL PRIMARY KEY, + question integer NOT NULL default '0', + subquestions varchar(255) NOT NULL default '' +); +# -------------------------------------------------------- +CREATE INDEX question_prefix_quiz_match_idx ON prefix_quiz_match (question); + +# +# Table structure for table `quiz_match_sub` +# + +CREATE TABLE `prefix_quiz_match_sub` ( + id SERIAL PRIMARY KEY, + question integer NOT NULL default '0', + questiontext text NOT NULL default '', + answertext varchar(255) NOT NULL default '' +); +# -------------------------------------------------------- +CREATE INDEX question_prefix_quiz_match_sub_idx ON prefix_quiz_match_sub (question); + # # Table structure for table quiz_multichoice # @@ -130,10 +155,10 @@ CREATE TABLE prefix_quiz_questions ( # -------------------------------------------------------- # -# Table structure for table quiz_randommatch +# Table structure for table quiz_randomsamatch # -CREATE TABLE prefix_quiz_randommatch ( +CREATE TABLE prefix_quiz_randomsamatch ( id SERIAL PRIMARY KEY, question integer NOT NULL default '0', choose integer NOT NULL default '4', diff --git a/mod/quiz/import.php b/mod/quiz/import.php index f2eb618328..d565586d4d 100644 --- a/mod/quiz/import.php +++ b/mod/quiz/import.php @@ -88,15 +88,15 @@ $rm->choose = 4; /// Always 4, for now. $rm->category = $category->id; - $rm->questiontext = get_string("randommatchintro", "quiz"); + $rm->questiontext = get_string("randomsamatchintro", "quiz"); $rm->image = ""; - $rm->qtype = RANDOMMATCH; + $rm->qtype = RANDOMSAMATCH; $rm->defaultgrade = $rm->choose; echo "


"; for ($i=1; $i<=$form->createrandom; $i++) { - $rm->name = get_string("randommatch", "quiz") . " $i ($rm->choose $strquestions)"; + $rm->name = get_string("randomsamatch", "quiz") . " $i ($rm->choose $strquestions)"; $db->debug = true; if (!$rm->id = insert_record("quiz_questions", $rm)) { @@ -145,7 +145,7 @@ choose_from_menu($QUIZ_FILE_FORMAT, "format", "missingword", ""); helpbutton("import", $strimportquestions, "quiz"); echo ""; - print_string("randommatchcreate", "quiz"); + print_string("randomsamatchcreate", "quiz"); echo ":"; for ($i=0;$i<=100;$i++) { $menu[$i] = $i; diff --git a/mod/quiz/lib.php b/mod/quiz/lib.php index 87f6565e85..590a103206 100644 --- a/mod/quiz/lib.php +++ b/mod/quiz/lib.php @@ -13,17 +13,18 @@ $QUIZ_GRADE_METHOD = array ( GRADEHIGHEST => get_string("gradehighest", "quiz"), ATTEMPTFIRST => get_string("attemptfirst", "quiz"), ATTEMPTLAST => get_string("attemptlast", "quiz")); -define("SHORTANSWER", "1"); -define("TRUEFALSE", "2"); -define("MULTICHOICE", "3"); -define("RANDOM", "4"); -define("MATCH", "5"); -define("RANDOMMATCH", "6"); - -$QUIZ_QUESTION_TYPE = array ( MULTICHOICE => get_string("multichoice", "quiz"), - TRUEFALSE => get_string("truefalse", "quiz"), - SHORTANSWER => get_string("shortanswer", "quiz"), - RANDOMMATCH => get_string("randommatch", "quiz") ); +define("SHORTANSWER", "1"); +define("TRUEFALSE", "2"); +define("MULTICHOICE", "3"); +define("RANDOM", "4"); +define("MATCH", "5"); +define("RANDOMSAMATCH", "6"); + +$QUIZ_QUESTION_TYPE = array ( MULTICHOICE => get_string("multichoice", "quiz"), + TRUEFALSE => get_string("truefalse", "quiz"), + SHORTANSWER => get_string("shortanswer", "quiz"), + MATCH => get_string("match", "quiz"), + RANDOMSAMATCH => get_string("randomsamatch", "quiz") ); $QUIZ_FILE_FORMAT = array ( "custom" => get_string("custom", "quiz"), "webct" => get_string("webct", "quiz"), @@ -32,6 +33,8 @@ $QUIZ_FILE_FORMAT = array ( "custom" => get_string("custom", "quiz"), define("QUIZ_PICTURE_DEFAULT_HEIGHT", "200"); +define("QUIZ_MAX_NUMBER_ANSWERS", "8"); + /// FUNCTIONS /////////////////////////////////////////////////////////////////// function quiz_add_instance($quiz) { @@ -283,7 +286,15 @@ function quiz_get_answers($question) { return false; // Not done yet break; - case RANDOMMATCH: // Could be any of many answers, return them all + case MATCH: + return get_records_sql("SELECT ms.*, g.grade + FROM {$CFG->prefix}quiz_match_sub ms, + {$CFG->prefix}quiz_question_grades g + WHERE ms.question = '$question->id' + AND ms.question = g.question"); + break; + + case RANDOMSAMATCH: // Could be any of many answers, return them all return get_records_sql("SELECT a.*, g.grade FROM {$CFG->prefix}quiz_questions q, {$CFG->prefix}quiz_answers a, @@ -360,7 +371,10 @@ function quiz_print_question_icon($question) { case RANDOM: echo ""; break; - case RANDOMMATCH: + case MATCH: + echo ""; + break; + case RANDOMSAMATCH: echo ""; break; } @@ -368,7 +382,7 @@ function quiz_print_question_icon($question) { } function quiz_print_question($number, $questionid, $grade, $courseid, - $feedback=NULL, $response=NULL, $actualgrade=NULL, $correct=NULL) { + $feedback=NULL, $response=NULL, $actualgrade=NULL, $correct=NULL) { /// Prints a quiz question, any format if (!$question = get_record("quiz_questions", "id", $questionid)) { @@ -524,8 +538,58 @@ function quiz_print_question($number, $questionid, $grade, $courseid, echo "

Random questions not supported yet

"; break; - case RANDOMMATCH: - if (!$options = get_record("quiz_randommatch", "question", $question->id)) { + case MATCH: + if (!$options = get_record("quiz_match", "question", $question->id)) { + notify("Error: Missing question options!"); + } + if (!$subquestions = get_records_list("quiz_match_sub", "id", $options->subquestions)) { + notify("Error: Missing subquestions for this question!"); + } + echo text_to_html($question->questiontext); + if ($question->image) { + print_file_picture($question->image, $courseid, QUIZ_PICTURE_DEFAULT_HEIGHT); + } + + foreach ($subquestions as $subquestion) { + $answers[$subquestion->id] = $subquestion->answertext; + } + + $answers = draw_rand_array($answers, count($answers)); + + echo ""; + foreach ($subquestions as $key => $subquestion) { + echo ""; + if (empty($response)) { + echo ""; + } + echo "
"; + echo $subquestion->questiontext; + echo ""; + choose_from_menu($answers, "q$question->id"."r$subquestion->id"); + } else { + if (empty($response[$key])) { + echo ""; + choose_from_menu($answers, "q$question->id"."r$subquestion->id"); + } else { + if ($response[$key] == $correct[$key]) { + echo ""; + choose_from_menu($answers, "q$question->id"."r$subquestion->id", $response[$key]); + } else { + echo ""; + choose_from_menu($answers, "q$question->id"."r$subquestion->id", $response[$key]); + } + } + + if (!empty($feedback[$key])) { + quiz_print_comment($feedback[$key]); + } + } + echo "
"; + + break; + + case RANDOMSAMATCH: + if (!$options = get_record("quiz_randomsamatch", "question", $question->id)) { notify("Error: Missing question options!"); } echo text_to_html($question->questiontext); @@ -1210,7 +1274,28 @@ function quiz_grade_attempt_results($quiz, $questions) { } break; - case RANDOMMATCH: + case MATCH: + $matchcount = $totalcount = 0; + + foreach ($question->answer as $questionanswer) { // Each answer is "questionid-answerid" + $totalcount++; + $qarr = explode('-', $questionanswer); // Extract question/answer. + if ($qarr[0] == $qarr[1]) { + $matchcount++; + $correct[$qarr[0]] = true; + $response[$qarr[0]] = $qarr[1]; + $questiongrade = $answers[$qarr[0]]->grade; + } else { + $correct[$qarr[0]] = false; + $response[$qarr[0]] = $qarr[1]; + } + } + + $grade = $questiongrade * $matchcount / $totalcount; + + break; + + case RANDOMSAMATCH: $bestanswer = array(); foreach ($answers as $answer) { // Loop through them all looking for correct answers if (empty($bestanswer[$answer->question])) { @@ -1406,18 +1491,55 @@ function quiz_save_question_options($question) { } break; - case RANDOMMATCH: + case MATCH: + delete_records("quiz_match", "question", $question->id); + delete_records("quiz_match_sub", "question", $question->id); + + $subquestions = array(); + + // Insert all the new question+answer pairs + foreach ($question->subquestions as $key => $questiontext) { + $answertext = $question->subanswers[$key]; + if (!empty($questiontext) and !empty($answertext)) { + unset($answer); + $subquestion->question = $question->id; + $subquestion->questiontext = $questiontext; + $subquestion->answertext = $answertext; + if (!$subquestion->id = insert_record("quiz_match_sub", $subquestion)) { + $result->error = "Could not insert quiz answer!"; + return $result; + } + $subquestions[] = $subquestion->id; + } + } + + if (count($subquestions) < 3) { + $result->notice = get_string("notenoughsubquestions", "quiz"); + return $result; + } + + unset($options); + $options->question = $question->id; + $options->subquestions = implode(",",$subquestions); + if (!insert_record("quiz_match", $options)) { + $result->error = "Could not insert quiz match options!"; + return $result; + } + + break; + + case RANDOMSAMATCH: $options->question = $question->id; $options->choose = $question->choose; - if ($existing = get_record("quiz_randommatch", "question", $options->question)) { + if ($existing = get_record("quiz_randomsamatch", "question", $options->question)) { $options->id = $existing->id; - if (!update_record("quiz_randommatch", $options)) { - $result->error = "Could not update quiz randommatch options!"; + if (!update_record("quiz_randomsamatch", $options)) { + $result->error = "Could not update quiz randomsamatch options!"; return $result; } } else { - if (!insert_record("quiz_randommatch", $options)) { - $result->error = "Could not insert quiz randommatch options!"; + if (!insert_record("quiz_randomsamatch", $options)) { + $result->error = "Could not insert quiz randomsamatch options!"; return $result; } } diff --git a/mod/quiz/pix/ma.gif b/mod/quiz/pix/ma.gif new file mode 100755 index 0000000000..4285d03d52 Binary files /dev/null and b/mod/quiz/pix/ma.gif differ diff --git a/mod/quiz/question.php b/mod/quiz/question.php index df70c28a20..f27dd9218d 100644 --- a/mod/quiz/question.php +++ b/mod/quiz/question.php @@ -254,7 +254,7 @@ if (!empty($options->answers)) { $answersraw = get_records_list("quiz_answers", "id", $options->answers); } - for ($i=0; $i<6; $i++) { + for ($i=0; $iid)) { + $options = get_record("quiz_match", "question", $question->id); + if (!empty($options->subquestions)) { + $oldsubquestions = get_records_list("quiz_match_sub", "id", $options->subquestions); + } + } + if (empty($subquestions) and empty($subanswers)) { + for ($i=0; $iquestiontext; // insert questions into slots + $subanswers[$i] = $oldsubquestion->answertext; // insert answers into slots + $i++; + } + } + } + print_heading_with_help(get_string("editingmatch", "quiz"), "match", "quiz"); + require("match.html"); + break; + + case RANDOMSAMATCH: if (!empty($question->id)) { - $options = get_record("quiz_randommatch", "question", $question->id); + $options = get_record("quiz_randomsamatch", "question", $question->id); } else { $options->choose = ""; } $numberavailable = count_records("quiz_questions", "category", $category->id, "qtype", SHORTANSWER); - print_heading_with_help(get_string("editingrandommatch", "quiz"), "randommatch", "quiz"); - require("randommatch.html"); + print_heading_with_help(get_string("editingrandomsamatch", "quiz"), "randomsamatch", "quiz"); + require("randomsamatch.html"); break; default: diff --git a/mod/quiz/randommatch.html b/mod/quiz/randommatch.html index e8006cc390..867763234c 100644 --- a/mod/quiz/randommatch.html +++ b/mod/quiz/randommatch.html @@ -13,7 +13,7 @@ name)) { - $question->name = get_string("randommatch", "quiz"); + $question->name = get_string("randomsamatch", "quiz"); } ?> @@ -28,7 +28,7 @@ echo "
"; } if (empty($question->questiontext)) { - $question->questiontext = get_string("randommatchintro", "quiz"); + $question->questiontext = get_string("randomsamatchintro", "quiz"); } print_textarea($usehtmleditor, 15, 60, 595, 300, "questiontext", $question->questiontext); if ($usehtmleditor) { @@ -40,7 +40,7 @@ -

:

+

:

version = 2003032601; // The (date) version of this module +$module->version = 2003033100; // The (date) version of this module $module->cron = 0; // How often should cron check this module (seconds)? ?>