Skip to content

Commit

Permalink
CONTRIB-490 Added support for scripted generation of questions. Calcu…
Browse files Browse the repository at this point in the history
…lated type not yet supported (datasets too complicated ;)
  • Loading branch information
nicolasconnault committed Jun 12, 2008
1 parent ea2fdf5 commit b9bd6da
Show file tree
Hide file tree
Showing 9 changed files with 212 additions and 16 deletions.
29 changes: 13 additions & 16 deletions lib/questionlib.php
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ function question_register_questiontype($qtype) {
* Long-time Moodle programmers will realise that this replaces the old $QTYPE_MENU array.
* The array returned will only hold the names of all the question types that the user should
* be able to create directly. Some internal question types like random questions are excluded.
*
*
* @return array an array of question type names translated to the user's language.
*/
function question_type_menu() {
Expand Down Expand Up @@ -571,7 +571,7 @@ function question_delete_course_category($category, $newcategory, $feedback=true
// Loop over question categories.
if ($categories = $DB->get_records('question_categories', array('contextid'=>$context->id), 'parent', 'id, parent, name')) {
foreach ($categories as $category) {

// Deal with any questions in the category.
if ($questions = $DB->get_records('question', array('category'=>$category->id))) {

Expand Down Expand Up @@ -635,9 +635,9 @@ function question_delete_course_category($category, $newcategory, $feedback=true
*
* @param string $questionids list of questionids
* @param object $newcontext the context to create the saved category in.
* @param string $oldplace a textual description of the think being deleted, e.g. from get_context_name
* @param string $oldplace a textual description of the think being deleted, e.g. from get_context_name
* @param object $newcategory
* @return mixed false on
* @return mixed false on
*/
function question_save_from_deletion($questionids, $newcontextid, $oldplace, $newcategory = null) {
global $DB;
Expand Down Expand Up @@ -757,8 +757,8 @@ function questionbank_navigation_tabs(&$row, $contexts, $querystring) {

/**
* Load a set of questions, given a list of ids. The $join and $extrafields arguments can be used
* together to pull in extra data. See, for example, the usage in mod/quiz/attempt.php, and
* read the code below to see how the SQL is assembled.
* together to pull in extra data. See, for example, the usage in mod/quiz/attempt.php, and
* read the code below to see how the SQL is assembled.
*
* @param string $questionlist list of comma-separated question ids.
* @param string $extrafields
Expand All @@ -769,7 +769,7 @@ function questionbank_navigation_tabs(&$row, $contexts, $querystring) {
function question_load_questions($questionlist, $extrafields = '', $join = '') {
global $CFG, $DB;
if ($join) {
$join = ' JOIN {'.$join.'}';
$join = ' JOIN '.$join.'';
}
if ($extrafields) {
$extrafields = ', ' . $extrafields;
Expand Down Expand Up @@ -1027,8 +1027,7 @@ function save_question_session(&$question, &$state) {
}

// create or update the session
if (!$session = $DB->get_record('question_sessions', 'attemptid',
$state->attempt, 'questionid', $question->id)) {
if (!$session = $DB->get_record('question_sessions', array('attemptid' => $state->attempt, 'questionid' => $question->id))) {
$session->attemptid = $state->attempt;
$session->questionid = $question->id;
$session->newest = $state->id;
Expand Down Expand Up @@ -1264,7 +1263,7 @@ function regrade_question_in_attempt($question, $attempt, $cmoptions, $verbose=f
}

if ($action->event == QUESTION_EVENTMANUALGRADE) {
// Ensure that the grade is in range - in the past this was not checked,
// Ensure that the grade is in range - in the past this was not checked,
// but now it is (MDL-14835) - so we need to ensure the data is valid before
// proceeding.
if ($states[$j]->grade < 0) {
Expand Down Expand Up @@ -1934,12 +1933,7 @@ function question_make_default_categories($contexts) {
$toreturn = null;
// If it already exists, just return it.
foreach ($contexts as $key => $context) {
$exists = $DB->record_exists("question_categories", array('contextid'=>$context->id));

if ($exists === false) {
print_error('cannotgetcats');
}
if (!$exists){
if (!$exists = $DB->record_exists("question_categories", array('contextid'=>$context->id))){
// Otherwise, we need to make one
$category = new stdClass;
$contextname = print_context_name($context, false, true);
Expand All @@ -1952,7 +1946,10 @@ function question_make_default_categories($contexts) {
if (!$category->id = $DB->insert_record('question_categories', $category)) {
print_error('cannotcreatedefaultcat', '', '', print_context_name($context));
}
} else {
$category = $DB->get_record('question_categories', array('contextid' => $context->id));
}

if ($context->contextlevel == CONTEXT_COURSE){
$toreturn = clone($category);
}
Expand Down
20 changes: 20 additions & 0 deletions question/type/essay/questiontype.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,26 @@ function backup($bf, $preferences, $questionid, $level = 6) {
return question_backup_answers($bf, $preferences, $questionid, $level);
}

/**
* 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) {
global $DB;
list($form, $question) = parent::generate_test($name, $courseid);
$form->questiontext = "What is the purpose of life?";
$form->feedback = "feedback";
$form->generalfeedback = "General feedback";
$form->fraction = 0;
$form->penalty = 0;

if ($courseid) {
$course = $DB->get_record('course', array('id' => $courseid));
}

return $this->save_question($question, $form, $course);
}

// Restore method not needed.
}
//// END OF CLASS ////
Expand Down
19 changes: 19 additions & 0 deletions question/type/match/questiontype.php
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,25 @@ function replace_file_links($question, $fromcourseid, $tocourseid, $url, $destin
}
}
}

/**
* 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) {
global $DB;
list($form, $question) = parent::generate_test($name, $courseid);
$form->shuffleanswers = 1;
$form->noanswers = 3;
$form->subquestions = array('cat', 'dog', 'cow');
$form->subanswers = array('feline', 'canine', 'bovine');

if ($courseid) {
$course = $DB->get_record('course', array('id' => $courseid));
}

return $this->save_question($question, $form, $course);
}
}
//// END OF CLASS ////

Expand Down
28 changes: 28 additions & 0 deletions question/type/multianswer/questiontype.php
Original file line number Diff line number Diff line change
Expand Up @@ -707,6 +707,34 @@ function restore_recode_answer($state, $restore) {
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) {
global $DB;
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 = $DB->get_record('course', array('id' => $courseid));
}

return $this->save_question($question, $form, $course);
}

}
//// END OF CLASS ////
Expand Down
29 changes: 29 additions & 0 deletions question/type/multichoice/questiontype.php
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,35 @@ function replace_file_links($question, $fromcourseid, $tocourseid, $url, $destin
}
}
}

/**
* 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) {
global $DB;
list($form, $question) = parent::generate_test($name, $courseid);
$question->category = $form->category;
$form->questiontext = "How old is the sun?";
$form->generalfeedback = "General feedback";
$form->penalty = 0.1;
$form->single = 1;
$form->shuffleanswers = 1;
$form->answernumbering = 'abc';
$form->noanswers = 3;
$form->answer = array('Ancient', '5 billion years old', '4.5 billion years old');
$form->fraction = array(0.3, 0.9, 1);
$form->feedback = array('True, but lacking in accuracy', 'Close, but no cigar!', 'Yep, that is it!');
$form->correctfeedback = 'Excellent!';
$form->incorrectfeedback = 'Nope!';
$form->partiallycorrectfeedback = 'Not bad';

if ($courseid) {
$course = $DB->get_record('course', array('id' => $courseid));
}

return $this->save_question($question, $form, $course);
}
}

// Register this question type with the question bank.
Expand Down
28 changes: 28 additions & 0 deletions question/type/numerical/questiontype.php
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,34 @@ function restore($old_question_id,$new_question_id,$info,$restore) {
return $status;
}

/**
* 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) {
global $DB;
list($form, $question) = default_questiontype::generate_test($name, $courseid);
$question->category = $form->category;

$form->questiontext = "What is 674 * 36?";
$form->generalfeedback = "Thank you";
$form->penalty = 0.1;
$form->defaultgrade = 1;
$form->noanswers = 3;
$form->answer = array('24264', '24264', '1');
$form->tolerance = array(10, 100, 0);
$form->fraction = array(1, 0.5, 0);
$form->nounits = 2;
$form->unit = array(0 => null, 1 => null);
$form->multiplier = array(1, 0);
$form->feedback = array('Very good', 'Close, but not quite there', 'Well at least you tried....');

if ($courseid) {
$course = $DB->get_record('course', array('id' => $courseid));
}

return $this->save_question($question, $form, $course);
}
}

// INITIATION - Without this line the question type is not in use.
Expand Down
24 changes: 24 additions & 0 deletions question/type/questiontype.php
Original file line number Diff line number Diff line change
Expand Up @@ -1582,5 +1582,29 @@ function restore_recode_answer($state, $restore) {
// There is nothing to decode
return $state->answer;
}

/**
* Abstract function implemented by each question type. It runs all the code
* required to set up and save a question of any type for testing purposes.
* Alternate DB table prefix may be used to facilitate data deletion.
*/
function generate_test($name, $courseid=null) {
$form = new stdClass();
$form->name = $name;
$form->questiontextformat = 1;
$form->questiontext = 'test question, generated by script';
$form->defaultgrade = 1;
$form->penalty = 0.1;
$form->generalfeedback = "Well done";

$context = get_context_instance(CONTEXT_COURSE, $courseid);
$newcategory = question_make_default_categories(array($context));
$form->category = $newcategory->id . ',1';

$question = new stdClass();
$question->courseid = $courseid;
$question->qtype = $this->qtype;
return array($form, $question);
}
}
?>
29 changes: 29 additions & 0 deletions question/type/shortanswer/questiontype.php
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,35 @@ function print_question_grading_details(&$question, &$state, $cmoptions, $option
}
}
}

/**
* 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) {
global $DB;
list($form, $question) = parent::generate_test($name, $courseid);
$question->category = $form->category;

$form->questiontext = "What is the purpose of life, the universe, and everything";
$form->generalfeedback = "Congratulations, you may have solved my biggest problem!";
$form->penalty = 0.1;
$form->usecase = false;
$form->defaultgrade = 1;
$form->noanswers = 3;
$form->answer = array('42', 'who cares?', 'Be happy');
$form->fraction = array(1, 0.6, 0.8);
$form->feedback = array('True, but what does that mean?', 'Well you do, dont you?', 'Yes, but thats not funny...');
$form->correctfeedback = 'Excellent!';
$form->incorrectfeedback = 'Nope!';
$form->partiallycorrectfeedback = 'Not bad';

if ($courseid) {
$course = $DB->get_record('course', array('id' => $courseid));
}

return $this->save_question($question, $form, $course);
}
}
//// END OF CLASS ////

Expand Down
22 changes: 22 additions & 0 deletions question/type/truefalse/questiontype.php
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,28 @@ function restore_recode_answer($state, $restore) {
}
}

/**
* 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) {
global $DB;
list($form, $question) = parent::generate_test($name, $courseid);
$question->category = $form->category;

$form->questiontext = "This question is really stupid";
$form->penalty = 1;
$form->defaultgrade = 1;
$form->correctanswer = 0;
$form->feedbacktrue = 'Can you justify such a hasty judgment?';
$form->feedbackfalse = 'Wisdom has spoken!';

if ($courseid) {
$course = $DB->get_record('course', array('id' => $courseid));
}

return $this->save_question($question, $form, $course);
}
}
//// END OF CLASS ////

Expand Down

0 comments on commit b9bd6da

Please sign in to comment.