2004-09-12 17:34:35 +00:00
|
|
|
<?php // $Id$
|
2002-10-04 02:59:05 +00:00
|
|
|
|
2002-10-13 07:17:48 +00:00
|
|
|
/// Library of function for module quiz
|
2002-10-04 02:59:05 +00:00
|
|
|
|
2002-10-13 07:17:48 +00:00
|
|
|
/// CONSTANTS ///////////////////////////////////////////////////////////////////
|
2002-10-04 02:59:05 +00:00
|
|
|
|
2002-10-13 07:17:48 +00:00
|
|
|
define("GRADEHIGHEST", "1");
|
|
|
|
define("GRADEAVERAGE", "2");
|
|
|
|
define("ATTEMPTFIRST", "3");
|
|
|
|
define("ATTEMPTLAST", "4");
|
|
|
|
$QUIZ_GRADE_METHOD = array ( GRADEHIGHEST => get_string("gradehighest", "quiz"),
|
|
|
|
GRADEAVERAGE => get_string("gradeaverage", "quiz"),
|
|
|
|
ATTEMPTFIRST => get_string("attemptfirst", "quiz"),
|
|
|
|
ATTEMPTLAST => get_string("attemptlast", "quiz"));
|
|
|
|
|
2003-03-30 16:46:50 +00:00
|
|
|
define("SHORTANSWER", "1");
|
|
|
|
define("TRUEFALSE", "2");
|
|
|
|
define("MULTICHOICE", "3");
|
|
|
|
define("RANDOM", "4");
|
|
|
|
define("MATCH", "5");
|
|
|
|
define("RANDOMSAMATCH", "6");
|
2003-07-06 04:00:05 +00:00
|
|
|
define("DESCRIPTION", "7");
|
2003-07-10 13:25:07 +00:00
|
|
|
define("NUMERICAL", "8");
|
2003-08-01 08:37:11 +00:00
|
|
|
define("MULTIANSWER", "9");
|
2004-07-30 14:50:58 +00:00
|
|
|
define("CALCULATED", "10");
|
2003-03-30 16:46:50 +00:00
|
|
|
|
|
|
|
$QUIZ_QUESTION_TYPE = array ( MULTICHOICE => get_string("multichoice", "quiz"),
|
|
|
|
TRUEFALSE => get_string("truefalse", "quiz"),
|
|
|
|
SHORTANSWER => get_string("shortanswer", "quiz"),
|
2003-07-10 13:25:07 +00:00
|
|
|
NUMERICAL => get_string("numerical", "quiz"),
|
2004-07-30 14:50:58 +00:00
|
|
|
CALCULATED => get_string("calculated", "quiz"),
|
2003-03-30 16:46:50 +00:00
|
|
|
MATCH => get_string("match", "quiz"),
|
2003-07-10 13:25:07 +00:00
|
|
|
DESCRIPTION => get_string("description", "quiz"),
|
2003-04-09 06:32:51 +00:00
|
|
|
RANDOM => get_string("random", "quiz"),
|
2003-08-01 08:37:11 +00:00
|
|
|
RANDOMSAMATCH => get_string("randomsamatch", "quiz"),
|
|
|
|
MULTIANSWER => get_string("multianswer", "quiz")
|
2003-07-10 13:25:07 +00:00
|
|
|
);
|
2002-10-13 07:17:48 +00:00
|
|
|
|
2003-02-16 07:08:57 +00:00
|
|
|
|
2003-05-23 15:20:41 +00:00
|
|
|
define("QUIZ_PICTURE_MAX_HEIGHT", "600"); // Not currently implemented
|
|
|
|
define("QUIZ_PICTURE_MAX_WIDTH", "600"); // Not currently implemented
|
2002-10-13 07:17:48 +00:00
|
|
|
|
2004-01-10 07:39:19 +00:00
|
|
|
define("QUIZ_MAX_NUMBER_ANSWERS", "10");
|
2003-03-30 16:46:50 +00:00
|
|
|
|
2004-05-17 17:04:01 +00:00
|
|
|
define("QUIZ_MAX_EVENT_LENGTH", "432000"); // 5 days maximum
|
2004-04-28 02:56:40 +00:00
|
|
|
|
2004-07-21 13:01:08 +00:00
|
|
|
$QUIZ_QTYPES= array();
|
|
|
|
|
|
|
|
/// QUIZ_QTYPES INITIATION //////////////////
|
|
|
|
class quiz_default_questiontype {
|
|
|
|
|
|
|
|
function name() {
|
|
|
|
return 'default';
|
|
|
|
}
|
|
|
|
|
2004-08-04 23:35:18 +00:00
|
|
|
function uses_quizfile($question, $relativefilepath) {
|
|
|
|
// The default does only check whether the file is used as image:
|
|
|
|
return $question->image == $relativefilepath;
|
|
|
|
}
|
|
|
|
|
2004-07-21 13:01:08 +00:00
|
|
|
function save_question_options($question) {
|
|
|
|
/// Given some question info and some data about the the answers
|
|
|
|
/// this function parses, organises and saves the question
|
|
|
|
/// It is used by question.php through ->save_question when
|
|
|
|
/// saving new data from a form, and also by import.php when
|
|
|
|
/// importing questions
|
|
|
|
///
|
|
|
|
/// If this is an update, and old answers already exist, then
|
|
|
|
/// these are overwritten using an update(). To do this, it
|
|
|
|
/// it is assumed that the IDs in quiz_answers are in the same
|
|
|
|
/// sort order as the new answers being saved. This should always
|
|
|
|
/// be true, but it's something to keep in mind if fiddling with
|
|
|
|
/// question.php
|
|
|
|
///
|
|
|
|
/// Returns $result->error or $result->noticeyesno or $result->notice
|
|
|
|
|
|
|
|
/// This default implementation must be overridden:
|
|
|
|
|
|
|
|
$result->error = "Unsupported question type ($question->qtype)!";
|
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
|
|
|
|
function save_question($question, $form, $course) {
|
|
|
|
// This default implementation is suitable for most
|
|
|
|
// question types.
|
|
|
|
|
|
|
|
// First, save the basic question itself
|
|
|
|
|
2004-08-05 05:31:40 +00:00
|
|
|
$question->name = trim($form->name);
|
|
|
|
$question->questiontext = trim($form->questiontext);
|
2004-07-21 13:01:08 +00:00
|
|
|
$question->questiontextformat = $form->questiontextformat;
|
|
|
|
|
|
|
|
if (empty($form->image)) {
|
|
|
|
$question->image = "";
|
|
|
|
} else {
|
|
|
|
$question->image = $form->image;
|
|
|
|
}
|
|
|
|
|
2004-08-05 05:31:40 +00:00
|
|
|
if (empty($question->name)) {
|
|
|
|
$question->name = strip_tags($question->questiontext);
|
|
|
|
if (empty($question->name)) {
|
|
|
|
$question->name = '-';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-07-21 13:01:08 +00:00
|
|
|
if (isset($form->defaultgrade)) {
|
|
|
|
$question->defaultgrade = $form->defaultgrade;
|
|
|
|
}
|
|
|
|
|
2004-08-05 05:31:40 +00:00
|
|
|
if (!empty($question->id)) { // Question already exists
|
|
|
|
$question->version ++; // Update version number of question
|
|
|
|
if (!update_record("quiz_questions", $question)) {
|
|
|
|
error("Could not update question!");
|
2004-07-21 13:01:08 +00:00
|
|
|
}
|
2004-08-05 05:31:40 +00:00
|
|
|
} else { // Question is a new one
|
|
|
|
$question->stamp = make_unique_id_code(); // Set the unique code (not to be changed)
|
|
|
|
$question->version = 1;
|
|
|
|
if (!$question->id = insert_record("quiz_questions", $question)) {
|
|
|
|
error("Could not insert new question!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now to save all the answers and type-specific options
|
2004-07-21 13:01:08 +00:00
|
|
|
|
2004-08-05 05:31:40 +00:00
|
|
|
$form->id = $question->id;
|
|
|
|
$form->qtype = $question->qtype;
|
|
|
|
$form->category = $question->category;
|
2004-07-21 13:01:08 +00:00
|
|
|
|
2004-08-05 05:31:40 +00:00
|
|
|
$result = $this->save_question_options($form);
|
2004-07-21 13:01:08 +00:00
|
|
|
|
2004-08-05 05:31:40 +00:00
|
|
|
if (!empty($result->error)) {
|
|
|
|
error($result->error);
|
|
|
|
}
|
2004-07-21 13:01:08 +00:00
|
|
|
|
2004-08-05 05:31:40 +00:00
|
|
|
if (!empty($result->notice)) {
|
|
|
|
notice($result->notice, "question.php?id=$question->id");
|
|
|
|
}
|
2004-07-21 13:01:08 +00:00
|
|
|
|
2004-08-05 05:31:40 +00:00
|
|
|
if (!empty($result->noticeyesno)) {
|
|
|
|
notice_yesno($result->noticeyesno, "question.php?id=$question->id", "edit.php");
|
|
|
|
print_footer($course);
|
|
|
|
exit;
|
2004-07-21 13:01:08 +00:00
|
|
|
}
|
2004-08-05 05:31:40 +00:00
|
|
|
|
|
|
|
redirect("edit.php");
|
2004-07-21 13:01:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Convenience function that is used within the question types only
|
|
|
|
function extract_response_id($responsekey) {
|
|
|
|
if (ereg('[0-9]'.$this->name().'([0-9]+)', $responsekey, $regs)) {
|
|
|
|
return $regs[1];
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function wrapped_questions($question) {
|
|
|
|
/// Overridden only by question types, whose questions can
|
|
|
|
/// wrap other questions. Two question types that do this
|
|
|
|
/// are RANDOMSAMATCH and RANDOM
|
|
|
|
|
|
|
|
/// If there are wrapped questions, than this method returns
|
|
|
|
/// comma separated list of them...
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
function convert_to_response_answer_field($questionresponse) {
|
|
|
|
/// This function is very much the inverse of extract_response
|
|
|
|
/// This function and extract_response, should be
|
|
|
|
/// obsolete as soon as we get a better response storage
|
|
|
|
/// Right now they are a bridge between a consistent
|
|
|
|
/// response model and the old field answer in quiz_responses
|
|
|
|
|
|
|
|
/// This is the default implemention...
|
|
|
|
return implode(',', $questionresponse);
|
|
|
|
}
|
|
|
|
|
|
|
|
function get_answers($question) {
|
|
|
|
// Returns the answers for the specified question
|
|
|
|
|
|
|
|
// The default behaviour that signals that something is wrong
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
function create_response($question, $nameprefix, $questionsinuse) {
|
|
|
|
/// This rather smart solution works for most cases:
|
|
|
|
$rawresponse->question = $question->id;
|
|
|
|
$rawresponse->answer = '';
|
|
|
|
return $this->extract_response($rawresponse, $nameprefix);
|
|
|
|
}
|
|
|
|
|
|
|
|
function extract_response($rawresponse, $nameprefix) {
|
2004-09-16 06:35:49 +00:00
|
|
|
/// This function is very much the inverse of convert_to_response_answer_field
|
|
|
|
/// This function and convert_to_response_answer_field, should be
|
2004-07-21 13:01:08 +00:00
|
|
|
/// obsolete as soon as we get a better response storage
|
|
|
|
/// Right now they are a bridge between a consistent
|
|
|
|
/// response model and the old field answer in quiz_responses
|
|
|
|
|
|
|
|
/// Default behaviour that works for singlton response question types
|
|
|
|
/// like SHORTANSWER, NUMERICAL and TRUEFALSE
|
|
|
|
|
|
|
|
return array($nameprefix => $rawresponse->answer);
|
|
|
|
}
|
|
|
|
|
|
|
|
function print_question_number_and_grading_details
|
|
|
|
($number, $grade, $actualgrade=false, $recentlyadded=false) {
|
|
|
|
|
|
|
|
/// Print question number and grade:
|
|
|
|
|
2004-11-11 12:07:08 +00:00
|
|
|
echo '<center><b>' . $number . '</b></center>';
|
2004-07-21 13:01:08 +00:00
|
|
|
if (false !== $grade) {
|
|
|
|
$strmarks = get_string("marks", "quiz");
|
2004-11-11 12:07:08 +00:00
|
|
|
//echo '<p align="center"><font size="1">';
|
|
|
|
echo '<br /><center><font size="1">';
|
2004-07-21 13:01:08 +00:00
|
|
|
if (false !== $actualgrade) {
|
2004-11-11 12:07:08 +00:00
|
|
|
echo "$strmarks: $actualgrade/$grade</font></center>";
|
2004-07-21 13:01:08 +00:00
|
|
|
} else {
|
2004-11-11 12:07:08 +00:00
|
|
|
echo "$grade $strmarks</font></center>";
|
2004-07-21 13:01:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
print_spacer(1,100);
|
|
|
|
|
|
|
|
/// Print possible recently-added information:
|
|
|
|
|
|
|
|
if ($recentlyadded) {
|
|
|
|
echo '</td><td valign="top" align="right">';
|
|
|
|
// Notify the user of this recently added question
|
|
|
|
echo '<font color="red">';
|
|
|
|
echo get_string('recentlyaddedquestion', 'quiz');
|
|
|
|
echo '</font>';
|
|
|
|
echo '</td></tr><tr><td></td><td valign="top">';
|
|
|
|
|
|
|
|
} else { // The normal case
|
|
|
|
echo '</td><td valign="top">';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function print_question($currentnumber, $quiz, $question,
|
|
|
|
$readonly, $resultdetails) {
|
|
|
|
/// Note that this method must return the number of the next
|
|
|
|
/// question, making it possible not to increase the number when
|
|
|
|
/// overriding this method (as for qtype=DESCRIPTION).
|
|
|
|
|
|
|
|
echo '<table width="100%" cellspacing="10">';
|
|
|
|
echo '<tr><td nowrap="nowrap" width="100" valign="top">';
|
|
|
|
|
|
|
|
$this->print_question_number_and_grading_details
|
|
|
|
($currentnumber,
|
|
|
|
$quiz->grade ? $question->maxgrade : false,
|
|
|
|
empty($resultdetails) ? false : $resultdetails->grade,
|
2004-08-05 05:31:40 +00:00
|
|
|
isset($question->recentlyadded) ? $question->recentlyadded : false);
|
2004-07-21 13:01:08 +00:00
|
|
|
|
|
|
|
$this->print_question_formulation_and_controls(
|
2004-08-14 12:42:54 +00:00
|
|
|
$question, $quiz, $readonly,
|
|
|
|
empty($resultdetails) ? false : $resultdetails->answers,
|
|
|
|
empty($resultdetails) ? false : $resultdetails->correctanswers,
|
2004-07-21 13:01:08 +00:00
|
|
|
quiz_qtype_nameprefix($question));
|
|
|
|
|
|
|
|
echo "</td></tr></table>";
|
|
|
|
return $currentnumber + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
function print_question_formulation_and_controls($question,
|
|
|
|
$quiz, $readonly, $answers, $correctanswers, $nameprefix) {
|
|
|
|
/// This default implementation must be overridden by all
|
|
|
|
/// question type implemenations, unless the default
|
|
|
|
/// implementation of print_question has been overridden...
|
|
|
|
|
|
|
|
notify('Error: Question formulation and input controls has not'
|
|
|
|
.' been implemented for question type '.$this->name());
|
|
|
|
}
|
|
|
|
|
|
|
|
function grade_response($question, $nameprefix) {
|
|
|
|
// Analyzes $question->response[] and determines the result
|
|
|
|
// The result is to be returned in this structure:
|
|
|
|
// ->grade (The fraction of maxgrade awarded on the question)
|
|
|
|
// ->answers (result answer records)
|
|
|
|
// ->correctanswers (potential answer records for best ->response[])
|
|
|
|
|
|
|
|
error('grade_response has not been implemented for question type '
|
|
|
|
.$this->name());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
quiz_load_questiontypes();
|
|
|
|
function quiz_load_questiontypes() {
|
|
|
|
global $QUIZ_QTYPES;
|
|
|
|
global $CFG;
|
|
|
|
|
|
|
|
$qtypenames= get_list_of_plugins('mod/quiz/questiontypes');
|
|
|
|
foreach($qtypenames as $qtypename) {
|
|
|
|
// Instanciates all plug-in question types
|
2004-07-29 06:15:54 +00:00
|
|
|
$qtypefilepath= "$CFG->dirroot/mod/quiz/questiontypes/$qtypename/questiontype.php";
|
2004-07-21 13:01:08 +00:00
|
|
|
|
|
|
|
// echo "Loading $qtypename<br/>"; // Uncomment for debugging
|
|
|
|
if (is_readable($qtypefilepath)) {
|
|
|
|
require_once($qtypefilepath);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-10-13 07:17:48 +00:00
|
|
|
/// FUNCTIONS ///////////////////////////////////////////////////////////////////
|
2002-10-04 02:59:05 +00:00
|
|
|
|
|
|
|
function quiz_add_instance($quiz) {
|
2004-06-02 18:03:05 +00:00
|
|
|
/// Given an object containing all the necessary data,
|
|
|
|
/// (defined by the form in mod.html) this function
|
|
|
|
/// will create a new instance and return the id number
|
2002-10-13 07:17:48 +00:00
|
|
|
/// of the new instance.
|
2002-10-04 02:59:05 +00:00
|
|
|
|
2004-05-16 10:20:26 +00:00
|
|
|
global $SESSION;
|
|
|
|
|
|
|
|
unset($SESSION->modform);
|
|
|
|
|
2002-10-15 16:22:18 +00:00
|
|
|
$quiz->created = time();
|
2002-10-04 02:59:05 +00:00
|
|
|
$quiz->timemodified = time();
|
2004-06-02 18:03:05 +00:00
|
|
|
$quiz->timeopen = make_timestamp($quiz->openyear, $quiz->openmonth, $quiz->openday,
|
2002-12-30 05:10:01 +00:00
|
|
|
$quiz->openhour, $quiz->openminute, 0);
|
2004-06-02 18:03:05 +00:00
|
|
|
$quiz->timeclose = make_timestamp($quiz->closeyear, $quiz->closemonth, $quiz->closeday,
|
2002-12-30 05:10:01 +00:00
|
|
|
$quiz->closehour, $quiz->closeminute, 0);
|
2002-10-04 02:59:05 +00:00
|
|
|
|
2002-10-14 12:21:18 +00:00
|
|
|
if (!$quiz->id = insert_record("quiz", $quiz)) {
|
|
|
|
return false; // some error occurred
|
|
|
|
}
|
|
|
|
|
2002-10-14 15:57:33 +00:00
|
|
|
// The grades for every question in this quiz are stored in an array
|
2002-10-14 12:21:18 +00:00
|
|
|
if ($quiz->grades) {
|
|
|
|
foreach ($quiz->grades as $question => $grade) {
|
2003-07-06 04:00:05 +00:00
|
|
|
if ($question) {
|
2002-10-15 12:54:11 +00:00
|
|
|
unset($questiongrade);
|
|
|
|
$questiongrade->quiz = $quiz->id;
|
|
|
|
$questiongrade->question = $question;
|
|
|
|
$questiongrade->grade = $grade;
|
|
|
|
if (!insert_record("quiz_question_grades", $questiongrade)) {
|
|
|
|
return false;
|
|
|
|
}
|
2002-10-14 12:21:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-04-28 02:56:40 +00:00
|
|
|
|
2004-05-23 10:25:46 +00:00
|
|
|
delete_records('event', 'modulename', 'quiz', 'instance', $quiz->id); // Just in case
|
|
|
|
|
2004-04-28 02:56:40 +00:00
|
|
|
$event = NULL;
|
|
|
|
$event->name = $quiz->name;
|
|
|
|
$event->description = $quiz->intro;
|
|
|
|
$event->courseid = $quiz->course;
|
|
|
|
$event->groupid = 0;
|
|
|
|
$event->userid = 0;
|
|
|
|
$event->modulename = 'quiz';
|
|
|
|
$event->instance = $quiz->id;
|
2004-05-17 17:04:01 +00:00
|
|
|
$event->eventtype = 'open';
|
2004-04-28 02:56:40 +00:00
|
|
|
$event->timestart = $quiz->timeopen;
|
2004-08-08 15:08:50 +00:00
|
|
|
$event->visible = instance_is_visible('quiz', $quiz);
|
2004-04-28 02:56:40 +00:00
|
|
|
$event->timeduration = ($quiz->timeclose - $quiz->timeopen);
|
2004-05-17 17:04:01 +00:00
|
|
|
|
|
|
|
if ($event->timeduration > QUIZ_MAX_EVENT_LENGTH) { /// Long durations create two events
|
|
|
|
$event2 = $event;
|
|
|
|
|
|
|
|
$event->name .= ' ('.get_string('quizopens', 'quiz').')';
|
|
|
|
$event->timeduration = 0;
|
|
|
|
|
|
|
|
$event2->timestart = $quiz->timeclose;
|
|
|
|
$event2->eventtype = 'close';
|
|
|
|
$event2->timeduration = 0;
|
|
|
|
$event2->name .= ' ('.get_string('quizcloses', 'quiz').')';
|
|
|
|
|
|
|
|
add_event($event2);
|
2004-04-28 02:56:40 +00:00
|
|
|
}
|
2004-05-17 17:04:01 +00:00
|
|
|
|
2004-04-28 02:56:40 +00:00
|
|
|
add_event($event);
|
|
|
|
|
2002-10-14 12:21:18 +00:00
|
|
|
return $quiz->id;
|
2002-10-04 02:59:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function quiz_update_instance($quiz) {
|
2004-06-02 18:03:05 +00:00
|
|
|
/// Given an object containing all the necessary data,
|
|
|
|
/// (defined by the form in mod.html) this function
|
2002-10-13 07:17:48 +00:00
|
|
|
/// will update an existing instance with new data.
|
2002-10-04 02:59:05 +00:00
|
|
|
|
2004-05-16 10:20:26 +00:00
|
|
|
global $SESSION;
|
|
|
|
|
|
|
|
unset($SESSION->modform);
|
|
|
|
|
2002-10-04 02:59:05 +00:00
|
|
|
$quiz->timemodified = time();
|
2004-06-02 18:03:05 +00:00
|
|
|
$quiz->timeopen = make_timestamp($quiz->openyear, $quiz->openmonth, $quiz->openday,
|
2002-12-30 05:10:01 +00:00
|
|
|
$quiz->openhour, $quiz->openminute, 0);
|
2004-06-02 18:03:05 +00:00
|
|
|
$quiz->timeclose = make_timestamp($quiz->closeyear, $quiz->closemonth, $quiz->closeday,
|
2002-12-30 05:10:01 +00:00
|
|
|
$quiz->closehour, $quiz->closeminute, 0);
|
2002-10-04 02:59:05 +00:00
|
|
|
$quiz->id = $quiz->instance;
|
|
|
|
|
2002-10-14 12:21:18 +00:00
|
|
|
if (!update_record("quiz", $quiz)) {
|
|
|
|
return false; // some error occurred
|
|
|
|
}
|
2002-10-04 02:59:05 +00:00
|
|
|
|
2002-10-14 12:21:18 +00:00
|
|
|
|
2002-10-14 15:57:33 +00:00
|
|
|
// The grades for every question in this quiz are stored in an array
|
2002-10-14 12:21:18 +00:00
|
|
|
// Insert or update records as appropriate
|
|
|
|
|
|
|
|
$existing = get_records("quiz_question_grades", "quiz", $quiz->id, "", "question,grade,id");
|
|
|
|
|
|
|
|
if ($quiz->grades) {
|
|
|
|
foreach ($quiz->grades as $question => $grade) {
|
2003-07-06 04:00:05 +00:00
|
|
|
if ($question) {
|
2002-10-15 12:54:11 +00:00
|
|
|
unset($questiongrade);
|
|
|
|
$questiongrade->quiz = $quiz->id;
|
|
|
|
$questiongrade->question = $question;
|
|
|
|
$questiongrade->grade = $grade;
|
|
|
|
if (isset($existing[$question])) {
|
|
|
|
if ($existing[$question]->grade != $grade) {
|
|
|
|
$questiongrade->id = $existing[$question]->id;
|
|
|
|
if (!update_record("quiz_question_grades", $questiongrade)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!insert_record("quiz_question_grades", $questiongrade)) {
|
2002-10-14 12:21:18 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-04-28 02:56:40 +00:00
|
|
|
|
2004-05-23 10:25:46 +00:00
|
|
|
delete_records('event', 'modulename', 'quiz', 'instance', $quiz->id); // Delete old and add new
|
2004-04-28 02:56:40 +00:00
|
|
|
|
2004-05-23 10:25:46 +00:00
|
|
|
$event = NULL;
|
|
|
|
$event->name = $quiz->name;
|
|
|
|
$event->description = $quiz->intro;
|
|
|
|
$event->courseid = $quiz->course;
|
|
|
|
$event->groupid = 0;
|
|
|
|
$event->userid = 0;
|
|
|
|
$event->modulename = 'quiz';
|
|
|
|
$event->instance = $quiz->id;
|
|
|
|
$event->eventtype = 'open';
|
|
|
|
$event->timestart = $quiz->timeopen;
|
2004-08-08 15:09:39 +00:00
|
|
|
$event->visible = instance_is_visible('quiz', $quiz);
|
2004-05-23 10:25:46 +00:00
|
|
|
$event->timeduration = ($quiz->timeclose - $quiz->timeopen);
|
2004-04-28 02:56:40 +00:00
|
|
|
|
2004-05-23 10:25:46 +00:00
|
|
|
if ($event->timeduration > QUIZ_MAX_EVENT_LENGTH) { /// Long durations create two events
|
|
|
|
$event2 = $event;
|
2004-04-28 02:56:40 +00:00
|
|
|
|
2004-05-23 10:25:46 +00:00
|
|
|
$event->name .= ' ('.get_string('quizopens', 'quiz').')';
|
|
|
|
$event->timeduration = 0;
|
|
|
|
|
|
|
|
$event2->timestart = $quiz->timeclose;
|
|
|
|
$event2->eventtype = 'close';
|
|
|
|
$event2->timeduration = 0;
|
|
|
|
$event2->name .= ' ('.get_string('quizcloses', 'quiz').')';
|
|
|
|
|
|
|
|
add_event($event2);
|
2004-04-28 02:56:40 +00:00
|
|
|
}
|
|
|
|
|
2004-05-23 10:25:46 +00:00
|
|
|
add_event($event);
|
|
|
|
|
2002-10-14 12:21:18 +00:00
|
|
|
return true;
|
2002-10-04 02:59:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function quiz_delete_instance($id) {
|
2004-06-02 18:03:05 +00:00
|
|
|
/// Given an ID of an instance of this module,
|
|
|
|
/// this function will permanently delete the instance
|
|
|
|
/// and any data that depends on it.
|
2002-10-04 02:59:05 +00:00
|
|
|
|
|
|
|
if (! $quiz = get_record("quiz", "id", "$id")) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
$result = true;
|
|
|
|
|
2004-04-07 23:38:48 +00:00
|
|
|
if ($attempts = get_records("quiz_attempts", "quiz", "$quiz->id")) {
|
2002-10-14 15:57:33 +00:00
|
|
|
foreach ($attempts as $attempt) {
|
|
|
|
if (! delete_records("quiz_responses", "attempt", "$attempt->id")) {
|
|
|
|
$result = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! delete_records("quiz_attempts", "quiz", "$quiz->id")) {
|
|
|
|
$result = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! delete_records("quiz_grades", "quiz", "$quiz->id")) {
|
|
|
|
$result = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! delete_records("quiz_question_grades", "quiz", "$quiz->id")) {
|
|
|
|
$result = false;
|
|
|
|
}
|
2002-10-04 02:59:05 +00:00
|
|
|
|
|
|
|
if (! delete_records("quiz", "id", "$quiz->id")) {
|
|
|
|
$result = false;
|
|
|
|
}
|
|
|
|
|
2004-05-17 17:04:01 +00:00
|
|
|
if (! delete_records('event', 'modulename', 'quiz', 'instance', $quiz->id)) {
|
|
|
|
$result = false;
|
|
|
|
}
|
|
|
|
|
2002-10-04 02:59:05 +00:00
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
|
2004-01-21 16:44:22 +00:00
|
|
|
function quiz_delete_course($course) {
|
|
|
|
/// Given a course object, this function will clean up anything that
|
|
|
|
/// would be leftover after all the instances were deleted
|
2004-04-07 23:38:48 +00:00
|
|
|
/// In this case, all non-publish quiz categories and questions
|
2004-01-21 16:44:22 +00:00
|
|
|
|
2004-04-07 23:38:48 +00:00
|
|
|
if ($categories = get_records_select("quiz_categories", "course = '$course->id' AND publish = '0'")) {
|
2004-01-21 16:44:22 +00:00
|
|
|
foreach ($categories as $category) {
|
|
|
|
if ($questions = get_records("quiz_questions", "category", $category->id)) {
|
|
|
|
foreach ($questions as $question) {
|
|
|
|
delete_records("quiz_answers", "question", $question->id);
|
|
|
|
delete_records("quiz_match", "question", $question->id);
|
|
|
|
delete_records("quiz_match_sub", "question", $question->id);
|
|
|
|
delete_records("quiz_multianswers", "question", $question->id);
|
|
|
|
delete_records("quiz_multichoice", "question", $question->id);
|
|
|
|
delete_records("quiz_numerical", "question", $question->id);
|
|
|
|
delete_records("quiz_randommatch", "question", $question->id);
|
|
|
|
delete_records("quiz_responses", "question", $question->id);
|
|
|
|
delete_records("quiz_shortanswer", "question", $question->id);
|
|
|
|
delete_records("quiz_truefalse", "question", $question->id);
|
|
|
|
}
|
|
|
|
delete_records("quiz_questions", "category", $category->id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return delete_records("quiz_categories", "course", $course->id);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-10-04 02:59:05 +00:00
|
|
|
function quiz_user_outline($course, $user, $mod, $quiz) {
|
2004-06-02 18:03:05 +00:00
|
|
|
/// Return a small object with summary information about what a
|
2002-10-13 07:17:48 +00:00
|
|
|
/// user has done with a given particular instance of this module
|
|
|
|
/// Used for user activity reports.
|
|
|
|
/// $return->time = the time they did it
|
|
|
|
/// $return->info = a short text description
|
2002-12-23 09:39:26 +00:00
|
|
|
if ($grade = get_record("quiz_grades", "userid", $user->id, "quiz", $quiz->id)) {
|
2004-06-02 18:03:05 +00:00
|
|
|
|
2002-10-17 08:28:18 +00:00
|
|
|
if ($grade->grade) {
|
|
|
|
$result->info = get_string("grade").": $grade->grade";
|
|
|
|
}
|
|
|
|
$result->time = $grade->timemodified;
|
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
return NULL;
|
2002-10-04 02:59:05 +00:00
|
|
|
|
|
|
|
return $return;
|
|
|
|
}
|
|
|
|
|
|
|
|
function quiz_user_complete($course, $user, $mod, $quiz) {
|
2004-06-02 18:03:05 +00:00
|
|
|
/// Print a detailed representation of what a user has done with
|
2002-10-13 07:17:48 +00:00
|
|
|
/// a given particular instance of this module, for user activity reports.
|
2002-10-04 02:59:05 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
function quiz_cron () {
|
2002-10-13 07:17:48 +00:00
|
|
|
/// Function to be run periodically according to the moodle cron
|
2004-06-02 18:03:05 +00:00
|
|
|
/// This function searches for things that need to be done, such
|
|
|
|
/// as sending out mail, toggling flags etc ...
|
2002-10-04 02:59:05 +00:00
|
|
|
|
|
|
|
global $CFG;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2002-10-17 07:23:51 +00:00
|
|
|
function quiz_grades($quizid) {
|
2002-10-17 07:55:54 +00:00
|
|
|
/// Must return an array of grades, indexed by user, and a max grade.
|
|
|
|
|
2003-09-10 05:02:39 +00:00
|
|
|
$quiz = get_record("quiz", "id", $quizid);
|
|
|
|
if (empty($quiz) or empty($quiz->grade)) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2002-12-23 09:39:26 +00:00
|
|
|
$return->grades = get_records_menu("quiz_grades", "quiz", $quizid, "", "userid,grade");
|
2002-10-17 07:55:54 +00:00
|
|
|
$return->maxgrade = get_field("quiz", "grade", "id", "$quizid");
|
|
|
|
return $return;
|
2002-10-17 07:23:51 +00:00
|
|
|
}
|
|
|
|
|
2003-09-28 14:57:16 +00:00
|
|
|
function quiz_get_participants($quizid) {
|
|
|
|
/// Returns an array of users who have data in a given quiz
|
|
|
|
/// (users with records in quiz_attempts, students)
|
|
|
|
|
|
|
|
global $CFG;
|
|
|
|
|
|
|
|
return get_records_sql("SELECT DISTINCT u.*
|
|
|
|
FROM {$CFG->prefix}user u,
|
|
|
|
{$CFG->prefix}quiz_attempts a
|
2004-06-02 18:03:05 +00:00
|
|
|
WHERE a.quiz = '$quizid' and
|
2003-09-28 14:57:16 +00:00
|
|
|
u.id = a.userid");
|
|
|
|
}
|
2002-10-04 02:59:05 +00:00
|
|
|
|
2004-04-28 02:56:40 +00:00
|
|
|
function quiz_refresh_events($courseid = 0) {
|
|
|
|
// This standard function will check all instances of this module
|
|
|
|
// and make sure there are up-to-date events created for each of them.
|
2004-05-17 17:04:01 +00:00
|
|
|
// If courseid = 0, then every quiz event in the site is checked, else
|
|
|
|
// only quiz events belonging to the course specified are checked.
|
2004-04-28 02:56:40 +00:00
|
|
|
// This function is used, in its new format, by restore_refresh_events()
|
|
|
|
|
|
|
|
if ($courseid == 0) {
|
|
|
|
if (! $quizzes = get_records("quiz")) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (! $quizzes = get_records("quiz", "course", $courseid)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2004-05-05 07:07:56 +00:00
|
|
|
$moduleid = get_field('modules', 'id', 'name', 'quiz');
|
2004-06-02 18:03:05 +00:00
|
|
|
|
2004-04-28 02:56:40 +00:00
|
|
|
foreach ($quizzes as $quiz) {
|
|
|
|
$event = NULL;
|
2004-05-17 17:04:01 +00:00
|
|
|
$event2 = NULL;
|
|
|
|
$event2old = NULL;
|
|
|
|
|
|
|
|
if ($events = get_records_select('event', "modulename = 'quiz' AND instance = '$quiz->id' ORDER BY timestart")) {
|
|
|
|
$event = array_shift($events);
|
|
|
|
if (!empty($events)) {
|
|
|
|
$event2old = array_shift($events);
|
|
|
|
if (!empty($events)) {
|
|
|
|
foreach ($events as $badevent) {
|
|
|
|
delete_records('event', 'id', $badevent->id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-04-28 02:56:40 +00:00
|
|
|
$event->name = addslashes($quiz->name);
|
|
|
|
$event->description = addslashes($quiz->intro);
|
2004-05-17 17:04:01 +00:00
|
|
|
$event->courseid = $quiz->course;
|
|
|
|
$event->groupid = 0;
|
|
|
|
$event->userid = 0;
|
|
|
|
$event->modulename = 'quiz';
|
|
|
|
$event->instance = $quiz->id;
|
2004-08-08 15:09:39 +00:00
|
|
|
$event->visible = instance_is_visible('quiz', $quiz);
|
2004-04-28 02:56:40 +00:00
|
|
|
$event->timestart = $quiz->timeopen;
|
2004-05-17 17:04:01 +00:00
|
|
|
$event->eventtype = 'open';
|
2004-04-28 02:56:40 +00:00
|
|
|
$event->timeduration = ($quiz->timeclose - $quiz->timeopen);
|
|
|
|
|
2004-05-17 17:04:01 +00:00
|
|
|
if ($event->timeduration > QUIZ_MAX_EVENT_LENGTH) { /// Set up two events
|
2004-04-28 02:56:40 +00:00
|
|
|
|
2004-05-17 17:04:01 +00:00
|
|
|
$event2 = $event;
|
2004-04-28 02:56:40 +00:00
|
|
|
|
2004-05-17 17:04:01 +00:00
|
|
|
$event->name = addslashes($quiz->name).' ('.get_string('quizopens', 'quiz').')';
|
|
|
|
$event->timeduration = 0;
|
|
|
|
|
|
|
|
$event2->name = addslashes($quiz->name).' ('.get_string('quizcloses', 'quiz').')';
|
|
|
|
$event2->timestart = $quiz->timeclose;
|
|
|
|
$event2->eventtype = 'close';
|
|
|
|
$event2->timeduration = 0;
|
|
|
|
|
|
|
|
if (empty($event2old->id)) {
|
|
|
|
unset($event2->id);
|
|
|
|
add_event($event2);
|
|
|
|
} else {
|
|
|
|
$event2->id = $event2old->id;
|
|
|
|
update_event($event2);
|
|
|
|
}
|
|
|
|
} else if (!empty($event2->id)) {
|
|
|
|
delete_event($event2->id);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (empty($event->id)) {
|
2004-04-28 02:56:40 +00:00
|
|
|
add_event($event);
|
2004-05-17 17:04:01 +00:00
|
|
|
} else {
|
|
|
|
update_event($event);
|
2004-04-28 02:56:40 +00:00
|
|
|
}
|
2004-05-17 17:04:01 +00:00
|
|
|
|
2004-04-28 02:56:40 +00:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2002-12-22 13:55:30 +00:00
|
|
|
/// SQL FUNCTIONS ////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
function quiz_move_questions($category1, $category2) {
|
|
|
|
global $CFG;
|
2004-06-02 18:03:05 +00:00
|
|
|
return execute_sql("UPDATE {$CFG->prefix}quiz_questions
|
|
|
|
SET category = '$category2'
|
|
|
|
WHERE category = '$category1'",
|
2002-12-22 13:55:30 +00:00
|
|
|
false);
|
|
|
|
}
|
|
|
|
|
|
|
|
function quiz_get_question_grades($quizid, $questionlist) {
|
|
|
|
global $CFG;
|
|
|
|
|
2004-06-02 18:03:05 +00:00
|
|
|
return get_records_sql("SELECT question,grade
|
|
|
|
FROM {$CFG->prefix}quiz_question_grades
|
|
|
|
WHERE quiz = '$quizid'
|
2002-12-22 13:55:30 +00:00
|
|
|
AND question IN ($questionlist)");
|
|
|
|
}
|
|
|
|
|
|
|
|
function quiz_get_grade_records($quiz) {
|
|
|
|
/// Gets all info required to display the table of quiz results
|
|
|
|
/// for report.php
|
|
|
|
global $CFG;
|
|
|
|
|
2004-06-02 18:03:05 +00:00
|
|
|
return get_records_sql("SELECT qg.*, u.firstname, u.lastname, u.picture
|
|
|
|
FROM {$CFG->prefix}quiz_grades qg,
|
2002-12-22 13:55:30 +00:00
|
|
|
{$CFG->prefix}user u
|
|
|
|
WHERE qg.quiz = '$quiz->id'
|
2002-12-23 09:39:26 +00:00
|
|
|
AND qg.userid = u.id");
|
2002-12-22 13:55:30 +00:00
|
|
|
}
|
|
|
|
|
2004-07-21 13:01:08 +00:00
|
|
|
function quiz_get_answers($question) {
|
2003-04-09 06:32:51 +00:00
|
|
|
// Given a question, returns the correct answers for a given question
|
2004-07-21 13:01:08 +00:00
|
|
|
global $QUIZ_QTYPES;
|
2003-08-01 08:37:11 +00:00
|
|
|
|
2004-07-21 13:01:08 +00:00
|
|
|
return $QUIZ_QTYPES[$question->qtype]->get_answers($question);
|
2002-12-22 13:55:30 +00:00
|
|
|
}
|
|
|
|
|
2004-07-21 13:01:08 +00:00
|
|
|
function quiz_get_attempt_questions($quiz, $attempt, $attempting = false) {
|
|
|
|
/// Returns the questions of the quiz attempt at a format used for
|
|
|
|
/// grading and printing them...
|
|
|
|
/// On top of the ordinary persistent question fields,
|
2004-09-16 06:35:49 +00:00
|
|
|
/// this function also set these properties:
|
|
|
|
//
|
2004-07-21 13:01:08 +00:00
|
|
|
/// ->response - contains names (as keys) and values (as values)
|
|
|
|
/// for all question html-form inputs
|
|
|
|
/// ->recentlyadded - true only if the question has been added to the quiz
|
|
|
|
/// after the responses for the attempt were saved;
|
|
|
|
/// false otherwise
|
|
|
|
/// ->maxgrade - the max grade the question has on the quiz if grades
|
|
|
|
/// are used on the quiz; false otherwise
|
|
|
|
|
|
|
|
global $QUIZ_QTYPES;
|
2002-12-22 13:55:30 +00:00
|
|
|
global $CFG;
|
2004-06-02 18:03:05 +00:00
|
|
|
|
2004-09-16 06:35:49 +00:00
|
|
|
/////////////////////////
|
2004-07-21 13:01:08 +00:00
|
|
|
/// Get the questions:
|
2004-09-16 06:35:49 +00:00
|
|
|
/////////////////////////
|
2004-07-21 13:01:08 +00:00
|
|
|
if (!($questions =
|
|
|
|
get_records_list('quiz_questions', 'id', $quiz->questions))) {
|
|
|
|
notify('Error when reading questions from the database!');
|
2002-12-22 13:55:30 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2004-09-16 06:35:49 +00:00
|
|
|
////////////////////////////////////////////
|
|
|
|
/// Determine ->maxgrade for all questions
|
|
|
|
////////////////////////////////////////////
|
2004-07-21 13:01:08 +00:00
|
|
|
If (!($grades = quiz_get_question_grades($quiz->id, $quiz->questions))) {
|
|
|
|
$grades = array();
|
|
|
|
}
|
|
|
|
foreach ($questions as $qid => $question) {
|
|
|
|
if (isset($grades[$qid])) {
|
|
|
|
$questions[$qid]->maxgrade = $grades[$qid]->grade;
|
|
|
|
} else {
|
|
|
|
$questions[$qid]->maxgrade = 0.0;
|
|
|
|
}
|
2003-04-09 06:32:51 +00:00
|
|
|
}
|
2004-09-16 06:35:49 +00:00
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
/// Determine attributes ->response and ->recentlyadded (hard)
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
/// Get all existing responses on this attempt
|
|
|
|
$rawresponses = get_records_sql("
|
|
|
|
SELECT question, answer, attempt
|
|
|
|
FROM {$CFG->prefix}quiz_responses
|
|
|
|
WHERE attempt = '$attempt->id' ");
|
2004-07-21 13:01:08 +00:00
|
|
|
|
2004-09-16 06:35:49 +00:00
|
|
|
/// The setting for ->recentlyadded depends on whether this is
|
|
|
|
/// a test attempt of just a review
|
2004-07-21 13:01:08 +00:00
|
|
|
if ($attempting) {
|
2004-09-16 06:35:49 +00:00
|
|
|
/// This is a test attempt so there is a need to create responses
|
|
|
|
/// in case there are none existing.
|
|
|
|
/// Further - the attribute recentlyadded is determined from
|
|
|
|
/// whether the question has a response in the previous attempt,
|
|
|
|
/// which might be used in case the attemptonlast quiz option
|
|
|
|
/// is true.
|
|
|
|
|
|
|
|
$prevattempt = $attempt->attempt;
|
|
|
|
$prevresponses= array();
|
|
|
|
while (--$prevattempt) {
|
|
|
|
$prevresponses = get_records_sql("
|
|
|
|
SELECT r.question, r.answer, r.attempt
|
|
|
|
FROM {$CFG->prefix}quiz_responses r, {$CFG->prefix}quiz_attempts a
|
|
|
|
WHERE a.quiz='$quiz->id' AND a.userid='$attempt->userid'
|
|
|
|
AND a.attempt='$prevattempt' AND r.attempt=a.id ");
|
|
|
|
if (!empty($prevresponses)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2004-07-21 13:01:08 +00:00
|
|
|
|
2004-09-16 06:35:49 +00:00
|
|
|
$questionsinuse = $quiz->questions; // used if responses must be created
|
|
|
|
foreach ($questions as $qid => $question) {
|
|
|
|
if ($questions[$qid]->recentlyadded =
|
|
|
|
$prevattempt && empty($prevresponses[$qid])) {
|
|
|
|
/* No action */
|
|
|
|
|
|
|
|
} else if ($prevattempt && $quiz->attemptonlast
|
|
|
|
&& empty($rawresponses[$qid])) {
|
|
|
|
/// Store the previous response on this attempt!
|
|
|
|
$rawresponses[$qid] = $prevresponses[$qid];
|
|
|
|
$rawresponses[$qid]->attempt = $attempt->id;
|
|
|
|
$rawresponses[$qid]->id =
|
|
|
|
insert_record("quiz_responses", $rawresponses[$qid])
|
|
|
|
or error("Unable to create attemptonlast response for question $qid");
|
|
|
|
|
|
|
|
///////////////////////////////////////////
|
|
|
|
/// WORKAROUND FOR QUESTION TYPE RANDOM ///
|
|
|
|
///////////////////////////////////////////
|
|
|
|
if (RANDOM == $question->qtype) {
|
|
|
|
$randomqid = $prevresponses[$qid]->answer;
|
|
|
|
if (empty($prevresponses[$randomqid]) || ereg(
|
|
|
|
"(^|,)$randomqid(,|$)", $questionsinuse)) {
|
|
|
|
// Ooops!
|
|
|
|
// The randomly picked question has been included
|
|
|
|
// among the fixed ones or did not get any response
|
|
|
|
// in the previous attempt - either way the raw
|
|
|
|
// responserecord created above needs to go!
|
|
|
|
delete_records('quiz_responses', 'id',
|
|
|
|
$rawresponses[$qid]->id);
|
|
|
|
unset($rawresponses[$qid]);
|
|
|
|
|
|
|
|
} else if (empty($rawresponses[$randomqid])) {
|
|
|
|
/// Also copy this response from the previous attempt
|
|
|
|
$rawresponses[$randomqid] = $prevresponses[$randomqid];
|
|
|
|
$rawresponses[$randomqid]->attempt = $attempt->id;
|
|
|
|
$rawresponses[$randomqid]->id =
|
|
|
|
insert_record('quiz_responses', $rawresponses[$randomqid])
|
|
|
|
or error("Unable to create attemptonlast response for question $qid");
|
|
|
|
|
|
|
|
}
|
|
|
|
} ////// END OF WORKAROUND ///////
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Extract possible response and its wrapped questions */
|
|
|
|
if (!empty($rawresponses[$qid])) {
|
|
|
|
$questions[$qid]->response = $QUIZ_QTYPES[$question->qtype]
|
|
|
|
->extract_response($rawresponses[$qid],
|
|
|
|
quiz_qtype_nameprefix($question));
|
|
|
|
/// Catch any additional wrapped questions:
|
|
|
|
if ($wrapped = $QUIZ_QTYPES[$question->qtype]
|
|
|
|
->wrapped_questions($questions[$question->id],
|
|
|
|
quiz_qtype_nameprefix($question))) {
|
|
|
|
$questionsinuse .= ",$wrapped";
|
|
|
|
}
|
2004-07-21 13:01:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Make sure all the questions will have responses:
|
|
|
|
foreach ($questions as $question) {
|
|
|
|
if (empty($question->response)) {
|
2004-09-16 06:35:49 +00:00
|
|
|
/// No response on this question
|
|
|
|
|
2004-07-21 13:01:08 +00:00
|
|
|
$nameprefix = quiz_qtype_nameprefix($question);
|
|
|
|
$questions[$question->id]->response =
|
|
|
|
$QUIZ_QTYPES[$question->qtype]->create_response
|
|
|
|
($question, $nameprefix, $questionsinuse);
|
|
|
|
|
2004-09-16 06:35:49 +00:00
|
|
|
//////////////////////////////////////////////
|
|
|
|
// Saving the newly created response before
|
|
|
|
// continuing with the quiz...
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
$responserecord->attempt = $attempt->id;
|
|
|
|
$responserecord->question = $question->id;
|
|
|
|
$responserecord->answer = $QUIZ_QTYPES[$question->qtype]
|
|
|
|
->convert_to_response_answer_field
|
|
|
|
($questions[$question->id]->response);
|
|
|
|
|
|
|
|
///////////////////////////////////////////
|
|
|
|
// WORKAROUND for question type RANDOM:
|
|
|
|
///////////////////////////////////////////
|
|
|
|
if ($question->qtype == RANDOM and ereg(
|
|
|
|
'^random([0-9]+)-(.*)$', $responserecord->answer, $afields)) {
|
|
|
|
$responserecord->answer = $afields[1];
|
|
|
|
insert_record("quiz_responses", $responserecord)
|
|
|
|
or error("Unable to create an initial random response for question $question->id");
|
|
|
|
|
|
|
|
$responserecord->question = $responserecord->answer;
|
|
|
|
$responserecord->answer = $afields[2];
|
|
|
|
} /// End of WORKAROUND //////////////////////
|
|
|
|
|
|
|
|
insert_record("quiz_responses", $responserecord)
|
|
|
|
or error("Unable to create initial response for question $question->id");
|
2004-07-21 13:01:08 +00:00
|
|
|
|
|
|
|
/// Catch any additional wrapped questions:
|
|
|
|
if ($wrapped = $QUIZ_QTYPES[$question->qtype]
|
|
|
|
->wrapped_questions($questions[$question->id],
|
2004-09-16 06:35:49 +00:00
|
|
|
quiz_qtype_nameprefix($question))) {
|
2004-07-21 13:01:08 +00:00
|
|
|
$questionsinuse .= ",$wrapped";
|
|
|
|
}
|
|
|
|
}
|
2003-04-09 06:32:51 +00:00
|
|
|
}
|
2004-09-16 06:35:49 +00:00
|
|
|
|
|
|
|
} else {
|
|
|
|
/// In the case of review, the recentlyadded flag is set true
|
|
|
|
/// when the question has been added after the attempt and new
|
|
|
|
/// responses are never created
|
|
|
|
|
|
|
|
foreach ($questions as $qid => $question) {
|
|
|
|
if ($questions[$qid]->recentlyadded = empty($rawresponses[$qid])) {
|
|
|
|
/* No action */
|
|
|
|
} else {
|
|
|
|
$questions[$qid]->response = $QUIZ_QTYPES[$question->qtype]
|
|
|
|
->extract_response($rawresponses[$qid],
|
|
|
|
quiz_qtype_nameprefix($question));
|
|
|
|
}
|
|
|
|
}
|
2002-12-22 13:55:30 +00:00
|
|
|
}
|
|
|
|
|
2004-07-21 13:01:08 +00:00
|
|
|
return $questions;
|
2002-12-22 13:55:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-02-19 07:53:09 +00:00
|
|
|
function get_list_of_questions($questionlist) {
|
|
|
|
/// Returns an ordered list of questions, including course for each
|
|
|
|
|
|
|
|
global $CFG;
|
|
|
|
|
2004-06-02 18:03:05 +00:00
|
|
|
return get_records_sql("SELECT q.*,c.course
|
2004-02-19 07:53:09 +00:00
|
|
|
FROM {$CFG->prefix}quiz_questions q,
|
|
|
|
{$CFG->prefix}quiz_categories c
|
|
|
|
WHERE q.id in ($questionlist)
|
|
|
|
AND q.category = c.id");
|
|
|
|
}
|
2002-12-22 13:55:30 +00:00
|
|
|
|
2002-10-04 02:59:05 +00:00
|
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
2004-06-02 18:03:05 +00:00
|
|
|
/// Any other quiz functions go here. Each of them must have a name that
|
2002-10-13 07:17:48 +00:00
|
|
|
/// starts with quiz_
|
2002-10-04 02:59:05 +00:00
|
|
|
|
2004-07-21 13:01:08 +00:00
|
|
|
function quiz_qtype_nameprefix($question, $prefixstart='question') {
|
|
|
|
global $QUIZ_QTYPES;
|
|
|
|
return $prefixstart.$question->id.$QUIZ_QTYPES[$question->qtype]->name();
|
|
|
|
}
|
|
|
|
function quiz_extract_posted_id($name, $nameprefix='question') {
|
|
|
|
if (ereg("^$nameprefix([0-9]+)", $name, $regs)) {
|
|
|
|
return $regs[1];
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-10-16 09:35:04 +00:00
|
|
|
function quiz_print_comment($text) {
|
|
|
|
global $THEME;
|
|
|
|
|
2004-02-18 03:07:50 +00:00
|
|
|
echo "<span class=\"feedbacktext\">".format_text($text, true, false)."</span>";
|
2002-10-16 09:35:04 +00:00
|
|
|
}
|
|
|
|
|
2002-10-20 05:35:25 +00:00
|
|
|
function quiz_print_correctanswer($text) {
|
|
|
|
global $THEME;
|
|
|
|
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "<p align=\"right\"><span class=\"highlight\">$text</span></p>";
|
2002-10-20 05:35:25 +00:00
|
|
|
}
|
|
|
|
|
2003-04-09 06:32:51 +00:00
|
|
|
function quiz_print_question_icon($question, $editlink=true) {
|
2002-10-20 17:15:39 +00:00
|
|
|
// Prints a question icon
|
2002-10-23 12:10:38 +00:00
|
|
|
|
|
|
|
global $QUIZ_QUESTION_TYPE;
|
2004-07-21 13:01:08 +00:00
|
|
|
global $QUIZ_QTYPES;
|
2002-10-23 12:10:38 +00:00
|
|
|
|
2003-04-09 06:32:51 +00:00
|
|
|
if ($editlink) {
|
2004-07-21 13:01:08 +00:00
|
|
|
echo "<a href=\"question.php?id=$question->id\" title=\""
|
|
|
|
.$QUIZ_QUESTION_TYPE[$question->qtype]."\">";
|
2002-10-20 17:15:39 +00:00
|
|
|
}
|
2004-07-21 13:01:08 +00:00
|
|
|
echo '<img border="0" height="16" width="16" src="questiontypes/';
|
2004-09-16 17:13:57 +00:00
|
|
|
echo $QUIZ_QTYPES[$question->qtype]->name().'/icon.gif" alt="" />';
|
2003-04-09 06:32:51 +00:00
|
|
|
if ($editlink) {
|
2003-07-10 13:25:07 +00:00
|
|
|
echo "</a>\n";
|
2003-04-09 06:32:51 +00:00
|
|
|
}
|
2002-10-20 17:15:39 +00:00
|
|
|
}
|
|
|
|
|
2003-11-02 21:36:25 +00:00
|
|
|
function quiz_print_possible_question_image($quizid, $question) {
|
2004-07-21 13:01:08 +00:00
|
|
|
// Includes the question image if there is one
|
2002-10-16 09:35:04 +00:00
|
|
|
|
2003-11-02 21:36:25 +00:00
|
|
|
global $CFG;
|
|
|
|
|
|
|
|
if ($question->image) {
|
2003-12-30 07:28:43 +00:00
|
|
|
echo '<img border="0" src="';
|
2003-11-02 21:36:25 +00:00
|
|
|
|
2003-12-30 07:28:43 +00:00
|
|
|
if (substr(strtolower($question->image), 0, 7) == 'http://') {
|
2003-11-02 21:36:25 +00:00
|
|
|
echo $question->image;
|
|
|
|
|
|
|
|
} else if ($CFG->slasharguments) { // Use this method if possible for better caching
|
|
|
|
echo "$CFG->wwwroot/mod/quiz/quizfile.php/$quizid/$question->id/$question->image";
|
|
|
|
|
|
|
|
} else {
|
|
|
|
echo "$CFG->wwwroot/mod/quiz/quizfile.php?file=/$quizid/$question->id/$question->image";
|
|
|
|
}
|
2004-09-16 17:13:57 +00:00
|
|
|
echo '" alt="" />';
|
2003-11-02 21:36:25 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
}
|
2003-04-09 06:32:51 +00:00
|
|
|
|
2004-07-21 13:01:08 +00:00
|
|
|
function quiz_print_quiz_questions($quiz, $questions,
|
|
|
|
$results=NULL, $shuffleorder=NULL) {
|
2002-10-13 07:17:48 +00:00
|
|
|
// Prints a whole quiz on one page.
|
|
|
|
|
2004-07-21 13:01:08 +00:00
|
|
|
global $QUIZ_QTYPES;
|
2003-04-09 06:32:51 +00:00
|
|
|
|
2004-07-21 13:01:08 +00:00
|
|
|
/// Check arguments
|
2003-04-09 07:23:42 +00:00
|
|
|
|
2004-07-21 13:01:08 +00:00
|
|
|
if (empty($questions)) {
|
|
|
|
notify("No questions have been defined!");
|
|
|
|
return false;
|
2003-05-14 16:52:25 +00:00
|
|
|
}
|
2003-04-09 13:57:08 +00:00
|
|
|
|
2003-05-14 16:52:25 +00:00
|
|
|
if (!$shuffleorder) {
|
|
|
|
if (!empty($quiz->shufflequestions)) { // Mix everything up
|
2003-04-09 13:57:08 +00:00
|
|
|
$questions = swapshuffle_assoc($questions);
|
2003-05-14 15:23:54 +00:00
|
|
|
} else {
|
2003-05-14 16:52:25 +00:00
|
|
|
$shuffleorder = explode(",", $quiz->questions); // Use originally defined order
|
2003-04-09 13:57:08 +00:00
|
|
|
}
|
2003-04-09 06:32:51 +00:00
|
|
|
}
|
|
|
|
|
2004-07-21 13:01:08 +00:00
|
|
|
if ($shuffleorder) { // Order has been defined, so reorder questions
|
2003-04-16 13:48:16 +00:00
|
|
|
$oldquestions = $questions;
|
|
|
|
$questions = array();
|
2003-08-03 21:39:32 +00:00
|
|
|
foreach ($shuffleorder as $key) {
|
2004-07-21 13:01:08 +00:00
|
|
|
$questions[] = $oldquestions[$key]; // This loses the index key, but doesn't matter
|
2003-04-09 07:23:42 +00:00
|
|
|
}
|
2002-10-13 07:17:48 +00:00
|
|
|
}
|
|
|
|
|
2002-12-09 08:20:19 +00:00
|
|
|
$strconfirmattempt = addslashes(get_string("readytosend", "quiz"));
|
|
|
|
|
2003-11-15 03:31:37 +00:00
|
|
|
if (empty($quiz->grade)) {
|
|
|
|
$onsubmit = "";
|
|
|
|
} else {
|
|
|
|
$onsubmit = "onsubmit=\"return confirm('$strconfirmattempt');\"";
|
|
|
|
}
|
2004-06-02 18:03:05 +00:00
|
|
|
// BEGIN EDIT
|
|
|
|
if($quiz->timelimit > 0) {
|
|
|
|
?>
|
|
|
|
<script language="javascript" type="text/javascript">
|
|
|
|
<!--
|
|
|
|
document.write("<form method=\"post\" action=\"attempt.php\" <?php print(addslashes($onsubmit));?>>\n");
|
|
|
|
// -->
|
|
|
|
</script>
|
|
|
|
<noscript>
|
2004-06-20 10:57:27 +00:00
|
|
|
<center><p><strong><?php print_string("noscript","quiz"); ?></strong></p></center>
|
2004-06-02 18:03:05 +00:00
|
|
|
</noscript>
|
|
|
|
<?php
|
|
|
|
} else {
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "<form method=\"post\" action=\"attempt.php\" $onsubmit>\n";
|
2004-06-02 18:03:05 +00:00
|
|
|
}
|
|
|
|
// END EDIT
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "<input type=\"hidden\" name=\"q\" value=\"$quiz->id\" />\n";
|
2002-10-16 09:35:04 +00:00
|
|
|
|
2004-07-21 13:01:08 +00:00
|
|
|
// $count = 0;
|
|
|
|
$nextquestionnumber = 1;
|
2003-04-16 13:10:48 +00:00
|
|
|
$questionorder = array();
|
|
|
|
|
2004-07-21 13:01:08 +00:00
|
|
|
// $readonly determines if it is an attempt or an review,
|
|
|
|
// The condition used here is unfortunatelly somewhat confusing...
|
|
|
|
$readonly = !empty($results) && !isset($results->attemptbuildsonthelast)
|
2004-11-25 10:01:56 +00:00
|
|
|
? ' disabled="disabled" ' : '';
|
2003-07-06 04:00:05 +00:00
|
|
|
|
2004-07-21 13:01:08 +00:00
|
|
|
foreach ($questions as $question) {
|
2003-04-09 06:32:51 +00:00
|
|
|
|
2004-11-10 14:06:20 +00:00
|
|
|
if (empty($question->qtype)) { // Just for robustness
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2003-04-16 13:48:16 +00:00
|
|
|
$questionorder[] = $question->id;
|
|
|
|
|
2004-07-21 13:01:08 +00:00
|
|
|
if ($results && isset($results->details[$question->id])) {
|
|
|
|
$details = $results->details[$question->id];
|
2003-04-09 06:32:51 +00:00
|
|
|
} else {
|
2004-07-21 13:01:08 +00:00
|
|
|
$details = false;
|
2002-10-16 09:35:04 +00:00
|
|
|
}
|
2002-10-20 05:35:25 +00:00
|
|
|
|
2003-12-30 07:04:04 +00:00
|
|
|
print_simple_box_start("center", "90%");
|
2004-07-21 13:01:08 +00:00
|
|
|
$nextquestionnumber = $QUIZ_QTYPES[$question->qtype]->print_question
|
|
|
|
($nextquestionnumber, $quiz, $question, $readonly, $details);
|
2002-10-13 07:17:48 +00:00
|
|
|
print_simple_box_end();
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "<br />";
|
2002-10-13 07:17:48 +00:00
|
|
|
}
|
2002-10-16 09:35:04 +00:00
|
|
|
|
2004-07-21 13:01:08 +00:00
|
|
|
if (empty($readonly)) {
|
2003-04-16 13:10:48 +00:00
|
|
|
if (!empty($quiz->shufflequestions)) { // Things have been mixed up, so pass the question order
|
|
|
|
$shuffleorder = implode(',', $questionorder);
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "<input type=\"hidden\" name=\"shuffleorder\" value=\"$shuffleorder\" />\n";
|
2003-04-16 13:10:48 +00:00
|
|
|
}
|
2004-06-20 10:57:27 +00:00
|
|
|
if($quiz->timelimit > 0) {
|
|
|
|
echo "<script language=\"javascript\" type=\"text/javascript\">\n";
|
|
|
|
echo "<!--\n";
|
|
|
|
echo "document.write('<center><input type=\"button\" value=\"".get_string("savemyanswers", "quiz")."\" onclick=\"return send_data();\" /></center>');\n";
|
|
|
|
echo "// -->\n";
|
|
|
|
echo "</script>\n";
|
|
|
|
echo "<noscript>\n";
|
|
|
|
echo "<center><strong>".get_string("noscript","quiz")."</strong></center>\n";
|
|
|
|
echo "</noscript>\n";
|
|
|
|
} else {
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "<center>\n<input type=\"submit\" value=\"".get_string("savemyanswers", "quiz")."\" />\n</center>";
|
2002-10-16 09:35:04 +00:00
|
|
|
}
|
2004-06-20 10:57:27 +00:00
|
|
|
}
|
2003-04-16 13:10:48 +00:00
|
|
|
echo "</form>";
|
2002-10-14 15:57:33 +00:00
|
|
|
|
|
|
|
return true;
|
2002-10-13 07:17:48 +00:00
|
|
|
}
|
2003-04-09 06:32:51 +00:00
|
|
|
|
|
|
|
|
2004-06-02 18:03:05 +00:00
|
|
|
|
2002-10-14 09:07:13 +00:00
|
|
|
function quiz_get_default_category($courseid) {
|
2003-04-09 06:32:51 +00:00
|
|
|
/// Returns the current category
|
|
|
|
|
2002-10-14 09:07:13 +00:00
|
|
|
if ($categories = get_records("quiz_categories", "course", $courseid, "id")) {
|
|
|
|
foreach ($categories as $category) {
|
|
|
|
return $category; // Return the first one (lowest id)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, we need to make one
|
2002-10-14 15:57:33 +00:00
|
|
|
$category->name = get_string("default", "quiz");
|
|
|
|
$category->info = get_string("defaultinfo", "quiz");
|
2002-10-14 09:07:13 +00:00
|
|
|
$category->course = $courseid;
|
|
|
|
$category->publish = 0;
|
2003-08-28 17:07:24 +00:00
|
|
|
$category->stamp = make_unique_id_code();
|
2002-10-14 09:07:13 +00:00
|
|
|
|
|
|
|
if (!$category->id = insert_record("quiz_categories", $category)) {
|
|
|
|
notify("Error creating a default category!");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return $category;
|
|
|
|
}
|
|
|
|
|
2002-10-20 17:15:39 +00:00
|
|
|
function quiz_get_category_menu($courseid, $published=false) {
|
2003-04-10 13:11:34 +00:00
|
|
|
/// Returns the list of categories
|
|
|
|
$publish = "";
|
2002-10-20 17:15:39 +00:00
|
|
|
if ($published) {
|
|
|
|
$publish = "OR publish = '1'";
|
|
|
|
}
|
2002-12-22 13:55:30 +00:00
|
|
|
return get_records_select_menu("quiz_categories", "course='$courseid' $publish", "name ASC", "id,name");
|
2002-10-20 17:15:39 +00:00
|
|
|
}
|
|
|
|
|
2002-10-14 09:07:13 +00:00
|
|
|
function quiz_print_category_form($course, $current) {
|
2004-11-18 07:32:31 +00:00
|
|
|
/// Prints a form to choose categories
|
2002-10-14 09:07:13 +00:00
|
|
|
|
2004-11-18 07:32:31 +00:00
|
|
|
/// Make sure the default category exists for this course
|
|
|
|
if (!$categories = get_records("quiz_categories", "course", $course->id, "id ASC")) {
|
2002-10-14 09:07:13 +00:00
|
|
|
if (!$category = quiz_get_default_category($course->id)) {
|
|
|
|
notify("Error creating a default category!");
|
|
|
|
}
|
2004-11-18 07:32:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Get all the existing categories now
|
|
|
|
if (!$categories = get_records_select("quiz_categories", "course = '$course->id' OR publish = '1'", "name ASC")) {
|
|
|
|
notify("Could not find any question categories!");
|
|
|
|
return false; // Something is really wrong
|
2002-10-14 09:07:13 +00:00
|
|
|
}
|
2002-10-15 12:54:11 +00:00
|
|
|
foreach ($categories as $key => $category) {
|
2004-01-21 16:04:55 +00:00
|
|
|
if ($catcourse = get_record("course", "id", $category->course)) {
|
|
|
|
if ($category->publish) {
|
2002-10-20 17:41:24 +00:00
|
|
|
$category->name .= " ($catcourse->shortname)";
|
2002-10-15 12:54:11 +00:00
|
|
|
}
|
2004-01-21 16:04:55 +00:00
|
|
|
$catmenu[$category->id] = $category->name;
|
2002-10-15 12:54:11 +00:00
|
|
|
}
|
|
|
|
}
|
2002-10-14 09:07:13 +00:00
|
|
|
$strcategory = get_string("category", "quiz");
|
|
|
|
$strshow = get_string("show", "quiz");
|
2002-10-15 16:45:39 +00:00
|
|
|
$streditcats = get_string("editcategories", "quiz");
|
2002-10-14 09:07:13 +00:00
|
|
|
|
2004-01-15 15:26:34 +00:00
|
|
|
echo "<table width=\"100%\"><tr><td width=\"20\" nowrap=\"nowrap\">";
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "<b>$strcategory:</b> ";
|
2004-01-15 15:26:34 +00:00
|
|
|
echo "</td><td>";
|
2004-01-21 03:22:16 +00:00
|
|
|
popup_form ("edit.php?cat=", $catmenu, "catmenu", $current, "choose", "", "", false, "self");
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "</td><td align=\"right\">";
|
2004-06-02 18:03:05 +00:00
|
|
|
echo "<form method=\"get\" action=\"category.php\">";
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "<input type=\"hidden\" name=\"id\" value=\"$course->id\" />";
|
|
|
|
echo "<input type=\"submit\" value=\"$streditcats\" />";
|
|
|
|
echo "</form>";
|
|
|
|
echo "</td></tr></table>";
|
2002-10-14 09:07:13 +00:00
|
|
|
}
|
|
|
|
|
2004-06-23 09:33:47 +00:00
|
|
|
function quiz_category_select_menu($courseid,$published=false,$only_editable=false,$selected="") {
|
2004-06-18 12:59:06 +00:00
|
|
|
/// displays a select menu of categories with appended coursenames
|
|
|
|
/// optionaly non editable categories may be excluded
|
|
|
|
/// added Howard Miller June '04
|
|
|
|
// get sql fragment for published
|
|
|
|
$publishsql="";
|
|
|
|
if ($published) {
|
|
|
|
$publishsql = "or publish=1";
|
|
|
|
}
|
|
|
|
$categories = get_records_select("quiz_categories","course=$courseid $publishsql");
|
|
|
|
echo "<select name=\"category\">\n";
|
|
|
|
foreach ($categories as $category) {
|
|
|
|
$cid = $category->id;
|
|
|
|
$cname = quiz_get_category_coursename( $category );
|
2004-06-23 09:33:47 +00:00
|
|
|
$seltxt = "";
|
|
|
|
if ($cid==$selected) {
|
2004-11-11 12:07:08 +00:00
|
|
|
$seltxt = "selected=\"selected\"";
|
2004-06-23 09:33:47 +00:00
|
|
|
}
|
2004-06-18 12:59:06 +00:00
|
|
|
if ((!$only_editable) || isteacheredit($category->course)) {
|
2004-06-23 09:33:47 +00:00
|
|
|
echo " <option value=\"$cid\" $seltxt>$cname</option>\n";
|
2004-06-18 12:59:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
echo "</select>\n";
|
|
|
|
}
|
2002-10-14 09:07:13 +00:00
|
|
|
|
2004-06-17 17:29:07 +00:00
|
|
|
function quiz_get_category_coursename($category) {
|
|
|
|
/// if the category is published, adds on the course
|
2004-06-22 20:44:59 +00:00
|
|
|
/// name
|
2004-06-17 17:29:07 +00:00
|
|
|
$cname=$category->name;
|
|
|
|
if ($category->publish) {
|
|
|
|
if ($catcourse=get_record("course","id",$category->id)) {
|
|
|
|
$cname .= " ($catcourse->shortname) ";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return $cname;
|
|
|
|
}
|
2003-04-09 06:32:51 +00:00
|
|
|
|
2002-10-14 12:21:18 +00:00
|
|
|
function quiz_get_all_question_grades($questionlist, $quizid) {
|
2004-06-02 18:03:05 +00:00
|
|
|
// Given a list of question IDs, finds grades or invents them to
|
2002-10-14 12:21:18 +00:00
|
|
|
// create an array of matching grades
|
|
|
|
|
2003-04-14 13:52:59 +00:00
|
|
|
if (empty($questionlist)) {
|
|
|
|
return array();
|
|
|
|
}
|
|
|
|
|
2002-12-22 13:55:30 +00:00
|
|
|
$questions = quiz_get_question_grades($quizid, $questionlist);
|
2002-10-14 12:21:18 +00:00
|
|
|
|
|
|
|
$list = explode(",", $questionlist);
|
|
|
|
$grades = array();
|
|
|
|
|
|
|
|
foreach ($list as $qid) {
|
|
|
|
if (isset($questions[$qid])) {
|
|
|
|
$grades[$qid] = $questions[$qid]->grade;
|
|
|
|
} else {
|
|
|
|
$grades[$qid] = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return $grades;
|
|
|
|
}
|
|
|
|
|
2003-10-31 21:27:43 +00:00
|
|
|
function quiz_gradesmenu_options($defaultgrade) {
|
|
|
|
// Especially for multianswer questions it is often
|
|
|
|
// desirable to have the grade of the question in a quiz
|
|
|
|
// larger than the earlier maximum of 10 points.
|
|
|
|
// This function makes quiz question list grade selector drop-down
|
|
|
|
// have the maximum grade option set to the highest value between 10
|
|
|
|
// and the defaultgrade of the question.
|
|
|
|
|
|
|
|
if ($defaultgrade && $defaultgrade>10) {
|
|
|
|
$maxgrade = $defaultgrade;
|
|
|
|
} else {
|
|
|
|
$maxgrade = 10;
|
|
|
|
}
|
|
|
|
|
|
|
|
unset($gradesmenu);
|
|
|
|
for ($i=$maxgrade ; $i>=0 ; --$i) {
|
|
|
|
$gradesmenu[$i] = $i;
|
|
|
|
}
|
|
|
|
return $gradesmenu;
|
|
|
|
}
|
2002-10-14 12:21:18 +00:00
|
|
|
|
|
|
|
function quiz_print_question_list($questionlist, $grades) {
|
2002-10-14 09:07:13 +00:00
|
|
|
// Prints a list of quiz questions in a small layout form with knobs
|
2002-10-14 12:21:18 +00:00
|
|
|
// $questionlist is comma-separated list
|
|
|
|
// $grades is an array of corresponding grades
|
2002-10-14 09:07:13 +00:00
|
|
|
|
|
|
|
global $THEME;
|
|
|
|
|
|
|
|
if (!$questionlist) {
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "<p align=\"center\">";
|
2002-10-14 09:07:13 +00:00
|
|
|
print_string("noquestions", "quiz");
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "</p>";
|
2002-10-14 09:07:13 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
$order = explode(",", $questionlist);
|
|
|
|
|
2004-02-19 07:53:09 +00:00
|
|
|
if (!$questions = get_list_of_questions($questionlist)) {
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "<p align=\"center\">";
|
2003-04-28 06:36:14 +00:00
|
|
|
print_string("noquestions", "quiz");
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "</p>";
|
2003-04-28 06:36:14 +00:00
|
|
|
return;
|
|
|
|
|
2002-10-14 09:07:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
$strorder = get_string("order");
|
|
|
|
$strquestionname = get_string("questionname", "quiz");
|
|
|
|
$strgrade = get_string("grade");
|
|
|
|
$strdelete = get_string("delete");
|
|
|
|
$stredit = get_string("edit");
|
|
|
|
$strmoveup = get_string("moveup");
|
|
|
|
$strmovedown = get_string("movedown");
|
|
|
|
$strsavegrades = get_string("savegrades", "quiz");
|
2002-10-20 17:15:39 +00:00
|
|
|
$strtype = get_string("type", "quiz");
|
2004-08-16 15:16:26 +00:00
|
|
|
$strpreview = get_string("preview", "quiz");
|
2002-10-14 09:07:13 +00:00
|
|
|
|
|
|
|
$count = 0;
|
|
|
|
$sumgrade = 0;
|
|
|
|
$total = count($order);
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "<form method=\"post\" action=\"edit.php\">";
|
|
|
|
echo "<table border=\"0\" cellpadding=\"5\" cellspacing=\"2\" width=\"100%\">\n";
|
|
|
|
echo "<tr><th width=\"*\" colspan=\"3\" nowrap=\"nowrap\">$strorder</th><th align=\"left\" width=\"100%\" nowrap=\"nowrap\">$strquestionname</th><th width=\"*\" nowrap=\"nowrap\">$strtype</th><th width=\"*\" nowrap=\"nowrap\">$strgrade</th><th width=\"*\" nowrap=\"nowrap\">$stredit</th></tr>\n";
|
2002-10-14 09:07:13 +00:00
|
|
|
foreach ($order as $qnum) {
|
2003-02-24 10:37:56 +00:00
|
|
|
if (empty($questions[$qnum])) {
|
|
|
|
continue;
|
|
|
|
}
|
2003-07-06 04:19:11 +00:00
|
|
|
$question = $questions[$qnum];
|
2004-02-19 07:53:09 +00:00
|
|
|
$canedit = isteacheredit($question->course);
|
2002-10-14 09:07:13 +00:00
|
|
|
$count++;
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "<tr bgcolor=\"$THEME->cellcontent\">";
|
|
|
|
echo "<td>$count</td>";
|
|
|
|
echo "<td>";
|
2002-10-14 09:07:13 +00:00
|
|
|
if ($count != 1) {
|
2004-06-02 18:03:05 +00:00
|
|
|
echo "<a title=\"$strmoveup\" href=\"edit.php?up=$qnum\"><img
|
2004-09-16 17:13:57 +00:00
|
|
|
src=\"../../pix/t/up.gif\" border=\"0\" alt=\"\" /></a>";
|
2002-10-14 09:07:13 +00:00
|
|
|
}
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "</td>";
|
|
|
|
echo "<td>";
|
2002-10-14 09:07:13 +00:00
|
|
|
if ($count != $total) {
|
2004-06-02 18:03:05 +00:00
|
|
|
echo "<a title=\"$strmovedown\" href=\"edit.php?down=$qnum\"><img
|
2004-09-16 17:13:57 +00:00
|
|
|
src=\"../../pix/t/down.gif\" border=\"0\" alt=\"\" /></a>";
|
2002-10-14 09:07:13 +00:00
|
|
|
}
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "</td>";
|
|
|
|
echo "<td>$question->name</td>";
|
|
|
|
echo "<td align=\"center\">";
|
2004-02-19 07:53:09 +00:00
|
|
|
quiz_print_question_icon($question, $canedit);
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "</td>";
|
|
|
|
echo "<td>";
|
2003-07-06 04:19:11 +00:00
|
|
|
if ($question->qtype == DESCRIPTION) {
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "<input type=\"hidden\" name=\"q$qnum\" value=\"0\" /> \n";
|
2003-07-06 04:19:11 +00:00
|
|
|
} else {
|
2003-10-31 21:27:43 +00:00
|
|
|
choose_from_menu(quiz_gradesmenu_options($question->defaultgrade),
|
|
|
|
"q$qnum", (string)$grades[$qnum], "");
|
2003-07-06 04:19:11 +00:00
|
|
|
}
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "<td>";
|
2004-06-02 18:03:05 +00:00
|
|
|
echo "<a title=\"$strdelete\" href=\"edit.php?delete=$qnum\"><img
|
2004-09-16 17:13:57 +00:00
|
|
|
src=\"../../pix/t/delete.gif\" border=\"0\" alt=\"\" /></a> ";
|
2004-08-16 15:16:26 +00:00
|
|
|
echo "<a title=\"$strpreview\" href=\"#\" onClick=\"openpopup('/mod/quiz/preview.php?id=$qnum','$strpreview','scrollbars=yes,resizable=yes,width=700,height=480', false)\"><img
|
2004-09-16 17:13:57 +00:00
|
|
|
src=\"../../pix/i/search.gif\" border=\"0\" alt=\"\" /></a> ";
|
2004-08-16 15:16:26 +00:00
|
|
|
|
2004-02-19 07:53:09 +00:00
|
|
|
if ($canedit) {
|
2004-06-02 18:03:05 +00:00
|
|
|
echo "<a title=\"$stredit\" href=\"question.php?id=$qnum\"><img
|
2004-09-16 17:13:57 +00:00
|
|
|
src=\"../../pix/t/edit.gif\" border=\"0\" alt=\"\" /></a>\n";
|
2004-02-19 07:53:09 +00:00
|
|
|
}
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "</td>";
|
2002-10-14 09:07:13 +00:00
|
|
|
|
2002-10-14 12:21:18 +00:00
|
|
|
$sumgrade += $grades[$qnum];
|
2002-10-14 09:07:13 +00:00
|
|
|
}
|
2004-09-12 17:34:35 +00:00
|
|
|
echo "<tr><td colspan=\"5\" align=\"right\">\n";
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "<input type=\"submit\" value=\"$strsavegrades:\" />\n";
|
|
|
|
echo "<input type=\"hidden\" name=\"setgrades\" value=\"save\" />\n";
|
|
|
|
echo "<td align=\"left\" bgcolor=\"$THEME->cellcontent\">\n";
|
|
|
|
echo "<b>$sumgrade</b>";
|
|
|
|
echo "</td><td>\n</td></tr>\n";
|
|
|
|
echo "</table>\n";
|
|
|
|
echo "</form>\n";
|
2002-10-14 15:57:33 +00:00
|
|
|
|
|
|
|
return $sumgrade;
|
2002-10-14 09:07:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-12-10 20:03:59 +00:00
|
|
|
function quiz_print_cat_question_list($categoryid, $quizselected=true) {
|
2002-10-14 09:07:13 +00:00
|
|
|
// Prints a form to choose categories
|
|
|
|
|
|
|
|
global $THEME, $QUIZ_QUESTION_TYPE;
|
|
|
|
|
2002-10-14 15:57:33 +00:00
|
|
|
$strcategory = get_string("category", "quiz");
|
2002-10-14 09:07:13 +00:00
|
|
|
$strquestion = get_string("question", "quiz");
|
2003-02-16 07:08:57 +00:00
|
|
|
$straddquestions = get_string("addquestions", "quiz");
|
|
|
|
$strimportquestions = get_string("importquestions", "quiz");
|
2004-06-17 17:29:07 +00:00
|
|
|
$strexportquestions = get_string("exportquestions", "quiz");
|
2002-10-14 09:07:13 +00:00
|
|
|
$strnoquestions = get_string("noquestions", "quiz");
|
|
|
|
$strselect = get_string("select", "quiz");
|
2003-02-17 18:13:41 +00:00
|
|
|
$strselectall = get_string("selectall", "quiz");
|
2002-10-14 09:07:13 +00:00
|
|
|
$strcreatenewquestion = get_string("createnewquestion", "quiz");
|
|
|
|
$strquestionname = get_string("questionname", "quiz");
|
|
|
|
$strdelete = get_string("delete");
|
|
|
|
$stredit = get_string("edit");
|
|
|
|
$straddselectedtoquiz = get_string("addselectedtoquiz", "quiz");
|
2002-10-20 17:15:39 +00:00
|
|
|
$strtype = get_string("type", "quiz");
|
2003-04-10 17:55:57 +00:00
|
|
|
$strcreatemultiple = get_string("createmultiple", "quiz");
|
2004-08-16 15:16:26 +00:00
|
|
|
$strpreview = get_string("preview","quiz");
|
2002-10-14 09:07:13 +00:00
|
|
|
|
|
|
|
if (!$categoryid) {
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "<p align=\"center\"><b>";
|
2002-10-14 09:07:13 +00:00
|
|
|
print_string("selectcategoryabove", "quiz");
|
2003-05-23 15:20:41 +00:00
|
|
|
echo "</b></p>";
|
2003-12-10 20:03:59 +00:00
|
|
|
if ($quizselected) {
|
|
|
|
echo "<p>";
|
|
|
|
print_string("addingquestions", "quiz");
|
|
|
|
echo "</p>";
|
|
|
|
}
|
2002-10-14 09:07:13 +00:00
|
|
|
return;
|
|
|
|
}
|
2002-10-13 07:17:48 +00:00
|
|
|
|
2002-10-14 09:07:13 +00:00
|
|
|
if (!$category = get_record("quiz_categories", "id", "$categoryid")) {
|
|
|
|
notify("Category not found!");
|
|
|
|
return;
|
|
|
|
}
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "<center>";
|
2004-01-15 15:26:34 +00:00
|
|
|
echo format_text($category->info, FORMAT_MOODLE);
|
|
|
|
|
|
|
|
echo '<table><tr>';
|
2003-02-16 07:08:57 +00:00
|
|
|
|
2004-06-22 11:02:37 +00:00
|
|
|
// check if editing of this category is allowed
|
|
|
|
if (isteacheredit($category->course)) {
|
|
|
|
echo "<td valign=\"top\"><b>$strcreatenewquestion:</b></td>";
|
|
|
|
echo '<td valign="top" align="right">';
|
2004-09-16 17:13:57 +00:00
|
|
|
popup_form ("question.php?category=$category->id&qtype=", $QUIZ_QUESTION_TYPE, "addquestion",
|
2004-06-22 11:02:37 +00:00
|
|
|
"", "choose", "", "", false, "self");
|
|
|
|
echo '<td width="10" valign="top" align="right">';
|
|
|
|
helpbutton("questiontypes", $strcreatenewquestion, "quiz");
|
|
|
|
echo '</td></tr>';
|
2004-06-22 20:44:59 +00:00
|
|
|
|
2004-06-22 11:02:37 +00:00
|
|
|
echo '<tr><td colspan="3" align="right">';
|
|
|
|
echo '<form method="get" action="import.php">';
|
|
|
|
echo "<input type=\"hidden\" name=\"category\" value=\"$category->id\" />";
|
|
|
|
echo "<input type=\"submit\" value=\"$strimportquestions\" />";
|
|
|
|
helpbutton("import", $strimportquestions, "quiz");
|
|
|
|
echo '</form>';
|
|
|
|
echo '</td></tr>';
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
echo '<tr><td>';
|
|
|
|
print_string("publishedit","quiz");
|
|
|
|
echo '</td></tr>';
|
|
|
|
}
|
2003-02-16 07:08:57 +00:00
|
|
|
|
2004-06-17 17:29:07 +00:00
|
|
|
echo '<tr><td colspan="3" align="right">';
|
|
|
|
echo '<form method="get" action="export.php">';
|
|
|
|
echo "<input type=\"hidden\" name=\"category\" value=\"$category->id\" />";
|
|
|
|
echo "<input type=\"submit\" value=\"$strexportquestions\" />";
|
|
|
|
helpbutton("export", $strexportquestions, "quiz");
|
|
|
|
echo '</form>';
|
|
|
|
echo '</td></tr>';
|
|
|
|
|
2004-06-22 11:02:37 +00:00
|
|
|
if (isteacheredit($category->course)) {
|
|
|
|
echo '<tr><td colspan="3" align="right">';
|
|
|
|
echo '<form method="get" action="multiple.php">';
|
|
|
|
echo "<input type=\"hidden\" name=\"category\" value=\"$category->id\" />";
|
|
|
|
echo "<input type=\"submit\" value=\"$strcreatemultiple\" />";
|
|
|
|
helpbutton("createmultiple", $strcreatemultiple, "quiz");
|
|
|
|
echo '</form>';
|
|
|
|
echo '</td></tr>';
|
|
|
|
}
|
2003-04-10 17:55:57 +00:00
|
|
|
|
2004-01-15 15:26:34 +00:00
|
|
|
echo '</table>';
|
2003-02-16 07:08:57 +00:00
|
|
|
|
2004-01-15 15:26:34 +00:00
|
|
|
echo '</center>';
|
2002-10-14 09:07:13 +00:00
|
|
|
|
2003-03-01 05:11:44 +00:00
|
|
|
if (!$questions = get_records("quiz_questions", "category", $category->id, "qtype ASC")) {
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "<p align=\"center\">";
|
2002-10-14 09:07:13 +00:00
|
|
|
print_string("noquestions", "quiz");
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "</p>";
|
2002-10-14 09:07:13 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-12-10 20:03:59 +00:00
|
|
|
$canedit = isteacheredit($category->course);
|
2002-10-14 15:57:33 +00:00
|
|
|
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "<form method=\"post\" action=\"edit.php\">";
|
|
|
|
echo "<table border=\"0\" cellpadding=\"5\" cellspacing=\"2\" width=\"100%\">";
|
|
|
|
echo "<tr>";
|
2003-12-10 20:03:59 +00:00
|
|
|
if ($quizselected) {
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "<th width=\"*\" nowrap=\"nowrap\">$strselect</th>";
|
2003-12-10 20:03:59 +00:00
|
|
|
}
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "<th width=\"100%\" align=\"left\" nowrap=\"nowrap\">$strquestionname</th><th width=\"*\" nowrap=\"nowrap\">$strtype</th>";
|
2002-10-14 15:57:33 +00:00
|
|
|
if ($canedit) {
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "<th width=\"*\" nowrap=\"nowrap\">$stredit</th>";
|
2002-10-14 15:57:33 +00:00
|
|
|
}
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "</tr>\n";
|
2002-10-14 09:07:13 +00:00
|
|
|
foreach ($questions as $question) {
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "<tr bgcolor=\"$THEME->cellcontent\">\n";
|
2003-12-10 20:03:59 +00:00
|
|
|
if ($quizselected) {
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "<td align=\"center\">";
|
|
|
|
echo "<input type=\"checkbox\" name=\"q$question->id\" value=\"1\" />\n";
|
|
|
|
echo "</td>";
|
2003-12-10 20:03:59 +00:00
|
|
|
}
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "<td>".$question->name."</td>\n";
|
|
|
|
echo "<td align=\"center\">\n";
|
2004-02-19 07:53:09 +00:00
|
|
|
quiz_print_question_icon($question, $canedit);
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "</td>\n";
|
2002-10-14 15:57:33 +00:00
|
|
|
if ($canedit) {
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "<td>\n";
|
2004-09-16 17:13:57 +00:00
|
|
|
echo "<a title=\"$strdelete\" href=\"question.php?id=$question->id&delete=$question->id\">\n<img
|
|
|
|
src=\"../../pix/t/delete.gif\" border=\"0\" alt=\"\" /></a> ";
|
2004-08-16 15:16:26 +00:00
|
|
|
echo "<a title=\"$strpreview\" href=\"#\" onClick=\"openpopup('/mod/quiz/preview.php?id=$question->id','$strpreview','scrollbars=yes,resizable=yes,width=700,height=480', false)\"><img
|
2004-09-16 17:13:57 +00:00
|
|
|
src=\"../../pix/i/search.gif\" border=\"0\" alt=\"\" /></a> ";
|
2004-06-02 18:03:05 +00:00
|
|
|
echo "<a title=\"$stredit\" href=\"question.php?id=$question->id\"><img
|
2004-09-16 17:13:57 +00:00
|
|
|
src=\"../../pix/t/edit.gif\" border=\"0\" alt=\"\" /></a>";
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "</td>\n";// deleted </tr> jm
|
2002-10-14 15:57:33 +00:00
|
|
|
}
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "</tr>\n";
|
2002-10-14 09:07:13 +00:00
|
|
|
}
|
2003-12-10 20:03:59 +00:00
|
|
|
if ($quizselected) {
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "<tr>\n<td colspan=\"3\">";
|
|
|
|
echo "<input type=\"submit\" name=\"add\" value=\"<< $straddselectedtoquiz\" />\n";
|
2004-09-12 17:34:35 +00:00
|
|
|
//echo "<input type=\"submit\" name=\"delete\" value=\"XX Delete selected\">";
|
2003-12-30 07:28:43 +00:00
|
|
|
echo "<input type=\"button\" onclick=\"checkall()\" value=\"$strselectall\" />\n";
|
2003-12-30 07:04:04 +00:00
|
|
|
echo "</td></tr>";
|
|
|
|
}
|
|
|
|
echo "</table>\n";
|
|
|
|
echo "</form>\n";
|
2002-10-14 09:07:13 +00:00
|
|
|
}
|
2002-10-13 07:17:48 +00:00
|
|
|
|
2002-10-06 03:23:16 +00:00
|
|
|
|
2002-10-18 16:05:21 +00:00
|
|
|
function quiz_start_attempt($quizid, $userid, $numattempt) {
|
|
|
|
$attempt->quiz = $quizid;
|
2002-12-23 09:39:26 +00:00
|
|
|
$attempt->userid = $userid;
|
2002-10-18 16:05:21 +00:00
|
|
|
$attempt->attempt = $numattempt;
|
|
|
|
$attempt->timestart = time();
|
2004-06-02 18:03:05 +00:00
|
|
|
$attempt->timefinish = 0;
|
2002-10-18 16:05:21 +00:00
|
|
|
$attempt->timemodified = time();
|
2004-07-21 13:01:08 +00:00
|
|
|
$attempt->id = insert_record("quiz_attempts", $attempt);
|
|
|
|
return $attempt;
|
2002-10-18 16:05:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function quiz_get_user_attempt_unfinished($quizid, $userid) {
|
|
|
|
// Returns an object containing an unfinished attempt (if there is one)
|
2002-12-23 09:39:26 +00:00
|
|
|
return get_record("quiz_attempts", "quiz", $quizid, "userid", $userid, "timefinish", 0);
|
2002-10-18 16:05:21 +00:00
|
|
|
}
|
|
|
|
|
2002-10-06 03:23:16 +00:00
|
|
|
function quiz_get_user_attempts($quizid, $userid) {
|
2002-10-13 07:17:48 +00:00
|
|
|
// Returns a list of all attempts by a user
|
2004-06-02 18:03:05 +00:00
|
|
|
return get_records_select("quiz_attempts", "quiz = '$quizid' AND userid = '$userid' AND timefinish > 0",
|
2002-12-22 13:55:30 +00:00
|
|
|
"attempt ASC");
|
2002-10-06 03:23:16 +00:00
|
|
|
}
|
|
|
|
|
2002-10-15 12:54:11 +00:00
|
|
|
|
|
|
|
function quiz_get_user_attempts_string($quiz, $attempts, $bestgrade) {
|
2004-06-02 18:03:05 +00:00
|
|
|
/// Returns a simple little comma-separated list of all attempts,
|
2002-10-22 04:25:58 +00:00
|
|
|
/// with each grade linked to the feedback report and with the best grade highlighted
|
2002-10-15 12:54:11 +00:00
|
|
|
|
|
|
|
$bestgrade = format_float($bestgrade);
|
|
|
|
foreach ($attempts as $attempt) {
|
|
|
|
$attemptgrade = format_float(($attempt->sumgrades / $quiz->sumgrades) * $quiz->grade);
|
|
|
|
if ($attemptgrade == $bestgrade) {
|
2004-09-16 17:13:57 +00:00
|
|
|
$userattempts[] = "<span class=\"highlight\"><a href=\"review.php?q=$quiz->id&attempt=$attempt->id\">$attemptgrade</a></span>";
|
2002-10-15 12:54:11 +00:00
|
|
|
} else {
|
2004-09-16 17:13:57 +00:00
|
|
|
$userattempts[] = "<a href=\"review.php?q=$quiz->id&attempt=$attempt->id\">$attemptgrade</a>";
|
2002-10-15 12:54:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return implode(",", $userattempts);
|
|
|
|
}
|
|
|
|
|
2002-10-13 07:17:48 +00:00
|
|
|
function quiz_get_best_grade($quizid, $userid) {
|
|
|
|
/// Get the best current grade for a particular user in a quiz
|
2002-12-23 09:39:26 +00:00
|
|
|
if (!$grade = get_record("quiz_grades", "quiz", $quizid, "userid", $userid)) {
|
2004-01-18 06:17:02 +00:00
|
|
|
return "";
|
2002-10-06 03:23:16 +00:00
|
|
|
}
|
|
|
|
|
2002-10-21 13:13:33 +00:00
|
|
|
return (round($grade->grade,0));
|
2002-10-06 03:23:16 +00:00
|
|
|
}
|
|
|
|
|
2002-10-22 06:52:23 +00:00
|
|
|
function quiz_save_best_grade($quiz, $userid) {
|
2002-10-13 07:17:48 +00:00
|
|
|
/// Calculates the best grade out of all attempts at a quiz for a user,
|
|
|
|
/// and then saves that grade in the quiz_grades table.
|
|
|
|
|
2002-10-22 06:52:23 +00:00
|
|
|
if (!$attempts = quiz_get_user_attempts($quiz->id, $userid)) {
|
2002-10-21 12:39:46 +00:00
|
|
|
notify("Could not find any user attempts");
|
2002-10-13 07:17:48 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
$bestgrade = quiz_calculate_best_grade($quiz, $attempts);
|
|
|
|
$bestgrade = (($bestgrade / $quiz->sumgrades) * $quiz->grade);
|
|
|
|
|
2002-12-23 09:39:26 +00:00
|
|
|
if ($grade = get_record("quiz_grades", "quiz", $quiz->id, "userid", $userid)) {
|
2003-01-03 16:05:44 +00:00
|
|
|
$grade->grade = round($bestgrade, 2);
|
2002-10-13 07:17:48 +00:00
|
|
|
$grade->timemodified = time();
|
|
|
|
if (!update_record("quiz_grades", $grade)) {
|
2002-10-21 12:39:46 +00:00
|
|
|
notify("Could not update best grade");
|
2002-10-13 07:17:48 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$grade->quiz = $quiz->id;
|
2002-12-23 09:39:26 +00:00
|
|
|
$grade->userid = $userid;
|
2002-10-21 13:02:14 +00:00
|
|
|
$grade->grade = round($bestgrade, 2);
|
2002-10-13 07:17:48 +00:00
|
|
|
$grade->timemodified = time();
|
|
|
|
if (!insert_record("quiz_grades", $grade)) {
|
2002-10-21 12:39:46 +00:00
|
|
|
notify("Could not insert new best grade");
|
2002-10-13 07:17:48 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-10-06 03:23:16 +00:00
|
|
|
function quiz_calculate_best_grade($quiz, $attempts) {
|
2002-10-13 07:17:48 +00:00
|
|
|
/// Calculate the best grade for a quiz given a number of attempts by a particular user.
|
2002-10-06 03:23:16 +00:00
|
|
|
|
|
|
|
switch ($quiz->grademethod) {
|
2002-10-13 07:17:48 +00:00
|
|
|
|
|
|
|
case ATTEMPTFIRST:
|
2002-10-06 03:23:16 +00:00
|
|
|
foreach ($attempts as $attempt) {
|
2002-10-13 07:17:48 +00:00
|
|
|
return $attempt->sumgrades;
|
2002-10-06 03:23:16 +00:00
|
|
|
}
|
2002-10-13 07:17:48 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ATTEMPTLAST:
|
|
|
|
foreach ($attempts as $attempt) {
|
|
|
|
$final = $attempt->sumgrades;
|
|
|
|
}
|
|
|
|
return $final;
|
2002-10-06 03:23:16 +00:00
|
|
|
|
2002-10-13 07:17:48 +00:00
|
|
|
case GRADEAVERAGE:
|
2002-10-06 03:23:16 +00:00
|
|
|
$sum = 0;
|
|
|
|
$count = 0;
|
|
|
|
foreach ($attempts as $attempt) {
|
2002-10-13 07:17:48 +00:00
|
|
|
$sum += $attempt->sumgrades;
|
2002-10-06 03:23:16 +00:00
|
|
|
$count++;
|
|
|
|
}
|
|
|
|
return (float)$sum/$count;
|
|
|
|
|
|
|
|
default:
|
2002-10-13 07:17:48 +00:00
|
|
|
case GRADEHIGHEST:
|
|
|
|
$max = 0;
|
2002-10-06 03:23:16 +00:00
|
|
|
foreach ($attempts as $attempt) {
|
2002-10-13 07:17:48 +00:00
|
|
|
if ($attempt->sumgrades > $max) {
|
|
|
|
$max = $attempt->sumgrades;
|
|
|
|
}
|
2002-10-06 03:23:16 +00:00
|
|
|
}
|
2002-10-13 07:17:48 +00:00
|
|
|
return $max;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-04-09 06:32:51 +00:00
|
|
|
|
2003-07-24 16:48:10 +00:00
|
|
|
function quiz_calculate_best_attempt($quiz, $attempts) {
|
|
|
|
/// Return the attempt with the best grade for a quiz
|
|
|
|
|
|
|
|
switch ($quiz->grademethod) {
|
|
|
|
|
|
|
|
case ATTEMPTFIRST:
|
|
|
|
foreach ($attempts as $attempt) {
|
|
|
|
return $attempt;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GRADEAVERAGE: // need to do something with it :-)
|
|
|
|
case ATTEMPTLAST:
|
|
|
|
foreach ($attempts as $attempt) {
|
|
|
|
$final = $attempt;
|
|
|
|
}
|
|
|
|
return $final;
|
|
|
|
|
|
|
|
default:
|
|
|
|
case GRADEHIGHEST:
|
|
|
|
$max = -1;
|
|
|
|
foreach ($attempts as $attempt) {
|
|
|
|
if ($attempt->sumgrades > $max) {
|
|
|
|
$max = $attempt->sumgrades;
|
|
|
|
$maxattempt = $attempt;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return $maxattempt;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-10-13 07:17:48 +00:00
|
|
|
function quiz_save_attempt($quiz, $questions, $result, $attemptnum) {
|
2004-06-02 18:03:05 +00:00
|
|
|
/// Given a quiz, a list of attempted questions and a total grade
|
2002-10-13 07:17:48 +00:00
|
|
|
/// this function saves EVERYTHING so it can be reconstructed later
|
|
|
|
/// if necessary.
|
|
|
|
|
|
|
|
global $USER;
|
2004-07-21 13:01:08 +00:00
|
|
|
global $QUIZ_QTYPES;
|
2002-10-13 07:17:48 +00:00
|
|
|
|
2002-10-18 16:05:21 +00:00
|
|
|
// First find the attempt in the database (start of attempt)
|
|
|
|
|
|
|
|
if (!$attempt = quiz_get_user_attempt_unfinished($quiz->id, $USER->id)) {
|
|
|
|
notify("Trying to save an attempt that was not started!");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2004-07-27 13:19:12 +00:00
|
|
|
// Not usually necessary, but there's some sort of very rare glitch
|
|
|
|
// I've seen where the number wasn't already the same. In these cases
|
|
|
|
// We upgrade the database to match the attemptnum we calculated
|
|
|
|
$attempt->attempt = $attemptnum;
|
2002-10-18 16:05:21 +00:00
|
|
|
|
|
|
|
// Now let's complete this record and save it
|
2002-10-13 07:17:48 +00:00
|
|
|
|
|
|
|
$attempt->sumgrades = $result->sumgrades;
|
2002-10-18 16:05:21 +00:00
|
|
|
$attempt->timefinish = time();
|
2002-10-13 07:17:48 +00:00
|
|
|
$attempt->timemodified = time();
|
|
|
|
|
2004-09-16 06:35:49 +00:00
|
|
|
if (!update_record("quiz_attempts", $attempt)) {
|
2002-10-15 17:13:11 +00:00
|
|
|
notify("Error while saving attempt");
|
2002-10-13 07:17:48 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now let's save all the questions for this attempt
|
|
|
|
|
|
|
|
foreach ($questions as $question) {
|
2003-04-09 06:32:51 +00:00
|
|
|
|
2004-09-16 06:35:49 +00:00
|
|
|
// Fetch the response record for this question...
|
|
|
|
$response = get_record('quiz_responses',
|
|
|
|
'attempt', $attempt->id, 'question', $question->id);
|
|
|
|
|
|
|
|
$response->grade = $result->details[$question->id]->grade;
|
|
|
|
|
2004-07-21 13:01:08 +00:00
|
|
|
if (!empty($question->response)) {
|
2004-09-16 06:35:49 +00:00
|
|
|
$responseanswerfield = $QUIZ_QTYPES[$question->qtype]
|
2004-07-21 13:01:08 +00:00
|
|
|
->convert_to_response_answer_field($question->response);
|
|
|
|
|
|
|
|
///////////////////////////////////////////
|
|
|
|
// WORKAROUND for question type RANDOM:
|
|
|
|
///////////////////////////////////////////
|
2004-09-16 06:35:49 +00:00
|
|
|
if ($question->qtype == RANDOM) {
|
|
|
|
|
|
|
|
/// This will update the grade only
|
|
|
|
/// Everything else must already be in place...
|
|
|
|
if (!update_record('quiz_responses', $response)) {
|
|
|
|
notify("Error while saving grade on random response");
|
2004-07-21 13:01:08 +00:00
|
|
|
return false;
|
|
|
|
}
|
2004-09-16 06:35:49 +00:00
|
|
|
|
|
|
|
/// Rescue grade before fetching response record for actual question
|
|
|
|
$responsegradefield = $response->grade;
|
|
|
|
|
|
|
|
/// Fetch the response record containing
|
|
|
|
/// the response on the actual question
|
|
|
|
$response = get_record('quiz_responses',
|
|
|
|
'attempt', $attempt->id, 'question', $response->answer);
|
|
|
|
|
|
|
|
$response->grade = $responsegradefield;
|
|
|
|
ereg('^random[0-9]+-(.*)$', $responseanswerfield, $afields);
|
|
|
|
$responseanswerfield = $afields[1];
|
2004-07-21 13:01:08 +00:00
|
|
|
} /// End of WORKAROUND //////////////////////
|
|
|
|
|
2004-09-16 06:35:49 +00:00
|
|
|
$response->answer = $responseanswerfield;
|
2002-10-13 07:17:48 +00:00
|
|
|
} else {
|
2004-09-16 06:35:49 +00:00
|
|
|
$response->answer = '';
|
2002-10-13 07:17:48 +00:00
|
|
|
}
|
2004-09-16 06:35:49 +00:00
|
|
|
|
|
|
|
if (!update_record("quiz_responses", $response)) {
|
2002-10-15 17:13:11 +00:00
|
|
|
notify("Error while saving response");
|
2002-10-13 07:17:48 +00:00
|
|
|
return false;
|
|
|
|
}
|
2002-10-06 03:23:16 +00:00
|
|
|
}
|
2004-02-17 12:14:02 +00:00
|
|
|
return $attempt;
|
2002-10-06 03:23:16 +00:00
|
|
|
}
|
2002-10-04 02:59:05 +00:00
|
|
|
|
2004-07-21 13:01:08 +00:00
|
|
|
function quiz_extract_correctanswers($answers, $nameprefix) {
|
|
|
|
/// Convinience function that is used by some single-response
|
|
|
|
/// question-types for determining correct answers.
|
|
|
|
|
|
|
|
$bestanswerfraction = 0.0;
|
|
|
|
$correctanswers = array();
|
|
|
|
foreach ($answers as $answer) {
|
|
|
|
if ($answer->fraction > $bestanswerfraction) {
|
|
|
|
$correctanswers = array($nameprefix.$answer->id => $answer);
|
|
|
|
$bestanswerfraction = $answer->fraction;
|
|
|
|
} else if ($answer->fraction == $bestanswerfraction) {
|
|
|
|
$correctanswers[$nameprefix.$answer->id] = $answer;
|
|
|
|
}
|
2003-07-29 09:11:06 +00:00
|
|
|
}
|
2004-07-21 13:01:08 +00:00
|
|
|
return $correctanswers;
|
2003-07-29 09:11:06 +00:00
|
|
|
}
|
2002-10-13 07:17:48 +00:00
|
|
|
|
2004-07-21 13:01:08 +00:00
|
|
|
function quiz_grade_responses($quiz, $questions) {
|
|
|
|
/// Given a list of questions (including ->response[] and ->maxgrade
|
|
|
|
/// on each question) this function does all the hard work of calculating the
|
|
|
|
/// score for each question, as well as a total grade for
|
|
|
|
/// for the whole quiz. It returns everything in a structure
|
|
|
|
/// that lookas like this
|
|
|
|
/// ->sumgrades (sum of all grades for all questions)
|
|
|
|
/// ->grade (final grade result for the whole quiz)
|
|
|
|
/// ->percentage (Percentage of the max grade achieved)
|
|
|
|
/// ->details[]
|
|
|
|
/// The array ->details[] is indexed like the $questions argument
|
|
|
|
/// and contains scoring information per question. Each element has
|
|
|
|
/// this structure:
|
|
|
|
/// []->grade (Grade awarded on the specifik question)
|
|
|
|
/// []->answers[] (result answer records for the question response(s))
|
|
|
|
/// []->correctanswers[] (answer records if question response(s) had been correct)
|
|
|
|
/// The array ->answers[] is indexed like ->respoonse[] on its corresponding
|
|
|
|
/// element in $questions. It is the case for ->correctanswers[] when
|
|
|
|
/// there can be multiple responses per question but if there can be only one
|
|
|
|
/// response per question then all possible correctanswers will be
|
|
|
|
/// represented, indexed like the response index concatinated with the ->id
|
|
|
|
/// of its answer record.
|
|
|
|
|
|
|
|
global $QUIZ_QTYPES;
|
2002-10-13 07:17:48 +00:00
|
|
|
|
|
|
|
if (!$questions) {
|
|
|
|
error("No questions!");
|
|
|
|
}
|
2003-04-09 06:32:51 +00:00
|
|
|
|
2004-07-21 13:01:08 +00:00
|
|
|
$result->sumgrades = 0.0;
|
|
|
|
foreach ($questions as $qid => $question) {
|
2002-10-13 07:17:48 +00:00
|
|
|
|
2004-10-16 17:30:51 +00:00
|
|
|
if (empty($question->qtype)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2004-07-21 13:01:08 +00:00
|
|
|
$resultdetails = $QUIZ_QTYPES[$question->qtype]->grade_response
|
|
|
|
($question, quiz_qtype_nameprefix($question));
|
2003-04-09 06:32:51 +00:00
|
|
|
|
2004-07-21 13:01:08 +00:00
|
|
|
// Negative grades will not do:
|
|
|
|
if (((float)($resultdetails->grade)) <= 0.0) {
|
|
|
|
$resultdetails->grade = 0.0;
|
2004-06-02 18:03:05 +00:00
|
|
|
|
2004-07-21 13:01:08 +00:00
|
|
|
// Neither will extra credit:
|
|
|
|
} else if (((float)($resultdetails->grade)) >= 1.0) {
|
|
|
|
$resultdetails->grade = $question->maxgrade;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
$resultdetails->grade *= $question->maxgrade;
|
2002-10-13 07:17:48 +00:00
|
|
|
}
|
2003-04-09 06:32:51 +00:00
|
|
|
|
2004-06-22 20:44:59 +00:00
|
|
|
// if time limit is enabled and exceeded, return zero grades
|
2004-07-21 13:01:08 +00:00
|
|
|
if ($quiz->timelimit > 0) {
|
|
|
|
if (($quiz->timelimit + 60) <= $quiz->timesincestart) {
|
|
|
|
$resultdetails->grade = 0;
|
2004-06-22 20:44:59 +00:00
|
|
|
}
|
|
|
|
}
|
2002-10-14 15:57:33 +00:00
|
|
|
|
2004-07-21 13:01:08 +00:00
|
|
|
$result->sumgrades += $resultdetails->grade;
|
|
|
|
$resultdetails->grade = round($resultdetails->grade, 2);
|
|
|
|
$result->details[$qid] = $resultdetails;
|
2002-10-13 07:17:48 +00:00
|
|
|
}
|
|
|
|
|
2002-10-15 12:54:11 +00:00
|
|
|
$fraction = (float)($result->sumgrades / $quiz->sumgrades);
|
|
|
|
$result->percentage = format_float($fraction * 100.0);
|
|
|
|
$result->grade = format_float($fraction * $quiz->grade);
|
2002-10-26 06:11:43 +00:00
|
|
|
$result->sumgrades = round($result->sumgrades, 2);
|
2002-10-13 07:17:48 +00:00
|
|
|
|
|
|
|
return $result;
|
|
|
|
}
|
2002-10-22 04:25:58 +00:00
|
|
|
|
2004-02-15 06:26:55 +00:00
|
|
|
function quiz_get_recent_mod_activity(&$activities, &$index, $sincetime, $courseid, $quiz="0", $user="", $groupid="") {
|
2004-02-04 15:12:06 +00:00
|
|
|
// Returns all quizzes since a given time. If quiz is specified then
|
|
|
|
// this restricts the results
|
|
|
|
|
|
|
|
global $CFG;
|
|
|
|
|
|
|
|
if ($quiz) {
|
2004-02-15 06:26:55 +00:00
|
|
|
$quizselect = " AND cm.id = '$quiz'";
|
2004-02-04 15:12:06 +00:00
|
|
|
} else {
|
|
|
|
$quizselect = "";
|
|
|
|
}
|
2004-02-05 20:40:59 +00:00
|
|
|
if ($user) {
|
|
|
|
$userselect = " AND u.id = '$user'";
|
|
|
|
} else {
|
|
|
|
$userselect = "";
|
|
|
|
}
|
2004-02-04 15:12:06 +00:00
|
|
|
|
2004-02-15 06:26:55 +00:00
|
|
|
$quizzes = get_records_sql("SELECT qa.*, q.name, u.firstname, u.lastname, u.picture,
|
|
|
|
q.course, q.sumgrades as maxgrade, cm.instance, cm.section
|
|
|
|
FROM {$CFG->prefix}quiz_attempts qa,
|
|
|
|
{$CFG->prefix}quiz q,
|
|
|
|
{$CFG->prefix}user u,
|
|
|
|
{$CFG->prefix}course_modules cm
|
|
|
|
WHERE qa.timefinish > '$sincetime'
|
|
|
|
AND qa.userid = u.id $userselect
|
|
|
|
AND qa.quiz = q.id $quizselect
|
|
|
|
AND cm.instance = q.id
|
|
|
|
AND cm.course = '$courseid'
|
|
|
|
AND q.course = cm.course
|
|
|
|
ORDER BY qa.timefinish ASC");
|
2004-02-04 15:12:06 +00:00
|
|
|
|
2004-02-20 21:47:55 +00:00
|
|
|
if (empty($quizzes))
|
|
|
|
return;
|
2004-02-04 15:12:06 +00:00
|
|
|
|
2004-02-20 21:47:55 +00:00
|
|
|
foreach ($quizzes as $quiz) {
|
|
|
|
if (empty($groupid) || ismember($groupid, $quiz->userid)) {
|
2004-02-04 15:12:06 +00:00
|
|
|
|
2004-02-20 21:47:55 +00:00
|
|
|
$tmpactivity->type = "quiz";
|
|
|
|
$tmpactivity->defaultindex = $index;
|
|
|
|
$tmpactivity->instance = $quiz->quiz;
|
2004-02-04 15:12:06 +00:00
|
|
|
|
2004-02-20 21:47:55 +00:00
|
|
|
$tmpactivity->name = $quiz->name;
|
|
|
|
$tmpactivity->section = $quiz->section;
|
2004-02-04 15:12:06 +00:00
|
|
|
|
2004-02-20 21:47:55 +00:00
|
|
|
$tmpactivity->content->attemptid = $quiz->id;
|
|
|
|
$tmpactivity->content->sumgrades = $quiz->sumgrades;
|
|
|
|
$tmpactivity->content->maxgrade = $quiz->maxgrade;
|
|
|
|
$tmpactivity->content->attempt = $quiz->attempt;
|
2004-02-04 15:12:06 +00:00
|
|
|
|
2004-02-20 21:47:55 +00:00
|
|
|
$tmpactivity->user->userid = $quiz->userid;
|
|
|
|
$tmpactivity->user->fullname = fullname($quiz);
|
|
|
|
$tmpactivity->user->picture = $quiz->picture;
|
2004-02-04 15:12:06 +00:00
|
|
|
|
2004-02-20 21:47:55 +00:00
|
|
|
$tmpactivity->timestamp = $quiz->timefinish;
|
2004-02-04 15:12:06 +00:00
|
|
|
|
2004-02-20 21:47:55 +00:00
|
|
|
$activities[] = $tmpactivity;
|
|
|
|
|
|
|
|
$index++;
|
|
|
|
}
|
|
|
|
}
|
2004-02-04 15:12:06 +00:00
|
|
|
|
2004-02-15 06:26:55 +00:00
|
|
|
return;
|
|
|
|
}
|
2004-02-04 15:12:06 +00:00
|
|
|
|
2004-02-20 21:47:55 +00:00
|
|
|
|
2004-02-15 06:26:55 +00:00
|
|
|
function quiz_print_recent_mod_activity($activity, $course, $detail=false) {
|
|
|
|
global $CFG, $THEME;
|
2004-02-04 15:12:06 +00:00
|
|
|
|
2004-02-15 06:26:55 +00:00
|
|
|
echo '<table border="0" cellpadding="3" cellspacing="0">';
|
2004-02-04 15:12:06 +00:00
|
|
|
|
2004-02-15 06:26:55 +00:00
|
|
|
echo "<tr><td bgcolor=\"$THEME->cellcontent2\" class=\"forumpostpicture\" width=\"35\" valign=\"top\">";
|
|
|
|
print_user_picture($activity->user->userid, $course, $activity->user->picture);
|
2004-09-12 17:34:35 +00:00
|
|
|
echo "</td><td width=\"100%\"><font size=\"2\">";
|
2004-02-15 06:26:55 +00:00
|
|
|
|
|
|
|
if ($detail) {
|
|
|
|
echo "<img src=\"$CFG->modpixpath/$activity->type/icon.gif\" ".
|
2004-09-16 17:13:57 +00:00
|
|
|
"height=\"16\" width=\"16\" alt=\"$activity->type\" /> ";
|
2004-02-15 06:26:55 +00:00
|
|
|
echo "<a href=\"$CFG->wwwroot/mod/quiz/view.php?id=" . $activity->instance . "\">"
|
|
|
|
. $activity->name . "</a> - ";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isteacher($USER)) {
|
|
|
|
$grades = "(" . $activity->content->sumgrades . " / " . $activity->content->maxgrade . ") ";
|
|
|
|
echo "<a href=\"$CFG->wwwroot/mod/quiz/review.php?q="
|
2004-09-16 17:13:57 +00:00
|
|
|
. $activity->instance . "&attempt="
|
2004-02-15 06:26:55 +00:00
|
|
|
. $activity->content->attemptid . "\">" . $grades . "</a> ";
|
|
|
|
|
2004-09-12 14:41:49 +00:00
|
|
|
echo get_string("attempt", "quiz") . " - " . $activity->content->attempt . "<br />";
|
2004-02-04 15:12:06 +00:00
|
|
|
}
|
2004-02-15 06:26:55 +00:00
|
|
|
echo "<a href=\"$CFG->wwwroot/user/view.php?id="
|
2004-09-16 17:13:57 +00:00
|
|
|
. $activity->user->userid . "&course=$course\">"
|
2004-02-15 06:26:55 +00:00
|
|
|
. $activity->user->fullname . "</a> ";
|
|
|
|
|
|
|
|
echo " - " . userdate($activity->timestamp);
|
|
|
|
|
|
|
|
echo "</font></td></tr>";
|
|
|
|
echo "</table>";
|
|
|
|
|
|
|
|
return;
|
2004-02-04 15:12:06 +00:00
|
|
|
}
|
2003-09-07 21:56:46 +00:00
|
|
|
|
2004-08-23 16:46:50 +00:00
|
|
|
// this function creates default export filename
|
|
|
|
function default_export_filename($course,$category) {
|
|
|
|
//Take off some characters in the filename !!
|
|
|
|
$takeoff = array(" ", ":", "/", "\\", "|");
|
|
|
|
$export_word = str_replace($takeoff,"_",strtolower(get_string("exportfilename","quiz")));
|
|
|
|
//If non-translated, use "export"
|
|
|
|
if (substr($export_word,0,1) == "[") {
|
|
|
|
$export_word= "export";
|
|
|
|
}
|
|
|
|
|
|
|
|
//Calculate the date format string
|
|
|
|
$export_date_format = str_replace(" ","_",get_string("exportnameformat","quiz"));
|
|
|
|
//If non-translated, use "%Y%m%d-%H%M"
|
|
|
|
if (substr($export_date_format,0,1) == "[") {
|
|
|
|
$export_date_format = "%%Y%%m%%d-%%H%%M";
|
|
|
|
}
|
|
|
|
|
|
|
|
//Calculate the shortname
|
|
|
|
$export_shortname = clean_filename($course->shortname);
|
|
|
|
if (empty($export_shortname) or $export_shortname == '_' ) {
|
|
|
|
$export_shortname = $course->id;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Calculate the category name
|
|
|
|
$export_categoryname = clean_filename($category->name);
|
|
|
|
|
|
|
|
//Calculate the final export filename
|
|
|
|
//The export word
|
|
|
|
$export_name = $export_word."-";
|
|
|
|
//The shortname
|
|
|
|
$export_name .= strtolower($export_shortname)."-";
|
|
|
|
//The category name
|
|
|
|
$export_name .= strtolower($export_categoryname)."-";
|
|
|
|
//The date format
|
|
|
|
$export_name .= userdate(time(),$export_date_format,99,false);
|
|
|
|
//The extension - no extension, supplied by format
|
|
|
|
// $export_name .= ".txt";
|
|
|
|
|
|
|
|
return $export_name;
|
|
|
|
}
|
2004-06-17 17:29:07 +00:00
|
|
|
|
|
|
|
// function to read all questions for category into big array
|
|
|
|
// added by Howard Miller June 2004
|
|
|
|
function get_questions_category( $category ) {
|
|
|
|
|
|
|
|
// questions will be added to an array
|
|
|
|
$qresults = array();
|
|
|
|
|
|
|
|
// get the list of questions for the category
|
|
|
|
$questions = get_records("quiz_questions","category",$category->id);
|
|
|
|
|
2004-06-22 20:44:59 +00:00
|
|
|
// iterate through questions, getting stuff we need
|
2004-06-17 17:29:07 +00:00
|
|
|
foreach($questions as $question) {
|
|
|
|
$new_question = get_question_data( $question );
|
|
|
|
$qresults[] = $new_question;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $qresults;
|
|
|
|
}
|
|
|
|
|
|
|
|
// function to read single question, parameter is object view of
|
2004-06-22 20:44:59 +00:00
|
|
|
// quiz_categories record, results is a combined object
|
2004-06-17 17:29:07 +00:00
|
|
|
// defined as follows...
|
2004-06-22 20:44:59 +00:00
|
|
|
// ->id quiz_questions id
|
|
|
|
// ->category category
|
|
|
|
// ->name q name
|
2004-06-17 17:29:07 +00:00
|
|
|
// ->questiontext
|
|
|
|
// ->image
|
2004-06-22 20:44:59 +00:00
|
|
|
// ->qtype see defines at the top of this file
|
|
|
|
// ->stamp not too sure
|
|
|
|
// ->version not sure
|
2004-06-17 17:29:07 +00:00
|
|
|
// ----SHORTANSWER
|
|
|
|
// ->usecase
|
2004-06-22 20:44:59 +00:00
|
|
|
// ->answers array of answers
|
2004-06-17 17:29:07 +00:00
|
|
|
// ----TRUEFALSE
|
2004-06-22 20:44:59 +00:00
|
|
|
// ->trueanswer truefalse answer
|
2004-06-17 17:29:07 +00:00
|
|
|
// ->falseanswer truefalse answer
|
|
|
|
// ----MULTICHOICE
|
|
|
|
// ->layout
|
2004-06-22 20:44:59 +00:00
|
|
|
// ->single many or just one correct answer
|
|
|
|
// ->answers array of answer objects
|
2004-06-30 10:11:21 +00:00
|
|
|
// ----NUMERIC
|
|
|
|
// ->min minimum answer span
|
|
|
|
// ->max maximum answer span
|
|
|
|
// ->answer single answer
|
|
|
|
// ----MATCH
|
|
|
|
// ->subquestions array of sub questions
|
|
|
|
// ---->questiontext
|
|
|
|
// ---->answertext
|
2004-06-17 17:29:07 +00:00
|
|
|
function get_question_data( $question ) {
|
|
|
|
// what to do next depends of question type (qtype)
|
|
|
|
switch ($question->qtype) {
|
2004-08-23 16:46:50 +00:00
|
|
|
case SHORTANSWER:
|
|
|
|
$shortanswer = get_record("quiz_shortanswer","question",$question->id);
|
|
|
|
$question->usecase = $shortanswer->usecase;
|
|
|
|
$question->answers = get_exp_answers( $question->id );
|
|
|
|
break;
|
|
|
|
case TRUEFALSE:
|
|
|
|
if (!$truefalse = get_record("quiz_truefalse","question",$question->id)) {
|
|
|
|
error( "quiz_truefalse record $question->id not found" );
|
2004-06-17 17:29:07 +00:00
|
|
|
}
|
2004-08-23 16:46:50 +00:00
|
|
|
$question->trueanswer = get_exp_answer( $truefalse->trueanswer );
|
|
|
|
$question->falseanswer = get_exp_answer( $truefalse->falseanswer );
|
|
|
|
break;
|
|
|
|
case MULTICHOICE:
|
|
|
|
if (!$multichoice = get_record("quiz_multichoice","question",$question->id)) {
|
|
|
|
error( "quiz_multichoice $question->id not found" );
|
2004-06-17 17:29:07 +00:00
|
|
|
}
|
2004-08-23 16:46:50 +00:00
|
|
|
$question->layout = $multichoice->layout;
|
|
|
|
$question->single = $multichoice->single;
|
|
|
|
$question->answers = get_exp_answers( $multichoice->question );
|
|
|
|
break;
|
|
|
|
case NUMERICAL:
|
|
|
|
if (!$numeric = get_record("quiz_numerical","question",$question->id)) {
|
|
|
|
error( "quiz_numerical $question->id not found" );
|
|
|
|
}
|
|
|
|
$question->min = $numeric->min;
|
|
|
|
$question->max = $numeric->max;
|
|
|
|
$question->answer = get_exp_answer( $numeric->answer );
|
|
|
|
break;
|
|
|
|
case MATCH:
|
|
|
|
if (!$subquestions = get_records("quiz_match_sub","question",$question->id)) {
|
|
|
|
error( "quiz_match_sub $question->id not found" );
|
|
|
|
}
|
|
|
|
$question->subquestions = $subquestions;
|
|
|
|
break;
|
|
|
|
case DESCRIPTION:
|
|
|
|
// nothing to do
|
|
|
|
break;
|
|
|
|
case MULTIANSWER:
|
|
|
|
// nothing to do
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
notify("No handler for question type $question->qtype in get_question");
|
2004-06-17 17:29:07 +00:00
|
|
|
}
|
|
|
|
return $question;
|
|
|
|
}
|
|
|
|
|
|
|
|
// function to return single answer
|
2004-06-22 20:44:59 +00:00
|
|
|
// ->id answer id
|
|
|
|
// ->question question number
|
2004-06-17 17:29:07 +00:00
|
|
|
// ->answer
|
|
|
|
// ->fraction
|
|
|
|
// ->feedback
|
|
|
|
function get_exp_answer( $id ) {
|
|
|
|
if (!$answer = get_record("quiz_answers","id",$id )) {
|
|
|
|
error( "quiz_answers record $id not found" );
|
2004-08-23 16:46:50 +00:00
|
|
|
}
|
2004-06-17 17:29:07 +00:00
|
|
|
return $answer;
|
|
|
|
}
|
|
|
|
|
|
|
|
// function to return array of answers for export
|
|
|
|
function get_exp_answers( $question_num ) {
|
|
|
|
if (!$answers = get_records("quiz_answers","question",$question_num)) {
|
|
|
|
error( "quiz_answers question $question_num not found" );
|
2004-08-23 16:46:50 +00:00
|
|
|
}
|
2004-06-17 17:29:07 +00:00
|
|
|
return $answers;
|
|
|
|
}
|
2004-07-08 07:50:49 +00:00
|
|
|
|
2002-10-04 02:59:05 +00:00
|
|
|
?>
|