quiz settings: MDL-18485 Improve quiz settings form

* Reorder form fields to group things more logically.
** and on the corresponding admin page too.

* Set some options to be 'Advanced' by default:
** Apply penalties.
** Each attempt builds on the last.
** Decimal places for question grades.
** The five 'Extra restrictions on attempts' settings. (password, etc.)
* Admins can still change this to suit their institiution at Administration > Plugins > Activity modules > Quiz.
* These new defaults are applied if the admin had not previously set any fields to be advanced.

* Disable some filds when they are not applicable:
** Grading method, if num attempts = 1
** Penaly scheme, if adaptive mode = no
** Each attempt builds of last, if num attempts = 1
** Review after quiz closed options, if no close date.
** Delay between 1st and 2nd attempts, if num attempts = 1
** Delay between later attempts, if num attempts < 3

* Convert quiz.timelimit to be in seconds, for consistency, and ready for the new duration field type (MDL 18500).
** Including ensuring that backup and restore is backwards compatible.

* MDL-5537 New setting, questiondecimalpoints, so, for example, you can show the quiz grade as an integer, but have fractional question grades.
** There is a 'Same as overall decimal points' option, which is the default.

* Improve some field labels.

* Make corresponding changes in the help files.
This commit is contained in:
tjhunt 2009-03-10 08:39:51 +00:00
parent 48f7eb9868
commit 84e628a027
20 changed files with 494 additions and 272 deletions

View File

@ -145,15 +145,19 @@ $string['completedon'] = 'Completed on';
$string['configadaptive'] = 'If you choose Yes for this option then the student will be allowed multiple responses to a question even within the same attempt at the quiz.';
$string['configattemptsallowed'] = 'Restriction on the number of attempts students are allowed at the quiz.';
$string['configdecimaldigits'] = 'Number of digits that should be shown after the decimal point when displaying grades.';
$string['configdecimalplaces'] = 'Number of digits that should be shown after the decimal point when displaying grades for the quiz.';
$string['configdecimalplacesquestion'] = 'Number of digits that should be shown after the decimal point when displaying the grade for individual questions.';
$string['configdelay1'] = 'If you set a time delay, then a student has to wait for that time before they can attempt a quiz after the first attempt.';
$string['configdelay2'] = 'If you set a time delay here, then a student has to wait for that time before they can attempt their third or later attempts.';
$string['configdelay1st2nd'] = 'If you set a time delay here, the student cannot start their second attempt until this much time has passed since the end of their first attempt.';
$string['configdelaylater'] = 'If you set a time delay here, the student cannot start their third, fourth, ... attempt until this much time has passed since the end of their previous attempt.';
$string['configeachattemptbuildsonthelast'] = 'If multiple attempts are allowed then each new attempt contains the results of the previous attempt.';
$string['configgrademethod'] = 'When multiple attempts are allowed, which method should be used to calculate the student\'s final grade for the quiz.';
$string['configintro'] = 'The values you set here define the default values that are used in the settings form when you create a new quiz. You can also configure which quiz settings are considered advanced.';
$string['configmaximumgrade'] = 'The default grade that the quiz grade is scaled to be out of.';
$string['confignewpageevery'] = 'When adding questions to the quiz page breaks will automatically be inserted according to the setting you choose here.';
$string['configpenaltyscheme'] = 'Penalty subtracted for each wrong response in adaptive mode.';
$string['configpopup'] = 'Use JavaScript tricks to try to restrict copy and paste, etc. during quiz attempts.';
$string['configpopup'] = 'Force the attempt to open in a popup window, and use JavaScript tricks to try to restrict copy and paste, etc. during quiz attempts.';
$string['configrequirepassword'] = 'Students must enter this password before they can attempt the quiz.';
$string['configrequiresubnet'] = 'Students can only attempt the quiz from these computers.';
$string['configreviewoptions'] = 'These options control what information users can see when they review a quiz attempt or look at the quiz reports.';
@ -161,6 +165,7 @@ $string['configshowuserpicture'] = 'Show the user\'s picture on screen during at
$string['configshufflequestions'] = 'If you enable this option, then the order of questions in the quiz will be randomly shuffled each time a student attempts the quiz.';
$string['configshufflewithin'] = 'If you enable this option, then the parts making up the individual questions will be randomly shuffled each time a student starts an attempt at this quiz, provided the option is also enabled in the question settings.';
$string['configtimelimit'] = 'Default time limit for quizzes in minutes. 0 mean no time limit.';
$string['configtimelimitsec'] = 'Default time limit for quizzes in seconds. 0 mean no time limit.';
$string['configurerandomquestion'] = 'Configure question';
$string['confirmclose'] = 'You are about to close this attempt. Once you close the attempt you will no longer be able to change your answers.';
$string['confirmserverdelete'] = 'Are you sure you want to remove the server <b>$a</b> from the list?';
@ -195,6 +200,8 @@ $string['datasetdefinitions'] = 'Reusable dataset definitions for category $a';
$string['datasetnumber'] = 'Number';
$string['daysavailable'] = 'Days available';
$string['decimaldigits'] = 'Decimal digits in grades';
$string['decimalplaces'] = 'Decimal places in grades';
$string['decimalplacesquestion'] = 'Decimal places in question grades';
$string['decimalformat'] = 'decimals';
$string['decimalpoints'] = 'Decimal points';
$string['decimals'] = 'with $a';
@ -203,6 +210,8 @@ $string['defaultgrade'] = 'Default question grade';
$string['defaultinfo'] = 'The default category for questions.';
$string['delay1'] = 'Time delay between first and second attempt';
$string['delay2'] = 'Time delay between later attempts';
$string['delay1st2nd'] = 'Enforced delay between 1st and 2nd attempts';
$string['delaylater'] = 'Enforced delay between later attempts';
$string['deleteattemptcheck'] = 'Are you absolutely sure you want to completely delete these attempts?';
$string['deletequestioncheck'] = 'Are you absolutely sure you want to delete \'$a\'?';
$string['deletequestionscheck'] = 'Are you absolutely sure you want to delete the following questions?<br /><br />$a';
@ -284,6 +293,7 @@ $string['exportingquestions'] = 'Questions are being exported to file';
$string['exportname'] = 'File name';
$string['exportnameformat'] = '%%Y%%m%%d-%%H%%M';
$string['exportquestions'] = 'Export questions to file';
$string['extraattemptrestrictions'] = 'Extra restrictions on attempts';
$string['false'] = 'False';
$string['feedback'] = 'Feedback';
$string['feedbackerrorboundaryformat'] = 'Feedback grade boundaries must be either a percentage or a number. The value you entered in boundary $a is not recognised.';
@ -376,6 +386,11 @@ $string['itemsource'] = 'Item Source';
$string['itemsourceformat'] = 'Item Source Format';
$string['itemtypes'] = 'Remote Question Types';
$string['lastanswer'] = 'Your last answer was';
$string['layout'] = 'Layout';
$string['layoutasshown'] = 'Page layout as shown.';
$string['layoutasshownwithpages'] = 'Page layout as shown. <small>(Automatic new page every $a questions.)</small>';
$string['layoutshuffledandpaged'] = 'Questions randomly shuffled with $a questions per page.';
$string['layoutshuffledsinglepage'] = 'Questions randomly shuffled, all on one page.';
$string['learnwise'] = 'Learnwise format';
$string['link'] = 'Link';
$string['listitems'] = 'Listing of Items in Quiz';
@ -498,6 +513,7 @@ $string['qtypename'] = 'type, name';
$string['question'] = 'Question';
$string['questionbankcontents'] = 'Question Bank contents';
$string['questionbankmanagement'] = 'Question Bank management';
$string['questionbehaviour'] = 'Question behaviour';
$string['questioncats'] = 'Question Categories';
$string['questiondeleted'] = 'This question has been deleted. Please contact your teacher';
$string['questioninuse'] = 'The question \'$a->questionname\' is currently being used in: <br />$a->quiznames<br />The question will not be deleted from these quizzes but only from the category list.';
@ -618,6 +634,7 @@ $string['reviewresponse'] = 'Review response';
$string['reviewthisattempt'] = 'Review your responses to this attempt';
$string['rqp'] = 'Remote Question';
$string['rqps'] = 'Remote Questions';
$string['sameasoverall'] = 'Same as for overall grades';
$string['save'] = 'Save';
$string['saveandedit'] = 'Save changes and edit questions';
$string['saveattemptfailed'] = 'Failed to save the current quiz attempt.';
@ -650,6 +667,7 @@ $string['showcorrectanswer'] = 'In feedback, show correct answers?';
$string['showdetailedmarks'] = 'Show mark details';
$string['showfeedback'] = 'After answering, show feedback?';
$string['showhidden'] = 'Also show old questions';
$string['showinsecurepopup'] = 'Use a \'secure\' popup window for attempts';
$string['shownoattempts'] = 'Show students with no attempts';
$string['shownoattemptsonly'] = 'Show only students with no attempts';
$string['showquestiontext'] = 'Show question text in the question list';
@ -658,8 +676,7 @@ $string['showuserpicture'] = 'Show the user\'s picture';
$string['shuffle'] = 'Shuffle';
$string['shuffleanswers'] = 'Shuffle answers';
$string['shufflequestions'] = 'Shuffle questions';
$string['shufflequestionsx'] = 'Shuffle questions: $a';
$string['shufflequestionsselected'] = '* Shuffle questions has been set so question order is random. As a result, the button Reorder questions has been disabled. You can change this in $a.';
$string['shufflequestionsselected'] = 'Shuffle questions has been set, so some actions relating to pages are not available. To change the shuffle option go to $a.';
$string['shufflewithin'] = 'Shuffle within questions';
$string['significantfigures'] = 'with $a';
$string['significantfiguresformat'] = 'significant figures';
@ -690,6 +707,7 @@ $string['timeleft'] = 'Time left';
$string['timelimit'] = 'Time limit';
$string['timelimitexeeded'] = 'Sorry! Quiz time limit exceeded!';
$string['timelimitmin'] = 'Time limit (minutes)';
$string['timelimitsec'] = 'Time limit (seconds)';
$string['timestr'] = '%%H:%%M:%%S on %%d/%%m/%%y';
$string['timesup'] = 'Time is up!';
$string['timetaken'] = 'Time taken';

