]> git.mjollnir.org Git - moodle.git/commitdiff
MDL-15631 "move detailled responses report out of contrib into main distribution...
authorjamiesensei <jamiesensei>
Sun, 20 Jul 2008 14:29:10 +0000 (14:29 +0000)
committerjamiesensei <jamiesensei>
Sun, 20 Jul 2008 14:29:10 +0000 (14:29 +0000)
lang/en_utf8/quiz_responses.php
mod/quiz/report/responses/report.php [new file with mode: 0644]
mod/quiz/report/responses/responses_table.php [new file with mode: 0644]
mod/quiz/report/responses/responsessettings_form.php [new file with mode: 0644]
mod/quiz/report/responses/styles.css [new file with mode: 0644]

index bf2c049677b9242f5b5247e4288250842407c3c6..ca90ac34ed0c234c48830be2801bd57a9a8b1a9a 100644 (file)
@@ -1,11 +1,9 @@
-<?PHP // $Id$ 
-      // quiz_responses.php - created with Moodle 1.7 beta + (2006101003)
-
-
-$string['pagesize'] = 'Attempts per page:';
-$string['reportresponses'] = 'Responses';
-$string['responses'] = 'Responses';
+<?php
+// $Id$
 $string['responsesoptions'] = 'Responses options';
 $string['responsestitle'] = 'Detailed responses';
