From aad5b0fca94bbc278f754634134a3839267ceb36 Mon Sep 17 00:00:00 2001 From: jamiesensei Date: Thu, 15 May 2008 12:27:27 +0000 Subject: [PATCH] MDL-14200 "Add group and course averages" added extra rows to the end of the table in quiz overview report also MDL-14187 "Improve tablelib - improve api and add functionality to download table contents in a variety of formats - XLS, ODS and CSV" implemented the first of my proposals for improving tablelib. Added a extra method to use keyed arrays to add a row to a table. Seems obvious that this is an improvement to tablelib and it is an addition to the API so won't affect existing code. Merged from 1.9 branch. --- lib/tablelib.php | 21 ++++++++ mod/quiz/report/overview/report.php | 76 +++++++++++++++++++---------- mod/quiz/report/reportlib.php | 73 ++++++++++++++++++++++++++- 3 files changed, 141 insertions(+), 29 deletions(-) diff --git a/lib/tablelib.php b/lib/tablelib.php index d22f528e67..7534dddb32 100644 --- a/lib/tablelib.php +++ b/lib/tablelib.php @@ -774,6 +774,27 @@ class flexible_table { } $this->data[] = NULL; } + + /** + * Add a row of data to the table. This function takes an array with + * column names as keys. + * It ignores any elements with keys that are not defined as columns. It + * puts in empty strings into the row when there is no element in the passed + * array corresponding to a column in the table. It puts the row elements in + * the proper order. + * @param $rowwithkeys array + * + */ + function add_data_keyed($rowwithkeys){ + foreach (array_keys($this->columns) as $column){ + if (isset($rowwithkeys[$column])){ + $row [] = $rowwithkeys[$column]; + } else { + $row[] =''; + } + } + $this->add_data($row); + } } diff --git a/mod/quiz/report/overview/report.php b/mod/quiz/report/overview/report.php index 285b7da03c..3d4070b0ac 100644 --- a/mod/quiz/report/overview/report.php +++ b/mod/quiz/report/overview/report.php @@ -44,10 +44,6 @@ class quiz_report extends quiz_default_report { //twice. } - // Set of format options for teacher-created content, for example overall feedback. - $nocleanformatoptions = new stdClass; - $nocleanformatoptions->noclean = true; - // 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(); @@ -197,6 +193,8 @@ class quiz_report extends quiz_default_report { $table->column_suppress('fullname'); $table->column_class('picture', 'picture'); + $table->column_class('fullname', 'bold'); + $table->column_class('sumgrades', 'bold'); $table->set_attribute('cellspacing', '0'); $table->set_attribute('id', 'attempts'); @@ -293,17 +291,15 @@ class quiz_report extends quiz_default_report { echo implode("\t", $headers)." \n"; } - // Get users with quiz attempt capability 'students'. - // don't need to do this expensive call if we are listing all attempts though. - 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))); - } else { - - // all users who can attempt quizzes and who are in the currently selected group - $allowed = join(',',array_keys(get_users_by_capability($context, 'mod/quiz:attempt','','','','',$currentgroup,'',false))); - } + $students = join(',',array_keys(get_users_by_capability($context, 'mod/quiz:attempt','','','','','','',false))); + if (empty($currentgroup)) { + // all users who can attempt quizzes + $groupstudents = ''; + $allowed = $students; + } else { + // all users who can attempt quizzes and who are in the currently selected group + $groupstudents = join(',',array_keys(get_users_by_capability($context, 'mod/quiz:attempt','','','','',$currentgroup,'',false))); + $allowed = $groupstudents; } // Construct the SQL @@ -336,6 +332,7 @@ class quiz_report extends quiz_default_report { $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; @@ -390,14 +387,6 @@ class quiz_report extends quiz_default_report { $table->pagesize($pagesize, $total); } - // If there is feedback, include it in the query. - if ($hasfeedback) { - $factor = $quiz->grade/$quiz->sumgrades; - $select .= ', qf.feedbacktext '; - $from .= " LEFT JOIN {$CFG->prefix}quiz_feedback qf ON " . - "qf.quizid = $quiz->id AND qf.mingrade <= qa.sumgrades * $factor AND qa.sumgrades * $factor < qf.maxgrade"; - } - // Fetch the attempts if (!$download) { $attempts = get_records_sql($select.$from.$where.$sort, @@ -523,7 +512,7 @@ class quiz_report extends quiz_default_report { // Feedback column. if ($hasfeedback) { if ($attempt->timefinish) { - $row[] = format_text($attempt->feedbacktext, FORMAT_MOODLE, $nocleanformatoptions); + $row[] = quiz_report_feedback_for_grade(quiz_rescale_grade($attempt->sumgrades, $quiz), $quiz->id); } else { $row[] = '-'; } @@ -542,6 +531,37 @@ class quiz_report extends quiz_default_report { echo $text." \n"; } } + //end of adding data from attempts data to table / download + //now add averages : + if (!$download && $attempts){ + + $averagesql = "SELECT AVG(qg.grade) AS grade " . + "FROM {$CFG->prefix}quiz_grades qg " . + "WHERE quiz=".$quiz->id; + + $table->add_separator(); + if ($groupstudents){ + $groupaveragesql = $averagesql." AND qg.userid IN ($groupstudents)"; + $groupaverage = get_record_sql($groupaveragesql); + $groupaveragerow = array('fullname' => get_string('groupavg', 'grades'), + 'sumgrades' => round($groupaverage->grade, $quiz->decimalpoints), + 'feedbacktext'=> quiz_report_feedback_for_grade($groupaverage->grade, $quiz->id)); + if($detailedmarks && $qmfilter) { + $avggradebyq = quiz_get_average_grade_for_questions($quiz, $groupstudents); + $groupaveragerow += quiz_format_average_grade_for_questions($avggradebyq, $questions, $quiz, $download); + } + $table->add_data_keyed($groupaveragerow); + } + $overallaverage = get_record_sql($averagesql." AND qg.userid IN ($students)"); + $overallaveragerow = array('fullname' => get_string('overallaverage', 'grades'), + 'sumgrades' => round($overallaverage->grade, $quiz->decimalpoints), + 'feedbacktext'=> quiz_report_feedback_for_grade($overallaverage->grade, $quiz->id)); + if($detailedmarks && $qmfilter) { + $avggradebyq = quiz_get_average_grade_for_questions($quiz, $students); + $overallaveragerow += quiz_format_average_grade_for_questions($avggradebyq, $questions, $quiz, $download); + } + $table->add_data_keyed($overallaveragerow); + } if (!$download) { // Start form echo '
'; @@ -604,9 +624,11 @@ class quiz_report extends quiz_default_report { // Print display options $mform->set_data($displayoptions +compact('detailedmarks', 'pagesize')); $mform->display(); - $imageurl = $CFG->wwwroot.'/mod/quiz/report/overview/overviewgraph.php?id='.$quiz->id; - print_heading(get_string('overviewreportgraph', 'quiz_overview')); - echo '
'.get_string('overviewreportgraph', 'quiz_overview').'
'; + if ($attempts){ + $imageurl = $CFG->wwwroot.'/mod/quiz/report/overview/overviewgraph.php?id='.$quiz->id; + print_heading(get_string('overviewreportgraph', 'quiz_overview')); + echo '
'.get_string('overviewreportgraph', 'quiz_overview').'
'; + } } return true; } diff --git a/mod/quiz/report/reportlib.php b/mod/quiz/report/reportlib.php index c325abcfff..48ff50f9cb 100644 --- a/mod/quiz/report/reportlib.php +++ b/mod/quiz/report/reportlib.php @@ -36,6 +36,44 @@ function quiz_get_newgraded_states($attemptids, $idxattemptq = true){ return array(); } } + +function quiz_get_average_grade_for_questions($quiz, $userids){ + global $CFG; + $gradedevents = QUESTION_EVENTGRADE.','. + QUESTION_EVENTCLOSEANDGRADE.','. + QUESTION_EVENTMANUALGRADE; + $qmfilter = quiz_report_qm_filter_subselect($quiz, 'qa.userid'); + $questionavgssql = "SELECT qs.question, AVG(qs.grade) FROM " . + "{$CFG->prefix}question_sessions qns, " . + "{$CFG->prefix}quiz_attempts qa, " . + "{$CFG->prefix}question_states qs " . + "WHERE qns.attemptid = qa.uniqueid AND " . + "qa.quiz = {$quiz->id} AND " . + ($qmfilter?$qmfilter.' AND ':''). + "qa.userid IN ({$userids}) AND " . + "qs.event IN ($gradedevents) AND ". + "qns.newgraded = qs.id GROUP BY qs.question"; + return get_records_sql_menu($questionavgssql); +} +function quiz_format_average_grade_for_questions($avggradebyq, $questions, $quiz, $download){ + $row = array(); + if (!$avggradebyq){ + $avggradebyq = array(); + } + foreach(array_keys($questions) as $questionid) { + if (isset($avggradebyq[$questionid])){ + $grade = $avggradebyq[$questionid]; + $grade = quiz_rescale_grade($grade, $quiz); + } else { + $grade = '--'; + } + if (!$download) { + $grade = $grade.'/'.quiz_rescale_grade($questions[$questionid]->grade, $quiz); + } + $row['$'.$questionid]= $grade; + } + return $row; +} /** * Load the question data necessary in the reports. * - Remove description questions. @@ -78,7 +116,7 @@ function quiz_report_load_questions($quiz){ * 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($quiz){ +function quiz_report_qm_filter_subselect($quiz, $useridsql = 'u.id'){ global $CFG; if ($quiz->attempts == 1) {//only one attempt allowed on this quiz return ''; @@ -100,7 +138,7 @@ function quiz_report_qm_filter_subselect($quiz){ } if ($qmfilterattempts){ $qmsubselect = "(SELECT id FROM {$CFG->prefix}quiz_attempts " . - "WHERE quiz = {$quiz->id} AND u.id = userid " . + "WHERE quiz = {$quiz->id} AND $useridsql = userid " . "ORDER BY $qmorderby LIMIT 1)=qa.id"; } else { $qmsubselect = ''; @@ -141,4 +179,35 @@ function quiz_report_highlighting_grading_method($quiz, $qmsubselect, $qmfilter) (''.quiz_get_grading_option_name($quiz->grademethod).''))."

"; } } + + +/** + * Get the feedback text for a grade on this quiz. The feedback is + * processed ready for display. + * + * @param float $grade a grade on this quiz. + * @param integer $quizid the id of the quiz object. + * @return string the comment that corresponds to this grade (empty string if there is not one. + */ +function quiz_report_feedback_for_grade($grade, $quizid) { + static $feedbackcache = array(); + if (!isset($feedbackcache[$quizid])){ + $feedbackcache[$quizid] = get_records('quiz_feedback', 'quizid', $quizid); + } + $feedbacks = $feedbackcache[$quizid]; + $feedbacktext = ''; + foreach ($feedbacks as $feedback) { + if ($feedback->mingrade <= $grade && $grade < $feedback->maxgrade){ + $feedbacktext = $feedback->feedbacktext; + break; + } + } + + // Clean the text, ready for display. + $formatoptions = new stdClass; + $formatoptions->noclean = true; + $feedbacktext = format_text($feedbacktext, FORMAT_MOODLE, $formatoptions); + + return $feedbacktext; +} ?> -- 2.39.5