diff --git a/mod/quiz/classes/local/reports/attempts_report_options.php b/mod/quiz/classes/local/reports/attempts_report_options.php index 8f55cbdcb32..bd9f2ab2e9e 100644 --- a/mod/quiz/classes/local/reports/attempts_report_options.php +++ b/mod/quiz/classes/local/reports/attempts_report_options.php @@ -46,8 +46,10 @@ class attempts_report_options { * @var array form field name => corresponding quiz_attempt:: state constant. */ protected static $statefields = [ + 'statenotstarted' => quiz_attempt::NOT_STARTED, 'stateinprogress' => quiz_attempt::IN_PROGRESS, 'stateoverdue' => quiz_attempt::OVERDUE, + 'statesubmitted' => quiz_attempt::SUBMITTED, 'statefinished' => quiz_attempt::FINISHED, 'stateabandoned' => quiz_attempt::ABANDONED, ]; @@ -65,8 +67,14 @@ class attempts_report_options { * @var array|null of quiz_attempt::IN_PROGRESS, etc. constants. null means * no restriction. */ - public $states = [quiz_attempt::IN_PROGRESS, quiz_attempt::OVERDUE, - quiz_attempt::FINISHED, quiz_attempt::ABANDONED]; + public $states = [ + quiz_attempt::NOT_STARTED, + quiz_attempt::IN_PROGRESS, + quiz_attempt::OVERDUE, + quiz_attempt::SUBMITTED, + quiz_attempt::FINISHED, + quiz_attempt::ABANDONED, + ]; /** * @var bool whether to show all finished attmepts, or just the one that gave diff --git a/mod/quiz/classes/local/reports/attempts_report_options_form.php b/mod/quiz/classes/local/reports/attempts_report_options_form.php index dfc3993fc9a..caeadd853a4 100644 --- a/mod/quiz/classes/local/reports/attempts_report_options_form.php +++ b/mod/quiz/classes/local/reports/attempts_report_options_form.php @@ -66,10 +66,14 @@ abstract class attempts_report_options_form extends \moodleform { ]); $stategroup = [ + $mform->createElement('advcheckbox', 'statenotstarted', '', + get_string('statenotstarted', 'quiz')), $mform->createElement('advcheckbox', 'stateinprogress', '', get_string('stateinprogress', 'quiz')), $mform->createElement('advcheckbox', 'stateoverdue', '', get_string('stateoverdue', 'quiz')), + $mform->createElement('advcheckbox', 'statesubmitted', '', + get_string('statesubmitted', 'quiz')), $mform->createElement('advcheckbox', 'statefinished', '', get_string('statefinished', 'quiz')), $mform->createElement('advcheckbox', 'stateabandoned', '', @@ -77,12 +81,17 @@ abstract class attempts_report_options_form extends \moodleform { ]; $mform->addGroup($stategroup, 'stateoptions', get_string('reportattemptsthatare', 'quiz'), [' '], false); + $mform->addHelpButton('stateoptions', 'stateoptions', 'quiz'); + $mform->setDefault('statenotstarted', 1); $mform->setDefault('stateinprogress', 1); $mform->setDefault('stateoverdue', 1); + $mform->setDefault('statesubmitted', 1); $mform->setDefault('statefinished', 1); $mform->setDefault('stateabandoned', 1); + $mform->disabledIf('statenotstarted', 'attempts', 'eq', attempts_report::ENROLLED_WITHOUT); $mform->disabledIf('stateinprogress', 'attempts', 'eq', attempts_report::ENROLLED_WITHOUT); $mform->disabledIf('stateoverdue', 'attempts', 'eq', attempts_report::ENROLLED_WITHOUT); + $mform->disabledIf('statesubmitted', 'attempts', 'eq', attempts_report::ENROLLED_WITHOUT); $mform->disabledIf('statefinished', 'attempts', 'eq', attempts_report::ENROLLED_WITHOUT); $mform->disabledIf('stateabandoned', 'attempts', 'eq', attempts_report::ENROLLED_WITHOUT); @@ -126,8 +135,17 @@ abstract class attempts_report_options_form extends \moodleform { public function validation($data, $files) { $errors = parent::validation($data, $files); - if ($data['attempts'] != attempts_report::ENROLLED_WITHOUT && !( - $data['stateinprogress'] || $data['stateoverdue'] || $data['statefinished'] || $data['stateabandoned'])) { + if ( + $data['attempts'] != attempts_report::ENROLLED_WITHOUT && + !( + $data['stateinprogress'] + || $data['stateoverdue'] + || $data['statefinished'] + || $data['stateabandoned'] + || $data['statenotstarted'] + || $data['statesubmitted'] + ) + ) { $errors['stateoptions'] = get_string('reportmustselectstate', 'quiz'); } diff --git a/mod/quiz/classes/local/reports/attempts_report_table.php b/mod/quiz/classes/local/reports/attempts_report_table.php index eb15fff95b4..18985b9217a 100644 --- a/mod/quiz/classes/local/reports/attempts_report_table.php +++ b/mod/quiz/classes/local/reports/attempts_report_table.php @@ -229,7 +229,7 @@ abstract class attempts_report_table extends \table_sql { * @return string HTML content to go inside the td. */ public function col_timestart($attempt) { - if ($attempt->attempt) { + if ($attempt->attempt && $attempt->timestart) { return userdate($attempt->timestart, $this->strtimeformat); } else { return '-'; diff --git a/mod/quiz/lang/en/quiz.php b/mod/quiz/lang/en/quiz.php index 85e2446b0e6..0e07c060130 100644 --- a/mod/quiz/lang/en/quiz.php +++ b/mod/quiz/lang/en/quiz.php @@ -951,10 +951,10 @@ $string['reports'] = 'Reports'; $string['reportshowonly'] = 'Show only attempts'; $string['reportshowonlyfinished'] = 'Show at most one finished attempt per user ({$a})'; $string['reportsimplestat'] = 'Simple statistics'; -$string['reportusersall'] = 'all users who have attempted the quiz'; -$string['reportuserswith'] = 'enrolled users who have attempted the quiz'; -$string['reportuserswithorwithout'] = 'enrolled users who have, or have not, attempted the quiz'; -$string['reportuserswithout'] = 'enrolled users who have not attempted the quiz'; +$string['reportusersall'] = 'all users who have a quiz attempt'; +$string['reportuserswith'] = 'enrolled users who have a quiz attempt'; +$string['reportuserswithorwithout'] = 'enrolled users who have, or do not have, a quiz attempt'; +$string['reportuserswithout'] = 'enrolled users who do not have a quiz attempt'; $string['reportwhattoinclude'] = 'What to include in the report'; $string['requirepassword'] = 'Require password'; $string['requirepassword_help'] = 'If a password is specified, a student must enter it in order to attempt the quiz.'; @@ -1081,8 +1081,18 @@ $string['statefinished'] = 'Finished'; $string['statefinisheddetails'] = 'Submitted {$a}'; $string['stateinprogress'] = 'In progress'; $string['statenotloaded'] = 'The state for question {$a} has not been loaded from the database'; +$string['statenotstarted'] = 'Not started'; +$string['stateoptions'] = 'Attempt state options'; +$string['stateoptions_help'] = ' +* Not started: The attempt was automatically created before the quiz opened. The student has not started the attempt yet. +* In progress: The student has started the attempt. They still have time to submit it. +* Overdue: The attempt has been open for longer than the allowed time limit. The student can still submit it within the grade period. +* Submitted: The student has completed the attempt and submitted their responses. It is queued for automatic marking. +* Finished: The attempt has been submitted and any automatic marking is complete. +* Never submitted: The student started the attempt, but did not submit it within the time limit or grace period.'; $string['stateoverdue'] = 'Overdue'; $string['stateoverduedetails'] = 'Must be submitted by {$a}'; +$string['statesubmitted'] = 'Submitted'; $string['status'] = 'Status'; $string['stoponerror'] = 'Stop on error'; $string['submission_confirmation'] = 'Submit all your answers and finish?'; diff --git a/mod/quiz/locallib.php b/mod/quiz/locallib.php index 3c5bdb31840..320866827de 100644 --- a/mod/quiz/locallib.php +++ b/mod/quiz/locallib.php @@ -1006,10 +1006,14 @@ function quiz_questions_per_page_options() { */ function quiz_attempt_state_name($state) { switch ($state) { + case quiz_attempt::NOT_STARTED: + return get_string('statenotstarted', 'quiz'); case quiz_attempt::IN_PROGRESS: return get_string('stateinprogress', 'quiz'); case quiz_attempt::OVERDUE: return get_string('stateoverdue', 'quiz'); + case quiz_attempt::SUBMITTED: + return get_string('statesubmitted', 'quiz'); case quiz_attempt::FINISHED: return get_string('statefinished', 'quiz'); case quiz_attempt::ABANDONED: diff --git a/mod/quiz/report/overview/tests/behat/attempt_states.feature b/mod/quiz/report/overview/tests/behat/attempt_states.feature new file mode 100644 index 00000000000..7f658a26ab0 --- /dev/null +++ b/mod/quiz/report/overview/tests/behat/attempt_states.feature @@ -0,0 +1,52 @@ +@mod @mod_quiz @quiz @quiz_overview +Feature: View attempt states + In order to see how students are progressing through the quiz + As a teacher + I need to see different attempt states on the overview report + + Background: + Given the following "users" exist: + | username | firstname | lastname | email | + | teacher1 | Teacher | 1 | teacher1@example.com | + | student1 | Student | 1 | student1@example.com | + | student2 | Student | 2 | student2@example.com | + | student3 | Student | 3 | student3@example.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 | + | student2 | C1 | student | + | student3 | C1 | student | + And the following "question categories" exist: + | contextlevel | reference | name | + | Course | C1 | Test questions | + And the following "activities" exist: + | activity | name | intro | course | idnumber | + | quiz | Quiz 1 | Quiz 1 description | C1 | quiz1 | + And the following "questions" exist: + | questioncategory | qtype | name | questiontext | + | Test questions | description | Intro | Welcome to this quiz | + | Test questions | truefalse | TF1 | First question | + | Test questions | truefalse | TF2 | Second question | + And quiz "Quiz 1" contains the following questions: + | question | page | maxmark | + | Intro | 1 | | + | TF1 | 1 | | + | TF2 | 1 | 3.0 | + + Scenario: View attempts in different states + Given quiz "Quiz 1" has pre-created attempts + And user "student1" has started an attempt at quiz "Quiz 1" + And user "student2" has attempted "Quiz 1" with responses: + | slot | response | + | 2 | True | + | 3 | False | + When I am on the "Quiz 1" "mod_quiz > Grades report" page logged in as "teacher 1" + Then the following should exist in the "attempts" table: + | Email address | Status | Started | Completed | Grade/100.00 | + | student1@example.com | In progress | ## now ##%d %B %Y %I:%M %p## | - | - | + | student2@example.com | Finished | ## now ##%d %B %Y %I:%M %p## | ## now ##%d %B %Y %I:%M %p## | 25.00 | + | student3@example.com | Not started | - | - | - | diff --git a/mod/quiz/report/overview/tests/behat/basic.feature b/mod/quiz/report/overview/tests/behat/basic.feature index 868eb5d4615..c5d5dcac94a 100644 --- a/mod/quiz/report/overview/tests/behat/basic.feature +++ b/mod/quiz/report/overview/tests/behat/basic.feature @@ -77,13 +77,13 @@ Feature: Basic use of the Grades report And I should see "100.00" in the "S2 Student2" "table_row" # Check changing the form parameters - And I set the field "Attempts from" to "enrolled users who have not attempted the quiz" + And I set the field "Attempts from" to "enrolled users who do not have a quiz attempt" And I press "Show report" # Note: teachers should not appear in the report. # Check student3's grade And I should see "-" in the "S3 Student3" "table_row" - And I set the field "Attempts from" to "enrolled users who have, or have not, attempted the quiz" + And I set the field "Attempts from" to "enrolled users who have, or do not have, a quiz attempt" And I press "Show report" # Check student1's grade And I should see "25.00" in the "S1 Student1" "table_row" @@ -92,7 +92,7 @@ Feature: Basic use of the Grades report # Check student3's grade And I should see "-" in the "S3 Student3" "table_row" - And I set the field "Attempts from" to "all users who have attempted the quiz" + And I set the field "Attempts from" to "all users who have a quiz attempt" And I press "Show report" # Check student1's grade And I should see "25.00" in the "S1 Student1" "table_row" diff --git a/mod/quiz/report/responses/tests/behat/basic.feature b/mod/quiz/report/responses/tests/behat/basic.feature index c9524946158..50b822b3430 100644 --- a/mod/quiz/report/responses/tests/behat/basic.feature +++ b/mod/quiz/report/responses/tests/behat/basic.feature @@ -36,7 +36,7 @@ Feature: Basic use of the Responses report When I am on the "Quiz 1" "mod_quiz > Responses report" page logged in as teacher Then I should see "Attempts: 0" And I should see "Nothing to display" - And I set the field "Attempts from" to "enrolled users who have not attempted the quiz" + And I set the field "Attempts from" to "enrolled users who have a quiz attempt" @javascript Scenario: Report works when there are attempts @@ -56,7 +56,7 @@ Feature: Basic use of the Responses report Then I should see "Attempts: 1" And I should see "Student One" And I should not see "Student Two" - And I set the field "Attempts from" to "enrolled users who have, or have not, attempted the quiz" + And I set the field "Attempts from" to "enrolled users who have, or do not have, a quiz attempt" And I set the field "Which tries" to "All tries" And I should see "Response 1a" And I press "Show report" @@ -71,5 +71,5 @@ Feature: Basic use of the Responses report Scenario: Report does not allow strange combinations of options Given I am on the "Quiz 1" "mod_quiz > Responses report" page logged in as teacher And the "Which tries" "select" should be enabled - When I set the field "Attempts from" to "enrolled users who have not attempted the quiz" + When I set the field "Attempts from" to "enrolled users who do not have a quiz attempt" Then the "Which tries" "select" should be disabled