View File

@ -1753,7 +1753,7 @@ function question_apply_penalty_and_timelimit(&$question, &$state, $attempt, $cm
// deal with timelimit
if ($cmoptions->timelimit) {
// We allow for 5% uncertainty in the following test
if ($state->timestamp - $attempt->timestart > $cmoptions->timelimit * 63) {
if ($state->timestamp - $attempt->timestart > $cmoptions->timelimit * 1.05) {
$cm = get_coursemodule_from_instance('quiz', $cmoptions->id);
if (!has_capability('mod/quiz:ignoretimelimits', get_context_instance(CONTEXT_MODULE, $cm->id),
$attempt->userid, false)) {
@ -2007,12 +2007,25 @@ function question_hash($question) {
/**
* Round a grade to to the correct number of decimal places, and format it for display.
* If $cmoptions->questiondecimalpoints is set, that is used, otherwise
* else if $cmoptions->decimalpoints is used,
* otherwise a default of 2 is used, but this should not be relied upon, and generated a developer debug warning.
* However, if $cmoptions->questiondecimalpoints is -1, the means use $cmoptions->decimalpoints.
*
* @param object $cmoptions The modules settings, only ->decimalpoints is used.
* @param object $cmoptions The modules settings.
* @param float $grade The grade to round.
*/
function question_format_grade($cmoptions, $grade) {
return format_float($grade, $cmoptions->decimalpoints);
if (isset($cmoptions->questiondecimalpoints) && $cmoptions->questiondecimalpoints != -1) {
$decimalplaces = $cmoptions->questiondecimalpoints;
} else if (isset($cmoptions->decimalpoints)) {
$decimalplaces = $cmoptions->decimalpoints;
} else {
$decimalplaces = 2;
debugging('Code that leads to question_format_grade being called should set ' .
'$cmoptions->questiondecimalpoints or $cmoptions->decimalpoints', DEBUG_DEVELOPER);
}
return format_float($grade, $decimalplaces);
}
/**

View File

@ -12,10 +12,11 @@ class quiz_access_manager {
/**
* Create an instance for a particular quiz.
* @param object $quiz the quiz we will be controlling access to.
* @param integer $timenow the
* @param boolean $canpreview whether the current user has the
* @param boolean $ignoretimelimits
* @param object $quizobj An instance of the class quiz from attemptlib.php.
* The quiz we will be controlling access to.
* @param integer $timenow The time to use as 'now'.
* @param boolean $canignoretimelimits Whether this user is exempt from time
* limits (has_capability('mod/quiz:ignoretimelimits', ...)).
*/
public function __construct($quizobj, $timenow, $canignoretimelimits) {
$this->_quizobj = $quizobj;
@ -668,10 +669,10 @@ class password_access_rule extends quiz_access_rule_base {
*/
class time_limit_access_rule extends quiz_access_rule_base {
public function description() {
return get_string('quiztimelimit', 'quiz', format_time($this->_quiz->timelimit * 60));
return get_string('quiztimelimit', 'quiz', format_time($this->_quiz->timelimit));
}
public function time_left($attempt, $timenow) {
return $attempt->timestart + $this->_quiz->timelimit*60 - $timenow;
return $attempt->timestart + $this->_quiz->timelimit - $timenow;
}
}

View File

@ -604,7 +604,7 @@ class quiz_attempt extends quiz {
public function get_question_score($questionid) {
$options = $this->get_render_options($this->states[$questionid]);
if ($options->scores) {
return quiz_format_grade($this->quiz, $this->states[$questionid]->last_graded->grade);
return quiz_format_question_grade($this->quiz, $this->states[$questionid]->last_graded->grade);
} else {
return '';
}

View File

@ -269,7 +269,8 @@
fwrite ($bf,full_tag("GRADE",4,false,$quiz->grade));
fwrite ($bf,full_tag("TIMECREATED",4,false,$quiz->timecreated));
fwrite ($bf,full_tag("TIMEMODIFIED",4,false,$quiz->timemodified));
fwrite ($bf,full_tag("TIMELIMIT",4,false,$quiz->timelimit));
fwrite ($bf,full_tag("TIMELIMIT",4,false,round($quiz->timelimit/60)));
fwrite ($bf,full_tag("TIMELIMITSECS",4,false,$quiz->timelimit));
fwrite ($bf,full_tag("PASSWORD",4,false,$quiz->password));
fwrite ($bf,full_tag("SUBNET",4,false,$quiz->subnet));
fwrite ($bf,full_tag("POPUP",4,false,$quiz->popup));

View File

@ -17,8 +17,9 @@
<FIELD NAME="attempts" TYPE="int" LENGTH="6" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="The maximum number of attempts that a student is allowed at this quiz. 0 mean no limit." PREVIOUS="penaltyscheme" NEXT="attemptonlast"/>
<FIELD NAME="attemptonlast" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="Whether each attempt builds on last mode is on." PREVIOUS="attempts" NEXT="grademethod"/>
<FIELD NAME="grademethod" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="false" DEFAULT="1" SEQUENCE="false" ENUM="false" COMMENT="How individual attempt grades are combined to get the overall grade. From the top of mod/quiz/lib.php: 1 = QUIZ_GRADEHIGHEST, 2 = QUIZ_GRADEAVERAGE, 3 = QUIZ_ATTEMPTFIRST, 4 = QUIZ_ATTEMPTLAST." PREVIOUS="attemptonlast" NEXT="decimalpoints"/>
<FIELD NAME="decimalpoints" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="false" DEFAULT="2" SEQUENCE="false" ENUM="false" COMMENT="Number of decimal points to display when printing scores belonging to this quiz." PREVIOUS="grademethod" NEXT="review"/>
<FIELD NAME="review" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="A bitfield encoding the Review options setting. Read the code of function quiz_get_reviewoptions from mod/quiz/locallib.php to see what each bit means." PREVIOUS="decimalpoints" NEXT="questionsperpage"/>
<FIELD NAME="decimalpoints" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="false" DEFAULT="2" SEQUENCE="false" ENUM="false" COMMENT="Number of decimal points to display when printing scores belonging to this quiz." PREVIOUS="grademethod" NEXT="questiondecimalpoints"/>
<FIELD NAME="questiondecimalpoints" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="false" DEFAULT="-2" SEQUENCE="false" ENUM="false" COMMENT="The number of decimal digits to use when displaying question grades. -1 = use decimalpoints, otherwise a separate setting." PREVIOUS="decimalpoints" NEXT="review"/>
<FIELD NAME="review" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="A bitfield encoding the Review options setting. Read the code of function quiz_get_reviewoptions from mod/quiz/locallib.php to see what each bit means." PREVIOUS="questiondecimalpoints" NEXT="questionsperpage"/>
<FIELD NAME="questionsperpage" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="This does not do exactly what the name suggests, and the behaviour depends on the shufflequestions setting." PREVIOUS="review" NEXT="shufflequestions"/>
<FIELD NAME="shufflequestions" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="Whether the list of questions in the quiz should be randomly shuffled at the start of each attempt." PREVIOUS="questionsperpage" NEXT="shuffleanswers"/>
<FIELD NAME="shuffleanswers" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="Whether, in question types that support it, individual parts of a question should be shuffled." PREVIOUS="shufflequestions" NEXT="questions"/>
@ -27,7 +28,7 @@
<FIELD NAME="grade" TYPE="number" LENGTH="10" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" ENUM="false" DECIMALS="5" COMMENT="Maximum grade that you can get from this quiz." PREVIOUS="sumgrades" NEXT="timecreated"/>
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="Timestamp when this quiz was created." PREVIOUS="grade" NEXT="timemodified"/>
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="Timestamp when this row was last updated." PREVIOUS="timecreated" NEXT="timelimit"/>
<FIELD NAME="timelimit" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="Time limit in minutes. (This should really be changed to seconds for consistency.)" PREVIOUS="timemodified" NEXT="password"/>
<FIELD NAME="timelimit" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="Time limit in seconds." PREVIOUS="timemodified" NEXT="password"/>
<FIELD NAME="password" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" ENUM="false" COMMENT="Students must enter this password before they can attempt the quiz." PREVIOUS="timelimit" NEXT="subnet"/>
<FIELD NAME="subnet" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" ENUM="false" COMMENT="If set, only allow attempts from certain IP addresses. The checking is performed by the address_in_subnet function from lib/moodlelib.php." PREVIOUS="password" NEXT="popup"/>
<FIELD NAME="popup" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="Force the quiz to be attempted in a full-screen pop-up window with some evil JavaScript that attempts to prevent copying and pasting, etc." PREVIOUS="subnet" NEXT="delay1"/>

View File

@ -22,7 +22,7 @@
function xmldb_quiz_upgrade($oldversion) {
global $CFG, $DB;
$dbman = $DB->get_manager();
$result = true;
@ -77,7 +77,7 @@ function xmldb_quiz_upgrade($oldversion) {
upgrade_mod_savepoint($result, 2008062001, 'quiz');
}
if ($result && $oldversion < 2008072402) {
/// Define field lastcron to be added to quiz_report
@ -196,7 +196,7 @@ function xmldb_quiz_upgrade($oldversion) {
// question type, this is now a no-op.
upgrade_mod_savepoint($result, 2008082600, 'quiz');
}
if ($result && $oldversion < 2008112101) {
/// Define field lastcron to be added to quiz_report
@ -207,7 +207,7 @@ function xmldb_quiz_upgrade($oldversion) {
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
/// quiz savepoint reached
upgrade_mod_savepoint($result, 2008112101, 'quiz');
}
@ -227,7 +227,55 @@ function xmldb_quiz_upgrade($oldversion) {
upgrade_mod_savepoint($result, 2009010700, 'quiz');
}
if ($result && $oldversion < 2009030900) {
/// If there are no quiz settings set to advanced yet, the set up the default
/// advanced fields from Moodle 2.0.
$quizconfig = get_config('quiz');
$arealreadyadvanced = false;
foreach (array($quizconfig) as $name => $value) {
if (strpos($name, 'fix_') === 0 && !empty($value)) {
$arealreadyadvanced = true;
break;
}
}
if (!$arealreadyadvanced) {
set_config('fix_penaltyscheme', 1, 'quiz');
set_config('fix_attemptonlast', 1, 'quiz');
set_config('fix_questiondecimalpoints', 1, 'quiz');
set_config('fix_password', 1, 'quiz');
set_config('fix_subnet', 1, 'quiz');
set_config('fix_delay1', 1, 'quiz');
set_config('fix_delay2', 1, 'quiz');
set_config('fix_popup', 1, 'quiz');
}
/// quiz savepoint reached
upgrade_mod_savepoint($result, 2009030900, 'quiz');
}
if ($result && $oldversion < 2009031000) {
/// Add new questiondecimaldigits setting, separate form the overall decimaldigits one.
$table = new xmldb_table('quiz');
$field = new xmldb_field('questiondecimalpoints', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, null, null, '2', 'decimalpoints');
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
/// quiz savepoint reached
upgrade_mod_savepoint($result, 2009031000, 'quiz');
}
if ($result && $oldversion < 2009031001) {
/// Convert quiz.timelimit from minutes to seconds.
$DB->execute('UPDATE {quiz} SET timelimit = timelimit * 60');
$default = get_config('quiz', 'timelimit');
set_config('timelimit', 60 * $default, 'quiz');
/// quiz savepoint reached
upgrade_mod_savepoint($result, 2009031001, 'quiz');
}
return $result;
}
?>

View File

@ -1,16 +1,40 @@
<?php // $Id$
/**
* Library of functions for the quiz module.
*
* This contains functions that are called also from outside the quiz module
* Functions that are only called by the quiz module itself are in {@link locallib.php}
* @author Martin Dougiamas and many others.
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
* @package quiz
*/
require_once($CFG->libdir.'/pagelib.php');
require_once($CFG->libdir.'/eventslib.php');
///////////////////////////////////////////////////////////////////////////
// //
// NOTICE OF COPYRIGHT //
// //
// Moodle - Modular Object-Oriented Dynamic Learning Environment //
// http://moodle.org //
// //
// Copyright (C) 1999 onwards Martin Dougiamas http://dougiamas.com //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation; either version 2 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details: //
// //
// http://www.gnu.org/copyleft/gpl.html //
// //
///////////////////////////////////////////////////////////////////////////
/**
* Library of functions for the quiz module.
*
* This contains functions that are called also from outside the quiz module
* Functions that are only called by the quiz module itself are in {@link locallib.php}
*
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
* @package quiz
*/
require_once($CFG->libdir . '/pagelib.php');
require_once($CFG->libdir . '/eventslib.php');
/// CONSTANTS ///////////////////////////////////////////////////////////////////
@ -18,12 +42,17 @@ require_once($CFG->libdir.'/eventslib.php');
* Options determining how the grades from individual attempts are combined to give
* the overall grade for a user
*/
define("QUIZ_GRADEHIGHEST", "1");
define("QUIZ_GRADEAVERAGE", "2");
define("QUIZ_ATTEMPTFIRST", "3");
define("QUIZ_ATTEMPTLAST", "4");
define('QUIZ_GRADEHIGHEST', 1);
define('QUIZ_GRADEAVERAGE', 2);
define('QUIZ_ATTEMPTFIRST', 3);
define('QUIZ_ATTEMPTLAST', 4);
/**#@-*/
define('QUIZ_MAX_ATTEMPT_OPTION', 10);
define('QUIZ_MAX_QPP_OPTION', 50);
define('QUIZ_MAX_DECIMAL_OPTION', 5);
define('QUIZ_MAX_Q_DECIMAL_OPTION', 7);
/**#@+
* The different review options are stored in the bits of $quiz->review
* These constants help to extract the options
@ -241,7 +270,7 @@ function quiz_user_complete($course, $user, $mod, $quiz) {
if ($attempt->timefinish == 0) {
print_string('unfinished');
} else {
echo quiz_format_grade($quiz, $attempt->sumgrades).'/'.$quiz->sumgrades;
echo quiz_format_grade($quiz, $attempt->sumgrades) . '/' . quiz_format_grade($quiz, $quiz->sumgrades);
}
echo ' - '.userdate($attempt->timemodified).'<br />';
}
@ -330,6 +359,20 @@ function quiz_format_grade($quiz, $grade) {
return format_float($grade, $quiz->decimalpoints);
}
/**
* Round a grade to to the correct number of decimal places, and format it for display.
*
* @param object $quiz The quiz table row, only $quiz->decimalpoints is used.
* @param float $grade The grade to round.
*/
function quiz_format_question_grade($quiz, $grade) {
if ($quiz->questiondecimalpoints == -1) {
return format_float($grade, $quiz->decimalpoints);
} else {
return format_float($grade, $quiz->questiondecimalpoints);
}
}
/**
* Update grades in central gradebook
*
@ -733,22 +776,11 @@ function quiz_print_recent_mod_activity($activity, $courseid, $detail, $modnames
function quiz_process_options(&$quiz) {
$quiz->timemodified = time();
// Quiz open time.
if (empty($quiz->timeopen)) {
$quiz->preventlate = 0;
}
// Quiz name.
if (!empty($quiz->name)) {
$quiz->name = trim($quiz->name);
}
// Time limit. (Get rid of it if the checkbox was not ticked.)
if (empty($quiz->timelimitenable)) {
$quiz->timelimit = 0;
}
$quiz->timelimit = round($quiz->timelimit);
// Password field - different in form to stop browsers that remember passwords
// getting confused.
$quiz->password = $quiz->quizpassword;
@ -1233,4 +1265,3 @@ function quiz_get_extra_capabilities() {
return $caps;
}
?>

View File

@ -1,4 +1,28 @@
<?php // $Id$
///////////////////////////////////////////////////////////////////////////
// //
// NOTICE OF COPYRIGHT //
// //
// Moodle - Modular Object-Oriented Dynamic Learning Environment //
// http://moodle.org //
// //
// Copyright (C) 1999 onwards Martin Dougiamas http://dougiamas.com //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation; either version 2 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details: //
// //
// http://www.gnu.org/copyleft/gpl.html //
// //
///////////////////////////////////////////////////////////////////////////
/**
* Library of functions used by the quiz module.
*
@ -8,10 +32,6 @@
* the module-indpendent code for handling questions and which in turn
* initialises all the questiontype classes.
*
* @author Martin Dougiamas and many others. This has recently been completely
* rewritten by Alex Smith, Julian Sedding and Gustav Delius as part of
* the Serving Mathematics project
* {@link http://maths.york.ac.uk/serving_maths}
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
* @package quiz
*/
@ -25,8 +45,8 @@ if (!defined('MOODLE_INTERNAL')) {
*/
require_once($CFG->dirroot . '/mod/quiz/lib.php');
require_once($CFG->dirroot . '/mod/quiz/accessrules.php');
require_once($CFG->dirroot . '/question/editlib.php');
require_once($CFG->dirroot . '/mod/quiz/attemptlib.php');
require_once($CFG->dirroot . '/question/editlib.php');
require_once($CFG->libdir . '/eventslib.php');
/// Constants ///////////////////////////////////////////////////////////////////
@ -222,6 +242,15 @@ function quiz_delete_previews($quiz, $userid = null) {
}
}
/**
* @param integer $quizid The quiz id.
* @return boolean whether this quiz has any (non-preview) attempts.
*/
function quiz_has_attempts($quizid) {
global $DB;
return $DB->record_exists('quiz_attempts', array('quiz' => $quizid, 'preview' => 0));
}
/// Functions to do with quiz layout and pages ////////////////////////////////
/**
@ -440,13 +469,16 @@ function quiz_update_sumgrades($quiz) {
* grade for this quiz.
*
* @param float $rawgrade the unadjusted grade, fof example $attempt->sumgrades
* @param object $quiz the quiz object. Only the fields grade, sumgrades and decimalpoints are used.
* @param object $quiz the quiz object. Only the fields grade, sumgrades, decimalpoints and questiondecimalpoints are used.
* @param mixed $round false = don't round, true = round using quiz_format_grade, 'question' = round using quiz_format_question_grade.
* @return float the rescaled grade.
*/
function quiz_rescale_grade($rawgrade, $quiz, $round = true) {
if ($quiz->sumgrades != 0) {
$grade = $rawgrade * $quiz->grade / $quiz->sumgrades;
if ($round) {
if ($round === 'question') { // === really necessary here true == 'question' is true in PHP!
$grade = quiz_format_question_grade($quiz, $grade);
} else if ($round) {
$grade = quiz_format_grade($quiz, $grade);
}
} else {
@ -582,7 +614,7 @@ function quiz_save_best_grade($quiz, $userid = null, $attempts = array()) {
// Calculate the best grade
$bestgrade = quiz_calculate_best_grade($quiz, $attempts);
$bestgrade = quiz_rescale_grade($bestgrade, $quiz);
$bestgrade = quiz_rescale_grade($bestgrade, $quiz, false);
// Save the best grade in the database
if ($grade = $DB->get_record('quiz_grades', array('quiz' => $quiz->id, 'userid' => $userid))) {
@ -1249,4 +1281,3 @@ function quiz_error($quiz, $errorcode, $a = null) {
}
print_error($errorcode, 'quiz', $CFG->wwwroot . '/mod/quiz/view.php?q=' . $quiz, $a);
}
?>

View File

@ -1,8 +1,37 @@
<?php // $Id$
require_once ($CFG->dirroot.'/course/moodleform_mod.php');
require_once("$CFG->dirroot/mod/quiz/locallib.php");
///////////////////////////////////////////////////////////////////////////
// //
// NOTICE OF COPYRIGHT //
// //
// Moodle - Modular Object-Oriented Dynamic Learning Environment //
// http://moodle.org //
// //
// Copyright (C) 1999 onwards Martin Dougiamas http://dougiamas.com //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation; either version 2 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details: //
// //
// http://www.gnu.org/copyleft/gpl.html //
// //
///////////////////////////////////////////////////////////////////////////
require_once($CFG->dirroot . '/course/moodleform_mod.php');
require_once($CFG->dirroot . '/mod/quiz/locallib.php');
/**
* Settings form for the quiz module.
*
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
* @package quiz
*/
class mod_quiz_mod_form extends moodleform_mod {
var $_feedbacks;
@ -15,6 +44,7 @@ class mod_quiz_mod_form extends moodleform_mod {
//-------------------------------------------------------------------------------
$mform->addElement('header', 'general', get_string('general', 'form'));
/// Name.
$mform->addElement('text', 'name', get_string('name'), array('size'=>'64'));
if (!empty($CFG->formatstringstriptags)) {
$mform->setType('name', PARAM_TEXT);
@ -23,64 +53,57 @@ class mod_quiz_mod_form extends moodleform_mod {
}
$mform->addRule('name', null, 'required', null, 'client');
$mform->addElement('htmleditor', 'intro', get_string("introduction", "quiz"));
/// Introduction.
$mform->addElement('htmleditor', 'intro', get_string('introduction', 'quiz'));
$mform->setType('intro', PARAM_RAW);
$mform->setHelpButton('intro', array('richtext2', get_string('helprichtext')));
//-------------------------------------------------------------------------------
$mform->addElement('header', 'timinghdr', get_string('timing', 'form'));
$mform->addElement('date_time_selector', 'timeopen', get_string('quizopen', 'quiz'), array('optional'=>true));
/// Open and close dates.
$mform->addElement('date_time_selector', 'timeopen', get_string('quizopen', 'quiz'), array('optional' => true));
$mform->setHelpButton('timeopen', array('timeopen', get_string('quizopen', 'quiz'), 'quiz'));
$mform->addElement('date_time_selector', 'timeclose', get_string('quizclose', 'quiz'), array('optional'=>true));
$mform->addElement('date_time_selector', 'timeclose', get_string('quizclose', 'quiz'), array('optional' => true));
$mform->setHelpButton('timeclose', array('timeopen', get_string('quizclose', 'quiz'), 'quiz'));
$timelimitgrp=array();
$timelimitgrp[] = &$mform->createElement('text', 'timelimit');
$timelimitgrp[] = &$mform->createElement('checkbox', 'timelimitenable', '', get_string('enable'));
$mform->addGroup($timelimitgrp, 'timelimitgrp', get_string('timelimitmin', 'quiz'), array(' '), false);
$mform->setType('timelimit', PARAM_TEXT);
$timelimitgrprules = array();
$timelimitgrprules['timelimit'][] = array(null, 'numeric', null, 'client');
$mform->addGroupRule('timelimitgrp', $timelimitgrprules);
$mform->disabledIf('timelimitgrp', 'timelimitenable');
$mform->setAdvanced('timelimitgrp', $quizconfig->fix_timelimit);
$mform->setHelpButton('timelimitgrp', array("timelimit", get_string("quiztimer","quiz"), "quiz"));
/// Time limit.
$mform->addElement('duration', 'timelimit', get_string('timelimit', 'quiz'), array('optional' => true));
$mform->setHelpButton('timelimit', array('timelimit', get_string('quiztimer','quiz'), 'quiz'));
$mform->setAdvanced('timelimit', $quizconfig->fix_timelimit);
$mform->setDefault('timelimit', $quizconfig->timelimit);
$mform->setDefault('timelimitenable', !empty($quizconfig->timelimit));
//enforced time delay between quiz attempts add-on
$timedelayoptions = array();
$timedelayoptions[0] = get_string('none');
$timedelayoptions[1800] = get_string('numminutes', '', 30);
$timedelayoptions[3600] = get_string('numminutes', '', 60);
for($i=2; $i<=23; $i++) {
$seconds = $i*3600;
$timedelayoptions[$seconds] = get_string('numhours', '', $i);
/// Number of attempts.
$attemptoptions = array('0' => get_string('unlimited'));
for ($i = 1; $i <= QUIZ_MAX_ATTEMPT_OPTION; $i++) {
$attemptoptions[$i] = $i;
}
$timedelayoptions[86400] = get_string('numhours', '', 24);
for($i=2; $i<=7; $i++) {
$seconds = $i*86400;
$timedelayoptions[$seconds] = get_string('numdays', '', $i);
}
$mform->addElement('select', 'delay1', get_string("delay1", "quiz"), $timedelayoptions);
$mform->setHelpButton('delay1', array("timedelay1", get_string("delay1", "quiz"), "quiz"));
$mform->setAdvanced('delay1', $quizconfig->fix_delay1);
$mform->setDefault('delay1', $quizconfig->delay1);
$mform->addElement('select', 'attempts', get_string('attemptsallowed', 'quiz'), $attemptoptions);
$mform->setHelpButton('attempts', array('attempts', get_string('attemptsallowed','quiz'), 'quiz'));
$mform->setAdvanced('attempts', $quizconfig->fix_attempts);
$mform->setDefault('attempts', $quizconfig->attempts);
$mform->addElement('select', 'delay2', get_string("delay2", "quiz"), $timedelayoptions);
$mform->setHelpButton('delay2', array("timedelay2", get_string("delay2", "quiz"), "quiz"));
$mform->setAdvanced('delay2', $quizconfig->fix_delay2);
$mform->setDefault('delay2', $quizconfig->delay2);
/// Grading method.
$mform->addElement('select', 'grademethod', get_string('grademethod', 'quiz'), quiz_get_grading_options());
$mform->setHelpButton('grademethod', array('grademethod', get_string('grademethod','quiz'), 'quiz'));
$mform->setAdvanced('grademethod', $quizconfig->fix_grademethod);
$mform->setDefault('grademethod', $quizconfig->grademethod);
$mform->disabledIf('grademethod', 'attempts', 'eq', 1);
$mform->addElement('hidden', 'grade', $quizconfig->maximumgrade);
//-------------------------------------------------------------------------------
$mform->addElement('header', 'displayhdr', get_string('display', 'form'));
$mform->addElement('header', 'layouthdr', get_string('layout', 'quiz'));
/// Shuffle questions.
$mform->addElement('selectyesno', 'shufflequestions', get_string('shufflequestions', 'quiz'));
$mform->setHelpButton('shufflequestions', array('shufflequestions', get_string('shufflequestions','quiz'), 'quiz'));
$mform->setAdvanced('shufflequestions', $quizconfig->fix_shufflequestions);
$mform->setDefault('shufflequestions', $quizconfig->shufflequestions);
/// Questions per page.
$perpage = array();
$perpage[0] = get_string('never');
$perpage[1] = get_string('aftereachquestion', 'quiz');
for ($i = 2; $i <= 50; ++$i) {
for ($i = 2; $i <= QUIZ_MAX_QPP_OPTION; ++$i) {
$perpage[$i] = get_string('afternquestions', 'quiz', $i);
}
$mform->addElement('select', 'questionsperpage', get_string('newpageevery', 'quiz'), $perpage);
@ -88,72 +111,41 @@ class mod_quiz_mod_form extends moodleform_mod {
$mform->setAdvanced('questionsperpage', $quizconfig->fix_questionsperpage);
$mform->setDefault('questionsperpage', $quizconfig->questionsperpage);
$mform->addElement('selectyesno', 'shufflequestions', get_string("shufflequestions", "quiz"));
$mform->setHelpButton('shufflequestions', array("shufflequestions", get_string("shufflequestions","quiz"), "quiz"));
$mform->setAdvanced('shufflequestions', $quizconfig->fix_shufflequestions);
$mform->setDefault('shufflequestions', $quizconfig->shufflequestions);
//-------------------------------------------------------------------------------
$mform->addElement('header', 'interactionhdr', get_string('questionbehaviour', 'quiz'));
$mform->addElement('selectyesno', 'shuffleanswers', get_string("shufflewithin", "quiz"));
$mform->setHelpButton('shuffleanswers', array("shufflewithin", get_string("shufflewithin","quiz"), "quiz"));
/// Shuffle within questions.
$mform->addElement('selectyesno', 'shuffleanswers', get_string('shufflewithin', 'quiz'));
$mform->setHelpButton('shuffleanswers', array('shufflewithin', get_string('shufflewithin','quiz'), 'quiz'));
$mform->setAdvanced('shuffleanswers', $quizconfig->fix_shuffleanswers);
$mform->setDefault('shuffleanswers', $quizconfig->shuffleanswers);
$mform->addElement('selectyesno', 'showuserpicture', get_string('showuserpicture', 'quiz'));
$mform->setHelpButton('showuserpicture', array('showuserpicture', get_string('showuserpicture', 'quiz'), 'quiz'));
$mform->setAdvanced('showuserpicture', $quizconfig->fix_showuserpicture);
$mform->setDefault('showuserpicture', $quizconfig->showuserpicture);
//-------------------------------------------------------------------------------
$mform->addElement('header', 'attemptshdr', get_string('attempts', 'quiz'));
$attemptoptions = array('0' => get_string('unlimited'));
for ($i = 1; $i <= 10; $i++) {
$attemptoptions[$i] = $i;
}
$mform->addElement('select', 'attempts', get_string("attemptsallowed", "quiz"), $attemptoptions);
$mform->setHelpButton('attempts', array("attempts", get_string("attemptsallowed","quiz"), "quiz"));
$mform->setAdvanced('attempts', $quizconfig->fix_attempts);
$mform->setDefault('attempts', $quizconfig->attempts);
$mform->addElement('selectyesno', 'attemptonlast', get_string("eachattemptbuildsonthelast", "quiz"));
$mform->setHelpButton('attemptonlast', array("repeatattempts", get_string("eachattemptbuildsonthelast", "quiz"), "quiz"));
$mform->setAdvanced('attemptonlast', $quizconfig->fix_attemptonlast);
$mform->setDefault('attemptonlast', $quizconfig->attemptonlast);
$mform->addElement('selectyesno', 'adaptive', get_string("adaptive", "quiz"));
$mform->setHelpButton('adaptive', array("adaptive", get_string("adaptive","quiz"), "quiz"));
/// Adaptive mode.
$mform->addElement('selectyesno', 'adaptive', get_string('adaptive', 'quiz'));
$mform->setHelpButton('adaptive', array('adaptive', get_string('adaptive','quiz'), 'quiz'));
$mform->setAdvanced('adaptive', $quizconfig->fix_optionflags);
$mform->setDefault('adaptive', $quizconfig->optionflags & QUESTION_ADAPTIVE);
//-------------------------------------------------------------------------------
$mform->addElement('header', 'gradeshdr', get_string('grades', 'grades'));
$mform->addElement('select', 'grademethod', get_string("grademethod", "quiz"), quiz_get_grading_options());
$mform->setHelpButton('grademethod', array("grademethod", get_string("grademethod","quiz"), "quiz"));
$mform->setAdvanced('grademethod', $quizconfig->fix_grademethod);
$mform->setDefault('grademethod', $quizconfig->grademethod);
$mform->addElement('selectyesno', 'penaltyscheme', get_string("penaltyscheme", "quiz"));
$mform->setHelpButton('penaltyscheme', array("penaltyscheme", get_string("penaltyscheme","quiz"), "quiz"));
/// Apply penalties.
$mform->addElement('selectyesno', 'penaltyscheme', get_string('penaltyscheme', 'quiz'));
$mform->setHelpButton('penaltyscheme', array('penaltyscheme', get_string('penaltyscheme','quiz'), 'quiz'));
$mform->setAdvanced('penaltyscheme', $quizconfig->fix_penaltyscheme);
$mform->setDefault('penaltyscheme', $quizconfig->penaltyscheme);
$mform->disabledIf('penaltyscheme', 'adaptive', 'neq', 1);
$options = array(
0 => '0',
1 => '1',
2 => '2',
3 => '3');
$mform->addElement('select', 'decimalpoints', get_string("decimaldigits", "quiz"), $options);
$mform->setHelpButton('decimalpoints', array("decimalpoints", get_string("decimaldigits","quiz"), "quiz"));
$mform->setAdvanced('decimalpoints', $quizconfig->fix_decimalpoints);
$mform->setDefault('decimalpoints', $quizconfig->decimalpoints);
$mform->addElement('hidden', 'grade', $quizconfig->maximumgrade);
/// Each attempt builds on last.
$mform->addElement('selectyesno', 'attemptonlast', get_string('eachattemptbuildsonthelast', 'quiz'));
$mform->setHelpButton('attemptonlast', array('repeatattempts', get_string('eachattemptbuildsonthelast', 'quiz'), 'quiz'));
$mform->setAdvanced('attemptonlast', $quizconfig->fix_attemptonlast);
$mform->setDefault('attemptonlast', $quizconfig->attemptonlast);
$mform->disabledIf('attemptonlast', 'attempts', 'eq', 1);
//-------------------------------------------------------------------------------
$mform->addElement('header', 'reviewoptionshdr', get_string('reviewoptionsheading', 'quiz'));
$mform->setHelpButton('reviewoptionshdr', array('reviewoptions', get_string('reviewoptionsheading','quiz'), 'quiz'));
$mform->setAdvanced('reviewoptionshdr', $quizconfig->fix_review);
/// Review options.
$immediatelyoptionsgrp=array();
$immediatelyoptionsgrp[] = &$mform->createElement('checkbox', 'responsesimmediately', '', get_string('responses', 'quiz'));
$immediatelyoptionsgrp[] = &$mform->createElement('checkbox', 'answersimmediately', '', get_string('answers', 'quiz'));
@ -161,7 +153,7 @@ class mod_quiz_mod_form extends moodleform_mod {
$immediatelyoptionsgrp[] = &$mform->createElement('checkbox', 'generalfeedbackimmediately', '', get_string('generalfeedback', 'quiz'));
$immediatelyoptionsgrp[] = &$mform->createElement('checkbox', 'scoreimmediately', '', get_string('scores', 'quiz'));
$immediatelyoptionsgrp[] = &$mform->createElement('checkbox', 'overallfeedbackimmediately', '', get_string('overallfeedback', 'quiz'));
$mform->addGroup($immediatelyoptionsgrp, 'immediatelyoptionsgrp', get_string("reviewimmediately", "quiz"), null, false);
$mform->addGroup($immediatelyoptionsgrp, 'immediatelyoptionsgrp', get_string('reviewimmediately', 'quiz'), null, false);
$mform->setDefault('responsesimmediately', $quizconfig->review & QUIZ_REVIEW_RESPONSES & QUIZ_REVIEW_IMMEDIATELY);
$mform->setDefault('answersimmediately', $quizconfig->review & QUIZ_REVIEW_ANSWERS & QUIZ_REVIEW_IMMEDIATELY);
$mform->setDefault('feedbackimmediately', $quizconfig->review & QUIZ_REVIEW_FEEDBACK & QUIZ_REVIEW_IMMEDIATELY);
@ -176,7 +168,7 @@ class mod_quiz_mod_form extends moodleform_mod {
$openoptionsgrp[] = &$mform->createElement('checkbox', 'generalfeedbackopen', '', get_string('generalfeedback', 'quiz'));
$openoptionsgrp[] = &$mform->createElement('checkbox', 'scoreopen', '', get_string('scores', 'quiz'));
$openoptionsgrp[] = &$mform->createElement('checkbox', 'overallfeedbackopen', '', get_string('overallfeedback', 'quiz'));
$mform->addGroup($openoptionsgrp, 'openoptionsgrp', get_string("reviewopen", "quiz"), array(' '), false);
$mform->addGroup($openoptionsgrp, 'openoptionsgrp', get_string('reviewopen', 'quiz'), array(' '), false);
$mform->setDefault('responsesopen', $quizconfig->review & QUIZ_REVIEW_RESPONSES & QUIZ_REVIEW_OPEN);
$mform->setDefault('answersopen', $quizconfig->review & QUIZ_REVIEW_ANSWERS & QUIZ_REVIEW_OPEN);
$mform->setDefault('feedbackopen', $quizconfig->review & QUIZ_REVIEW_FEEDBACK & QUIZ_REVIEW_OPEN);
@ -184,7 +176,6 @@ class mod_quiz_mod_form extends moodleform_mod {
$mform->setDefault('scoreopen', $quizconfig->review & QUIZ_REVIEW_SCORES & QUIZ_REVIEW_OPEN);
$mform->setDefault('overallfeedbackopen', $quizconfig->review & QUIZ_REVIEW_OVERALLFEEDBACK & QUIZ_REVIEW_OPEN);
$closedoptionsgrp=array();
$closedoptionsgrp[] = &$mform->createElement('checkbox', 'responsesclosed', '', get_string('responses', 'quiz'));
$closedoptionsgrp[] = &$mform->createElement('checkbox', 'answersclosed', '', get_string('answers', 'quiz'));
@ -192,40 +183,81 @@ class mod_quiz_mod_form extends moodleform_mod {
$closedoptionsgrp[] = &$mform->createElement('checkbox', 'generalfeedbackclosed', '', get_string('generalfeedback', 'quiz'));
$closedoptionsgrp[] = &$mform->createElement('checkbox', 'scoreclosed', '', get_string('scores', 'quiz'));
$closedoptionsgrp[] = &$mform->createElement('checkbox', 'overallfeedbackclosed', '', get_string('overallfeedback', 'quiz'));
$mform->addGroup($closedoptionsgrp, 'closedoptionsgrp', get_string("reviewclosed", "quiz"), array(' '), false);
$mform->addGroup($closedoptionsgrp, 'closedoptionsgrp', get_string('reviewclosed', 'quiz'), array(' '), false);
$mform->setDefault('responsesclosed', $quizconfig->review & QUIZ_REVIEW_RESPONSES & QUIZ_REVIEW_CLOSED);
$mform->setDefault('answersclosed', $quizconfig->review & QUIZ_REVIEW_ANSWERS & QUIZ_REVIEW_CLOSED);
$mform->setDefault('feedbackclosed', $quizconfig->review & QUIZ_REVIEW_FEEDBACK & QUIZ_REVIEW_CLOSED);
$mform->setDefault('generalfeedbackclosed', $quizconfig->review & QUIZ_REVIEW_GENERALFEEDBACK & QUIZ_REVIEW_CLOSED);
$mform->setDefault('scoreclosed', $quizconfig->review & QUIZ_REVIEW_SCORES & QUIZ_REVIEW_CLOSED);
$mform->setDefault('overallfeedbackclosed', $quizconfig->review & QUIZ_REVIEW_OVERALLFEEDBACK & QUIZ_REVIEW_CLOSED);
$mform->disabledIf('closedoptionsgrp', 'timeclose[enabled]');
//-------------------------------------------------------------------------------
$mform->addElement('header', 'security', get_string('security', 'form'));
$mform->addElement('header', 'display', get_string('display', 'form'));
$mform->addElement('selectyesno', 'popup', get_string("popup", "quiz"));
$mform->setHelpButton('popup', array("popup", get_string("popup", "quiz"), "quiz"));
$mform->setAdvanced('popup', $quizconfig->fix_popup);
$mform->setDefault('popup', $quizconfig->popup);
/// Show user picture.
$mform->addElement('selectyesno', 'showuserpicture', get_string('showuserpicture', 'quiz'));
$mform->setHelpButton('showuserpicture', array('showuserpicture', get_string('showuserpicture', 'quiz'), 'quiz'));
$mform->setAdvanced('showuserpicture', $quizconfig->fix_showuserpicture);
$mform->setDefault('showuserpicture', $quizconfig->showuserpicture);
$mform->addElement('passwordunmask', 'quizpassword', get_string("requirepassword", "quiz"));
/// Overall decimal points.
$options = array();
for ($i = 0; $i <= QUIZ_MAX_DECIMAL_OPTION; $i++) {
$options[$i] = $i;
}
$mform->addElement('select', 'decimalpoints', get_string('decimalplaces', 'quiz'), $options);
$mform->setHelpButton('decimalpoints', array('decimalpoints', get_string('decimalplaces','quiz'), 'quiz'));
$mform->setAdvanced('decimalpoints', $quizconfig->fix_decimalpoints);
$mform->setDefault('decimalpoints', $quizconfig->decimalpoints);
/// Question decimal points.
$options = array(-1 => get_string('sameasoverall', 'quiz'));
for ($i = 0; $i <= QUIZ_MAX_Q_DECIMAL_OPTION; $i++) {
$options[$i] = $i;
}
$mform->addElement('select', 'questiondecimalpoints', get_string('decimalplacesquestion', 'quiz'), $options);
$mform->setHelpButton('questiondecimalpoints', array('decimalplacesquestion', get_string('decimalplacesquestion','quiz'), 'quiz'));
$mform->setAdvanced('questiondecimalpoints', $quizconfig->fix_questiondecimalpoints);
$mform->setDefault('questiondecimalpoints', $quizconfig->questiondecimalpoints);
//-------------------------------------------------------------------------------
$mform->addElement('header', 'security', get_string('extraattemptrestrictions', 'quiz'));
/// Enforced time delay between quiz attempts.
$mform->addElement('passwordunmask', 'quizpassword', get_string('requirepassword', 'quiz'));
$mform->setType('quizpassword', PARAM_TEXT);
$mform->setHelpButton('quizpassword', array("requirepassword", get_string("requirepassword", "quiz"), "quiz"));
$mform->setHelpButton('quizpassword', array('requirepassword', get_string('requirepassword', 'quiz'), 'quiz'));
$mform->setAdvanced('quizpassword', $quizconfig->fix_password);
$mform->setDefault('quizpassword', $quizconfig->password);
$mform->addElement('text', 'subnet', get_string("requiresubnet", "quiz"));
/// IP address.
$mform->addElement('text', 'subnet', get_string('requiresubnet', 'quiz'));
$mform->setType('subnet', PARAM_TEXT);
$mform->setHelpButton('subnet', array("requiresubnet", get_string("requiresubnet", "quiz"), "quiz"));
$mform->setHelpButton('subnet', array('requiresubnet', get_string('requiresubnet', 'quiz'), 'quiz'));
$mform->setAdvanced('subnet', $quizconfig->fix_subnet);
$mform->setDefault('subnet', $quizconfig->subnet);
//-------------------------------------------------------------------------------
$features = new stdClass;
$features->groups = true;
$features->groupings = true;
$features->groupmembersonly = true;
$this->standard_coursemodule_elements($features);
/// Enforced time delay between quiz attempts.
$mform->addElement('duration', 'delay1', get_string('delay1st2nd', 'quiz'), array('optional' => true));
$mform->setHelpButton('delay1', array('timedelay1', get_string('delay1st2nd', 'quiz'), 'quiz'));
$mform->setAdvanced('delay1', $quizconfig->fix_delay1);
$mform->setDefault('delay1', $quizconfig->delay1);
$mform->disabledIf('delay1', 'attempts', 'eq', 1);
$mform->addElement('duration', 'delay2', get_string('delaylater', 'quiz'), array('optional' => true));
$mform->setHelpButton('delay2', array('timedelay2', get_string('delaylater', 'quiz'), 'quiz'));
$mform->setAdvanced('delay2', $quizconfig->fix_delay2);
$mform->setDefault('delay2', $quizconfig->delay2);
$mform->disabledIf('delay2', 'attempts', 'eq', 1);
$mform->disabledIf('delay2', 'attempts', 'eq', 2);
/// 'Secure' window.
$mform->addElement('selectyesno', 'popup', get_string('showinsecurepopup', 'quiz'));
$mform->setHelpButton('popup', array('popup', get_string('showinsecurepopup', 'quiz'), 'quiz'));
$mform->setAdvanced('popup', $quizconfig->fix_popup);
$mform->setDefault('popup', $quizconfig->popup);
//-------------------------------------------------------------------------------
$mform->addElement('header', 'overallfeedbackhdr', get_string('overallfeedback', 'quiz'));
$mform->setHelpButton('overallfeedbackhdr', array('overallfeedback', get_string('overallfeedback', 'quiz'), 'quiz'));
@ -246,7 +278,7 @@ class mod_quiz_mod_form extends moodleform_mod {
$mform->setType('feedbacktext', PARAM_RAW);
$mform->setType('feedbackboundaries', PARAM_NOTAGS);
$nextel=$this->repeat_elements($repeatarray, $numfeedbacks-1,
$nextel=$this->repeat_elements($repeatarray, $numfeedbacks - 1,
array(), 'boundary_repeats', 'boundary_add_fields', 3,
get_string('addmoreoverallfeedbacks', 'quiz'), true);
@ -257,6 +289,13 @@ class mod_quiz_mod_form extends moodleform_mod {
$insertEl = &MoodleQuickForm::createElement('static', 'gradeboundarystatic2', get_string('gradeboundary', 'quiz'), '0%');
$mform->insertElementBefore($insertEl, 'boundary_add_fields');
//-------------------------------------------------------------------------------
$features = new stdClass;
$features->groups = true;
$features->groupings = true;
$features->groupmembersonly = true;
$this->standard_coursemodule_elements($features);
//-------------------------------------------------------------------------------
// buttons
$this->add_action_buttons();

View File

@ -162,11 +162,11 @@ function quiz_format_average_grade_for_questions($avggradebyq, $questions, $quiz
foreach(array_keys($questions) as $questionid) {
if (isset($avggradebyq[$questionid])){
$grade = $avggradebyq[$questionid];
$grade = quiz_rescale_grade($grade, $quiz);
$grade = quiz_rescale_grade($grade, $quiz, 'question');
} else {
$grade = '--';
}
$row['qsgrade'.$questionid]= $grade;
$row['qsgrade'.$questionid] = $grade;
}
return $row;
}

View File

@ -83,7 +83,11 @@
$quiz->grade = backup_todb($info['MOD']['#']['GRADE']['0']['#']);
$quiz->timecreated = backup_todb($info['MOD']['#']['TIMECREATED']['0']['#']);
$quiz->timemodified = backup_todb($info['MOD']['#']['TIMEMODIFIED']['0']['#']);
$quiz->timelimit = backup_todb($info['MOD']['#']['TIMELIMIT']['0']['#']);
if (isset($info['MOD']['#']['TIMELIMITSECS']['0']['#'])) {
$quiz->timelimit = backup_todb($info['MOD']['#']['TIMELIMITSECS']['0']['#']);
} else {
$quiz->timelimit = backup_todb($info['MOD']['#']['TIMELIMIT']['0']['#']) * 60;
}
$quiz->password = backup_todb($info['MOD']['#']['PASSWORD']['0']['#']);
$quiz->subnet = backup_todb($info['MOD']['#']['SUBNET']['0']['#']);
$quiz->popup = backup_todb($info['MOD']['#']['POPUP']['0']['#']);

View File

@ -1237,7 +1237,7 @@
$quiz->grade = backup_todb($info['MOD']['#']['GRADE']['0']['#']);
$quiz->timecreated = backup_todb($info['MOD']['#']['TIMECREATED']['0']['#']);
$quiz->timemodified = backup_todb($info['MOD']['#']['TIMEMODIFIED']['0']['#']);
$quiz->timelimit = backup_todb($info['MOD']['#']['TIMELIMIT']['0']['#']);
$quiz->timelimit = backup_todb($info['MOD']['#']['TIMELIMIT']['0']['#']) * 60;
$quiz->password = backup_todb($info['MOD']['#']['PASSWORD']['0']['#']);
$quiz->subnet = backup_todb($info['MOD']['#']['SUBNET']['0']['#']);
$quiz->popup = backup_todb($info['MOD']['#']['POPUP']['0']['#']);

View File

@ -116,13 +116,12 @@
/// Work out some time-related things.
$attempt = $attemptobj->get_attempt();
$quiz = $attemptobj->get_quiz();
$timelimit = $quiz->timelimit * 60;
$overtime = 0;
if ($attempt->timefinish) {
if ($timetaken = ($attempt->timefinish - $attempt->timestart)) {
if($timelimit && $timetaken > ($timelimit + 60)) {
$overtime = $timetaken - $timelimit;
if($quiz->timelimit && $timetaken > ($quiz->timelimit + 60)) {
$overtime = $timetaken - $quiz->timelimit;
$overtime = format_time($overtime);
}
$timetaken = format_time($timetaken);

View File

@ -39,119 +39,115 @@ $quizsettings = new admin_settingpage('modsettingquiz', $pagetitle, 'moodle/site
// Introductory explanation that all the settings are defaults for the add quiz form.
$quizsettings->add(new admin_setting_heading('quizintro', '', get_string('configintro', 'quiz')));
// timelimit
// Time limit
$quizsettings->add(new admin_setting_text_with_advanced('quiz/timelimit',
get_string('timelimit', 'quiz'), get_string('configtimelimit', 'quiz'),
get_string('timelimitsec', 'quiz'), get_string('configtimelimitsec', 'quiz'),
array('value' => '0', 'fix' => false), PARAM_INT));
// delay1 and delay2
$timedelayoptions = array();
$timedelayoptions[0] = get_string('none');
$timedelayoptions[1800] = get_string('numminutes', '', 30);
$timedelayoptions[3600] = get_string('numminutes', '', 60);
for($i=2; $i<=23; $i++) {
$seconds = $i*3600;
$timedelayoptions[$seconds] = get_string('numhours', '', $i);
}
$timedelayoptions[86400] = get_string('numhours', '', 24);
for($i=2; $i<=7; $i++) {
$seconds = $i*86400;
$timedelayoptions[$seconds] = get_string('numdays', '', $i);
}
$quizsettings->add(new admin_setting_combo_with_advanced('quiz/delay1',
get_string('delay1', 'quiz'), get_string('configdelay1', 'quiz'),
array('value' => 0, 'fix' => false), $timedelayoptions));
$quizsettings->add(new admin_setting_combo_with_advanced('quiz/delay2',
get_string('delay2', 'quiz'), get_string('configdelay2', 'quiz'),
array('value' => 0, 'fix' => false), $timedelayoptions));
// questionsperpage
$perpage = array();
$perpage[0] = get_string('never');
$perpage[1] = get_string('aftereachquestion', 'quiz');
for ($i = 2; $i <= 50; ++$i) {
$perpage[$i] = get_string('afternquestions', 'quiz', $i);
}
$quizsettings->add(new admin_setting_combo_with_advanced('quiz/questionsperpage',
get_string('newpageevery', 'quiz'), get_string('confignewpageevery', 'quiz'),
array('value' => 1, 'fix' => false), $perpage));
// shufflequestions
$quizsettings->add(new admin_setting_yesno_with_advanced('quiz/shufflequestions',
get_string('shufflequestions', 'quiz'), get_string('configshufflequestions', 'quiz'),
array('value' => 0, 'fix' => false)));
// shuffleanswers
$quizsettings->add(new admin_setting_yesno_with_advanced('quiz/shuffleanswers',
get_string('shufflewithin', 'quiz'), get_string('configshufflewithin', 'quiz'),
array('value' => 1, 'fix' => false)));
// showuserpicture
$quizsettings->add(new admin_setting_yesno_with_advanced('quiz/showuserpicture',
get_string('showuserpicture', 'quiz'), get_string('configshowuserpicture', 'quiz'),
array('value' => 0, 'fix' => false)));
// attempts
// Number of attempts
$options = array(get_string('unlimited'));
for ($i = 1; $i <= 6; $i++) {
for ($i = 1; $i <= QUIZ_MAX_ATTEMPT_OPTION; $i++) {
$options[$i] = $i;
}
$quizsettings->add(new admin_setting_combo_with_advanced('quiz/attempts',
get_string('attemptsallowed', 'quiz'), get_string('configattemptsallowed', 'quiz'),
array('value' => 0, 'fix' => false), $options));
// attemptonlast
$quizsettings->add(new admin_setting_yesno_with_advanced('quiz/attemptonlast',
get_string('eachattemptbuildsonthelast', 'quiz'), get_string('configeachattemptbuildsonthelast', 'quiz'),
array('value' => 0, 'fix' => false)));
// optionflags
$quizsettings->add(new admin_setting_yesno_with_advanced('quiz/optionflags',
get_string('adaptive', 'quiz'), get_string('configadaptive', 'quiz'),
array('value' => 1, 'fix' => false)));
// maximumgrade
$quizsettings->add(new admin_setting_configtext('quiz/maximumgrade',
get_string('maximumgrade'), get_string('configmaximumgrade', 'quiz'), 10, PARAM_INT));
// grademethod
// Grading method.
$quizsettings->add(new admin_setting_combo_with_advanced('quiz/grademethod',
get_string('grademethod', 'quiz'), get_string('configgrademethod', 'quiz'),
array('value' => QUIZ_GRADEHIGHEST, 'fix' => false), quiz_get_grading_options()));
// penaltyscheme
$quizsettings->add(new admin_setting_yesno_with_advanced('quiz/penaltyscheme',
get_string('penaltyscheme', 'quiz'), get_string('configpenaltyscheme', 'quiz'),
// Maximum grade
$quizsettings->add(new admin_setting_configtext('quiz/maximumgrade',
get_string('maximumgrade'), get_string('configmaximumgrade', 'quiz'), 10, PARAM_INT));
// Shuffle questions
$quizsettings->add(new admin_setting_yesno_with_advanced('quiz/shufflequestions',
get_string('shufflequestions', 'quiz'), get_string('configshufflequestions', 'quiz'),
array('value' => 0, 'fix' => false)));
// Questions per page
$perpage = array();
$perpage[0] = get_string('never');
$perpage[1] = get_string('aftereachquestion', 'quiz');
for ($i = 2; $i <= QUIZ_MAX_QPP_OPTION; ++$i) {
$perpage[$i] = get_string('afternquestions', 'quiz', $i);
}
$quizsettings->add(new admin_setting_combo_with_advanced('quiz/questionsperpage',
get_string('newpageevery', 'quiz'), get_string('confignewpageevery', 'quiz'),
array('value' => 1, 'fix' => false), $perpage));
// Shuffle within questions
$quizsettings->add(new admin_setting_yesno_with_advanced('quiz/shuffleanswers',
get_string('shufflewithin', 'quiz'), get_string('configshufflewithin', 'quiz'),
array('value' => 1, 'fix' => false)));
// decimalpoints
// Adaptive mode.
$quizsettings->add(new admin_setting_yesno_with_advanced('quiz/optionflags',
get_string('adaptive', 'quiz'), get_string('configadaptive', 'quiz'),
array('value' => 1, 'fix' => false)));
// Apply penalties.
$quizsettings->add(new admin_setting_yesno_with_advanced('quiz/penaltyscheme',
get_string('penaltyscheme', 'quiz'), get_string('configpenaltyscheme', 'quiz'),
array('value' => 1, 'fix' => true)));
// Each attempt builds on last.
$quizsettings->add(new admin_setting_yesno_with_advanced('quiz/attemptonlast',
get_string('eachattemptbuildsonthelast', 'quiz'), get_string('configeachattemptbuildsonthelast', 'quiz'),
array('value' => 0, 'fix' => true)));
// Review options.
$quizsettings->add(new admin_setting_quiz_reviewoptions('quiz/review',
get_string('reviewoptions', 'quiz'), get_string('configreviewoptions', 'quiz'),
array('value' => QUIZ_REVIEW_IMMEDIATELY | QUIZ_REVIEW_OPEN | QUIZ_REVIEW_CLOSED, 'fix' => false)));
// Show the user's picture
$quizsettings->add(new admin_setting_yesno_with_advanced('quiz/showuserpicture',
get_string('showuserpicture', 'quiz'), get_string('configshowuserpicture', 'quiz'),
array('value' => 0, 'fix' => false)));
// Decimal places for overall grades.
$options = array();
for ($i = 0; $i <= 5; $i++) {
for ($i = 0; $i <= QUIZ_MAX_DECIMAL_OPTION; $i++) {
$options[$i] = $i;
}
$quizsettings->add(new admin_setting_combo_with_advanced('quiz/decimalpoints',
get_string('decimaldigits', 'quiz'), get_string('configdecimaldigits', 'quiz'),
get_string('decimalplaces', 'quiz'), get_string('configdecimalplaces', 'quiz'),
array('value' => 2, 'fix' => false), $options));
// review
$quizsettings->add(new admin_setting_quiz_reviewoptions('quiz/review',
get_string('reviewoptions', 'quiz'), get_string('configreviewoptions', 'quiz'),
array('value' => 0x3fffffff, 'fix' => false)));
// Decimal places for question grades.
$options = array(-1 => get_string('sameasoverall', 'quiz'));
for ($i = 0; $i <= QUIZ_MAX_Q_DECIMAL_OPTION; $i++) {
$options[$i] = $i;
}
$quizsettings->add(new admin_setting_combo_with_advanced('quiz/questiondecimalpoints',
get_string('decimalplacesquestion', 'quiz'), get_string('configdecimalplacesquestion', 'quiz'),
array('value' => -1, 'fix' => true), $options));
// popup
$quizsettings->add(new admin_setting_yesno_with_advanced('quiz/popup',
get_string('popup', 'quiz'), get_string('configpopup', 'quiz'),
array('value' => 0, 'fix' => false)));
// quizpassword
// Password.
$quizsettings->add(new admin_setting_text_with_advanced('quiz/password',
get_string('requirepassword', 'quiz'), get_string('configrequirepassword', 'quiz'),
array('value' => '', 'fix' => false), PARAM_TEXT));
array('value' => '', 'fix' => true), PARAM_TEXT));
// subnet
// IP restrictions.
$quizsettings->add(new admin_setting_text_with_advanced('quiz/subnet',
get_string('requiresubnet', 'quiz'), get_string('configrequiresubnet', 'quiz'),
array('value' => '', 'fix' => false), PARAM_TEXT));
array('value' => '', 'fix' => true), PARAM_TEXT));
// Enforced delay between attempts.
$quizsettings->add(new admin_setting_text_with_advanced('quiz/delay1',
get_string('delay1st2nd', 'quiz'), get_string('configdelay1st2nd', 'quiz'),
array('value' => 0, 'fix' => true), PARAM_INTEGER));
$quizsettings->add(new admin_setting_text_with_advanced('quiz/delay2',
get_string('delaylater', 'quiz'), get_string('configdelaylater', 'quiz'),
array('value' => 0, 'fix' => true), PARAM_INTEGER));
// 'Secure' window.
$quizsettings->add(new admin_setting_yesno_with_advanced('quiz/popup',
get_string('showinsecurepopup', 'quiz'), get_string('configpopup', 'quiz'),
array('value' => 0, 'fix' => true)));
/// Now, depending on whether any reports have their own settings page, add
/// the quiz setting page to the appropriate place in the tree.
@ -171,4 +167,3 @@ if (empty($reportsbyname)) {
$ADMIN->add('modsettingsquizcat', $settings);
}
}
?>

View File

@ -74,7 +74,7 @@ class simple_rules_test extends UnitTestCase {
function test_time_limit_access_rule() {
$quiz = new stdClass;
$quiz->timelimit = 60;
$quiz->timelimit = 3600;
$quiz->questions = '';
$cm = new stdClass;
$cm->id = 0;

View File

@ -26,5 +26,32 @@ class quiz_lib_test extends UnitTestCase {
$quiz->sumgrades = '100.0000';
$this->assertFalse(quiz_has_grades($quiz));
}
function test_quiz_format_grade() {
$quiz = new stdClass;
$quiz->decimalpoints = 2;
$this->assertEqual(quiz_format_grade($quiz, 0.12345678), format_float(0.12, 2));
$this->assertEqual(quiz_format_grade($quiz, 0), format_float(0, 2));
$this->assertEqual(quiz_format_grade($quiz, 1.000000000000), format_float(1, 2));
$quiz->decimalpoints = 0;
$this->assertEqual(quiz_format_grade($quiz, 0.12345678), '0');
}
function test_quiz_format_question_grade() {
$quiz = new stdClass;
$quiz->decimalpoints = 2;
$quiz->questiondecimalpoints = 2;
$this->assertEqual(quiz_format_question_grade($quiz, 0.12345678), format_float(0.12, 2));
$this->assertEqual(quiz_format_question_grade($quiz, 0), format_float(0, 2));
$this->assertEqual(quiz_format_question_grade($quiz, 1.000000000000), format_float(1, 2));
$quiz->decimalpoints = 3;
$quiz->questiondecimalpoints = -1;
$this->assertEqual(quiz_format_question_grade($quiz, 0.12345678), format_float(0.123, 3));
$this->assertEqual(quiz_format_question_grade($quiz, 0), format_float(0, 3));
$this->assertEqual(quiz_format_question_grade($quiz, 1.000000000000), format_float(1, 3));
$quiz->questiondecimalpoints = 4;
$this->assertEqual(quiz_format_question_grade($quiz, 0.12345678), format_float(0.1235, 4));
$this->assertEqual(quiz_format_question_grade($quiz, 0), format_float(0, 4));
$this->assertEqual(quiz_format_question_grade($quiz, 1.000000000000), format_float(1, 4));
}
}
?>

View File

@ -71,5 +71,19 @@ class quiz_locallib_test extends UnitTestCase {
$this->assertEqual(quiz_clean_layout('1,0,2', true), '1,0,2,0');
$this->assertEqual(quiz_clean_layout('0,1,0,0,2,0', true), '1,0,2,0');
}
function test_quiz_rescale_grade() {
$quiz = new stdClass;
$quiz->decimalpoints = 2;
$quiz->questiondecimalpoints = 3;
$quiz->grade = 10;
$quiz->sumgrades = 10;
$this->assertEqual(quiz_rescale_grade(0.12345678, $quiz, false), 0.12345678);
$this->assertEqual(quiz_rescale_grade(0.12345678, $quiz, true), format_float(0.12, 2));
$this->assertEqual(quiz_rescale_grade(0.12345678, $quiz, 'question'), format_float(0.123, 3));
$quiz->sumgrades = 5;
$this->assertEqual(quiz_rescale_grade(0.12345678, $quiz, false), 0.24691356);
$this->assertEqual(quiz_rescale_grade(0.12345678, $quiz, true), format_float(0.25, 2));
$this->assertEqual(quiz_rescale_grade(0.12345678, $quiz, 'question'), format_float(0.247, 3));
}
}
?>

View File

@ -5,7 +5,7 @@
// This fragment is called by moodle_needs_upgrading() and /admin/index.php
////////////////////////////////////////////////////////////////////////////////
$module->version = 2009011400; // The (date) version of this module
$module->version = 2009031001; // The (date) version of this module
$module->requires = 2008072401; // Requires this Moodle version
$module->cron = 0; // How often should cron check this module (seconds)?

View File

@ -258,11 +258,11 @@
}
// Ouside the if because we may be showing feedback but not grades.
$attemptgrade = quiz_rescale_grade($attempt->sumgrades, $quiz);
$attemptgrade = quiz_rescale_grade($attempt->sumgrades, $quiz, false);
if ($gradecolumn) {
if ($attemptoptions->scores && $attempt->timefinish > 0) {
$formattedgrade = $attemptgrade;
$formattedgrade = quiz_format_grade($quiz, $attemptgrade);
// highlight the highest grade if appropriate
if ($overallstats && !$attempt->preview && $numattempts > 1 && !is_null($mygrade) &&
$attemptgrade == $mygrade && $quiz->grademethod == QUIZ_GRADEHIGHEST) {