For the overview report : MDL-14199 "Option to only show / export final grade" and MDL-14198 "Make it clear which student attempt gives the final grade, if the scoring method is first, last or highest score"
This commit is contained in:
@@ -5,15 +5,20 @@
|
||||
$string['allattempts'] = 'Show all attempts';
|
||||
$string['allstudents'] = 'Show all $a';
|
||||
$string['attemptsonly'] = 'Show $a with attempts only';
|
||||
$string['attemptsprepage'] = 'Attempts shown per page';
|
||||
$string['noattemptsonly'] = 'Show $a with no attempts only';
|
||||
$string['optallattempts'] = 'all attempts';
|
||||
$string['optallstudents'] = 'all $a';
|
||||
$string['optattemptsonly'] = '$a with attempts only';
|
||||
$string['optnoattemptsonly'] = '$a with no attempts only';
|
||||
$string['optallstudents'] = 'all \'$a\'';
|
||||
$string['optattemptsonly'] = '\'$a\' with attempts only';
|
||||
$string['optnoattemptsonly'] = '\'$a\' with no attempts only';
|
||||
$string['optonlygradedattempts'] = 'only the attempt that is graded for each user';
|
||||
$string['overview'] = 'Overview';
|
||||
$string['overviewdownload'] = 'Overview download';
|
||||
$string['overviewdownload'] = 'Overview download';
|
||||
$string['pagesize'] = 'Page size';
|
||||
$string['preferencespage'] = 'Preferences just for this page';
|
||||
$string['preferencessave'] = 'Save preferences';
|
||||
$string['preferencesuser'] = 'Your preferences for this report';
|
||||
$string['show'] = 'Show';
|
||||
$string['showdetailedmarks'] = 'Show marks for each question';
|
||||
?>
|
||||
|
||||
@@ -8,21 +8,25 @@ class mod_quiz_report_overview_settings extends moodleform {
|
||||
//-------------------------------------------------------------------------------
|
||||
$mform->addElement('header', 'general', get_string('preferencespage', 'quiz_overview'));
|
||||
|
||||
$options = array(0 => get_string('attemptsonly','quiz_overview', $COURSE->students));
|
||||
$options = array();
|
||||
$options[QUIZ_REPORT_ATTEMPTS_ALL] = get_string('optallattempts','quiz_overview');
|
||||
if ($COURSE->id != SITEID) {
|
||||
$options[1] = get_string('noattemptsonly', 'quiz_overview', $COURSE->students);
|
||||
$options[2] = get_string('allstudents','quiz_overview', $COURSE->students);
|
||||
$options[3] = get_string('allattempts','quiz_overview');
|
||||
$options[QUIZ_REPORT_ATTEMPTS_ALL_STUDENTS] = get_string('optallstudents','quiz_overview', $COURSE->students);
|
||||
$options[QUIZ_REPORT_ATTEMPTS_STUDENTS_WITH] =
|
||||
get_string('optattemptsonly','quiz_overview', $COURSE->students);
|
||||
$options[QUIZ_REPORT_ATTEMPTS_STUDENTS_WITH_NO] = get_string('optnoattemptsonly', 'quiz_overview', $COURSE->students);
|
||||
}
|
||||
$mform->addElement('select', 'attemptsmode', get_string('show', 'quiz_overview'), $options);
|
||||
|
||||
if ($this->_customdata['qmsubselect']){
|
||||
$mform->addElement('advcheckbox', 'qmfilter', get_string('show', 'quiz_overview'), get_string('optonlygradedattempts', 'quiz_overview'), array(0,1));
|
||||
}
|
||||
//-------------------------------------------------------------------------------
|
||||
$mform->addElement('header', 'general', get_string('preferencesuser', 'quiz_overview'));
|
||||
|
||||
$mform->addElement('text', 'pagesize', get_string('pagesize', 'quiz'));
|
||||
$mform->addElement('text', 'pagesize', get_string('pagesize', 'quiz_overview'));
|
||||
$mform->setType('pagesize', PARAM_INT);
|
||||
|
||||
$mform->addElement('selectyesno', 'detailedmarks', get_string('showdetailedmarks', 'quiz'));
|
||||
$mform->addElement('selectyesno', 'detailedmarks', get_string('showdetailedmarks', 'quiz_overview'));
|
||||
|
||||
$this->add_action_buttons(false, get_string('preferencessave', 'quiz_overview'));
|
||||
}
|
||||
|
||||
+138
-124
@@ -74,15 +74,25 @@ class quiz_report extends quiz_default_report {
|
||||
$pageoptions['mode'] = 'overview';
|
||||
|
||||
$reporturl = new moodle_url($CFG->wwwroot.'/mod/quiz/report.php', $pageoptions);
|
||||
$mform = new mod_quiz_report_overview_settings($reporturl);
|
||||
$qmsubselect = quiz_report_qm_filter_subselect($quiz->grademethod);
|
||||
$mform = new mod_quiz_report_overview_settings($reporturl, compact('qmsubselect'));
|
||||
if ($fromform = $mform->get_data()){
|
||||
$attemptsmode = $fromform->attemptsmode;
|
||||
if ($qmsubselect){
|
||||
//control is not on the form if
|
||||
//the grading method is not set
|
||||
//to grade one attempt per user eg. for average attempt grade.
|
||||
$qmfilter = $fromform->qmfilter;
|
||||
} else {
|
||||
$qmfilter = 0;
|
||||
}
|
||||
set_user_preference('quiz_report_overview_detailedmarks', $fromform->detailedmarks);
|
||||
set_user_preference('quiz_report_pagesize', $fromform->pagesize);
|
||||
$detailedmarks = $fromform->detailedmarks;
|
||||
$pagesize = $fromform->pagesize;
|
||||
} else {
|
||||
$attemptsmode = optional_param('attemptsmode', 0, PARAM_INT);
|
||||
$qmfilter = optional_param('qmfilter', 0, PARAM_INT);
|
||||
$attemptsmode = optional_param('attemptsmode', QUIZ_REPORT_ATTEMPTS_STUDENTS_WITH, PARAM_INT);
|
||||
$detailedmarks = get_user_preferences('quiz_report_overview_detailedmarks', 1);
|
||||
$pagesize = get_user_preferences('quiz_report_pagesize', 0);
|
||||
}
|
||||
@@ -92,6 +102,7 @@ class quiz_report extends quiz_default_report {
|
||||
|
||||
$displayoptions = array();
|
||||
$displayoptions['attemptsmode'] = $attemptsmode;
|
||||
$displayoptions['qmfilter'] = $qmfilter;
|
||||
$reporturlwithdisplayoptions = new moodle_url($CFG->wwwroot.'/mod/quiz/report.php', $pageoptions + $displayoptions);
|
||||
|
||||
/// find out current groups mode
|
||||
@@ -302,7 +313,7 @@ class quiz_report extends quiz_default_report {
|
||||
|
||||
// Get users with quiz attempt capability 'students'.
|
||||
// don't need to do this expensive call if we are listing all attempts though.
|
||||
if ( $attemptsmode != 3 ) {
|
||||
if ( $attemptsmode != QUIZ_REPORT_ATTEMPTS_ALL ) {
|
||||
if (empty($currentgroup)) {
|
||||
// all users who can attempt quizzes
|
||||
$allowed = join(',',array_keys(get_users_by_capability($context, 'mod/quiz:attempt','','','','','','',false)));
|
||||
@@ -315,27 +326,33 @@ class quiz_report extends quiz_default_report {
|
||||
|
||||
// Construct the SQL
|
||||
$select = 'SELECT '.sql_concat('u.id', '\'#\'', $db->IfNull('qa.attempt', '0')).' AS uniqueid, '.
|
||||
($qmsubselect?$qmsubselect.' AS gradedattempt, ':'').
|
||||
'qa.uniqueid AS attemptuniqueid, qa.id AS attempt, u.id AS userid, u.firstname, u.lastname, u.picture, '.
|
||||
'qa.sumgrades, qa.timefinish, qa.timestart, qa.timefinish - qa.timestart AS duration ';
|
||||
|
||||
// This part is the same for all cases - join users and quiz_attempts tables
|
||||
$from = 'FROM '.$CFG->prefix.'user u ';
|
||||
$from .= 'LEFT JOIN '.$CFG->prefix.'quiz_attempts qa ON qa.userid = u.id AND qa.quiz = '.$quiz->id;
|
||||
|
||||
if ( $attemptsmode == 3 ) { // Show all attempts, including students who are no longer in the course
|
||||
|
||||
$where = ' WHERE qa.id IS NOT NULL';
|
||||
// Comment out the following line to include preview attempts in the 'show all attempts' filter
|
||||
$where .= ' AND qa.preview = 0';
|
||||
} else { // All non-admin users with quiz attempt capabilites - e.g. students
|
||||
|
||||
$where = ' WHERE u.id IN (' .$allowed. ') AND (qa.preview = 0 OR qa.preview IS NULL)';
|
||||
|
||||
if ( empty( $attemptsmode )) { // Show only students with attempts
|
||||
$where .= ' AND qa.id IS NOT NULL';
|
||||
} else if ( $attemptsmode == 1 ) { // Show only students without attempts
|
||||
$where .= ' AND qa.id IS NULL';
|
||||
}
|
||||
if ($qmsubselect && $qmfilter){
|
||||
$from .= ' AND '.$qmsubselect;
|
||||
}
|
||||
switch ($attemptsmode){
|
||||
case QUIZ_REPORT_ATTEMPTS_ALL:
|
||||
// Show all attempts, including students who are no longer in the course
|
||||
$where = ' WHERE qa.id IS NOT NULL AND qa.preview = 0';
|
||||
break;
|
||||
case QUIZ_REPORT_ATTEMPTS_STUDENTS_WITH:
|
||||
// Show only students with attempts
|
||||
$where = ' WHERE u.id IN (' .$allowed. ') AND qa.preview = 0 AND qa.id IS NOT NULL';
|
||||
break;
|
||||
case QUIZ_REPORT_ATTEMPTS_STUDENTS_WITH_NO:
|
||||
// Show only students without attempts
|
||||
$where = ' WHERE u.id IN (' .$allowed. ') AND qa.id IS NULL';
|
||||
break;
|
||||
case QUIZ_REPORT_ATTEMPTS_ALL_STUDENTS:
|
||||
// Show all students with or without attempts
|
||||
$where = ' WHERE u.id IN (' .$allowed. ') AND (qa.preview = 0 OR qa.preview IS NULL)';
|
||||
break;
|
||||
}
|
||||
|
||||
$countsql = 'SELECT COUNT(DISTINCT('.sql_concat('u.id', '\'#\'', $db->IfNull('qa.attempt', '0')).')) '.$from.$where;
|
||||
@@ -414,126 +431,123 @@ class quiz_report extends quiz_default_report {
|
||||
$table->initialbars($totalinitials>20);
|
||||
}
|
||||
|
||||
if(!empty($attempts) || !empty($attemptsmode)) {
|
||||
if ($attempts) {
|
||||
if($detailedmarks) {
|
||||
//get all the attempt ids we want to display on this page
|
||||
//or to export for download.
|
||||
$attemptids = array();
|
||||
foreach ($attempts as $attempt){
|
||||
if ($attempt->attemptuniqueid > 0){
|
||||
$attemptids[] = $attempt->attemptuniqueid;
|
||||
}
|
||||
}
|
||||
$gradedstatesbyattempt = quiz_get_newgraded_states($attemptids);
|
||||
if ($attempts) {
|
||||
if($detailedmarks) {
|
||||
//get all the attempt ids we want to display on this page
|
||||
//or to export for download.
|
||||
$attemptids = array();
|
||||
foreach ($attempts as $attempt){
|
||||
if ($attempt->attemptuniqueid > 0){
|
||||
$attemptids[] = $attempt->attemptuniqueid;
|
||||
}
|
||||
}
|
||||
foreach ($attempts as $attempt) {
|
||||
$picture = print_user_picture($attempt->userid, $course->id, $attempt->picture, false, true);
|
||||
$gradedstatesbyattempt = quiz_get_newgraded_states($attemptids);
|
||||
}
|
||||
foreach ($attempts as $attempt) {
|
||||
$picture = print_user_picture($attempt->userid, $course->id, $attempt->picture, false, true);
|
||||
|
||||
$userlink = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$attempt->userid.
|
||||
'&course='.$course->id.'">'.fullname($attempt).'</a>';
|
||||
$userlink = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$attempt->userid.
|
||||
'&course='.$course->id.'">'.fullname($attempt).'</a>';
|
||||
// Username columns.
|
||||
$row = array();
|
||||
if (!$download) {
|
||||
if (!empty($attemptactions)) {
|
||||
$row[] = '<input type="checkbox" name="attemptid[]" value="'.$attempt->attempt.'" />';
|
||||
}
|
||||
$row[] = $picture;
|
||||
$row[] = $userlink;
|
||||
} else {
|
||||
$row[] = fullname($attempt);
|
||||
}
|
||||
|
||||
// Username columns.
|
||||
$row = array();
|
||||
// Timing columns.
|
||||
if ($attempt->attempt) {
|
||||
$startdate = userdate($attempt->timestart, $strtimeformat);
|
||||
if (!$download) {
|
||||
if (!empty($attemptactions)) {
|
||||
$row[] = '<input type="checkbox" name="attemptid[]" value="'.$attempt->attempt.'" />';
|
||||
}
|
||||
$row[] = $picture;
|
||||
$row[] = $userlink;
|
||||
$row[] = '<a href="review.php?q='.$quiz->id.'&attempt='.$attempt->attempt.'">'.$startdate.'</a>';
|
||||
} else {
|
||||
$row[] = fullname($attempt);
|
||||
$row[] = $startdate;
|
||||
}
|
||||
|
||||
// Timing columns.
|
||||
if ($attempt->attempt) {
|
||||
$startdate = userdate($attempt->timestart, $strtimeformat);
|
||||
if ($attempt->timefinish) {
|
||||
$timefinish = userdate($attempt->timefinish, $strtimeformat);
|
||||
$duration = format_time($attempt->duration);
|
||||
if (!$download) {
|
||||
$row[] = '<a href="review.php?q='.$quiz->id.'&attempt='.$attempt->attempt.'">'.$startdate.'</a>';
|
||||
$row[] = '<a href="review.php?q='.$quiz->id.'&attempt='.$attempt->attempt.'">'.$timefinish.'</a>';
|
||||
} else {
|
||||
$row[] = $startdate;
|
||||
$row[] = $timefinish;
|
||||
}
|
||||
if ($attempt->timefinish) {
|
||||
$timefinish = userdate($attempt->timefinish, $strtimeformat);
|
||||
$duration = format_time($attempt->duration);
|
||||
if (!$download) {
|
||||
$row[] = '<a href="review.php?q='.$quiz->id.'&attempt='.$attempt->attempt.'">'.$timefinish.'</a>';
|
||||
} else {
|
||||
$row[] = $timefinish;
|
||||
}
|
||||
$row[] = $duration;
|
||||
$row[] = $duration;
|
||||
} else {
|
||||
$row[] = '-';
|
||||
$row[] = get_string('unfinished', 'quiz');
|
||||
}
|
||||
} else {
|
||||
$row[] = '-';
|
||||
$row[] = '-';
|
||||
$row[] = '-';
|
||||
}
|
||||
|
||||
// Grades columns.
|
||||
if ($showgrades) {
|
||||
if ($attempt->timefinish) {
|
||||
$grade = quiz_rescale_grade($attempt->sumgrades, $quiz);
|
||||
if (!$download) {
|
||||
$row[] = '<a href="review.php?q='.$quiz->id.'&attempt='.$attempt->attempt.'">'.$grade.'</a>';
|
||||
} else {
|
||||
$row[] = '-';
|
||||
$row[] = get_string('unfinished', 'quiz');
|
||||
$row[] = $grade;
|
||||
}
|
||||
} else {
|
||||
$row[] = '-';
|
||||
$row[] = '-';
|
||||
$row[] = '-';
|
||||
}
|
||||
}
|
||||
|
||||
// Grades columns.
|
||||
if ($showgrades) {
|
||||
if ($attempt->timefinish) {
|
||||
$grade = quiz_rescale_grade($attempt->sumgrades, $quiz);
|
||||
if($detailedmarks) {
|
||||
//get the detailled grade data for this attempt
|
||||
if(empty($attempt->attempt)) {
|
||||
foreach($questions as $question) {
|
||||
$row[] = '-';
|
||||
}
|
||||
} else {
|
||||
foreach($questions as $questionid => $question) {
|
||||
$stateforqinattempt = $gradedstatesbyattempt[$attempt->attemptuniqueid][$questionid];
|
||||
if (question_state_is_graded($stateforqinattempt)) {
|
||||
$grade = quiz_rescale_grade($stateforqinattempt->grade, $quiz);
|
||||
$grade = $grade;
|
||||
} else {
|
||||
$grade = '--';
|
||||
}
|
||||
if (!$download) {
|
||||
$row[] = '<a href="review.php?q='.$quiz->id.'&attempt='.$attempt->attempt.'">'.$grade.'</a>';
|
||||
$grade = $grade.'/'.quiz_rescale_grade($question->grade, $quiz);
|
||||
$row[] = link_to_popup_window('/mod/quiz/reviewquestion.php?state='.
|
||||
$stateforqinattempt->id.'&number='.$question->number,
|
||||
'reviewquestion', $grade, 450, 650, $strreviewquestion, 'none', true);
|
||||
} else {
|
||||
$row[] = $grade;
|
||||
}
|
||||
} else {
|
||||
$row[] = '-';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($detailedmarks) {
|
||||
//get the detailled grade data for this attempt
|
||||
if(empty($attempt->attempt)) {
|
||||
foreach($questions as $question) {
|
||||
$row[] = '-';
|
||||
}
|
||||
} else {
|
||||
foreach($questions as $questionid => $question) {
|
||||
$stateforqinattempt = $gradedstatesbyattempt[$attempt->attemptuniqueid][$questionid];
|
||||
if (question_state_is_graded($stateforqinattempt)) {
|
||||
$grade = quiz_rescale_grade($stateforqinattempt->grade, $quiz);
|
||||
$grade = $grade;
|
||||
} else {
|
||||
$grade = '--';
|
||||
}
|
||||
if (!$download) {
|
||||
$grade = $grade.'/'.quiz_rescale_grade($question->grade, $quiz);
|
||||
$row[] = link_to_popup_window('/mod/quiz/reviewquestion.php?state='.
|
||||
$stateforqinattempt->id.'&number='.$question->number,
|
||||
'reviewquestion', $grade, 450, 650, $strreviewquestion, 'none', true);
|
||||
} else {
|
||||
$row[] = $grade;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Feedback column.
|
||||
if ($hasfeedback) {
|
||||
if ($attempt->timefinish) {
|
||||
$row[] = format_text($attempt->feedbacktext, FORMAT_MOODLE, $nocleanformatoptions);
|
||||
} else {
|
||||
$row[] = '-';
|
||||
}
|
||||
|
||||
// Feedback column.
|
||||
if ($hasfeedback) {
|
||||
if ($attempt->timefinish) {
|
||||
$row[] = format_text($attempt->feedbacktext, FORMAT_MOODLE, $nocleanformatoptions);
|
||||
} else {
|
||||
$row[] = '-';
|
||||
}
|
||||
}
|
||||
if (!$download) {
|
||||
$table->add_data($row);
|
||||
} else if ($download == 'Excel' or $download == 'ODS') {
|
||||
$colnum = 0;
|
||||
foreach($row as $item){
|
||||
$myxls->write($rownum,$colnum,$item,$format);
|
||||
$colnum++;
|
||||
}
|
||||
$rownum++;
|
||||
} else if ($download=='CSV') {
|
||||
$text = implode("\t", $row);
|
||||
echo $text." \n";
|
||||
}
|
||||
if (!$download) {
|
||||
$table->add_data($row);
|
||||
} else if ($download == 'Excel' or $download == 'ODS') {
|
||||
$colnum = 0;
|
||||
foreach($row as $item){
|
||||
$myxls->write($rownum,$colnum,$item,$format);
|
||||
$colnum++;
|
||||
}
|
||||
$rownum++;
|
||||
} else if ($download=='CSV') {
|
||||
$text = implode("\t", $row);
|
||||
echo $text." \n";
|
||||
}
|
||||
}
|
||||
if (!$download) {
|
||||
@@ -545,10 +559,10 @@ class quiz_report extends quiz_default_report {
|
||||
$strreallydel.'\') : true);">';
|
||||
echo $reporturlwithdisplayoptions->hidden_params_out();
|
||||
echo '<div>';
|
||||
|
||||
|
||||
// Print table
|
||||
$table->print_html();
|
||||
|
||||
|
||||
// Print "Select all" etc.
|
||||
if (!empty($attempts) && !empty($attemptactions)) {
|
||||
echo '<table id="commands">';
|
||||
@@ -572,7 +586,7 @@ document.getElementById("noscriptmenuaction").style.display = "none";
|
||||
// Close form
|
||||
echo '</div>';
|
||||
echo '</form></div>';
|
||||
|
||||
|
||||
if (!empty($attempts)) {
|
||||
echo '<table class="boxaligncenter"><tr>';
|
||||
echo '<td>';
|
||||
@@ -592,18 +606,18 @@ document.getElementById("noscriptmenuaction").style.display = "none";
|
||||
echo "</td>\n";
|
||||
echo '</tr></table>';
|
||||
}
|
||||
} else if ($download == 'Excel' or $download == 'ODS') {
|
||||
$workbook->close();
|
||||
exit;
|
||||
} else if ($download == 'CSV') {
|
||||
exit;
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
if (!$download) {
|
||||
$table->print_html();
|
||||
}
|
||||
}
|
||||
if ($download == 'Excel' or $download == 'ODS') {
|
||||
$workbook->close();
|
||||
exit;
|
||||
} else if ($download == 'CSV') {
|
||||
exit;
|
||||
}
|
||||
if (!$download) {
|
||||
// Print display options
|
||||
$mform->set_data($displayoptions +compact('detailedmarks', 'pagesize'));
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<?php
|
||||
define('QUIZ_REPORT_DEFAULT_PAGE_SIZE', 30);
|
||||
|
||||
define('QUIZ_REPORT_ATTEMPTS_ALL', 0);
|
||||
define('QUIZ_REPORT_ATTEMPTS_STUDENTS_WITH_NO', 1);
|
||||
define('QUIZ_REPORT_ATTEMPTS_STUDENTS_WITH', 2);
|
||||
define('QUIZ_REPORT_ATTEMPTS_ALL_STUDENTS', 3);
|
||||
/**
|
||||
* Get newest graded state or newest state for a number of attempts. Pass in the
|
||||
* uniqueid field from quiz_attempt table not the id. Use question_state_is_graded
|
||||
@@ -68,4 +73,33 @@ function quiz_report_load_questions($quiz){
|
||||
}
|
||||
return $realquestions;
|
||||
}
|
||||
/**
|
||||
* Given the quiz grading method return sub select sql to find the id of the
|
||||
* one attempt that will be graded for each user. Or return
|
||||
* empty string if all attempts contribute to final grade.
|
||||
*/
|
||||
function quiz_report_qm_filter_subselect($quizgrademethod){
|
||||
global $CFG;
|
||||
$qmfilterattempts = true;
|
||||
switch ($quizgrademethod) {
|
||||
case QUIZ_GRADEHIGHEST :
|
||||
$qmorderby = 'sumgrades DESC, timestart ASC';
|
||||
break;
|
||||
case QUIZ_GRADEAVERAGE :
|
||||
$qmfilterattempts = false;
|
||||
break;
|
||||
case QUIZ_ATTEMPTFIRST :
|
||||
$qmorderby = 'timestart ASC';
|
||||
break;
|
||||
case QUIZ_ATTEMPTLAST :
|
||||
$qmorderby = 'timestart DESC';
|
||||
break;
|
||||
}
|
||||
if ($qmfilterattempts){
|
||||
$qmsubselect = "(SELECT id FROM {$CFG->prefix}quiz_attempts WHERE u.id = userid ORDER BY $qmorderby LIMIT 1)=qa.id";
|
||||
} else {
|
||||
$qmsubselect = '';
|
||||
}
|
||||
return $qmsubselect;
|
||||
}
|
||||
?>
|
||||
|
||||
Reference in New Issue
Block a user