-
-?>
+$string['pagesize'] = 'Page Size';
+$string['reportresponses'] = 'Responses';
+$string['responses'] = 'Responses';
+$string['responsesdownload'] = 'Responses download';
+?>
\ No newline at end of file
diff --git a/mod/quiz/report/responses/report.php b/mod/quiz/report/responses/report.php
new file mode 100644 (file)
index 0000000..4ca2b9b
--- /dev/null
@@ -0,0 +1,326 @@
+<?php
+/**
+ * This script lists student attempts and responses
+ *
+ * @version $Id$
+
+ * @author Jean-Michel V�drine, Gustav Delius and others.
+ * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
+ * @package quiz
+ *//** */
+
+require_once($CFG->libdir.'/tablelib.php');
+require_once($CFG->dirroot.'/mod/quiz/report/responses/responsessettings_form.php');
+require_once($CFG->dirroot.'/mod/quiz/report/responses/responses_table.php');
+
+class quiz_responses_report extends quiz_default_report {
+
+    /**
+     * Display the report.
+     */
+    function display($quiz, $cm, $course) {
+        global $CFG, $COURSE, $DB;
+
+        $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+
+        // Work out some display options - whether there is feedback, and whether scores should be shown.
+        $hasfeedback = quiz_has_feedback($quiz->id) && $quiz->grade > 1.e-7 && $quiz->sumgrades > 1.e-7;
+        $fakeattempt = new stdClass();
+        $fakeattempt->preview = false;
+        $fakeattempt->timefinish = $quiz->timeopen;
+        $reviewoptions = quiz_get_reviewoptions($quiz, $fakeattempt, $context);
+        $showgrades = $quiz->grade && $quiz->sumgrades && $reviewoptions->scores;
+
+        $download = optional_param('download', '', PARAM_ALPHA);
+
+        if($attemptids = optional_param('attemptid', array(), PARAM_INT)) {
+            //attempts need to be deleted
+            require_capability('mod/quiz:deleteattempts', $context);
+            $attemptids = optional_param('attemptid', array(), PARAM_INT);
+            foreach($attemptids as $attemptid) {
+                add_to_log($course->id, 'quiz', 'delete attempt', 'report.php?id=' . $cm->id,
+                        $attemptid, $cm->id);
+                quiz_delete_attempt($attemptid, $quiz);
+            }
+            //No need for a redirect, any attemptids that do not exist are ignored.
+            //So no problem if the user refreshes and tries to delete the same attempts
+            //twice.
+        }
+
+
+        $pageoptions = array();
+        $pageoptions['id'] = $cm->id;
+        $pageoptions['q'] = $quiz->id;
+        $pageoptions['mode'] = 'responses';
+
+        $reporturl = new moodle_url($CFG->wwwroot.'/mod/quiz/report.php', $pageoptions);
+        $qmsubselect = quiz_report_qm_filter_select($quiz);
+
+        
+
+        /// find out current groups mode
+        $currentgroup = groups_get_activity_group($cm, true);
+
+        $mform = new mod_quiz_report_responses_settings($reporturl, array('qmsubselect'=> $qmsubselect, 'quiz'=>$quiz, 'currentgroup'=>$currentgroup));
+        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_pagesize', $fromform->pagesize);
+            $pagesize = $fromform->pagesize;
+        } else {
+            $qmfilter = optional_param('qmfilter', 0, PARAM_INT);
+            $attemptsmode = optional_param('attemptsmode', null, PARAM_INT);
+            if ($attemptsmode === null){
+                //default
+                $attemptsmode = QUIZ_REPORT_ATTEMPTS_ALL;
+            } else if ($currentgroup){
+                //default for when a group is selected
+                if ($attemptsmode === null  || $attemptsmode == QUIZ_REPORT_ATTEMPTS_ALL){
+                    $attemptsmode = QUIZ_REPORT_ATTEMPTS_STUDENTS_WITH;
+                }
+            } else if (!$currentgroup && $course->id == SITEID) {
+                //force report on front page to show all, unless a group is selected.
+                $attemptsmode = QUIZ_REPORT_ATTEMPTS_ALL;
+            }
+            $pagesize = get_user_preferences('quiz_report_pagesize', 0);
+        }
+        if ($pagesize < 1) {
+            $pagesize = QUIZ_REPORT_DEFAULT_PAGE_SIZE;
+        }
+        // We only want to show the checkbox to delete attempts
+        // if the user has permissions and if the report mode is showing attempts.
+        $candelete = has_capability('mod/quiz:deleteattempts', $context)
+                && ($attemptsmode!= QUIZ_REPORT_ATTEMPTS_STUDENTS_WITH_NO);
+
+
+        $displayoptions = array();
+        $displayoptions['attemptsmode'] = $attemptsmode;
+        $displayoptions['qmfilter'] = $qmfilter;
+
+        //work out the sql for this table.
+        if (!$students = get_users_by_capability($context, 'mod/quiz:attempt','','','','','','',false)){
+            $students = array();
+        } else {
+            $students = array_keys($students);
+        }
+
+        if (empty($currentgroup)) {
+            // all users who can attempt quizzes
+            $allowed = $students;
+            $groupstudents = array();
+        } else {
+            // all users who can attempt quizzes and who are in the currently selected group
+            if (!$groupstudents = get_users_by_capability($context, 'mod/quiz:attempt','','','','',$currentgroup,'',false)){
+                $groupstudents = array();
+            } else {
+                $groupstudents = array_keys($groupstudents);
+            }
+            $allowed = $groupstudents;
+        }
+
+        $questions = quiz_report_load_questions($quiz);
+
+        $table = new quiz_report_responses_table($quiz , $qmsubselect, $groupstudents,
+                $students, $questions, $candelete, $reporturl, $displayoptions);
+        $table->is_downloading($download, get_string('reportresponses','quiz_responses'),
+                    "$COURSE->shortname ".format_string($quiz->name,true));
+        if (!$table->is_downloading()) {
+            // Only print headers if not asked to download data
+            $meta = '<link rel="stylesheet" type="text/css" href="'.$CFG->wwwroot.'/mod/quiz/report/responses/styles.css" />'."\n";
+            $this->print_header_and_tabs($cm, $course, $quiz, "responses", $meta);
+        }
+
+        if ($groupmode = groups_get_activity_groupmode($cm)) {   // Groups are being used
+            if (!$table->is_downloading()) {
+                groups_print_activity_menu($cm, $reporturl->out(false, $displayoptions));
+            }
+        }
+        // Print information on the number of existing attempts
+        if (!$table->is_downloading()) { //do not print notices when downloading
+            if ($strattemptnum = quiz_num_attempt_summary($quiz, $cm, true, $currentgroup)) {
+                echo '<div class="quizattemptcounts">' . $strattemptnum . '</div>';
+            }
+        }
+        $nostudents = false;
+        if (!$students){
+            notify(get_string('nostudentsyet'));
+            $nostudents = true;
+        }else if ($currentgroup && !$groupstudents){
+            notify(get_string('nostudentsingroup'));
+            $nostudents = true;
+        }
+        if (!$table->is_downloading()) {
+            // Print display options
+            $mform->set_data($displayoptions +compact('pagesize'));
+            $mform->display();
+        }
+
+        if (!$nostudents || ($attemptsmode == QUIZ_REPORT_ATTEMPTS_ALL)){
+            // Print information on the grading method and whether we are displaying
+            //
+            if (!$table->is_downloading()) { //do not print notices when downloading
+                if ($strattempthighlight = quiz_report_highlighting_grading_method($quiz, $qmsubselect, $qmfilter)) {
+                    echo '<div class="quizattemptcounts">' . $strattempthighlight . '</div>';
+                }
+            }
+    
+    
+            $showgrades = $quiz->grade && $quiz->sumgrades && $reviewoptions->scores;
+            $hasfeedback = quiz_has_feedback($quiz->id) && $quiz->grade > 1.e-7 && $quiz->sumgrades > 1.e-7;
+    
+    
+            // Construct the SQL
+            $fields = $DB->sql_concat('u.id', '\'#\'', 'COALESCE(qa.attempt, \'0\')').' AS uniqueid, '.
+                ($qmsubselect?"($qmsubselect) AS gradedattempt, ":'').
+                'qa.uniqueid AS attemptuniqueid, qa.id AS attempt, u.id AS userid, u.idnumber, u.firstname,'.
+                ' u.lastname, u.institution, u.department, u.email, 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 = '{user} u ';
+            $from .= 'LEFT JOIN {quiz_attempts} qa ON qa.userid = u.id AND qa.quiz = :quizid';
+            $params = array('quizid' => $quiz->id);
+    
+            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 = 'qa.id IS NOT NULL AND qa.preview = 0';
+                     break;
+                 case QUIZ_REPORT_ATTEMPTS_STUDENTS_WITH:
+                     // Show only students with attempts
+                     list($allowed_usql, $allowed_params) = $DB->get_in_or_equal($allowed, SQL_PARAMS_NAMED, 'u0000');
+                     $params += $allowed_params;
+                    $where = "u.id $allowed_usql AND qa.preview = 0 AND qa.id IS NOT NULL";
+                     break;
+                 case QUIZ_REPORT_ATTEMPTS_STUDENTS_WITH_NO:
+                     // Show only students without attempts
+                     list($allowed_usql, $allowed_params) = $DB->get_in_or_equal($allowed, SQL_PARAMS_NAMED, 'u0000');
+                     $params += $allowed_params;
+                    $where = "u.id $allowed_usql AND qa.id IS NULL";
+                     break;
+                 case QUIZ_REPORT_ATTEMPTS_ALL_STUDENTS:
+                     // Show all students with or without attempts
+                     list($allowed_usql, $allowed_params) = $DB->get_in_or_equal($allowed, SQL_PARAMS_NAMED, 'u0000');
+                     $params += $allowed_params;
+                    $where = "u.id $allowed_usql AND (qa.preview = 0 OR qa.preview IS NULL)";
+                     break;
+             }
+    
+            $table->set_count_sql("SELECT COUNT(1) FROM $from WHERE $where", $params);
+    
+    
+            
+            $table->set_sql($fields, $from, $where, $params);
+            
+            // Define table columns
+            $columns = array();
+            $headers = array();
+    
+    
+            if (!$table->is_downloading() && $candelete) {
+                $columns[]= 'checkbox';
+                $headers[]= NULL;
+            }
+    
+            if (!$table->is_downloading() && $CFG->grade_report_showuserimage) {
+                $columns[]= 'picture';
+                $headers[]= '';
+            }
+            if (!$table->is_downloading()){
+                $columns[]= 'fullname';
+                $headers[]= get_string('name');
+            } else {
+                $columns[]= 'lastname';
+                $headers[]= get_string('lastname');
+                $columns[]= 'firstname';
+                $headers[]= get_string('firstname');
+            }
+    
+            if ($CFG->grade_report_showuseridnumber) {
+                $columns[]= 'idnumber';
+                $headers[]= get_string('idnumber');
+            }
+            if ($table->is_downloading()){
+                $columns[]= 'institution';
+                $headers[]= get_string('institution');
+
+                $columns[]= 'department';
+                $headers[]= get_string('department');
+
+                $columns[]= 'email';
+                $headers[]= get_string('email');
+
+                $columns[]= 'timestart';
+                $headers[]= get_string('startedon', 'quiz');
+    
+                $columns[]= 'timefinish';
+                $headers[]= get_string('timecompleted','quiz');
+    
+                $columns[]= 'duration';
+                $headers[]= get_string('attemptduration', 'quiz');
+            }
+            
+        if ($showgrades) {
+            $columns[] = 'sumgrades';
+            $headers[] = get_string('grade', 'quiz').'/'.$quiz->grade;
+        }
+    
+        // we want to display responses for all questions
+        foreach ($questions as $id => $question) {
+            // Ignore questions of zero length
+            $columns[] = 'qsanswer'.$id;
+            $headers[] = '#'.$question->number;
+        }
+
+        if ($hasfeedback) {
+            $columns[] = 'feedbacktext';
+            $headers[] = get_string('feedback', 'quiz');
+        }
+
+        // Load the question type specific information
+        if (!get_question_options($questions)) {
+            print_error('Could not load question options');
+        }
+
+        $table->define_columns($columns);
+        $table->define_headers($headers);
+        $table->sortable(true, 'uniqueid');
+    
+        // Set up the table
+        $table->define_baseurl($reporturl->out(false, $displayoptions));
+    
+        $table->collapsible(true);
+    
+        $table->column_suppress('picture');
+        $table->column_suppress('fullname');
+        $table->column_suppress('idnumber');
+    
+        $table->no_sorting('feedbacktext');
+    
+        $table->column_class('picture', 'picture');
+        $table->column_class('lastname', 'bold');
+        $table->column_class('firstname', 'bold');
+        $table->column_class('fullname', 'bold');
+        $table->column_class('sumgrades', 'bold');
+    
+        $table->set_attribute('id', 'attempts');
+    
+        $table->out($pagesize, true);
+    }
+        return true;
+    }
+
+}
+
+
+?>
\ No newline at end of file
diff --git a/mod/quiz/report/responses/responses_table.php b/mod/quiz/report/responses/responses_table.php
new file mode 100644 (file)
index 0000000..4a13c86
--- /dev/null
@@ -0,0 +1,225 @@
+<?php  // $Id$
+
+class quiz_report_responses_table extends table_sql {
+
+    var $useridfield = 'userid';
+
+    var $reporturl;
+    var $displayoptions;
+
+    function quiz_report_responses_table($quiz , $qmsubselect, $groupstudents,
+                $students, $questions, $candelete, $reporturl, $displayoptions){
+        parent::table_sql('mod-quiz-report-responses-report');
+        $this->quiz = $quiz;
+        $this->qmsubselect = $qmsubselect;
+        $this->groupstudents = $groupstudents;
+        $this->students = $students;
+        $this->questions = $questions;
+        $this->candelete = $candelete;
+        $this->reporturl = $reporturl;
+        $this->displayoptions = $displayoptions;
+    }
+    function build_table(){
+        global $CFG, $DB;
+        if ($this->rawdata) {
+            // Define some things we need later to process raw data from db.
+            $this->strtimeformat = get_string('strftimedatetime');
+            parent::build_table();
+            //end of adding data from attempts data to table / download
+            //now add averages at bottom of table :
+            $params = array($this->quiz->id);
+
+            $this->add_separator();
+            if ($this->is_downloading()){
+                $namekey = 'lastname';
+            } else {
+                $namekey = 'fullname';
+            }
+        }
+    }
+
+    function wrap_html_start(){
+        if (!$this->is_downloading()) {
+            if ($this->candelete) {
+                // Start form
+                $strreallydel  = addslashes_js(get_string('deleteattemptcheck','quiz'));
+                echo '<div id="tablecontainer">';
+                echo '<form id="attemptsform" method="post" action="' . $this->reporturl->out(true) .
+                        '" onsubmit="confirm(\''.$strreallydel.'\');">';
+                echo '<div style="display: none;">';
+                echo $this->reporturl->hidden_params_out(array(), 0, $this->displayoptions);
+                echo '</div>';
+                echo '<div>';
+            }
+        }
+    }
+    function wrap_html_finish(){
+        if (!$this->is_downloading()) {
+            // Print "Select all" etc.
+            if ($this->candelete) {
+                echo '<table id="commands">';
+                echo '<tr><td>';
+                echo '<a href="javascript:select_all_in(\'DIV\',null,\'tablecontainer\');">'.
+                        get_string('selectall', 'quiz').'</a> / ';
+                echo '<a href="javascript:deselect_all_in(\'DIV\',null,\'tablecontainer\');">'.
+                        get_string('selectnone', 'quiz').'</a> ';
+                echo '&nbsp;&nbsp;';
+                echo '<input type="submit" value="'.get_string('deleteselected', 'quiz_responses').'"/>';
+                echo '</td></tr></table>';
+                // Close form
+                echo '</div>';
+                echo '</form></div>';
+            }
+        }
+    }
+
+
+    function col_checkbox($attempt){
+        if ($attempt->attempt){
+            return '<input type="checkbox" name="attemptid[]" value="'.$attempt->attempt.'" />';
+        } else {
+            return '';
+        }
+    }
+
+    function col_picture($attempt){
+        global $COURSE;
+        return print_user_picture($attempt->userid, $COURSE->id, $attempt->picture, false, true);
+    }
+
+
+    function col_timestart($attempt){
+        if ($attempt->attempt) {
+            $startdate = userdate($attempt->timestart, $this->strtimeformat);
+            if (!$this->is_downloading()) {
+                return  '<a href="review.php?q='.$this->quiz->id.'&amp;attempt='.$attempt->attempt.'">'.$startdate.'</a>';
+            } else {
+                return  $startdate;
+            }
+        } else {
+            return  '-';
+        }
+    }
+    function col_timefinish($attempt){
+        if ($attempt->attempt) {
+            if ($attempt->timefinish) {
+                $timefinish = userdate($attempt->timefinish, $this->strtimeformat);
+                if (!$this->is_downloading()) {
+                    return '<a href="review.php?q='.$this->quiz->id.'&amp;attempt='.$attempt->attempt.'">'.$timefinish.'</a>';
+                } else {
+                    return $timefinish;
+                }
+            } else {
+                return  '-';
+            }
+        } else {
+            return  '-';
+        }
+    }
+
+    function col_duration($attempt){
+        if ($attempt->timefinish) {
+            return format_time($attempt->duration);
+        } elseif ($attempt->timestart) {
+            return get_string('unfinished', 'quiz');
+        } else {
+            return '-';
+        }
+    }
+    function col_sumgrades($attempt){
+        if ($attempt->timefinish) {
+            $grade = quiz_rescale_grade($attempt->sumgrades, $this->quiz);
+            if (!$this->is_downloading()) {
+                $gradehtml = '<a href="review.php?q='.$this->quiz->id.'&amp;attempt='.$attempt->attempt.'">'.$grade.'</a>';
+                if ($this->qmsubselect && $attempt->gradedattempt){
+                    $gradehtml = '<div class="highlight">'.$gradehtml.'</div>';
+                }
+                return $gradehtml;
+            } else {
+                return $grade;
+            }
+        } else {
+            return '-';
+        }
+    }
+    function other_cols($colname, $attempt){
+        static $gradedstatesbyattempt = null, $states =array();
+        if ($gradedstatesbyattempt === null){
+            //get all the attempt ids we want to display on this page
+            //or to export for download.
+            $attemptids = array();
+            foreach ($this->rawdata as $attempt){
+                if ($attempt->attemptuniqueid > 0){  
+                    $attemptids[] = $attempt->attemptuniqueid;
+                    $states[$attempt->attemptuniqueid] = get_question_states($this->questions, $this->quiz, $attempt);
+                }
+            }
+            $gradedstatesbyattempt = quiz_get_newgraded_states($attemptids, true, 'qs.id, qs.grade, qs.event, qs.question, qs.attempt');
+        }
+        if (preg_match('/^qsanswer([0-9]+)$/', $colname, $matches)){
+            $questionid = $matches[1];
+            $question = $this->questions[$questionid];
+            $stateforqinattempt = $gradedstatesbyattempt[$attempt->attemptuniqueid][$questionid];
+            $responses =  get_question_actual_response($question, $states[$attempt->attemptuniqueid][$questionid]);
+            $response = (!empty($responses)? implode(', ',$responses) : '-');
+            $grade = $stateforqinattempt->grade;
+            if (!$this->is_downloading()) {
+                $format_options = new stdClass;
+                $format_options->para = false;
+                $format_options->noclean = true;
+                $format_options->newlines = false;
+                if ($grade<= 0) {
+                    $qclass = 'uncorrect';
+                } elseif ($grade == 1) {
+                    $qclass = 'correct';
+                } else {
+                    $qclass = 'partialcorrect';
+                }          
+                return '<span class="'.$qclass.'">'.format_text($response, FORMAT_MOODLE, $format_options).'</span>';
+            } else {
+                return format_text($response, FORMAT_MOODLE, $format_options);
+            }
+        } else {
+            return NULL;
+        }
+    }
+
+    function col_feedbacktext($attempt){
+        if ($attempt->timefinish) {
+            if (!$this->is_downloading()) {
+                return quiz_report_feedback_for_grade(quiz_rescale_grade($attempt->sumgrades, $this->quiz), $this->quiz->id);
+            } else {
+                return strip_tags(quiz_report_feedback_for_grade(quiz_rescale_grade($attempt->sumgrades, $this->quiz), $this->quiz->id));
+            }
+        } else {
+            return '-';
+        }
+
+    }
+
+    function query_db($pagesize, $useinitialsbar=true){
+        // Add table joins so we can sort by question answer
+        // unfortunately can't join all tables necessary to fetch all answers
+        // to get the state for one question per attempt row we must join two tables
+        // and there is a limit to how many joins you can have in one query. In MySQL it
+        // is 61. This means that when having more than 29 questions the query will fail.
+        // So we join just the tables needed to sort the attempts.
+        if($sort = $this->get_sql_sort()) {
+                $this->sql->from .= ' ';
+                $sortparts    = explode(',', $sort);
+                $matches = array();
+                foreach($sortparts as $sortpart) {
+                    $sortpart = trim($sortpart);
+                    if (preg_match('/^qsanswer([0-9]+)/', $sortpart, $matches)){
+                        $qid = intval($matches[1]);
+                        $this->sql->fields .=  ", qs$qid.grade AS qsgrade$qid, qs$qid.answer AS qsanswer$qid, qs$qid.event AS qsevent$qid, qs$qid.id AS qsid$qid";
+                        $this->sql->from .= "LEFT JOIN {question_sessions} qns$qid ON qns$qid.attemptid = qa.uniqueid AND qns$qid.questionid = :qid$qid ";
+                        $this->sql->from .=  "LEFT JOIN  {question_states} qs$qid ON qs$qid.id = qns$qid.newgraded ";
+                        $this->sql->params['qid'.$qid] = $qid;
+                    }
+                }
+        }
+        parent::query_db($pagesize, $useinitialsbar);
+    }
+}
+?>
\ No newline at end of file
diff --git a/mod/quiz/report/responses/responsessettings_form.php b/mod/quiz/report/responses/responsessettings_form.php
new file mode 100644 (file)
index 0000000..c77e129
--- /dev/null
@@ -0,0 +1,43 @@
+<?php  // $Id$
+require_once "$CFG->libdir/formslib.php";
+class mod_quiz_report_responses_settings extends moodleform {
+
+    function definition() {
+        global $COURSE;
+        $mform    =& $this->_form;
+//-------------------------------------------------------------------------------
+        $mform->addElement('header', 'preferencespage', get_string('preferencespage', 'quiz_overview'));
+
+        if (!$this->_customdata['currentgroup']){
+            $studentsstring = "'".$COURSE->students."'";
+        } else {
+            $a = new object();
+            $a->coursestudent = $COURSE->students;
+            $a->groupname = groups_get_group_name($this->_customdata['currentgroup']);
+            $studentsstring = get_string('studentingroup', 'quiz_overview', $a);
+        }
+        $options = array();
+        if (!$this->_customdata['currentgroup']){
+            $options[QUIZ_REPORT_ATTEMPTS_ALL] = get_string('optallattempts','quiz_overview');
+        }
+        if ($this->_customdata['currentgroup'] || $COURSE->id != SITEID) {
+            $options[QUIZ_REPORT_ATTEMPTS_ALL_STUDENTS] = get_string('optallstudents','quiz_overview', $studentsstring);
+            $options[QUIZ_REPORT_ATTEMPTS_STUDENTS_WITH] =
+                     get_string('optattemptsonly','quiz_overview', $studentsstring);
+            $options[QUIZ_REPORT_ATTEMPTS_STUDENTS_WITH_NO] = get_string('optnoattemptsonly', 'quiz_overview', $studentsstring);
+        }
+        $mform->addElement('select', 'attemptsmode', get_string('show', 'quiz_overview'), $options);
+        if ($this->_customdata['qmsubselect']){
+            $gm = '<span class="highlight">'.quiz_get_grading_option_name($this->_customdata['quiz']->grademethod).'</span>';
+            $mform->addElement('advcheckbox', 'qmfilter', get_string('show', 'quiz_overview'), get_string('optonlygradedattempts', 'quiz_overview', $gm), null, array(0,1));
+        }
+//-------------------------------------------------------------------------------
+        $mform->addElement('header', 'preferencesuser', get_string('preferencesuser', 'quiz_overview'));
+
+        $mform->addElement('text', 'pagesize', get_string('pagesize', 'quiz_overview'));
+        $mform->setType('pagesize', PARAM_INT);
+
+        $this->add_action_buttons(false, get_string('preferencessave', 'quiz_overview'));
+    }
+}
+?>
\ No newline at end of file
diff --git a/mod/quiz/report/responses/styles.css b/mod/quiz/report/responses/styles.css
new file mode 100644 (file)
index 0000000..4ae9b26
--- /dev/null
@@ -0,0 +1,34 @@
+body#mod-quiz-report table#attempts {
+  margin: 20px auto;
+}
+body#mod-quiz-report table#attempts .header,
+body#mod-quiz-report table#attempts .cell
+{
+  padding: 4px;
+}
+body#mod-quiz-report table#attempts .header .commands {
+  display: inline;
+}
+body#mod-quiz-report table#attempts td {
+  border-width: 1px;
+  border-style: solid;
+}
+body#mod-quiz-report table#attempts .header {
+  text-align: left;
+}
+body#mod-quiz-report table#attempts .numcol {
+  text-align: center;
+  vertical-align : middle !important;
+}
+
+body#mod-quiz-report table#attempts .uncorrect {
+  background-color:#FF9090;
+}
+
+body#mod-quiz-report table#attempts .correct {
+  background-color:#90FF90;
+}
+
+body#mod-quiz-report table#attempts .partialcorrect {
+  background-color:#FFFF90;
+}