mirror of
https://github.com/moodle/moodle.git
synced 2025-08-05 17:06:53 +02:00
Merged from stable
This commit is contained in:
parent
cb998489a2
commit
fc44ee0de8
17 changed files with 307 additions and 414 deletions
|
@ -216,13 +216,13 @@
|
||||||
// list of questions needed by page
|
// list of questions needed by page
|
||||||
$pagelist = quiz_questions_on_page($attempt->layout, $page);
|
$pagelist = quiz_questions_on_page($attempt->layout, $page);
|
||||||
|
|
||||||
// add all questions that are on the submitted form
|
|
||||||
if ($newattempt) {
|
if ($newattempt) {
|
||||||
$questionlist = $attempt->layout;
|
$questionlist = quiz_questions_in_quiz($attempt->layout);
|
||||||
} else {
|
} else {
|
||||||
$questionlist = $pagelist;
|
$questionlist = $pagelist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add all questions that are on the submitted form
|
||||||
if ($questionids) {
|
if ($questionids) {
|
||||||
$questionlist .= ','.$questionids;
|
$questionlist .= ','.$questionids;
|
||||||
}
|
}
|
||||||
|
@ -253,6 +253,13 @@
|
||||||
error('Could not restore question sessions');
|
error('Could not restore question sessions');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Save all the newly created states
|
||||||
|
if ($newattempt) {
|
||||||
|
foreach ($questions as $i => $question) {
|
||||||
|
quiz_save_question_session($questions[$i], $states[$i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Process form data /////////////////////////////////////////////////
|
/// Process form data /////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -370,13 +377,16 @@
|
||||||
|
|
||||||
/// Print the attempt number or preview heading
|
/// Print the attempt number or preview heading
|
||||||
if ($isteacher) {
|
if ($isteacher) {
|
||||||
print_heading(get_string('previewquiz', 'quiz'));
|
print_heading(get_string('previewquiz', 'quiz', format_string($quiz->name)));
|
||||||
unset($buttonoptions);
|
unset($buttonoptions);
|
||||||
$buttonoptions['q'] = $quiz->id;
|
$buttonoptions['q'] = $quiz->id;
|
||||||
$buttonoptions['forcenew'] = true;
|
$buttonoptions['forcenew'] = true;
|
||||||
echo '<center>';
|
echo '<center>';
|
||||||
print_single_button($CFG->wwwroot.'/mod/quiz/attempt.php', $buttonoptions, get_string('startagain', 'quiz'));
|
print_single_button($CFG->wwwroot.'/mod/quiz/attempt.php', $buttonoptions, get_string('startagain', 'quiz'));
|
||||||
echo '</center>';
|
echo '</center>';
|
||||||
|
if ($quiz->popup) {
|
||||||
|
notify(get_string('popupnotice', 'quiz'));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
print_heading($strattemptnum);
|
print_heading($strattemptnum);
|
||||||
}
|
}
|
||||||
|
@ -434,14 +444,6 @@
|
||||||
quiz_save_question_session($questions[$i], $states[$i]);
|
quiz_save_question_session($questions[$i], $states[$i]);
|
||||||
$number += $questions[$i]->length;
|
$number += $questions[$i]->length;
|
||||||
}
|
}
|
||||||
if ($newattempt) {
|
|
||||||
$questionlist = explode(',', $attempt->layout);
|
|
||||||
foreach ($questionlist as $i) {
|
|
||||||
if ($i != 0) {
|
|
||||||
quiz_save_question_session($questions[$i], $states[$i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Print the submit buttons
|
/// Print the submit buttons
|
||||||
|
|
||||||
|
|
|
@ -932,7 +932,7 @@
|
||||||
fwrite ($bf,full_tag("ID",8,false,$newest_state->id));
|
fwrite ($bf,full_tag("ID",8,false,$newest_state->id));
|
||||||
fwrite ($bf,full_tag("QUESTIONID",8,false,$newest_state->questionid));
|
fwrite ($bf,full_tag("QUESTIONID",8,false,$newest_state->questionid));
|
||||||
fwrite ($bf,full_tag("NEWEST",8,false,$newest_state->newest));
|
fwrite ($bf,full_tag("NEWEST",8,false,$newest_state->newest));
|
||||||
fwrite ($bf,full_tag("NEWESTGRADED",8,false,$newest_state->newestgraded));
|
fwrite ($bf,full_tag("NEWGRADED",8,false,$newest_state->newgraded));
|
||||||
fwrite ($bf,full_tag("SUMPENALTY",8,false,$newest_state->sumpenalty));
|
fwrite ($bf,full_tag("SUMPENALTY",8,false,$newest_state->sumpenalty));
|
||||||
//End newest_state
|
//End newest_state
|
||||||
$status =fwrite ($bf,end_tag("NEWEST_STATE",7,true));
|
$status =fwrite ($bf,end_tag("NEWEST_STATE",7,true));
|
||||||
|
|
|
@ -3,11 +3,11 @@
|
||||||
-- http://www.phpmyadmin.net
|
-- http://www.phpmyadmin.net
|
||||||
--
|
--
|
||||||
-- Host: localhost
|
-- Host: localhost
|
||||||
-- Generation Time: May 25, 2005 at 06:50 AM
|
-- Generation Time: Jun 05, 2005 at 04:32 PM
|
||||||
-- Server version: 4.0.15
|
-- Server version: 4.0.15
|
||||||
-- PHP Version: 4.3.3
|
-- PHP Version: 4.3.3
|
||||||
--
|
--
|
||||||
-- Database: `upgrading`
|
-- Database: `moodle15`
|
||||||
--
|
--
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
-- --------------------------------------------------------
|
||||||
|
@ -399,7 +399,7 @@ CREATE TABLE prefix_quiz_rqp (
|
||||||
-- --------------------------------------------------------
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Table structure for table `prefix_quiz_rqp_states`
|
-- Table structure for table `prefix_quiz_rqp_servers`
|
||||||
--
|
--
|
||||||
|
|
||||||
CREATE TABLE prefix_quiz_rqp_servers (
|
CREATE TABLE prefix_quiz_rqp_servers (
|
||||||
|
@ -414,7 +414,7 @@ CREATE TABLE prefix_quiz_rqp_servers (
|
||||||
-- --------------------------------------------------------
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Table structure for table `mdl_quiz_rqp_states`
|
-- Table structure for table `prefix_quiz_rqp_states`
|
||||||
--
|
--
|
||||||
|
|
||||||
CREATE TABLE prefix_quiz_rqp_states (
|
CREATE TABLE prefix_quiz_rqp_states (
|
||||||
|
@ -429,15 +429,12 @@ CREATE TABLE prefix_quiz_rqp_states (
|
||||||
-- --------------------------------------------------------
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Table structure for table `prefix_quiz_rqp_type`
|
-- Table structure for table `prefix_quiz_rqp_types`
|
||||||
--
|
--
|
||||||
|
|
||||||
CREATE TABLE prefix_quiz_rqp_types (
|
CREATE TABLE prefix_quiz_rqp_types (
|
||||||
id int(10) unsigned NOT NULL auto_increment,
|
id int(10) unsigned NOT NULL auto_increment,
|
||||||
name varchar(255) NOT NULL default '',
|
name varchar(255) NOT NULL default '',
|
||||||
rendering_server varchar(255) NOT NULL default '',
|
|
||||||
cloning_server varchar(255) NOT NULL default '',
|
|
||||||
flags tinyint(3) NOT NULL default '0',
|
|
||||||
PRIMARY KEY (id),
|
PRIMARY KEY (id),
|
||||||
UNIQUE KEY name (name)
|
UNIQUE KEY name (name)
|
||||||
) TYPE=MyISAM COMMENT='RQP question types and the servers to be used to process the';
|
) TYPE=MyISAM COMMENT='RQP question types and the servers to be used to process the';
|
||||||
|
|
|
@ -408,14 +408,13 @@ if (self.name == 'editquestion') {
|
||||||
if (! $cm = get_coursemodule_from_instance("quiz", $modform->instance, $course->id)) {
|
if (! $cm = get_coursemodule_from_instance("quiz", $modform->instance, $course->id)) {
|
||||||
error("Course Module ID was incorrect");
|
error("Course Module ID was incorrect");
|
||||||
}
|
}
|
||||||
notify("$strattemptsexist<br /><a href=\"report.php?mode=overview&id=$cm->id\">$strviewallanswers ($usercount $strusers)</a>");
|
|
||||||
|
|
||||||
echo "<center>\n";
|
echo "<center>\n";
|
||||||
|
echo "$strattemptsexist<br /><a href=\"report.php?mode=overview&id=$cm->id\">$strviewallanswers ($usercount $strusers)</a>";
|
||||||
echo "<form target=\"_parent\" method=\"get\" action=\"$CFG->wwwroot/mod/quiz/edit.php\">\n";
|
echo "<form target=\"_parent\" method=\"get\" action=\"$CFG->wwwroot/mod/quiz/edit.php\">\n";
|
||||||
echo " <input type=\"hidden\" name=\"courseid\" value=\"$course->id\" />\n";
|
echo " <input type=\"hidden\" name=\"courseid\" value=\"$course->id\" />\n";
|
||||||
echo " <input type=\"submit\" value=\"".get_string("editcatquestions", "quiz")."\" />\n";
|
echo " <input type=\"submit\" value=\"".get_string("editcatquestions", "quiz")."\" />\n";
|
||||||
echo "</form>";
|
echo "</form>";
|
||||||
echo "</center>\n";
|
echo "</center><br/ >\n";
|
||||||
|
|
||||||
$sumgrades = quiz_print_question_list($modform, false, $SESSION->quiz_showbreaks);
|
$sumgrades = quiz_print_question_list($modform, false, $SESSION->quiz_showbreaks);
|
||||||
if (!set_field('quiz', 'sumgrades', $sumgrades, 'id', $modform->instance)) {
|
if (!set_field('quiz', 'sumgrades', $sumgrades, 'id', $modform->instance)) {
|
||||||
|
|
|
@ -247,7 +247,7 @@ class quiz_default_questiontype {
|
||||||
// The default implementation attaches all answers for this question
|
// The default implementation attaches all answers for this question
|
||||||
if (!$question->options->answers = get_records('quiz_answers', 'question',
|
if (!$question->options->answers = get_records('quiz_answers', 'question',
|
||||||
$question->id)) {
|
$question->id)) {
|
||||||
notify('Error: Missing question answers!');
|
//notify('Error: Missing question answers!');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -1349,13 +1349,14 @@ function quiz_save_question_session(&$question, &$state) {
|
||||||
$state->answer = isset($state->responses['']) ? $state->responses[''] : '';
|
$state->answer = isset($state->responses['']) ? $state->responses[''] : '';
|
||||||
|
|
||||||
// Save the state
|
// Save the state
|
||||||
unset($state->id);
|
if (isset($state->update)) {
|
||||||
|
update_record('quiz_states', $state);
|
||||||
|
} else {
|
||||||
if (!$state->id = insert_record('quiz_states', $state)) {
|
if (!$state->id = insert_record('quiz_states', $state)) {
|
||||||
unset($state->id);
|
unset($state->id);
|
||||||
unset($state->answer);
|
unset($state->answer);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
unset($state->answer);
|
|
||||||
|
|
||||||
// this is the most recent state
|
// this is the most recent state
|
||||||
if (!record_exists('quiz_newest_states', 'attemptid',
|
if (!record_exists('quiz_newest_states', 'attemptid',
|
||||||
|
@ -1381,6 +1382,9 @@ function quiz_save_question_session(&$question, &$state) {
|
||||||
update_record('quiz_newest_states', $newest);
|
update_record('quiz_newest_states', $newest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unset($state->answer);
|
||||||
|
|
||||||
// Save the question type specific state information and responses
|
// Save the question type specific state information and responses
|
||||||
if (!$QUIZ_QTYPES[$question->qtype]->save_session_and_responses(
|
if (!$QUIZ_QTYPES[$question->qtype]->save_session_and_responses(
|
||||||
|
@ -1465,9 +1469,10 @@ function quiz_extract_responses($questions, $responses, $defaultevent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For a given question instance we walk the complete history of states for
|
* For a given question in an attempt we walk the complete history of states
|
||||||
* each user and recalculate the grades as we go along.
|
* and recalculate the grades as we go along.
|
||||||
*
|
*
|
||||||
* This is used when a question in an existing quiz is changed and old student
|
* This is used when a question in an existing quiz is changed and old student
|
||||||
* responses need to be marked with the new version of a question.
|
* responses need to be marked with the new version of a question.
|
||||||
|
@ -1475,65 +1480,43 @@ function quiz_extract_responses($questions, $responses, $defaultevent) {
|
||||||
* TODO: Finish documenting this
|
* TODO: Finish documenting this
|
||||||
* @return boolean Indicates success/failure
|
* @return boolean Indicates success/failure
|
||||||
* @param object $question A question object
|
* @param object $question A question object
|
||||||
* @param array $quizlist An array of quiz ids, in which the question should
|
* @param object $attempt The attempt, in which the question needs to be regraded.
|
||||||
* be regraded. If quizlist == 'all' all quizzes are affected
|
* @param object $quiz Optional. The quiz object that the attempt corresponds to.
|
||||||
|
* @param boolean $verbose Optional. Whether to print progress information or not.
|
||||||
*/
|
*/
|
||||||
function quiz_regrade_question_in_quizzes($question, $quizlist) {
|
function quiz_regrade_question_in_attempt($question, $attempt, $quiz=false, $verbose=false) {
|
||||||
|
if (!$quiz && !($quiz = get_record('quiz', 'id', $attempt->quiz))) {
|
||||||
// Disable until tested
|
$verbose && notify("Regrading of quiz #{$attempt->quiz} failed; " .
|
||||||
return;
|
"Couldn't load quiz record from database!");
|
||||||
|
return false;
|
||||||
if (empty($quizlist)) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($quizlist == 'all') { // assume that all quizzes are affected
|
|
||||||
// fetch a list of all the quizzes using this question
|
|
||||||
if (! $instances = (array)get_records('quiz_question_instances',
|
|
||||||
'question', $question->id, '', 'id, quiz')) {
|
|
||||||
// No instances were found, so it successfully regraded all of them
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
$quizlist = array_map(create_function('$val', 'return $val->quiz;'), $instances);
|
|
||||||
unset($instances);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get all affected quizzes
|
|
||||||
$quizlist = implode(',', $quizlist);
|
|
||||||
if (! $quizzes = get_records_list('quiz', 'id', $quizlist)) {
|
|
||||||
error('Couldn\'t get quizzes for regrading!');
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($quizzes as $quiz) {
|
|
||||||
// All the attempts that need to be changed
|
|
||||||
if (! $attempts = get_records('quiz_attempts', 'quiz', $quiz->id)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$attempts = array_values($attempts);
|
|
||||||
if (! $instance = get_record('quiz_question_instances',
|
|
||||||
'quiz', $quiz->id, 'question', $question->id)) {
|
|
||||||
error("Couldn't get question instance for regrading!");
|
|
||||||
}
|
|
||||||
$question->maxgrade = $instance->grade;
|
|
||||||
for ($i = 0; $i < count($attempts); $i++) {
|
|
||||||
if ($states = get_records_select('quiz_states',
|
if ($states = get_records_select('quiz_states',
|
||||||
"attempt = '{$attempts[$i]->id}' ".
|
"attempt = '{$attempt->id}' AND question = '{$question->id}'", 'seq_number ASC')) {
|
||||||
"AND question = '{$question->id}'",
|
|
||||||
'seq_number ASC')) {
|
|
||||||
$states = array_values($states);
|
$states = array_values($states);
|
||||||
|
|
||||||
$attempts[$i]->sumgrades -= $states[count($states)-1]->grade;
|
$attempt->sumgrades -= $states[count($states)-1]->grade;
|
||||||
|
|
||||||
// Initialise the replaystate
|
// Initialise the replaystate
|
||||||
quiz_restore_state($question, $states[0]);
|
$state = clone($states[0]);
|
||||||
$replaystate = clone($states[0]);
|
quiz_restore_state($question, $state);
|
||||||
$replaystate->last_graded = clone($states[0]);
|
$state->sumpenalty = 0.0;
|
||||||
for($j = 1; $j < count($states); $j++) {
|
$state->raw_grade = 0;
|
||||||
|
$state->grade = 0;
|
||||||
|
$state->responses = array(''=>'');
|
||||||
|
$state->event = QUIZ_EVENTOPEN;
|
||||||
|
$replaystate = clone($state);
|
||||||
|
$replaystate->last_graded = $state;
|
||||||
|
|
||||||
|
$changed = 0;
|
||||||
|
for($j = 0; $j < count($states); $j++) {
|
||||||
quiz_restore_state($question, $states[$j]);
|
quiz_restore_state($question, $states[$j]);
|
||||||
$action = new stdClass;
|
$action = new stdClass;
|
||||||
$action->responses = $states[$j]->responses;
|
$action->responses = $states[$j]->responses;
|
||||||
|
$action->timestamp = $states[$j]->timestamp;
|
||||||
|
|
||||||
// Close the last state of a finished attempt
|
// Close the last state of a finished attempt
|
||||||
if (((count($states) - 1) === $j) && ($attempts[$i]->timefinish > 0)) {
|
if (((count($states) - 1) === $j) && ($attempt->timefinish > 0)) {
|
||||||
$action->event = QUIZ_EVENTCLOSE;
|
$action->event = QUIZ_EVENTCLOSE;
|
||||||
|
|
||||||
// Grade instead of closing, quiz_process_responses will then
|
// Grade instead of closing, quiz_process_responses will then
|
||||||
|
@ -1545,18 +1528,33 @@ function quiz_regrade_question_in_quizzes($question, $quizlist) {
|
||||||
} else {
|
} else {
|
||||||
$action->event = $states[$j]->event;
|
$action->event = $states[$j]->event;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reprocess (regrade) responses
|
// Reprocess (regrade) responses
|
||||||
quiz_process_responses($question, $replaystate, $action, $quiz,
|
if (!quiz_process_responses($question, $replaystate, $action, $quiz,
|
||||||
$attempts[$i]);
|
$attempt)) {
|
||||||
|
$verbose && notify("Couldn't regrade state #{$state->id}!");
|
||||||
|
}
|
||||||
|
if ((float)$replaystate->raw_grade != (float)$states[$j]->raw_grade) {
|
||||||
|
$changed++;
|
||||||
|
|
||||||
|
}
|
||||||
$replaystate->id = $states[$j]->id;
|
$replaystate->id = $states[$j]->id;
|
||||||
update_record('quiz_states', $replaystate);
|
$replaystate->update = true;
|
||||||
|
quiz_save_question_session($question, $replaystate);
|
||||||
}
|
}
|
||||||
update_record('quiz_attempts', $attempts[$i]);
|
if ($verbose) {
|
||||||
quiz_save_best_grade($quiz, $attempts[$i]->userid);
|
if ($changed) {
|
||||||
|
link_to_popup_window ('/mod/quiz/reviewquestion.php?attempt='.$attempt->id.'&question='.$question->id,
|
||||||
|
'reviewquestion', ' #'.$attempt->id, 450, 550, get_string('reviewresponse', 'quiz'));
|
||||||
|
update_record('quiz_attempts', $attempt);
|
||||||
|
} else {
|
||||||
|
echo ' #'.$attempt->id;
|
||||||
}
|
}
|
||||||
|
echo "\n"; flush(); ob_flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2244,7 +2242,7 @@ if (!$grade = get_record('quiz_grades', 'quiz', $quiz->id, 'userid', $userid)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: document this
|
* Save the overall grade for a user at a quiz in the quiz_grades table
|
||||||
*
|
*
|
||||||
* @return boolean Indicates success or failure.
|
* @return boolean Indicates success or failure.
|
||||||
* @param object $quiz The quiz for which the best grade is to be calculated
|
* @param object $quiz The quiz for which the best grade is to be calculated
|
||||||
|
@ -2269,11 +2267,12 @@ function quiz_save_best_grade($quiz, $userid=null) {
|
||||||
// Calculate the best grade
|
// Calculate the best grade
|
||||||
$bestgrade = quiz_calculate_best_grade($quiz, $attempts);
|
$bestgrade = quiz_calculate_best_grade($quiz, $attempts);
|
||||||
$bestgrade = (($bestgrade / $quiz->sumgrades) * $quiz->grade);
|
$bestgrade = (($bestgrade / $quiz->sumgrades) * $quiz->grade);
|
||||||
|
$bestgrade = round($bestgrade, $quiz->decimalpoints);
|
||||||
|
|
||||||
// Save the best grade in the database
|
// Save the best grade in the database
|
||||||
if ($grade = get_record('quiz_grades', 'quiz', $quiz->id, 'userid',
|
if ($grade = get_record('quiz_grades', 'quiz', $quiz->id, 'userid',
|
||||||
$userid)) {
|
$userid)) {
|
||||||
$grade->grade = round($bestgrade, $quiz->decimalpoints);
|
$grade->grade = $bestgrade;
|
||||||
$grade->timemodified = time();
|
$grade->timemodified = time();
|
||||||
if (!update_record('quiz_grades', $grade)) {
|
if (!update_record('quiz_grades', $grade)) {
|
||||||
notify('Could not update best grade');
|
notify('Could not update best grade');
|
||||||
|
@ -2282,7 +2281,7 @@ function quiz_save_best_grade($quiz, $userid=null) {
|
||||||
} else {
|
} else {
|
||||||
$grade->quiz = $quiz->id;
|
$grade->quiz = $quiz->id;
|
||||||
$grade->userid = $userid;
|
$grade->userid = $userid;
|
||||||
$grade->grade = round($bestgrade, $quiz->decimalpoints);
|
$grade->grade = $bestgrade;
|
||||||
$grade->timemodified = time();
|
$grade->timemodified = time();
|
||||||
if (!insert_record('quiz_grades', $grade)) {
|
if (!insert_record('quiz_grades', $grade)) {
|
||||||
notify('Could not insert new best grade');
|
notify('Could not insert new best grade');
|
||||||
|
@ -2292,9 +2291,14 @@ function quiz_save_best_grade($quiz, $userid=null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the overall grade for a quiz given a number of attempts by a particular user.
|
||||||
|
*
|
||||||
|
* @return float The overall grade
|
||||||
|
* @param object $quiz The quiz for which the best grade is to be calculated
|
||||||
|
* @param array $attempts An array of all the attempts of the user at the quiz
|
||||||
|
*/
|
||||||
function quiz_calculate_best_grade($quiz, $attempts) {
|
function quiz_calculate_best_grade($quiz, $attempts) {
|
||||||
/// Calculate the best grade for a quiz given a number of attempts by a particular user.
|
|
||||||
|
|
||||||
switch ($quiz->grademethod) {
|
switch ($quiz->grademethod) {
|
||||||
|
|
||||||
|
@ -2331,9 +2335,16 @@ function quiz_calculate_best_grade($quiz, $attempts) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the attempt with the best grade for a quiz
|
||||||
|
*
|
||||||
|
* Which attempt is the best depends on $quiz->grademethod. If the grade
|
||||||
|
* method is GRADEAVERAGE then this function simply returns the last attempt.
|
||||||
|
* @return object The attempt with the best grade
|
||||||
|
* @param object $quiz The quiz for which the best grade is to be calculated
|
||||||
|
* @param array $attempts An array of all the attempts of the user at the quiz
|
||||||
|
*/
|
||||||
function quiz_calculate_best_attempt($quiz, $attempts) {
|
function quiz_calculate_best_attempt($quiz, $attempts) {
|
||||||
/// Return the attempt with the best grade for a quiz
|
|
||||||
|
|
||||||
switch ($quiz->grademethod) {
|
switch ($quiz->grademethod) {
|
||||||
|
|
||||||
|
|
|
@ -272,11 +272,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($question->errors) && $QUIZ_QTYPES[$qtype]->finished_edit_wizard($form)) {
|
if (empty($question->errors) && $QUIZ_QTYPES[$qtype]->finished_edit_wizard($form)) {
|
||||||
|
// DISABLED AUTOMATIC REGRADING
|
||||||
// Automagically regrade all attempts (and states) in the affected quizzes
|
// Automagically regrade all attempts (and states) in the affected quizzes
|
||||||
if (!empty($replaceinquiz)) {
|
//if (!empty($replaceinquiz)) {
|
||||||
$QUIZ_QTYPES[$question->qtype]->get_question_options($question);
|
// $QUIZ_QTYPES[$question->qtype]->get_question_options($question);
|
||||||
quiz_regrade_question_in_quizzes($question, $replaceinquiz);
|
// quiz_regrade_question_in_quizzes($question, $replaceinquiz);
|
||||||
}
|
//}
|
||||||
redirect("edit.php");
|
redirect("edit.php");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -368,7 +368,8 @@ class quiz_calculated_qtype extends quiz_dataset_dependent_questiontype {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get answers
|
// Get answers
|
||||||
$answers = $question->options->answers;
|
// the next line is hacked to get rid of the PHP notice until this gets fixed properly
|
||||||
|
$answers = (isset($question->options->answers)) ? $question->options->answers : null;
|
||||||
$stranswers = get_string('answer', 'quiz');
|
$stranswers = get_string('answer', 'quiz');
|
||||||
$strmin = get_string('min', 'quiz');
|
$strmin = get_string('min', 'quiz');
|
||||||
$strmax = get_string('max', 'quiz');
|
$strmax = get_string('max', 'quiz');
|
||||||
|
@ -378,6 +379,7 @@ class quiz_calculated_qtype extends quiz_dataset_dependent_questiontype {
|
||||||
$state->responses = array();
|
$state->responses = array();
|
||||||
$state->options = new stdClass;
|
$state->options = new stdClass;
|
||||||
$virtualqtype = $this->get_virtual_qtype();
|
$virtualqtype = $this->get_virtual_qtype();
|
||||||
|
if ($answers) {
|
||||||
foreach ($answers as $answer) {
|
foreach ($answers as $answer) {
|
||||||
$calculated = quiz_qtype_calculated_calculate_answer(
|
$calculated = quiz_qtype_calculated_calculate_answer(
|
||||||
$answer->answer, $data, $answer->tolerance,
|
$answer->answer, $data, $answer->tolerance,
|
||||||
|
@ -399,6 +401,7 @@ class quiz_calculated_qtype extends quiz_dataset_dependent_questiontype {
|
||||||
|
|
||||||
$delimiter = ', ';
|
$delimiter = ', ';
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return "$stranswers<br/>$strmin<br/>$strmax<br/>$errors";
|
return "$stranswers<br/>$strmin<br/>$strmax<br/>$errors";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -239,7 +239,7 @@ class quiz_multichoice_qtype extends quiz_default_questiontype {
|
||||||
|
|
||||||
$answers = &$question->options->answers;
|
$answers = &$question->options->answers;
|
||||||
$correctanswers = $this->get_correct_responses($question, $state);
|
$correctanswers = $this->get_correct_responses($question, $state);
|
||||||
$readonly = empty($options->readonly) ? '' : 'disabled="disabled"';
|
$readonly = empty($options->readonly) ? '' : 'readonly="readonly"';
|
||||||
|
|
||||||
$formatoptions = new stdClass;
|
$formatoptions = new stdClass;
|
||||||
$formatoptions->para = false;
|
$formatoptions->para = false;
|
||||||
|
|
|
@ -246,7 +246,7 @@ class quiz_numerical_qtype extends quiz_shortanswer_qtype {
|
||||||
|
|
||||||
$answers = &$question->options->answers;
|
$answers = &$question->options->answers;
|
||||||
$correctanswers = $this->get_correct_responses($question, $state);
|
$correctanswers = $this->get_correct_responses($question, $state);
|
||||||
$readonly = empty($options->readonly) ? '' : 'disabled="disabled"';
|
$readonly = empty($options->readonly) ? '' : 'readonly="readonly"';
|
||||||
$nameprefix = $question->name_prefix;
|
$nameprefix = $question->name_prefix;
|
||||||
|
|
||||||
/// Print question text and media
|
/// Print question text and media
|
||||||
|
|
|
@ -7,13 +7,7 @@
|
||||||
/// QUESTION TYPE CLASS //////////////////
|
/// QUESTION TYPE CLASS //////////////////
|
||||||
class quiz_random_qtype extends quiz_default_questiontype {
|
class quiz_random_qtype extends quiz_default_questiontype {
|
||||||
|
|
||||||
var $possiblerandomqtypes = array(SHORTANSWER,
|
var $excludedtypes = array(RANDOM, RANDOMSAMATCH);
|
||||||
NUMERICAL,
|
|
||||||
MULTICHOICE,
|
|
||||||
MATCH,
|
|
||||||
// RANDOMSAMATCH,// Can cause unexpected outcomes
|
|
||||||
TRUEFALSE,
|
|
||||||
MULTIANSWER);
|
|
||||||
|
|
||||||
// Carries questions available as randoms sorted by category
|
// Carries questions available as randoms sorted by category
|
||||||
// This array is used when needed only
|
// This array is used when needed only
|
||||||
|
@ -52,8 +46,7 @@ class quiz_random_qtype extends quiz_default_questiontype {
|
||||||
// Need to fetch random questions from category $question->category"
|
// Need to fetch random questions from category $question->category"
|
||||||
// (Note: $this refers to the questiontype, not the question.)
|
// (Note: $this refers to the questiontype, not the question.)
|
||||||
global $CFG;
|
global $CFG;
|
||||||
$possiblerandomqtypes = "'"
|
$excludedtypes = implode(',', $this->excludedtypes);
|
||||||
. implode("','", $this->possiblerandomqtypes) . "'";
|
|
||||||
if ($question->questiontext == "1") {
|
if ($question->questiontext == "1") {
|
||||||
// recurse into subcategories
|
// recurse into subcategories
|
||||||
$categorylist = quiz_categorylist($question->category);
|
$categorylist = quiz_categorylist($question->category);
|
||||||
|
@ -65,7 +58,7 @@ class quiz_random_qtype extends quiz_default_questiontype {
|
||||||
WHERE category IN ($categorylist)
|
WHERE category IN ($categorylist)
|
||||||
AND parent = '0'
|
AND parent = '0'
|
||||||
AND id NOT IN ($quiz->questionsinuse)
|
AND id NOT IN ($quiz->questionsinuse)
|
||||||
AND qtype IN ($possiblerandomqtypes)");
|
AND qtype NOT IN ($excludedtypes)");
|
||||||
$this->catrandoms[$question->category] =
|
$this->catrandoms[$question->category] =
|
||||||
draw_rand_array($this->catrandoms[$question->category],
|
draw_rand_array($this->catrandoms[$question->category],
|
||||||
count($this->catrandoms[$question->category])); // from bug 1889
|
count($this->catrandoms[$question->category])); // from bug 1889
|
||||||
|
@ -80,13 +73,6 @@ class quiz_random_qtype extends quiz_default_questiontype {
|
||||||
global $QUIZ_QTYPES;
|
global $QUIZ_QTYPES;
|
||||||
$QUIZ_QTYPES[$wrappedquestion->qtype]
|
$QUIZ_QTYPES[$wrappedquestion->qtype]
|
||||||
->get_question_options($wrappedquestion);
|
->get_question_options($wrappedquestion);
|
||||||
|
|
||||||
// Backup the original state of the random question
|
|
||||||
// And change the $state to match the wrapped question. This
|
|
||||||
// is sensible, because so the wrapped question's state gets
|
|
||||||
// put through all the generic processing.
|
|
||||||
$state->options->state = clone($state);
|
|
||||||
$state->question = $wrappedquestion->id;
|
|
||||||
$QUIZ_QTYPES[$wrappedquestion->qtype]
|
$QUIZ_QTYPES[$wrappedquestion->qtype]
|
||||||
->create_session_and_responses($wrappedquestion,
|
->create_session_and_responses($wrappedquestion,
|
||||||
$state, $quiz, $attempt);
|
$state, $quiz, $attempt);
|
||||||
|
@ -97,38 +83,53 @@ class quiz_random_qtype extends quiz_default_questiontype {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
notify(get_string('toomanyrandom', 'quiz', $question->category));
|
$question->questiontext = '<span class="notifyproblem">'.
|
||||||
return false;
|
get_string('toomanyrandom', 'quiz', $question->category). '</span>';
|
||||||
|
$question->qtype = DESCRIPTION;
|
||||||
|
$state->responses = array('' => '');
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function restore_session_and_responses(&$question, &$state) {
|
function restore_session_and_responses(&$question, &$state) {
|
||||||
|
/// The raw response records for random questions come in two flavours:
|
||||||
|
/// ---- 1 ----
|
||||||
|
/// For responses stored by Moodle version 1.5 and later the answer
|
||||||
|
/// field has the pattern random#-* where the # part is the numeric
|
||||||
|
/// question id of the actual question shown in the quiz attempt
|
||||||
|
/// and * represents the student response to that actual question.
|
||||||
|
/// ---- 2 ----
|
||||||
|
/// For responses stored by older Moodle versions - the answer field is
|
||||||
|
/// simply the question id of the actual question. The student response
|
||||||
|
/// to the actual question is stored in a separate response record.
|
||||||
|
/// -----------------------
|
||||||
|
/// This means that prior to Moodle version 1.5, random questions needed
|
||||||
|
/// two response records for storing the response to a single question.
|
||||||
|
/// From version 1.5 and later the question type random works like all
|
||||||
|
/// the other question types in that it now only needs one response
|
||||||
|
/// record per question.
|
||||||
global $QUIZ_QTYPES;
|
global $QUIZ_QTYPES;
|
||||||
if(!$randomstate = get_record('quiz_states', 'question',
|
if (!ereg('^random([0-9]+)-(.*)$', $state->responses[''], $answerregs)) {
|
||||||
$question->id, 'attempt', $state->attempt)) {
|
// this must be an old-style state which stores only the id for the wrapped question
|
||||||
|
if (!$wrappedquestion = get_record('quiz_questions', 'id', $state->responses[''])) {
|
||||||
|
error("Can not find wrapped question $state->responses['']");
|
||||||
|
}
|
||||||
|
// In the old model the actual response was stored in a separate entry in
|
||||||
|
// the state table
|
||||||
|
if (!$state->responses[''] = get_field('quiz_states', 'answer', 'attempt', $state->attempt, 'question', $wrappedquestion->id)) {
|
||||||
|
error("Wrapped state missing");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!$wrappedquestion = get_record('quiz_questions', 'id', $answerregs[1])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
$state->responses[''] = $answerregs[2];
|
||||||
if (!$wrappedquestion = get_record('quiz_questions', 'id',
|
|
||||||
$randomstate->answer)) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
$state->question = $wrappedquestion->id;
|
|
||||||
|
|
||||||
if (!$QUIZ_QTYPES[$wrappedquestion->qtype]
|
if (!$QUIZ_QTYPES[$wrappedquestion->qtype]
|
||||||
->get_question_options($wrappedquestion)) {
|
->get_question_options($wrappedquestion)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to set responses[''] to whatever was saved in the most recent
|
|
||||||
// state of the wrapped question.
|
|
||||||
if(!$wrappedstates = get_records_select('quiz_states',
|
|
||||||
"question = $wrappedquestion->id AND attempt = $state->attempt",
|
|
||||||
'seq_number DESC')) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$wrappedstates = array_values($wrappedstates);
|
|
||||||
$state->responses = array('' => $wrappedstates[0]->answer);
|
|
||||||
|
|
||||||
if (!$QUIZ_QTYPES[$wrappedquestion->qtype]
|
if (!$QUIZ_QTYPES[$wrappedquestion->qtype]
|
||||||
->restore_session_and_responses($wrappedquestion, $state)) {
|
->restore_session_and_responses($wrappedquestion, $state)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -136,21 +137,12 @@ class quiz_random_qtype extends quiz_default_questiontype {
|
||||||
$wrappedquestion->name_prefix = $question->name_prefix;
|
$wrappedquestion->name_prefix = $question->name_prefix;
|
||||||
$wrappedquestion->maxgrade = $question->maxgrade;
|
$wrappedquestion->maxgrade = $question->maxgrade;
|
||||||
$state->options->question = &$wrappedquestion;
|
$state->options->question = &$wrappedquestion;
|
||||||
$state->options->state = &$randomstate;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function save_session_and_responses(&$question, &$state) {
|
function save_session_and_responses(&$question, &$state) {
|
||||||
global $QUIZ_QTYPES;
|
global $QUIZ_QTYPES;
|
||||||
$wrappedquestion = &$state->options->question;
|
$wrappedquestion = &$state->options->question;
|
||||||
$randomstate = &$state->options->state;
|
|
||||||
|
|
||||||
// We need to save the randomstate manually, because we can only process
|
|
||||||
// one response record automatically
|
|
||||||
if (empty($randomstate->id)) {
|
|
||||||
$randomstate->answer = $wrappedquestion->id;
|
|
||||||
$randomstate->id = insert_record('quiz_states', $randomstate);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Trick the wrapped question into pretending to be the random one.
|
// Trick the wrapped question into pretending to be the random one.
|
||||||
$realqid = $wrappedquestion->id;
|
$realqid = $wrappedquestion->id;
|
||||||
|
@ -158,6 +150,21 @@ class quiz_random_qtype extends quiz_default_questiontype {
|
||||||
$QUIZ_QTYPES[$wrappedquestion->qtype]
|
$QUIZ_QTYPES[$wrappedquestion->qtype]
|
||||||
->save_session_and_responses($wrappedquestion, $state);
|
->save_session_and_responses($wrappedquestion, $state);
|
||||||
|
|
||||||
|
// Read what the wrapped question has just set the answer field to
|
||||||
|
// (if anything)
|
||||||
|
$response = get_field('quiz_states', 'answer', 'id', $state->id);
|
||||||
|
if(false === $response) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prefix the answer field...
|
||||||
|
$response = "random$realqid-$response";
|
||||||
|
|
||||||
|
// ... and save it again.
|
||||||
|
if (!set_field('quiz_states', 'answer', $response, 'id', $state->id)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Restore the real id
|
// Restore the real id
|
||||||
$wrappedquestion->id = $realqid;
|
$wrappedquestion->id = $realqid;
|
||||||
return true;
|
return true;
|
||||||
|
@ -193,34 +200,7 @@ class quiz_random_qtype extends quiz_default_questiontype {
|
||||||
$QUIZ_QTYPES[$wrappedquestion->qtype]
|
$QUIZ_QTYPES[$wrappedquestion->qtype]
|
||||||
->print_question($wrappedquestion, $state, $number, $quiz, $options);
|
->print_question($wrappedquestion, $state, $number, $quiz, $options);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
function print_question_grading_details(&$question, &$state, $quiz,
|
|
||||||
$options) {
|
|
||||||
global $QUIZ_QTYPES;
|
|
||||||
$wrappedquestion = &$state->options->question;
|
|
||||||
$QUIZ_QTYPES[$wrappedquestion->qtype]
|
|
||||||
->print_question_grading_details($wrappedquestion, $state, $quiz,
|
|
||||||
$options);
|
|
||||||
}
|
|
||||||
|
|
||||||
function print_question_formulation_and_controls(&$question, &$state, $quiz,
|
|
||||||
$options) {
|
|
||||||
global $QUIZ_QTYPES;
|
|
||||||
$wrappedquestion = &$state->options->question;
|
|
||||||
$QUIZ_QTYPES[$wrappedquestion->qtype]
|
|
||||||
->print_question_formulation_and_controls($wrappedquestion, $state,
|
|
||||||
$quiz, $options);
|
|
||||||
}
|
|
||||||
|
|
||||||
function print_question_submit_buttons(&$question, &$state, $quiz,
|
|
||||||
$options) {
|
|
||||||
global $QUIZ_QTYPES;
|
|
||||||
$wrappedquestion = &$state->options->question;
|
|
||||||
$QUIZ_QTYPES[$wrappedquestion->qtype]
|
|
||||||
->print_question_submit_buttons($wrappedquestion, $state, $quiz,
|
|
||||||
$options);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
function grade_responses(&$question, &$state, $quiz) {
|
function grade_responses(&$question, &$state, $quiz) {
|
||||||
global $QUIZ_QTYPES;
|
global $QUIZ_QTYPES;
|
||||||
$wrappedquestion = &$state->options->question;
|
$wrappedquestion = &$state->options->question;
|
||||||
|
@ -255,173 +235,7 @@ class quiz_random_qtype extends quiz_default_questiontype {
|
||||||
return $QUIZ_QTYPES[$wrappedquestion->qtype]
|
return $QUIZ_QTYPES[$wrappedquestion->qtype]
|
||||||
->print_question_form_end($wrappedquestion, $state, $quizid);
|
->print_question_form_end($wrappedquestion, $state, $quizid);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
function convert_to_response_answer_field($questionresponse) {
|
|
||||||
global $QUIZ_QTYPES;
|
|
||||||
|
|
||||||
foreach ($questionresponse as $key => $response) {
|
|
||||||
if (ereg('[^0-9][0-9]+random$', $key)) {
|
|
||||||
unset($questionresponse[$key]);
|
|
||||||
$randomquestion = get_record('quiz_questions',
|
|
||||||
'id', $response);
|
|
||||||
return "random$response-"
|
|
||||||
.$QUIZ_QTYPES[$randomquestion->qtype]
|
|
||||||
->convert_to_response_answer_field($questionresponse);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function create_response($question, $nameprefix, $questionsinuse) {
|
|
||||||
// It's for question types like RANDOMSAMATCH and RANDOM that
|
|
||||||
// the true power of the pattern with this function comes to the surface.
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
function print_question_formulation_and_controls($question,
|
|
||||||
$quiz, $readonly, $answers, $correctanswers, $nameprefix) {
|
|
||||||
global $QUIZ_QTYPES;
|
|
||||||
|
|
||||||
// Get the wrapped question...
|
|
||||||
if ($actualquestion = $this->get_wrapped_question($question,
|
|
||||||
$nameprefix)) {
|
|
||||||
echo '<input type="hidden" name="' . $nameprefix
|
|
||||||
. '" value="' . $actualquestion->id . '" />';
|
|
||||||
return $QUIZ_QTYPES[$actualquestion->qtype]
|
|
||||||
->print_question_formulation_and_controls($actualquestion,
|
|
||||||
$quiz, $readonly, $answers, $correctanswers,
|
|
||||||
quiz_qtype_nameprefix($actualquestion, $nameprefix));
|
|
||||||
} else {
|
|
||||||
echo '<p>' . get_string('random', 'quiz') . '</p>';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function get_wrapped_question($question, $nameprefix) {
|
|
||||||
if (!empty($question->response[$nameprefix])
|
|
||||||
and $actualquestion = get_record('quiz_questions',
|
|
||||||
'id', $question->response[$nameprefix])) {
|
|
||||||
$actualquestion->response = $question->response;
|
|
||||||
unset($actualquestion->response[$nameprefix]);
|
|
||||||
$actualquestion->maxgrade = $question->maxgrade;
|
|
||||||
return $actualquestion;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function grade_response($question, $nameprefix) {
|
|
||||||
global $QUIZ_QTYPES;
|
|
||||||
|
|
||||||
// Get the wrapped question...
|
|
||||||
if ($actualquestion = $this->get_wrapped_question($question,
|
|
||||||
$nameprefix)) {
|
|
||||||
return $QUIZ_QTYPES[$actualquestion->qtype]->grade_response(
|
|
||||||
$actualquestion,
|
|
||||||
quiz_qtype_nameprefix($actualquestion, $nameprefix));
|
|
||||||
} else {
|
|
||||||
$result->grade = 0.0;
|
|
||||||
$result->answers = array();
|
|
||||||
$result->correctanswers = array();
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
function extract_response($rawresponse, $nameprefix) {
|
|
||||||
global $QUIZ_QTYPES;
|
|
||||||
|
|
||||||
/// The raw response records for random questions come in two flavours:
|
|
||||||
/// ---- 1 ----
|
|
||||||
/// For responses stored by Moodle version 1.5 and later the answer
|
|
||||||
/// field has the pattern random#-* where the # part is the numeric
|
|
||||||
/// question id of the actual question shown in the quiz attempt
|
|
||||||
/// and * represents the student response to that actual question.
|
|
||||||
/// ---- 2 ----
|
|
||||||
/// For responses stored by older Moodle versions - the answer field is
|
|
||||||
/// simply the question id of the actual question. The student response
|
|
||||||
/// to the actual question is stored in a separate response record.
|
|
||||||
/// -----------------------
|
|
||||||
/// This means that prior to Moodle version 1.5, random questions needed
|
|
||||||
/// two response records for storing the response to a single question.
|
|
||||||
/// From version 1.5 and later the question type random works like all
|
|
||||||
/// the other question types in that it now only needs one response
|
|
||||||
/// record per question.
|
|
||||||
/// Because updating the old response records to fit the new response
|
|
||||||
/// record format could need hours of CPU time and the equivalent
|
|
||||||
/// amount of down time for the Moodle site and because a response
|
|
||||||
/// storage with two response formats for random question only effect
|
|
||||||
/// this function, where the response record is translated, this
|
|
||||||
/// function is now able to handle both types of response record.
|
|
||||||
|
|
||||||
|
|
||||||
// Pick random question id from the answer field in a way that
|
|
||||||
/// works for both formats:
|
|
||||||
if (!ereg('^(random)?([0-9]+)(-(.*))?$', $rawresponse->answer, $answerregs)) {
|
|
||||||
error("The answer value '$rawresponse->answer' for the response with "
|
|
||||||
."id=$rawresponse->id to the random question "
|
|
||||||
."$rawresponse->question is malformated."
|
|
||||||
." - No response can be extracted!");
|
|
||||||
}
|
|
||||||
$randomquestionid = $answerregs[2];
|
|
||||||
|
|
||||||
if ($randomquestion = get_record('quiz_questions',
|
|
||||||
'id', $randomquestionid)) {
|
|
||||||
|
|
||||||
if ($answerregs[1] && $answerregs[3]) {
|
|
||||||
// The raw response is formatted according to
|
|
||||||
// Moodle version 1.5 or later
|
|
||||||
$randomresponse = $rawresponse;
|
|
||||||
$randomresponse->question = $randomquestionid;
|
|
||||||
$randomresponse->answer = $answerregs[4];
|
|
||||||
|
|
||||||
} else if ($randomresponse = get_record
|
|
||||||
('quiz_responses', 'question', $rawresponse->answer,
|
|
||||||
'attempt', $rawresponse->attempt)) {
|
|
||||||
// The response was stored by an older version of Moodle
|
|
||||||
// :-)
|
|
||||||
|
|
||||||
} else {
|
|
||||||
notify("Error: Cannot find response to random question $randomquestionid");
|
|
||||||
unset($randomresponse);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($randomresponse)) {
|
|
||||||
/// The prefered case:
|
|
||||||
/// There is a random question and a response field, from
|
|
||||||
/// which the response array can be extracted:
|
|
||||||
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/// Instead: workaround by creating a new response:
|
|
||||||
$response = $QUIZ_QTYPES[$randomquestion->qtype]
|
|
||||||
->create_response($randomquestion,
|
|
||||||
quiz_qtype_nameprefix($randomquestion, $nameprefix),
|
|
||||||
"$rawresponse->question,$randomquestionid");
|
|
||||||
// (That last argument is instead of $questionsinuse.
|
|
||||||
// It is not correct but it would be very messy to
|
|
||||||
// determine the correct value, while very few
|
|
||||||
// question types actually use it and they who do have
|
|
||||||
// good chances to execute properly anyway.)
|
|
||||||
}
|
|
||||||
$response[$nameprefix] = $randomquestionid;
|
|
||||||
//return $response;
|
|
||||||
return '';
|
|
||||||
} else {
|
|
||||||
notify("Error: Unable to find random question $rawresponse->question");
|
|
||||||
/// No new random question is picked as this is probably
|
|
||||||
/// not what the moodle user has in mind anyway
|
|
||||||
return array();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
//// END OF CLASS ////
|
//// END OF CLASS ////
|
||||||
|
|
||||||
|
|
|
@ -205,9 +205,18 @@ class quiz_rqp_qtype extends quiz_default_questiontype {
|
||||||
$options->persistent_data = $state->options->persistent_data;
|
$options->persistent_data = $state->options->persistent_data;
|
||||||
$options->template_vars =
|
$options->template_vars =
|
||||||
quiz_rqp_implode($state->options->template_vars);
|
quiz_rqp_implode($state->options->template_vars);
|
||||||
|
if ($state->update) {
|
||||||
|
if (!$options->id = get_field('quiz_rqp_states', 'id', 'stateid', $state->id)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!update_record('quiz_rqp_states', $options)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if (!insert_record('quiz_rqp_states', $options)) {
|
if (!insert_record('quiz_rqp_states', $options)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,7 @@ class quiz_shortanswer_qtype extends quiz_default_questiontype {
|
||||||
|
|
||||||
$answers = &$question->options->answers;
|
$answers = &$question->options->answers;
|
||||||
$correctanswers = $this->get_correct_responses($question, $state);
|
$correctanswers = $this->get_correct_responses($question, $state);
|
||||||
$readonly = empty($options->readonly) ? '' : 'disabled="disabled"';
|
$readonly = empty($options->readonly) ? '' : 'readonly="readonly"';
|
||||||
$nameprefix = $question->name_prefix;
|
$nameprefix = $question->name_prefix;
|
||||||
|
|
||||||
/// Print question text and media
|
/// Print question text and media
|
||||||
|
|
|
@ -120,7 +120,7 @@ class quiz_truefalse_qtype extends quiz_default_questiontype {
|
||||||
|
|
||||||
$answers = &$question->options->answers;
|
$answers = &$question->options->answers;
|
||||||
$correctanswers = $this->get_correct_responses($question, $state);
|
$correctanswers = $this->get_correct_responses($question, $state);
|
||||||
$readonly = $options->readonly ? ' disabled="disabled"' : '';
|
$readonly = $options->readonly ? ' readonly="readonly"' : '';
|
||||||
|
|
||||||
// Print question formulation
|
// Print question formulation
|
||||||
echo format_text($question->questiontext,
|
echo format_text($question->questiontext,
|
||||||
|
|
|
@ -12,7 +12,61 @@ class quiz_report extends quiz_default_report {
|
||||||
/// Print header
|
/// Print header
|
||||||
$this->print_header_and_tabs($cm, $course, $quiz, $reportmode="regrade");
|
$this->print_header_and_tabs($cm, $course, $quiz, $reportmode="regrade");
|
||||||
|
|
||||||
notify('Not yet implemented');
|
/// Fetch all attempts
|
||||||
|
if (!$attempts = get_records_select('quiz_attempts', "quiz = '$quiz->id' AND preview = 0")) {
|
||||||
|
print_heading(get_string('noattempts', 'quiz'));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetch all questions
|
||||||
|
$sql = "SELECT q.*, i.grade AS maxgrade FROM {$CFG->prefix}quiz_questions q,
|
||||||
|
{$CFG->prefix}quiz_question_instances i
|
||||||
|
WHERE i.quiz = $quiz->id
|
||||||
|
AND i.question = q.id";
|
||||||
|
|
||||||
|
if (! $questions = get_records_sql($sql)) {
|
||||||
|
error("Failed to get questions for regrading!");
|
||||||
|
}
|
||||||
|
quiz_get_question_options($questions);
|
||||||
|
|
||||||
|
/// Print heading
|
||||||
|
print_heading(get_string('regradingquiz', 'quiz', $quiz));
|
||||||
|
echo '<center>';
|
||||||
|
print_string('regradedisplayexplanation', 'quiz');
|
||||||
|
echo '<center>';
|
||||||
|
|
||||||
|
/// Loop through all questions and all attempts and regrade while printing progress info
|
||||||
|
foreach ($questions as $question) {
|
||||||
|
echo '<b>'.get_string('regradingquestion', 'quiz', $question->name).'</b> '.get_string('attempts', 'quiz').": \n";
|
||||||
|
foreach ($attempts as $attempt) {
|
||||||
|
quiz_regrade_question_in_attempt($question, $attempt, $quiz, true);
|
||||||
|
}
|
||||||
|
echo '<br/ >';
|
||||||
|
// the following makes sure that the output is sent immediately.
|
||||||
|
flush();ob_flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Loop through all questions and recalculate $attempt->sumgrade
|
||||||
|
$attemptschanged = 0;
|
||||||
|
foreach ($attempts as $attempt) {
|
||||||
|
$sumgrades = 0;
|
||||||
|
$questionids = explode(',', quiz_questions_in_quiz($attempt->layout));
|
||||||
|
foreach($questionids as $questionid) {
|
||||||
|
$lastgradedid = get_field('quiz_newest_states', 'newgraded', 'attemptid', $attempt->id, 'questionid', $questionid);
|
||||||
|
$sumgrades += get_field('quiz_states', 'grade', 'id', $lastgradedid);
|
||||||
|
}
|
||||||
|
if ($attempt->sumgrades != $sumgrades) {
|
||||||
|
$attemptschanged++;
|
||||||
|
set_field('quiz_attempts', 'sumgrades', $sumgrades, 'id', $attempt->id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Update the overall quiz grades
|
||||||
|
if ($grades = get_records('quiz_grades', 'quiz', $quiz->id)) {
|
||||||
|
foreach($grades as $grade) {
|
||||||
|
quiz_save_best_grade($quiz, $grade->userid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1420,6 +1420,9 @@
|
||||||
//This function restores the quiz_attempts
|
//This function restores the quiz_attempts
|
||||||
function quiz_attempts_restore_mods($quiz_id,$info,$restore) {
|
function quiz_attempts_restore_mods($quiz_id,$info,$restore) {
|
||||||
|
|
||||||
|
notify("Restoring quiz without user attempts. Restoring of user attempts will be implemented in Moodle 1.5.1");
|
||||||
|
return true;
|
||||||
|
|
||||||
global $CFG;
|
global $CFG;
|
||||||
|
|
||||||
$status = true;
|
$status = true;
|
||||||
|
@ -1761,7 +1764,7 @@
|
||||||
return $status;
|
return $status;
|
||||||
}
|
}
|
||||||
|
|
||||||
//This function restores the quiz_states
|
//This function restores the quiz_rqp_states
|
||||||
function quiz_rqp_states_restore_mods($state_id,$info,$restore) {
|
function quiz_rqp_states_restore_mods($state_id,$info,$restore) {
|
||||||
|
|
||||||
global $CFG;
|
global $CFG;
|
||||||
|
|
|
@ -18,8 +18,7 @@
|
||||||
$stateid = optional_param('state', 0, PARAM_INT); // state id
|
$stateid = optional_param('state', 0, PARAM_INT); // state id
|
||||||
$attemptid = optional_param('attempt', 0, PARAM_INT); // attempt id
|
$attemptid = optional_param('attempt', 0, PARAM_INT); // attempt id
|
||||||
$questionid = optional_param('question', 0, PARAM_INT); // attempt id
|
$questionid = optional_param('question', 0, PARAM_INT); // attempt id
|
||||||
|
$number = optional_param('number', 0, PARAM_INT); // question number
|
||||||
$number = required_param('number', PARAM_INT); // question number
|
|
||||||
|
|
||||||
if ($stateid) {
|
if ($stateid) {
|
||||||
if (! $state = get_record('quiz_states', 'id', $stateid)) {
|
if (! $state = get_record('quiz_states', 'id', $stateid)) {
|
||||||
|
|
|
@ -113,13 +113,14 @@
|
||||||
// This is all the teacher will get
|
// This is all the teacher will get
|
||||||
if ($isteacher) {
|
if ($isteacher) {
|
||||||
|
|
||||||
$attemptcount = count_records('quiz_attempts', 'quiz', $quiz->id, 'preview', 0);
|
if ($attemptcount = count_records('quiz_attempts', 'quiz', $quiz->id, 'preview', 0)) {
|
||||||
|
|
||||||
$strviewallanswers = get_string("viewallanswers", "quiz", $attemptcount);
|
$strviewallanswers = get_string("viewallanswers", "quiz", $attemptcount);
|
||||||
$usercount = count_records_select('quiz_attempts', "quiz = '$quiz->id' AND preview = '0'", 'COUNT(DISTINCT userid)');
|
$usercount = count_records_select('quiz_attempts', "quiz = '$quiz->id' AND preview = '0'", 'COUNT(DISTINCT userid)');
|
||||||
$strusers = $course->students;
|
$strusers = $course->students;
|
||||||
|
|
||||||
notify("<a href=\"report.php?mode=overview&id=$cm->id\">$strviewallanswers ($usercount $strusers)</a>");
|
notify("<a href=\"report.php?mode=overview&id=$cm->id\">$strviewallanswers ($usercount $strusers)</a>");
|
||||||
|
}
|
||||||
print_footer($course);
|
print_footer($course);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue