|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 // This file is part of Moodle - http://moodle.org/ 00003 // 00004 // Moodle is free software: you can redistribute it and/or modify 00005 // it under the terms of the GNU General Public License as published by 00006 // the Free Software Foundation, either version 3 of the License, or 00007 // (at your option) any later version. 00008 // 00009 // Moodle is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License 00015 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 00016 00027 defined('MOODLE_INTERNAL') || die(); 00028 00029 00036 class quiz_report_overview_table extends quiz_attempt_report_table { 00037 00038 protected $regradedqs = array(); 00039 00040 public function __construct($quiz, $context, $qmsubselect, $qmfilter, 00041 $attemptsmode, $groupstudents, $students, $detailedmarks, 00042 $questions, $includecheckboxes, $reporturl, $displayoptions) { 00043 parent::__construct('mod-quiz-report-overview-report', $quiz , $context, 00044 $qmsubselect, $qmfilter, $attemptsmode, $groupstudents, $students, 00045 $questions, $includecheckboxes, $reporturl, $displayoptions); 00046 $this->detailedmarks = $detailedmarks; 00047 } 00048 00049 public function build_table() { 00050 global $DB; 00051 00052 if (!$this->rawdata) { 00053 return; 00054 } 00055 00056 $this->strtimeformat = str_replace(',', '', get_string('strftimedatetime')); 00057 parent::build_table(); 00058 00059 // End of adding the data from attempts. Now add averages at bottom. 00060 $this->add_separator(); 00061 00062 if ($this->groupstudents) { 00063 $this->add_average_row(get_string('groupavg', 'grades'), $this->groupstudents); 00064 } 00065 00066 if ($this->students) { 00067 $this->add_average_row(get_string('overallaverage', 'grades'), $this->students); 00068 } 00069 } 00070 00076 protected function add_average_row($label, $users) { 00077 global $DB; 00078 00079 list($fields, $from, $where, $params) = $this->base_sql($users); 00080 $record = $DB->get_record_sql(" 00081 SELECT AVG(quiza.sumgrades) AS grade, COUNT(quiza.sumgrades) AS numaveraged 00082 FROM $from 00083 WHERE $where", $params); 00084 $record->grade = quiz_rescale_grade($record->grade, $this->quiz, false); 00085 00086 if ($this->is_downloading()) { 00087 $namekey = 'lastname'; 00088 } else { 00089 $namekey = 'fullname'; 00090 } 00091 $averagerow = array( 00092 $namekey => $label, 00093 'sumgrades' => $this->format_average($record), 00094 'feedbacktext'=> strip_tags(quiz_report_feedback_for_grade( 00095 $record->grade, $this->quiz->id, $this->context)) 00096 ); 00097 00098 if ($this->detailedmarks) { 00099 $dm = new question_engine_data_mapper(); 00100 $qubaids = new qubaid_join($from, 'quiza.uniqueid', $where, $params); 00101 $avggradebyq = $dm->load_average_marks($qubaids, array_keys($this->questions)); 00102 00103 $averagerow += $this->format_average_grade_for_questions($avggradebyq); 00104 } 00105 00106 $this->add_data_keyed($averagerow); 00107 } 00108 00114 protected function format_average_grade_for_questions($gradeaverages) { 00115 $row = array(); 00116 00117 if (!$gradeaverages) { 00118 $gradeaverages = array(); 00119 } 00120 00121 foreach ($this->questions as $question) { 00122 if (isset($gradeaverages[$question->slot]) && $question->maxmark > 0) { 00123 $record = $gradeaverages[$question->slot]; 00124 $record->grade = quiz_rescale_grade( 00125 $record->averagefraction * $question->maxmark, $this->quiz, false); 00126 00127 } else { 00128 $record = new stdClass(); 00129 $record->grade = null; 00130 $record->numaveraged = 0; 00131 } 00132 00133 $row['qsgrade' . $question->slot] = $this->format_average($record, true); 00134 } 00135 00136 return $row; 00137 } 00138 00143 protected function format_average($record, $question = false) { 00144 if (is_null($record->grade)) { 00145 $average = '-'; 00146 } else if ($question) { 00147 $average = quiz_format_question_grade($this->quiz, $record->grade); 00148 } else { 00149 $average = quiz_format_grade($this->quiz, $record->grade); 00150 } 00151 00152 if ($this->download) { 00153 return $average; 00154 } else if (is_null($record->numaveraged) || $record->numaveraged == 0) { 00155 return html_writer::tag('span', html_writer::tag('span', 00156 $average, array('class' => 'average')), array('class' => 'avgcell')); 00157 } else { 00158 return html_writer::tag('span', html_writer::tag('span', 00159 $average, array('class' => 'average')) . ' ' . html_writer::tag('span', 00160 '(' . $record->numaveraged . ')', array('class' => 'count')), 00161 array('class' => 'avgcell')); 00162 } 00163 } 00164 00165 protected function submit_buttons() { 00166 if (has_capability('mod/quiz:regrade', $this->context)) { 00167 echo '<input type="submit" name="regrade" value="' . 00168 get_string('regradeselected', 'quiz_overview') . '"/>'; 00169 } 00170 parent::submit_buttons(); 00171 } 00172 00173 public function col_sumgrades($attempt) { 00174 if (!$attempt->timefinish) { 00175 return '-'; 00176 } 00177 00178 $grade = quiz_rescale_grade($attempt->sumgrades, $this->quiz); 00179 if ($this->is_downloading()) { 00180 return $grade; 00181 } 00182 00183 if (isset($this->regradedqs[$attempt->usageid])) { 00184 $newsumgrade = 0; 00185 $oldsumgrade = 0; 00186 foreach ($this->questions as $question) { 00187 if (isset($this->regradedqs[$attempt->usageid][$question->slot])) { 00188 $newsumgrade += $this->regradedqs[$attempt->usageid] 00189 [$question->slot]->newfraction * $question->maxmark; 00190 $oldsumgrade += $this->regradedqs[$attempt->usageid] 00191 [$question->slot]->oldfraction * $question->maxmark; 00192 } else { 00193 $newsumgrade += $this->lateststeps[$attempt->usageid] 00194 [$question->slot]->fraction * $question->maxmark; 00195 $oldsumgrade += $this->lateststeps[$attempt->usageid] 00196 [$question->slot]->fraction * $question->maxmark; 00197 } 00198 } 00199 $newsumgrade = quiz_rescale_grade($newsumgrade, $this->quiz); 00200 $oldsumgrade = quiz_rescale_grade($oldsumgrade, $this->quiz); 00201 $grade = html_writer::tag('del', $oldsumgrade) . '/' . 00202 html_writer::empty_tag('br') . $newsumgrade; 00203 } 00204 return html_writer::link(new moodle_url('/mod/quiz/review.php', 00205 array('attempt' => $attempt->attempt)), $grade, 00206 array('title' => get_string('reviewattempt', 'quiz'))); 00207 } 00208 00216 public function other_cols($colname, $attempt) { 00217 if (!preg_match('/^qsgrade(\d+)$/', $colname, $matches)) { 00218 return null; 00219 } 00220 $slot = $matches[1]; 00221 $question = $this->questions[$slot]; 00222 if (!isset($this->lateststeps[$attempt->usageid][$slot])) { 00223 return '-'; 00224 } 00225 00226 $stepdata = $this->lateststeps[$attempt->usageid][$slot]; 00227 $state = question_state::get($stepdata->state); 00228 00229 if ($question->maxmark == 0) { 00230 $grade = '-'; 00231 } else if (is_null($stepdata->fraction)) { 00232 if ($state == question_state::$needsgrading) { 00233 $grade = get_string('requiresgrading', 'question'); 00234 } else { 00235 $grade = '-'; 00236 } 00237 } else { 00238 $grade = quiz_rescale_grade( 00239 $stepdata->fraction * $question->maxmark, $this->quiz, 'question'); 00240 } 00241 00242 if ($this->is_downloading()) { 00243 return $grade; 00244 } 00245 00246 if (isset($this->regradedqs[$attempt->usageid][$slot])) { 00247 $gradefromdb = $grade; 00248 $newgrade = quiz_rescale_grade( 00249 $this->regradedqs[$attempt->usageid][$slot]->newfraction * $question->maxmark, 00250 $this->quiz, 'question'); 00251 $oldgrade = quiz_rescale_grade( 00252 $this->regradedqs[$attempt->usageid][$slot]->oldfraction * $question->maxmark, 00253 $this->quiz, 'question'); 00254 00255 $grade = html_writer::tag('del', $oldgrade) . '/' . 00256 html_writer::empty_tag('br') . $newgrade; 00257 } 00258 00259 return $this->make_review_link($grade, $attempt, $slot); 00260 } 00261 00262 public function col_regraded($attempt) { 00263 if ($attempt->regraded == '') { 00264 return ''; 00265 } else if ($attempt->regraded == 0) { 00266 return get_string('needed', 'quiz_overview'); 00267 } else if ($attempt->regraded == 1) { 00268 return get_string('done', 'quiz_overview'); 00269 } 00270 } 00271 00272 protected function requires_latest_steps_loaded() { 00273 return $this->detailedmarks; 00274 } 00275 00276 protected function is_latest_step_column($column) { 00277 if (preg_match('/^qsgrade([0-9]+)/', $column, $matches)) { 00278 return $matches[1]; 00279 } 00280 return false; 00281 } 00282 00283 protected function get_required_latest_state_fields($slot, $alias) { 00284 return "$alias.fraction * $alias.maxmark AS qsgrade$slot"; 00285 } 00286 00287 public function query_db($pagesize, $useinitialsbar = true) { 00288 parent::query_db($pagesize, $useinitialsbar); 00289 00290 if ($this->detailedmarks && has_capability('mod/quiz:regrade', $this->context)) { 00291 $this->regradedqs = $this->get_regraded_questions(); 00292 } 00293 } 00294 00299 protected function get_regraded_questions() { 00300 global $DB; 00301 00302 $qubaids = $this->get_qubaids_condition(); 00303 $regradedqs = $DB->get_records_select('quiz_overview_regrades', 00304 'questionusageid ' . $qubaids->usage_id_in(), $qubaids->usage_id_in_params()); 00305 return quiz_report_index_by_keys($regradedqs, array('questionusageid', 'slot')); 00306 } 00307 }