mirror of
https://github.com/moodle/moodle.git
synced 2025-04-21 00:12:56 +02:00
MDL-37993 Quiz: completion upon all passing grade or attempts exhausted
This patch adds completion options to Quiz similar to what is available in scorm. One can have the quiz marked complete when either a passing grade is achieved or all attempts are used up. This will allow a quiz to complete when the user "passes or fails". (Where "fail" means "using up all attempts without passing".)
This commit is contained in:
parent
7784c3ad18
commit
db3686d546
@ -49,7 +49,7 @@ class backup_quiz_activity_structure_step extends backup_questions_activity_stru
|
||||
'questionsperpage', 'navmethod', 'shufflequestions', 'shuffleanswers',
|
||||
'sumgrades', 'grade', 'timecreated',
|
||||
'timemodified', 'password', 'subnet', 'browsersecurity',
|
||||
'delay1', 'delay2', 'showuserpicture', 'showblocks'));
|
||||
'delay1', 'delay2', 'showuserpicture', 'showblocks', 'completionattemptsexhausted', 'completionpass'));
|
||||
|
||||
// Define elements for access rule subplugin settings.
|
||||
$this->add_subplugin_structure('quizaccess', $quiz, true);
|
||||
|
@ -44,6 +44,8 @@
|
||||
<FIELD NAME="delay2" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Delay that must be left between the second and subsequent attempt, in seconds."/>
|
||||
<FIELD NAME="showuserpicture" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Option to show the user's picture during the attempt and on the review page."/>
|
||||
<FIELD NAME="showblocks" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Whether blocks should be shown on the attempt.php and review.php pages."/>
|
||||
<FIELD NAME="completionattemptsexhausted" TYPE="int" LENGTH="1" NOTNULL="false" DEFAULT="0" SEQUENCE="false"/>
|
||||
<FIELD NAME="completionpass" TYPE="int" LENGTH="1" NOTNULL="false" DEFAULT="0" SEQUENCE="false"/>
|
||||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
|
||||
|
@ -776,6 +776,33 @@ function xmldb_quiz_upgrade($oldversion) {
|
||||
// Moodle v2.7.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
if ($oldversion < 2014052800) {
|
||||
|
||||
// Define field completionattemptsexhausted to be added to quiz.
|
||||
$table = new xmldb_table('quiz');
|
||||
$field = new xmldb_field('completionattemptsexhausted', XMLDB_TYPE_INTEGER, '1', null, null, null, '0', 'showblocks');
|
||||
|
||||
// Conditionally launch add field completionattemptsexhausted.
|
||||
if (!$dbman->field_exists($table, $field)) {
|
||||
$dbman->add_field($table, $field);
|
||||
}
|
||||
// Quiz savepoint reached.
|
||||
upgrade_mod_savepoint(true, 2014052800, 'quiz');
|
||||
}
|
||||
|
||||
if ($oldversion < 2014052801) {
|
||||
// Define field completionpass to be added to quiz.
|
||||
$table = new xmldb_table('quiz');
|
||||
$field = new xmldb_field('completionpass', XMLDB_TYPE_INTEGER, '1', null, null, null, 0, 'completionattemptsexhausted');
|
||||
|
||||
// Conditionally launch add field completionpass.
|
||||
if (!$dbman->field_exists($table, $field)) {
|
||||
$dbman->add_field($table, $field);
|
||||
}
|
||||
|
||||
// Quiz savepoint reached.
|
||||
upgrade_mod_savepoint(true, 2014052801, 'quiz');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -152,6 +152,10 @@ $string['comment'] = 'Comment';
|
||||
$string['commentorgrade'] = 'Make comment or override grade';
|
||||
$string['comments'] = 'Comments';
|
||||
$string['completedon'] = 'Completed on';
|
||||
$string['completionpass'] = 'Require passing grade';
|
||||
$string['completionpass_help'] = 'If enabled, this activity is considered complete when the student receives a passing grade, with the pass grade set in the gradebook.';
|
||||
$string['completionattemptsexhausted'] = 'Or all available attempts completed';
|
||||
$string['completionattemptsexhausted_help'] = 'Mark quiz complete when the student has exhausted the maximum number of attempts.';
|
||||
$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.';
|
||||
|
@ -1560,6 +1560,7 @@ function quiz_supports($feature) {
|
||||
case FEATURE_GROUPMEMBERSONLY: return true;
|
||||
case FEATURE_MOD_INTRO: return true;
|
||||
case FEATURE_COMPLETION_TRACKS_VIEWS: return true;
|
||||
case FEATURE_COMPLETION_HAS_RULES: return true;
|
||||
case FEATURE_GRADE_HAS_GRADE: return true;
|
||||
case FEATURE_GRADE_OUTCOMES: return true;
|
||||
case FEATURE_BACKUP_MOODLE2: return true;
|
||||
@ -1790,3 +1791,52 @@ function quiz_get_navigation_options() {
|
||||
QUIZ_NAVMETHOD_SEQ => get_string('navmethod_seq', 'quiz')
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtains the automatic completion state for this quiz on any conditions
|
||||
* in quiz settings, such as if all attempts are used or a certain grade is achieved.
|
||||
*
|
||||
* @param object $course Course
|
||||
* @param object $cm Course-module
|
||||
* @param int $userid User ID
|
||||
* @param bool $type Type of comparison (or/and; can be used as return value if no conditions)
|
||||
* @return bool True if completed, false if not. (If no conditions, then return
|
||||
* value depends on comparison type)
|
||||
*/
|
||||
function quiz_get_completion_state($course, $cm, $userid, $type) {
|
||||
global $DB;
|
||||
global $CFG;
|
||||
|
||||
$quiz = $DB->get_record('quiz', array('id' => $cm->instance), '*', MUST_EXIST);
|
||||
if (!$quiz->completionattemptsexhausted && !$quiz->completionpass) {
|
||||
return $type;
|
||||
}
|
||||
|
||||
// Check if the user has used up all attempts.
|
||||
if ($quiz->completionattemptsexhausted) {
|
||||
$attempts = quiz_get_user_attempts($quiz->id, $userid, 'finished', true);
|
||||
if ($attempts) {
|
||||
$lastfinishedattempt = end($attempts);
|
||||
$context = context_module::instance($cm->id);
|
||||
$quizobj = quiz::create($quiz->id, $userid);
|
||||
$accessmanager = new quiz_access_manager($quizobj, time(),
|
||||
has_capability('mod/quiz:ignoretimelimits', $context, $userid, false));
|
||||
if ($accessmanager->is_finished(count($attempts), $lastfinishedattempt)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for passing grade.
|
||||
if ($quiz->completionpass) {
|
||||
require_once($CFG->libdir . '/gradelib.php');
|
||||
$item = grade_item::fetch(array('courseid' => $course->id, 'itemtype' => 'mod',
|
||||
'itemmodule' => 'quiz', 'iteminstance' => $cm->instance));
|
||||
if ($item) {
|
||||
$grades = grade_grade::fetch_users_grades($item, array($userid), false);
|
||||
return $grades[$userid]->is_passed($item);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -1641,6 +1641,11 @@ function quiz_attempt_submitted_handler($event) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Update completion state.
|
||||
$completion = new completion_info($course);
|
||||
if ($completion->is_enabled($cm) && ($quiz->completionattemptsexhausted || $quiz->completionpass)) {
|
||||
$completion->update_state($cm, COMPLETION_COMPLETE, $event->userid);
|
||||
}
|
||||
return quiz_send_notification_messages($course, $quiz, $attempt,
|
||||
context_module::instance($cm->id), $cm);
|
||||
}
|
||||
|
@ -585,4 +585,37 @@ class mod_quiz_mod_form extends moodleform_mod {
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display module-specific activity completion rules.
|
||||
* Part of the API defined by moodleform_mod
|
||||
* @return array Array of string IDs of added items, empty array if none
|
||||
*/
|
||||
public function add_completion_rules() {
|
||||
$mform = $this->_form;
|
||||
$items = array();
|
||||
|
||||
$group = array();
|
||||
$group[] = $mform->createElement('advcheckbox', 'completionpass', null, get_string('completionpass', 'quiz'),
|
||||
array('group' => 'cpass'));
|
||||
|
||||
$group[] = $mform->createElement('advcheckbox', 'completionattemptsexhausted', null,
|
||||
get_string('completionattemptsexhausted', 'quiz'),
|
||||
array('group' => 'cattempts'));
|
||||
$mform->disabledIf('completionattemptsexhausted', 'completionpass', 'notchecked');
|
||||
$mform->addGroup($group, 'completionpassgroup', get_string('completionpass', 'quiz'), '', false);
|
||||
$mform->addHelpButton('completionpassgroup', 'completionpass', 'quiz');
|
||||
$items[] = 'completionpassgroup';
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called during validation. Indicates whether a module-specific completion rule is selected.
|
||||
*
|
||||
* @param array $data Input data (not yet validated)
|
||||
* @return bool True if one or more rules is enabled, false if none are.
|
||||
*/
|
||||
public function completion_rule_enabled($data) {
|
||||
return !empty($data['completionattemptsexhausted']) || !empty($data['completionpass']);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,88 @@
|
||||
@mod @mod_quiz
|
||||
Feature: Set a quiz to be marked complete when the student uses all attempts allowed
|
||||
In order to ensure a student has learned the material before being marked complete
|
||||
As a teacher
|
||||
I need to set a quiz to complete when the student receives a passing grade, or completed_fail if they use all attempts without passing
|
||||
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| student1 | Student | 1 | student1@asd.com |
|
||||
| teacher1 | Teacher | 1 | teacher1@asd.com |
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname | category |
|
||||
| Course 1 | C1 | 0 |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
| student1 | C1 | student |
|
||||
And I log in as "admin"
|
||||
And I set the following administration settings values:
|
||||
| Enable completion tracking | 1 |
|
||||
And I expand "Grades" node
|
||||
And I follow "Grade item settings"
|
||||
And I set the field "Advanced grade item options" to "hiddenuntil"
|
||||
And I press "Save changes"
|
||||
And I log out
|
||||
|
||||
Scenario: student1 uses up both attempts without passing
|
||||
When I log in as "teacher1"
|
||||
And I follow "Course 1"
|
||||
And I turn editing mode on
|
||||
And I click on "Edit settings" "link" in the "Administration" "block"
|
||||
And I set the following fields to these values:
|
||||
| Enable completion tracking | Yes |
|
||||
And I press "Save changes"
|
||||
And I add a "Quiz" to section "1" and I fill the form with:
|
||||
| Name | Test quiz name |
|
||||
| Description | Test quiz description |
|
||||
| Completion tracking | Show activity as complete when conditions are met |
|
||||
| Attempts allowed | 2 |
|
||||
| Require passing grade | 1 |
|
||||
| Or all available attempts completed | 1 |
|
||||
And I add a "True/False" question to the "Test quiz name" quiz with:
|
||||
| Question name | First question |
|
||||
| Question text | Answer the first question |
|
||||
| General feedback | Thank you, this is the general feedback |
|
||||
| Correct answer | True |
|
||||
| Feedback for the response 'True'. | So you think it is true |
|
||||
| Feedback for the response 'False'. | So you think it is false |
|
||||
And I follow "Course 1"
|
||||
And I follow "Grades"
|
||||
And I follow "Simple view"
|
||||
And I follow "Edit quiz Test quiz name"
|
||||
Then I should see "Edit grade item"
|
||||
And I set the field "gradepass" to "5"
|
||||
And I press "Save changes"
|
||||
And I should see "Simple view"
|
||||
Then I log out
|
||||
|
||||
And I log in as "student1"
|
||||
And I follow "Course 1"
|
||||
And "//img[contains(@alt, 'Not completed: Test quiz name')]" "xpath_element" should exist in the "li.modtype_quiz" "css_element"
|
||||
And I follow "Test quiz name"
|
||||
And I press "Attempt quiz now"
|
||||
And I should see "Question 1"
|
||||
And I should see "Answer the first question"
|
||||
And I set the field "False" to "1"
|
||||
And I press "Next"
|
||||
And I should see "Answer saved"
|
||||
And I press "Submit all and finish"
|
||||
And I follow "C1"
|
||||
And "//img[contains(@alt, 'Not completed: Test quiz name')]" "xpath_element" should exist in the "li.modtype_quiz" "css_element"
|
||||
And I follow "Test quiz name"
|
||||
And I press "Re-attempt quiz"
|
||||
Then I should see "Question 1"
|
||||
And I should see "Answer the first question"
|
||||
And I set the field "False" to "1"
|
||||
And I press "Next"
|
||||
And I should see "Answer saved"
|
||||
And I press "Submit all and finish"
|
||||
And I follow "C1"
|
||||
And "//img[contains(@alt, 'Completed: Test quiz name')]" "xpath_element" should exist in the "li.modtype_quiz" "css_element"
|
||||
And I log out
|
||||
And I log in as "teacher1"
|
||||
And I follow "Course 1"
|
||||
And I follow "Activity completion"
|
||||
Then "//img[contains(@title,'Test quiz name') and @alt='Completed']" "xpath_element" should exist in the "Student 1" "table_row"
|
||||
|
@ -0,0 +1,87 @@
|
||||
@mod @mod_quiz
|
||||
Feature: Set a quiz to be marked complete when the student passes
|
||||
In order to ensure a student has learned the material before being marked complete
|
||||
As a teacher
|
||||
I need to set a quiz to complete when the student recieves a passing grade
|
||||
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| student1 | Student | 1 | student1@asd.com |
|
||||
| teacher1 | Teacher | 1 | teacher1@asd.com |
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname | category |
|
||||
| Course 1 | C1 | 0 |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
| student1 | C1 | student |
|
||||
And I log in as "admin"
|
||||
And I set the following administration settings values:
|
||||
| Enable completion tracking | 1 |
|
||||
And I expand "Grades" node
|
||||
And I follow "Grade item settings"
|
||||
And I set the field "Advanced grade item options" to "hiddenuntil"
|
||||
And I press "Save changes"
|
||||
And I log out
|
||||
|
||||
Scenario: student1 passes on the first try
|
||||
When I log in as "teacher1"
|
||||
And I follow "Course 1"
|
||||
And I turn editing mode on
|
||||
And I click on "Edit settings" "link" in the "Administration" "block"
|
||||
And I set the following fields to these values:
|
||||
| Enable completion tracking | Yes |
|
||||
And I press "Save changes"
|
||||
And I add a "Quiz" to section "1" and I fill the form with:
|
||||
| Name | Test quiz name |
|
||||
| Description | Test quiz description |
|
||||
| Completion tracking | Show activity as complete when conditions are met |
|
||||
| Attempts allowed | 4 |
|
||||
| Require passing grade | 1 |
|
||||
And I add a "True/False" question to the "Test quiz name" quiz with:
|
||||
| Question name | First question |
|
||||
| Question text | Answer the first question |
|
||||
| General feedback | Thank you, this is the general feedback |
|
||||
| Correct answer | True |
|
||||
| Feedback for the response 'True'. | So you think it is true |
|
||||
| Feedback for the response 'False'. | So you think it is false |
|
||||
And I follow "Course 1"
|
||||
And I follow "Grades"
|
||||
And I select "Simple view" from "jump"
|
||||
And I press "Go"
|
||||
And I follow "Edit quiz Test quiz name"
|
||||
Then I should see "Edit grade item"
|
||||
And I set the field "gradepass" to "5"
|
||||
And I press "Save changes"
|
||||
Then I should see "Simple view"
|
||||
And I log out
|
||||
|
||||
And I log in as "student1"
|
||||
And I follow "Course 1"
|
||||
And "//img[contains(@alt, 'Not completed: Test quiz name')]" "xpath_element" should exist in the "li.modtype_quiz" "css_element"
|
||||
And I follow "Test quiz name"
|
||||
And I press "Attempt quiz now"
|
||||
Then I should see "Question 1"
|
||||
And I should see "Answer the first question"
|
||||
And I set the field "False" to "1"
|
||||
And I press "Next"
|
||||
And I should see "Answer saved"
|
||||
And I press "Submit all and finish"
|
||||
And I follow "C1"
|
||||
And "//img[contains(@alt, 'Not completed: Test quiz name')]" "xpath_element" should exist in the "li.modtype_quiz" "css_element"
|
||||
And I follow "Test quiz name"
|
||||
And I press "Re-attempt quiz"
|
||||
Then I should see "Question 1"
|
||||
And I should see "Answer the first question"
|
||||
And I set the field "True" to "1"
|
||||
And I press "Next"
|
||||
And I should see "Answer saved"
|
||||
And I press "Submit all and finish"
|
||||
And I follow "C1"
|
||||
And "//img[contains(@alt, 'Completed: Test quiz name')]" "xpath_element" should exist in the "li.modtype_quiz" "css_element"
|
||||
And I log out
|
||||
And I log in as "teacher1"
|
||||
And I follow "Course 1"
|
||||
And I follow "Activity completion"
|
||||
Then "//img[contains(@title,'Test quiz name') and @alt='Completed']" "xpath_element" should exist in the "Student 1" "table_row"
|
@ -24,7 +24,7 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2014051200; // The current module version (Date: YYYYMMDDXX).
|
||||
$plugin->version = 2014052801; // The current module version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2014050800; // Requires this Moodle version.
|
||||
$plugin->component = 'mod_quiz'; // Full name of the plugin (used for diagnostics).
|
||||
$plugin->cron = 60;
|
||||
|
Loading…
x
Reference in New Issue
Block a user