3 if (!defined('MOODLE_INTERNAL')) {
4 die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page
7 require_once($CFG->dirroot
.'/course/lib.php');
9 define('UNCATEGORISED', 'uncategorised');
11 global $GRADEPREFS, $GRADEPREFSDEFAULTS; // This variables are going to be global... :-/
13 $GRADEPREFS = array('use_advanced', // Only add new preferences to the end of this array!
14 'use_weighted_for_letter', // as the order counts and will affect backward compatibility
24 $GRADEPREFSDEFAULTS = array('use_advanced' => 0,
25 'use_weighted_for_letter' => 0,
26 'display_weighted' => 0,
27 'display_points' => 2,
28 'display_percent' => 1,
29 'display_letters' => 0,
30 'reprint_headers' => 0,
35 //******************************************************************
37 //******************************************************************
39 function grade_get_category_weight($course, $category) {
41 $sql = "SELECT id, weight, drop_x_lowest, bonus_points, hidden, c.id AS cat_id
42 FROM {$CFG->prefix}grade_category c
43 WHERE c.courseid=$course
44 AND c.name='$category'";
45 $temp = get_record_sql($sql);
49 function grade_get_grade_items($course) {
51 $sql = "SELECT i.id, c.name as cname, i.modid, mm.name as modname, i.cminstance, c.hidden, cm.visible, i.sort_order
52 FROM {$CFG->prefix}grade_item i,
53 {$CFG->prefix}grade_category c,
54 {$CFG->prefix}course_modules cm,
55 {$CFG->prefix}modules mm
57 AND i.courseid=c.courseid
58 AND c.courseid=$course
59 AND cm.course=c.courseid
62 AND cm.instance=i.cminstance";
63 $temp = get_records_sql($sql);
67 function grade_get_module_link($course, $cminstance, $modid) {
69 $sql = "SELECT cm.id, 1 FROM {$CFG->prefix}course_modules cm, {$CFG->prefix}modules mm, {$CFG->prefix}grade_item i
70 WHERE i.modid='".$modid."'
72 AND cm.instance = i.cminstance
73 AND i.cminstance=".$cminstance."
74 AND i.courseid=cm.course AND cm.module=mm.id AND i.courseid=$course";
75 $temp = get_record_sql($sql);
79 function grade_get_grade_letter($course, $grade) {
81 $sql = "SELECT id, letter FROM {$CFG->prefix}grade_letter WHERE courseid=$course AND grade_high >= $grade AND grade_low <= $grade";
82 $temp = get_record_sql($sql);
86 function grade_get_exceptions($course) {
88 $sql = "SELECT e.id, e.userid, gi.cminstance, gi.modid, c.name as catname, mm.name as modname
89 FROM {$CFG->prefix}grade_exceptions e,
90 {$CFG->prefix}grade_item gi,
91 {$CFG->prefix}grade_category c,
92 {$CFG->prefix}course_modules cm,
93 {$CFG->prefix}modules mm
94 WHERE e.courseid=$course
95 AND gi.id = e.grade_itemid
96 AND c.id = gi.category
97 AND cm.course=c.courseid
101 $temp = get_records_sql($sql);
105 function grade_get_exceptions_user($course, $userid) {
107 $sql = "SELECT e.id, e.userid, gi.cminstance, gi.modid, c.name as catname, mm.name as modname
108 FROM {$CFG->prefix}grade_exceptions e,
109 {$CFG->prefix}grade_item gi,
110 {$CFG->prefix}grade_category c,
111 {$CFG->prefix}course_modules cm,
112 {$CFG->prefix}modules mm
113 WHERE e.courseid=$course
115 AND gi.id = e.grade_itemid
116 AND c.id = gi.category
117 AND cm.course=c.courseid
121 $temp = get_records_sql($sql);
124 function grade_letters_set($course) {
126 $sql = "SELECT * FROM {$CFG->prefix}grade_letter WHERE courseid=$course";
127 $letters_set = get_records_sql($sql);
136 function grade_get_users_by_group($course, $group) {
138 $sql = "SELECT userid FROM {$CFG->prefix}groups_members WHERE courseid=$course AND groupid = $group";
139 $members = get_records_sql($sql);
141 foreach($members as $member) {
142 // FIX ME: there is no $userid defined!!! - from where is this function used anyway??
143 $group->$userid = true;
152 //******************************************************************
154 //******************************************************************
156 function grade_get_formatted_grades() {
161 $i = 2; // index to differentiate activities with the same name MDL-6876
162 $grades = grade_get_grades();
163 if (isset($grades)) {
164 // iterate through all students
165 foreach($grades as $cur_category=>$grade_category) {
166 // $cur_category holds the value of the current category name
167 // $grade_category holds an array of all the mod types that are in this category
168 if (isset($grade_category)) {
169 foreach($grade_category as $cur_mod=>$mod_category) {
170 // $cur_mod is the id of the current moodle module type
171 // $mod_category holds the grades for $cur_mod (current mod type)
172 $module_info = get_record('modules', 'id', $cur_mod);
173 $cur_modname = $module_info->name
;
174 if (isset($mod_category)) {
175 foreach($mod_category as $cur_cminstance=>$students_grade) {
176 // $cur_cminstance is the course module instance for the cur_mod
177 $instance = get_record($cur_modname, 'id',$cur_cminstance, 'course',$course->id
);
178 // it's necessary to check if the name is blank because some mods don't clean up the grades when the instance is deleted
179 // this is a bug. as it is plausible that some item could get created and have old data from a previous mod laying around
180 if ($instance->name
!= '') {
181 // duplicate grade item name, the user should know better than to name to things by the same name, but to make sure grades don't disappear lets modify the name slightly
182 if (isset($all_categories["$cur_category"]["$instance->name"])) {
183 $instance->name
= $instance->name
.' #'.$i++
;
186 if (isset($students_grade->grades
) && $students_grade->grades
!= '') {
187 foreach($students_grade->grades
as $student=>$grade) {
188 // add an entry for any student that has a grade
189 $grades_by_student["$student"]["$cur_category"]["$instance->name"]['grade'] = $grade;
190 $grades_by_student["$student"]["$cur_category"]["$instance->name"]['sort_order'] = $students_grade->sort_order
;
192 if (!isset($grades_by_student["$student"]["$cur_category"]['stats'])) {
193 $grades_by_student["$student"]["$cur_category"]['stats'] = array();
196 if (!isset($grades_by_student["$student"]["$cur_category"]['stats']['points'])) {
197 $grades_by_student["$student"]["$cur_category"]['stats']['points'] = $grade;
200 $grades_by_student["$student"]["$cur_category"]['stats']['points'] = $grades_by_student["$student"]["$cur_category"]['stats']['points'] +
$grade;
203 // This next block just creates a comma seperated list of all grades for the category
204 if (isset($grades_by_student["$student"]["$cur_category"]['stats']['allgrades'])) {
205 $grades_by_student["$student"]["$cur_category"]['stats']['allgrades'] .= ','.$grade;
208 $grades_by_student["$student"]["$cur_category"]['stats']['allgrades'] = $grade;
215 // set up a list of all categories and assignments (adjusting things for extra credit where necessary)
216 $all_categories["$cur_category"]["$instance->name"]['hidden'] = $students_grade->hidden
;
217 $all_categories["$cur_category"]["$instance->name"]['sort_order'] = $students_grade->sort_order
;
219 $all_categories["$cur_category"]["$instance->name"]['extra_credit'] = $students_grade->extra_credit
;
221 if ($all_categories["$cur_category"]["$instance->name"]['extra_credit'] != 1) {
222 $all_categories["$cur_category"]["$instance->name"]['maxgrade'] = $students_grade->maxgrade
;
225 $all_categories["$cur_category"]["$instance->name"]['maxgrade'] = 0;
227 $all_categories["$cur_category"]["$instance->name"]['scale_grade'] = $students_grade->scale_grade
;
228 if ($students_grade->scale_grade
!= 0) {
229 $all_categories["$cur_category"]["$instance->name"]['scaled_max'] = round($all_categories["$cur_category"]["$instance->name"]['maxgrade']/$students_grade->scale_grade
);
232 // avoids divide by zero... scale_grade shouldn't be set to 0 anyway
233 $all_categories["$cur_category"]["$instance->name"]['scaled_max'] = $all_categories["$cur_category"]["$instance->name"]['maxgrade'];
234 $all_categories["$cur_category"]["$instance->name"]['scale_grade'] = 1.0;
236 if (! isset($all_categories["$cur_category"]['stats']) ) {
237 $all_categories["$cur_category"]['stats'] = array();
239 $all_categories["$cur_category"]["$instance->name"]['grade_against'] = $all_categories["$cur_category"]["$instance->name"]['scaled_max'];
240 if (!isset($all_categories["$cur_category"]['stats']['weight'])) {
241 $weight = grade_get_category_weight($course->id
, $cur_category);
242 $all_categories["$cur_category"]['stats']['weight'] = $weight->weight
;
245 $all_categories["$cur_category"]["$instance->name"]['cminstance'] = $cur_cminstance;
246 $all_categories["$cur_category"]["$instance->name"]['modid'] = $cur_mod;
247 $modname = get_record('modules','id',$cur_mod);
248 $all_categories["$cur_category"]["$instance->name"]['modname'] = $modname->name
;
250 // get bonus points and drop the x lowest
251 $drop = get_record('grade_category', 'courseid', $course->id
, 'name', $cur_category);
252 $all_categories["$cur_category"]['stats']['drop'] = $drop->drop_x_lowest
;
253 $all_categories["$cur_category"]['stats']['bonus_points'] = $drop->bonus_points
;
260 if (!$students = grade_get_course_students($course->id
)) {
265 if (isset($students) && $students) {
266 foreach ($students as $userid => $student) {
267 $grades_by_student["$userid"]['student_data']['firstname'] = $student->firstname
;
268 $grades_by_student["$userid"]['student_data']['lastname'] = $student->lastname
;
269 $grades_by_student["$userid"]['student_data']['email'] = $student->email
;
270 if (isset($student->location
)) {
271 $grades_by_student["$userid"]['student_data']['location'] = $student->location
;
273 $grades_by_student["$userid"]['student_data']['department'] = $student->department
;
274 $grades_by_student["$userid"]['student_data']['idnumber'] = $student->idnumber
;
278 // unset any item that has a "" for a name at this point this inludes instructors who have grades or any student formerly enrolled.
279 if (isset($grades_by_student)) {
280 foreach ($grades_by_student as $student => $assignments) {
281 if (!isset($grades_by_student["$student"]['student_data']['firstname']) && !isset($grades_by_student["$student"]['student_data']['lastname'])) {
282 unset($grades_by_student["$student"]);
288 // set the totalpoints for each category taking into account drop_x_lowest
289 // also set the number of grade items for the category to make calculating grades for students who have not taken anything easier
290 foreach($all_categories as $category => $assignments) {
292 $all_categories["$category"]['stats']['totalpoints'] = 0;
293 $all_categories["$category"]['stats']['grade_items'] = 0;
294 if (isset($assignments)) {
295 foreach($assignments as $assignment=>$grade) {
296 if ($assignment != 'stats') {
297 if ($dropcount < $all_categories["$category"]['stats']['drop']) {
298 // skip a grade in the total
302 // make sure the current assignment is not extra credit and then add it to the totalpoints
303 if ($all_categories["$category"][$assignment]['extra_credit'] != 1) {
304 $all_categories["$category"]['stats']['totalpoints'] = $all_categories["$category"]['stats']['totalpoints'] +
$assignments["$assignment"]['grade_against'];
305 $all_categories["$category"]['stats']['grade_items'] = $all_categories["$category"]['stats']['grade_items'] +
1;
314 if (isset($_REQUEST['group'])) {
315 $group = clean_param($_REQUEST['group'], PARAM_INT
);
317 // if the user has selected a group to view by get the group members
318 if (isset($group) && $group != 0) {
319 $groupmembers = get_group_users($group);
322 // this next block catches any students who do not have a grade for any item in a particular category
323 foreach($all_categories as $category => $main_category) {
324 // make sure each student has an entry for each category
325 if (isset($grades_by_student)) {
326 foreach($grades_by_student as $student=>$categories) {
327 if ( (isset($groupmembers) && isset($groupmembers[$student])) ||
!isset($groupmembers)) {
329 $grades_by_student["$student"]["$category"]['stats']['totalpoints'] = $main_category['stats']['totalpoints'];
330 $grades_by_student["$student"]["$category"]['stats']['weight'] = $main_category['stats']['weight'];
331 $grades_by_student["$student"]["$category"]['stats']['grade_items'] = $main_category['stats']['grade_items'];
333 foreach($main_category as $assignment => $items) {
334 if ($assignment != 'stats') {
335 if(!isset($grades_by_student["$student"]["$category"]["$assignment"]['grade'])) {
336 if (isset($grades_by_student["$student"]["$category"]['stats']['allgrades'])) {
337 $grades_by_student["$student"]["$category"]['stats']['allgrades'] .= ',0';
339 $grades_by_student["$student"]["$category"]['stats']['allgrades'] = '0';
345 if (!isset($grades_by_student["$student"]["$category"]['stats']['points'])) {
346 $grades_by_student["$student"]["$category"]['stats']['points'] = '-';
351 // points are set... see if the current category is using drop the x lowest and do so
352 // also drop exceptions first, so then this grades(s) won't be recoqnized as the x lowest
353 // Get exception scores and assign them in the array
354 if ($main_category['stats']['drop'] != 0) {
355 $exceptions = grade_get_exceptions_user($course->id
, $student);
356 if (isset($exceptions) && $exceptions) {
357 foreach($exceptions as $exception) {
358 if (isset($grades_by_student["$exception->userid"])) {
359 if ($grades_by_student["$exception->userid"]["$exception->catname"]) {
360 $assgn = get_record($exception->modname
, 'id', $exception->cminstance
, 'course', $course->id
);
361 $grade = $grades_by_student["$exception->userid"]["$exception->catname"]["$assgn->name"]['grade'];
363 if (!isset($grades_by_student["$exception->userid"]["$exception->catname"]['stats']['exceptions'])) {
364 $grades_by_student["$exception->userid"]["$exception->catname"]['stats']['exceptions'] = $grade;
366 elseif (isset($grades_by_student["$exception->userid"]["$exception->catname"]['stats']['exceptions'])) {
367 $grades_by_student["$exception->userid"]["$exception->catname"]['stats']['exceptions'] .= ','. $grade;
374 if (isset($grades_by_student["$student"]["$category"]['stats']['exceptions'])) {
375 $grades_by_student["$student"]["$category"]['stats']['allgrades'] = grade_drop_exceptions($grades_by_student["$student"]["$category"]['stats']['allgrades'], $grades_by_student["$student"]["$category"]['stats']['exceptions']);
378 $grades_by_student["$student"]["$category"]['stats']['allgrades'] = grade_drop_lowest($grades_by_student["$student"]["$category"]['stats']['allgrades'], $main_category['stats']['drop'], $main_category['stats']['grade_items']);
379 if ($grades_by_student["$student"]["$category"]['stats']['points'] != '-') {
381 $count_grades = explode(',',$grades_by_student["$student"]["$category"]['stats']['allgrades']);
382 foreach($count_grades as $grade) {
383 $cat_points = $cat_points +
$grade;
385 $grades_by_student["$student"]["$category"]['stats']['points'] = $cat_points;
390 // add any bonus points for the category
391 if ($all_categories["$category"]['stats']['bonus_points'] != 0) {
392 $grades_by_student["$student"]["$category"]['stats']['points'] = $grades_by_student["$student"]["$category"]['stats']['points'] +
$all_categories["$category"]['stats']['bonus_points'];
395 foreach($main_category as $assignment => $items) {
396 if ($assignment != 'stats') {
397 if(!isset($grades_by_student["$student"]["$category"]["$assignment"]['maxgrade'])) {
398 $grades_by_student["$student"]["$category"]["$assignment"]['maxgrade'] = $all_categories["$category"]["$assignment"]['grade_against'];
400 if(!isset($grades_by_student["$student"]["$category"]["$assignment"]['grade'])) {
401 $grades_by_student["$student"]["$category"]["$assignment"]['grade'] = '-';
402 $grades_by_student["$student"]["$category"]["$assignment"]['sort_order'] = $all_categories["$category"]["$assignment"]['sort_order'];
406 } // end groupmember if
408 // unset grade since they are not in the selected group.
409 unset($grades_by_student["$student"]);
414 // set the total coursepoints
415 $all_categories['stats']['weight'] = 0;
416 $all_categories['stats']['totalpoints'] = 0;
417 foreach($all_categories as $category => $info) {
418 if ($category != 'stats') {
419 $all_categories['stats']['weight'] = $all_categories['stats']['weight'] +
$all_categories["$category"]['stats']['weight'];
420 $all_categories['stats']['totalpoints'] = $all_categories['stats']['totalpoints'] +
$all_categories["$category"]['stats']['totalpoints'];
424 // set each individuals total points by category so we can then exclude some grades if set to use exceptions
425 if (isset($grades_by_student)) {
426 foreach($grades_by_student as $student => $categories) {
427 foreach($all_categories as $category => $assignments) {
428 if ($category != 'stats') {
429 $grades_by_student["$student"]["$category"]['stats']['totalpoints'] = $all_categories["$category"]['stats']['totalpoints'];
432 $grades_by_student["$student"]['student_data']['totalpoints'] = $all_categories['stats']['totalpoints'];
436 // take into account any excluded grade_items
437 $strexcluded = get_string('excluded', 'grades');
438 $exceptions = grade_get_exceptions($course->id
);
439 if (isset($exceptions) && $exceptions) {
440 foreach($exceptions as $exception) {
441 if (isset($grades_by_student["$exception->userid"])) {
442 if ($grades_by_student["$exception->userid"]["$exception->catname"]) {
443 $assgn = get_record($exception->modname
, 'id', $exception->cminstance
, 'course', $course->id
);
444 $grades_by_student["$exception->userid"]['student_data']['totalpoints'] = $grades_by_student["$exception->userid"]['student_data']['totalpoints'] - $all_categories["$exception->catname"]["$assgn->name"]['maxgrade'];
445 //total point should not be smaller than grade against
446 if ($grades_by_student["$exception->userid"]["$exception->catname"]['stats']['totalpoints'] - $all_categories["$exception->catname"]["$assgn->name"]['grade_against'] != 0 ) {
447 $grades_by_student["$exception->userid"]["$exception->catname"]['stats']['totalpoints'] = $grades_by_student["$exception->userid"]["$exception->catname"]['stats']['totalpoints'] - $all_categories["$exception->catname"]["$assgn->name"]['grade_against'];
449 $grades_by_student["$exception->userid"]["$exception->catname"]['stats']['grade_items'] = $grades_by_student["$exception->userid"]["$exception->catname"]['stats']['grade_items'] - 1;
450 if ($grades_by_student["$exception->userid"]["$exception->catname"]['stats']['grade_items'] < 0) {
451 $grades_by_student["$exception->userid"]["$exception->catname"]['stats']['grade_items'] = 0;
453 if ($all_categories["$exception->catname"]['stats']['drop'] == 0) {
454 $grades_by_student["$exception->userid"]["$exception->catname"]['stats']['points'] = $grades_by_student["$exception->userid"]["$exception->catname"]['stats']['points'] - $grades_by_student["$exception->userid"]["$exception->catname"]["$assgn->name"]['grade'];
456 $grades_by_student["$exception->userid"]["$exception->catname"]["$assgn->name"]['maxgrade'] = $strexcluded;
457 $grades_by_student["$exception->userid"]["$exception->catname"]["$assgn->name"]['grade'] = $strexcluded;
458 // see if they are excluded entirely from a category
459 if ($grades_by_student["$exception->userid"]["$exception->catname"]['stats']['totalpoints'] == 0) {
460 $grades_by_student["$exception->userid"]["$exception->catname"]['stats']['totalpoints'] = $strexcluded;
461 $grades_by_student["$exception->userid"]["$exception->catname"]['stats']['percent'] = $strexcluded;
462 $grades_by_student["$exception->userid"]["$exception->catname"]['stats']['points'] = $strexcluded;
463 $grades_by_student["$exception->userid"]["$exception->catname"]['stats']['weight'] = $strexcluded;
464 $grades_by_student["$exception->userid"]["$exception->catname"]['stats']['weighted'] = $strexcluded;
469 // the user had exceptions, but was unenrolled from the course... we could delete it here, but we will leave it because the user may be re-added to the course
474 if (isset($grades_by_student)) {
475 foreach($grades_by_student as $student => $categories) {
476 $grades_by_student["$student"]['student_data']['points'] = '-';
477 $grades_by_student["$student"]['student_data']['totalpoints'] = 0;
478 $grades_by_student["$student"]['student_data']['weight'] = 0;
479 $grades_by_student["$student"]['student_data']['weighted'] = 0;
480 foreach($categories as $category => $assignments) {
481 if ($category != 'student_data') {
482 // set the student's total points earned
483 if ($grades_by_student["$student"]["$category"]['stats']['points'] != $strexcluded) {
484 if ($grades_by_student["$student"]["$category"]['stats']['points'] != '-') {
485 $grades_by_student["$student"]['student_data']['points'] = $grades_by_student["$student"]['student_data']['points'] +
$grades_by_student["$student"]["$category"]['stats']['points'];
487 $grades_by_student["$student"]['student_data']['totalpoints'] = $grades_by_student["$student"]['student_data']['totalpoints'] +
$grades_by_student["$student"]["$category"]['stats']['totalpoints'];
490 // set percents and weights for each assignment
491 foreach($assignments as $assignment => $info) {
492 if ($assignment != 'stats') {
493 if ($grades_by_student["$student"]["$category"]["$assignment"]['grade'] != $strexcluded) {
494 if ($grades_by_student["$student"]["$category"]["$assignment"]['maxgrade'] != 0) {
495 $grades_by_student["$student"]["$category"]["$assignment"]['percent'] = round($grades_by_student["$student"]["$category"]["$assignment"]['grade']/$grades_by_student["$student"]["$category"]["$assignment"]['maxgrade']*100,2);
498 $grades_by_student["$student"]["$category"]["$assignment"]['percent'] = 0;
500 if ($grades_by_student["$student"]["$category"]['stats']['totalpoints'] != 0) {
501 $grades_by_student["$student"]["$category"]["$assignment"]['weight'] = round($all_categories["$category"]['stats']['weight']*($grades_by_student["$student"]["$category"]["$assignment"]['maxgrade']/$grades_by_student["$student"]["$category"]['stats']['totalpoints']),2);
504 $grades_by_student["$student"]["$category"]["$assignment"]['weight'] = 0.00;
506 if ($grades_by_student["$student"]["$category"]["$assignment"]['weight'] != 0) {
507 $grades_by_student["$student"]["$category"]["$assignment"]['weighted'] = round($grades_by_student["$student"]["$category"]["$assignment"]['percent']*$grades_by_student["$student"]["$category"]["$assignment"]['weight']/100,2);
510 // should only be here if this is extra credit
511 $grades_by_student["$student"]["$category"]["$assignment"]['weighted'] = 0.00;
515 $grades_by_student["$student"]["$category"]["$assignment"]['percent'] = $strexcluded;
516 $grades_by_student["$student"]["$category"]["$assignment"]['weight'] = $strexcluded;
517 $grades_by_student["$student"]["$category"]["$assignment"]['weighted'] = $strexcluded;
521 // set the percent and weight per category
522 if ($grades_by_student["$student"]["$category"]['stats']['totalpoints'] != 0 ) {
523 $grades_by_student["$student"]["$category"]['stats']['percent'] = round($grades_by_student["$student"]["$category"]['stats']['points']/$grades_by_student["$student"]["$category"]['stats']['totalpoints']*100,2);
524 $grades_by_student["$student"]["$category"]['stats']['weighted'] = round($grades_by_student["$student"]["$category"]['stats']['points']/$grades_by_student["$student"]["$category"]['stats']['totalpoints']*$grades_by_student["$student"]["$category"]['stats']['weight'],2);
527 if ($grades_by_student["$student"]["$category"]['stats']['totalpoints'] != $strexcluded) {
528 $grades_by_student["$student"]["$category"]['stats']['percent'] = 0.00;
529 $grades_by_student["$student"]["$category"]['stats']['weighted'] = 0.00;
533 // set students overall weight (this is what percent they will be graded against)
534 if ($grades_by_student["$student"]["$category"]['stats']['weight'] != $strexcluded) {
535 $grades_by_student["$student"]['student_data']['weight'] = $grades_by_student["$student"]['student_data']['weight'] +
$grades_by_student["$student"]["$category"]['stats']['weight'];
538 // set the students total categories towards point total we have to defer the percent calculation until we know what total weight they should be graded against since they may
539 // be excluded from a whole category.
540 if ($all_categories["$category"]['stats']['totalpoints'] != 0) {
541 $grades_by_student["$student"]['student_data']['weighted'] = $grades_by_student["$student"]['student_data']['weighted'] +
$grades_by_student["$student"]["$category"]['stats']['weighted'];
548 // set the percent and weight overall
549 if ($grades_by_student["$student"]['student_data']['totalpoints'] != 0 && $grades_by_student["$student"]['student_data']['totalpoints'] != $strexcluded) {
550 $grades_by_student["$student"]['student_data']['percent'] = round($grades_by_student["$student"]['student_data']['points']/$grades_by_student["$student"]['student_data']['totalpoints']*100,2);
551 if ($grades_by_student["$student"]['student_data']['weight'] != 0) {
552 $grades_by_student["$student"]['student_data']['weighted'] = round($grades_by_student["$student"]['student_data']['weighted']/$grades_by_student["$student"]['student_data']['weight']*100,2);
555 $grades_by_student["$student"]['student_data']['weighted'] = 0.00;
558 else if ($grades_by_student["$student"]['student_data']['totalpoints'] == 0) {
559 $grades_by_student["$student"]['student_data']['percent'] = 0.00;
565 if (isset($grades_by_student)) {
566 $sort = optional_param('sort','default');
569 case 'highgrade_category':
570 uasort($grades_by_student, 'grade_sort_by_highgrade_category');
572 case 'highgrade_category_asc':
573 uasort($grades_by_student, 'grade_sort_by_highgrade_category_asc');
577 if ($preferences->use_weighted_for_letter
== 1) {
578 uasort($grades_by_student, 'grade_sort_by_weighted');
581 uasort($grades_by_student, 'grade_sort_by_percent');
586 uasort($grades_by_student, 'grade_sort_by_points');
589 uasort($grades_by_student, 'grade_sort_by_points_asc');
592 uasort($grades_by_student, 'grade_sort_by_weighted');
595 uasort($grades_by_student, 'grade_sort_by_weighted_asc');
598 uasort($grades_by_student, 'grade_sort_by_percent');
601 uasort($grades_by_student, 'grade_sort_by_percent_asc');
603 case 'highgrade_asc':
605 if ($preferences->use_weighted_for_letter
== 1) {
606 uasort($grades_by_student, 'grade_sort_by_weighted_asc');
609 uasort($grades_by_student, 'grade_sort_by_percent_asc');
614 uasort($grades_by_student, 'grade_sort_by_firstname');
617 uasort($grades_by_student, 'grade_sort_by_lastname');
621 $grades_by_student = 0;
623 $retval = array($grades_by_student, $all_categories);
626 $retval = array(0,0);
627 // echo "<center><font color=red>Could not find any graded items for this course.</font></center>";
632 function grade_drop_exceptions($grades, $grades_exceptions) {
633 $grade_array = explode(',',$grades);
634 $grade_exception_array = explode(',',$grades_exceptions);
635 $ret_grades = Array();
636 foreach ($grade_array as $key => $val) {
637 $posb = array_search($val,$grade_exception_array);
638 if (is_integer($posb)) {
639 unset($grade_exception_array[$posb]);
642 $ret_grades[] = $val;
645 $grades = implode(',', $ret_grades);
649 function grade_drop_lowest($grades, $drop, $total) {
650 // drops the lowest $drop numbers from the comma seperated $grades making sure that if $grades has
651 // fewer items than $total that we don't drop too many
652 $grade_array = explode(',',$grades);
653 if (count($grade_array) == 1) {
654 $grades = implode('', $grade_array);
656 else if ($drop > 0 AND (count($grade_array) > $drop)) {
659 for($i=0; $i < (count($grade_array) - $drop); $i++
) {
660 $ret_grades["$i"] = $grade_array["$i"];
662 if (isset($ret_grades)) {
663 $grades = implode(',',$ret_grades);
672 function grade_get_grades() {
675 $mods = grade_get_grade_items($course->id
);
676 $preferences = grade_get_preferences($course->id
);
679 foreach ($mods as $mod) {
680 // hidden is a gradebook setting for an assignment and visible is a course_module setting
681 if (($mod->hidden
!= 1 && $mod->visible
==1) or (has_capability('moodle/course:viewhiddenactivities', get_context_instance(CONTEXT_MODULE
, $mod->id
)) && $preferences->show_hidden
==1)) {
682 $libfile = "$CFG->dirroot/mod/$mod->modname/lib.php";
683 if (file_exists($libfile)) {
684 require_once($libfile);
685 $gradefunction = $mod->modname
."_grades";
686 if ($grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"] = $gradefunction($mod->cminstance
)) {
687 // added grades for particular mod
688 // now get the grade_item modifiers ie. scale_grade and extra credit
689 $scale_grade = get_record('grade_item', 'courseid', $course->id
, 'cminstance', $mod->cminstance
, 'modid', $mod->modid
);
691 if (isset($scale_grade)) {
692 $grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"]->scale_grade
= $scale_grade->scale_grade
;
693 $grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"]->extra_credit
= $scale_grade->extra_credit
;
696 $grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"]->scale_grade
= 1.00;
697 $grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"]->extra_credit
= 0;
700 if ($mod->hidden
!= 1 && $mod->visible
==1) {
701 $grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"]->hidden
= 0;
704 $grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"]->hidden
= 1;
707 $grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"]->sort_order
= $scale_grade->sort_order
;
709 // I don't think this should be necessary but it appears that the forum doesn't follow the grades API properly it returns blank or NULL when it
710 // should return a value for maxgrade according to the moodle API... so if it doesn't want to give us a grade let's not use it.
711 // this happens when grading is set to a non-numeric for a forum ie. uses "seperate and connected ways of knowing"
712 if ($grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"]->maxgrade
== '')
714 $grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"]->maxgrade
= 100;
715 //unset($grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"]);
719 // delete this item from the grade_item table since it was deleted through the mod interface
720 delete_records('grade_item', 'modid', $mods->modid
, 'courseid', $course->id
);
721 delete_records('grade_exceptions', 'grade_itemid', $mod->id
, 'courseid', $course->id
);
725 //echo "<center><font color=red>Could not find lib file for $mod->modid</font></center>";
731 // Do something here for no grades
732 //echo "<center><font color=red>No grades returned. It appears that there are no items with grades for this course.</font></center>";
734 if (isset($grades)) {
742 function grade_set_uncategorized() {
743 // this function checks to see if any mods have not been assigned a category and sets them to uncategorized.
746 $uncat = UNCATEGORISED
;
748 $uncat_id = get_record('grade_category', 'courseid', $course->id
, 'name', $uncat);
751 // insert the uncategorized category
753 $temp->courseid
=$course->id
;
754 $temp->drop_x_lowest
= 0;
755 $temp->bonus_points
= 0;
757 $temp->weight
= 100.00;
759 insert_record('grade_category', $temp);
760 $uncat_id = get_record('grade_category', 'courseid', $course->id
, 'name', $uncat);
762 error(get_string('errornocategorizedid','grades'));
768 /// Collect modules data
769 get_all_mods($course->id
, $mods, $modnames, $modnamesplural, $modnamesused);
772 // this will let us establish the order for gradebook item display
775 /// Search through all the modules, pulling out grade data
776 $sections = get_all_sections($course->id
); // Sort everything the same as the course
777 for ($i=0; $i<=$course->numsections
; $i++
) {
778 if (isset($sections["$i"])) { // should always be true
779 $section = $sections["$i"];
780 if ($section->sequence
) {
781 $sectionmods = explode(",", $section->sequence
);
782 foreach ($sectionmods as $sectionmod) {
783 if (isset($mods["$sectionmod"])) {
784 $mod = $mods["$sectionmod"];
785 $instance = get_record("$mod->modname", "id", "$mod->instance");
786 $libfile = "$CFG->dirroot/mod/$mod->modname/lib.php";
787 if (file_exists($libfile)) {
788 require_once($libfile);
789 $gradefunction = $mod->modname
."_grades";
790 if (function_exists($gradefunction)) { // Skip modules without grade function
791 if ($modgrades = $gradefunction($mod->instance
)) {
793 //modgrades contains student information with associated grade
794 //echo "<b>modname: $mod->modname id: $mod->id course: $mod->course</b><br/>";
795 // get instance name from db.
796 $instance = get_record($mod->modname
, 'id', $mod->instance
);
797 // see if the item is already in the category table and if it is call category select with the id so it is selected
798 get_record('modules', 'name', $mod->modname
);
799 $item = get_record('grade_item', 'courseid', $course->id
, 'modid', $mod->module
, 'cminstance', $mod->instance
);
801 // set the item to uncategorized in grade_item
802 $item->courseid
= $course->id
;
803 $item->category
= $uncat_id->id
;
804 $item->modid
= $mod->module
;
805 $item->cminstance
= $mod->instance
;
806 $item->id
= insert_record('grade_item', $item);
808 else if ($item->category
== 0) {
809 // this catches any errors where they may have some wierd category set
810 set_field('grade_item', 'category', $uncat_id->id
, 'id', $item->id
);
812 set_field('grade_item', 'sort_order', $sort, 'id', $item->id
);
824 // sorting functions for grades
825 function grade_sort_by_lastname($x,$y)
827 //$grades_by_student["$student->userid"]['student_data']['firstname'] = $student->firstname;
828 //$grades_by_student["$student->userid"]['student_data']['lastname'] = $student->lastname;
829 if (strnatcasecmp($x['student_data']['lastname'],$y['student_data']['lastname']) == 0) {
830 return strnatcasecmp($x['student_data']['firstname'],$y['student_data']['firstname']);
833 return strnatcasecmp($x['student_data']['lastname'],$y['student_data']['lastname']);
837 function grade_sort_by_firstname($x,$y)
839 //$grades_by_student["$student->userid"]['student_data']['firstname'] = $student->firstname;
840 //$grades_by_student["$student->userid"]['student_data']['lastname'] = $student->lastname;
841 if (strnatcasecmp($x['student_data']['firstname'],$y['student_data']['firstname']) == 0) {
842 return strnatcasecmp($x['student_data']['lastname'],$y['student_data']['lastname']);
845 return strnatcasecmp($x['student_data']['firstname'],$y['student_data']['firstname']);
849 function grade_sort_by_points($x,$y) {
850 if ($x['student_data']['points'] == $y['student_data']['points']) {
851 return grade_sort_by_lastname($x,$y);
854 if ($x['student_data']['points'] > $y['student_data']['points'])
861 function grade_sort_by_points_asc($x,$y) {
862 if ($x['student_data']['points'] == $y['student_data']['points']) {
863 return grade_sort_by_lastname($x,$y);
866 if ($x['student_data']['points'] < $y['student_data']['points'])
873 function grade_sort_by_weighted($x,$y) {
874 if ($x['student_data']['weighted'] == $y['student_data']['weighted']) {
875 return grade_sort_by_lastname($x,$y);
878 if ($x['student_data']['weighted'] > $y['student_data']['weighted'])
885 function grade_sort_by_percent($x,$y) {
886 if ($x['student_data']['percent'] == $y['student_data']['percent']) {
887 return grade_sort_by_lastname($x,$y);
890 if ($x['student_data']['percent'] > $y['student_data']['percent'])
897 function grade_sort_by_percent_asc($x,$y) {
898 if ($x['student_data']['percent'] == $y['student_data']['percent']) {
899 return grade_sort_by_lastname($x,$y);
902 if ($x['student_data']['percent'] < $y['student_data']['percent'])
909 function grade_sort_by_weighted_asc($x,$y) {
910 if ($x['student_data']['weighted'] == $y['student_data']['weighted']) {
911 return grade_sort_by_lastname($x,$y);
914 if ($x['student_data']['weighted'] < $y['student_data']['weighted'])
921 function grade_sort_by_highgrade_category($x,$y) {
925 $cview = optional_param('cview');
928 if ($x["$cview"]['stats']['points'] == $y["$cview"]['stats']['points']) {
929 return grade_sort_by_lastname($x,$y);
932 return ($y["$cview"]['stats']['points'] - $x["$cview"]['stats']['points']);
936 function grade_sort_by_highgrade_category_asc($x,$y) {
940 $cview = optional_param('cview');
942 if ($x["$cview"]['stats']['points'] == $y["$cview"]['stats']['points']) {
943 return grade_sort_by_lastname($x,$y);
946 return ($x["$cview"]['stats']['points'] - $y["$cview"]['stats']['points']);
951 function grade_set_preference($courseid, $name, $value) {
954 if (false !== ($key = array_search($name, $GRADEPREFS))) {
955 if ($record = get_record('grade_preferences', 'courseid', $courseid, 'preference', $key)) {
956 $record->value
= $value;
957 update_record('grade_preferences', $record);
958 } else { // Make a new one
959 $record->preference
= $key;
960 $record->courseid
= $courseid;
961 $record->value
= $value;
962 insert_record('grade_preferences', $record);
967 function grade_get_preference($courseid, $name) {
968 global $GRADEPREFS, $GRADEPREFSDEFAULTS;
970 if (false !== ($key = array_search($name, $GRADEPREFS))) {
971 if (!($record = get_record('grade_preferences', 'courseid', $courseid, 'preference', $key))) {
973 $record->preference
= $key;
974 $record->courseid
= $courseid;
975 $record->value
= $GRADEPREFSDEFAULTS[$name];
976 insert_record('grade_preferences', $record);
978 return $record->value
;
983 function grade_get_preferences($courseid) {
985 global $GRADEPREFS, $GRADEPREFSDEFAULTS;
989 // Get the preferences for the course.
990 if ($rawprefs = get_records('grade_preferences', 'courseid', $courseid)) {
991 foreach ($rawprefs as $pref) {
992 if (isset($GRADEPREFS[$pref->preference
])) { // Valid pref
993 $name = $GRADEPREFS[$pref->preference
];
994 $preferences->$name = $pref->value
;
999 // Check for any missing ones and create them from defaults
1000 // We don't save them in the database so we save space
1001 foreach ($GRADEPREFS as $number => $name) {
1002 if (!isset($preferences->$name)) {
1003 $preferences->$name = $GRADEPREFSDEFAULTS[$name];
1007 // Construct some other ones about which fields are shown
1009 $isteacher = has_capability('moodle/course:managegrades', get_context_instance(CONTEXT_COURSE
, $courseid));
1011 $preferences->show_weighted
= (($preferences->display_weighted
> 0 && $isteacher) ||
1012 ($preferences->display_weighted
> 1 && !$isteacher));
1014 $preferences->show_points
= (($preferences->display_points
> 0 && $isteacher) ||
1015 ($preferences->display_points
> 1 && !$isteacher));
1017 $preferences->show_percent
= (($preferences->display_percent
> 0 && $isteacher) ||
1018 ($preferences->display_percent
> 1 && !$isteacher));
1020 $preferences->show_letters
= (($preferences->display_letters
> 0 && $isteacher) ||
1021 ($preferences->display_letters
> 1 && !$isteacher));
1023 return $preferences;
1027 function grade_set_preferences($course, $newprefs) {
1029 if (!isset($newprefs->use_advanced
) or ($newprefs->use_advanced
== 1)) {
1030 foreach ($newprefs as $name => $value) { /// Just save them all
1031 grade_set_preference($course->id
, $name, $value);
1036 /// We don't need advanced features, and we need to unset all extra features
1037 /// So they don't affect grades (This approach should be revisited because it resets everything!!)
1039 grade_set_preference($course->id
, 'use_advanced', 0);
1040 grade_set_preference($course->id
, 'use_weighted_for_letter', 0);
1041 grade_set_preference($course->id
, 'display_weighted', 0);
1042 grade_set_preference($course->id
, 'display_points', 2);
1043 grade_set_preference($course->id
, 'display_percent', 0);
1044 grade_set_preference($course->id
, 'display_letters', 0);
1046 /// Lose all exceptions
1047 delete_records('grade_exceptions', 'courseid', $course->id
);
1049 if (!$uncat = get_record('grade_category', 'courseid', $course->id
, 'name', UNCATEGORISED
)) {
1050 /// Make a category for uncategorised stuff
1051 $uncat->name
=UNCATEGORISED
;
1052 $uncat->courseid
=$course->id
;
1053 if (!$uncat->id
= insert_record('grade_category', $uncat)) {
1054 error(get_string('errornocategorizedid','grades'));
1058 set_field('grade_item', 'category', $uncat->id
, 'courseid', $course->id
);
1059 set_field('grade_item', 'scale_grade', 1.00, 'courseid', $course->id
);
1060 set_field('grade_item', 'extra_credit', 0, 'courseid', $course->id
);
1062 set_field('grade_category', 'weight', 100.0, 'courseid', $course->id
, 'id', $uncat->id
);
1063 set_field('grade_category', 'bonus_points', '0', 'courseid', $course->id
);
1067 function grade_preferences_menu($action, $course, $group=0) {
1069 if (!has_capability('moodle/course:managegrades', get_context_instance(CONTEXT_COURSE
, $course->id
))) {
1073 // remap some actions to simplify later code
1076 case 'set_grade_preferences':
1077 $curraction = 'prefs';
1083 case 'insert_category':
1084 case 'assign_categories':
1085 case 'delete_category':
1086 $curraction = 'cats';
1088 case 'set_grade_weights':
1090 $curraction = 'weights';
1093 case 'set_letter_grades':
1094 $curraction = 'letters';
1096 case 'view_student_grades':
1097 case 'view_student_category_grades':
1099 $curraction = 'grades';
1102 $curraction = 'excepts';
1106 $curraction = 'grades';
1109 $tabs = $row = array();
1110 $row[] = new tabobject('grades', 'index.php?id='.$course->id
,
1111 get_string('viewgrades', 'grades'));
1112 $row[] = new tabobject('prefs', 'index.php?id='.$course->id
.'&action=prefs',
1113 get_string('setpreferences', 'grades'));
1114 // only show the extra options if advanced is turned on, they don't do anything otherwise
1115 if (grade_get_preference($course->id
, 'use_advanced') == 1) {
1116 $row[] = new tabobject('cats', 'index.php?id='.$course->id
.'&action=cats',
1117 get_string('setcategories', 'grades'));
1118 $row[] = new tabobject('weights', 'index.php?id='.$course->id
.'&action=weights',
1119 get_string('setweights', 'grades'));
1120 $row[] = new tabobject('letters', 'index.php?id='.$course->id
.'&action=letters',
1121 get_string('setgradeletters', 'grades'));
1122 $row[] = new tabobject('excepts', 'exceptions.php?id='.$course->id
.'&action=excepts',
1123 get_string('gradeexceptions', 'grades'));
1127 print_tabs($tabs, $curraction);
1131 function grade_nav($course, $action='grades') {
1136 $strgrades = get_string('grades', 'grades');
1137 $gradenav = "<a href=\"$CFG->wwwroot/course/view.php?id=$course->id\">$course->shortname</a>";
1139 if (has_capability('moodle/course:managegrades', get_context_instance(CONTEXT_COURSE
, $course->id
))) {
1142 case 'set_grade_preferences':
1143 $strcurpage = get_string('setpreferences','grades');
1146 case 'delete_category':
1148 case 'insert_category':
1149 case 'assign_categories':
1150 $strcurpage = get_string('setcategories','grades');
1153 case 'set_grade_weights':
1154 $strcurpage = get_string('setweights','grades');
1156 case 'set_letter_grades':
1158 $strcurpage = get_string('setgradeletters','grades');
1161 $strcurpage = get_string('gradeexceptions', 'grades');
1168 if ($action=='grades') {
1169 $gradenav .= " -> $strgrades";
1171 $gradenav .= " -> <a href=\"index.php?id=$course->id&action=grades\">$strgrades</a>";
1174 // if we are on a grades sub-page provide a link back (including grade preferences and grade items
1176 if (isset($strcurpage)) {
1177 $gradenav .= " -> $strcurpage";
1178 } else if($action =='vcats') {
1179 // show sub category
1180 if (isset($cview)) {
1181 $gradenav .= " -> $cview";
1186 $gradenav .= " -> $strgrades";
1192 function grade_download($download, $id) {
1197 if (! $course = get_record("course", "id", $id)) {
1198 error("Course ID was incorrect");
1201 require_capability('moodle/course:viewcoursegrades', get_context_instance(CONTEXT_COURSE
, $id));
1203 $strgrades = get_string("grades");
1204 $strgrade = get_string("grade");
1205 $strmax = get_string("maximumshort");
1206 $stractivityreport = get_string("activityreport");
1208 /// Check to see if groups are being used in this course
1209 if ($groupmode = groupmode($course)) { // Groups are being used
1210 if (isset($_GET['group'])) {
1211 $changegroup = $_GET['group']; /// 0 or higher
1213 $changegroup = -1; /// This means no group change was specified
1216 $currentgroup = get_and_set_current_group($course, $groupmode, $changegroup);
1218 $currentgroup = false;
1221 if ($currentgroup) {
1222 $students = get_group_students($currentgroup, "u.lastname ASC");
1224 $students = grade_get_course_students($course->id
);
1227 if (!empty($students)) {
1228 foreach ($students as $student) {
1229 $grades[$student->id
] = array(); // Collect all grades in this array
1230 $gradeshtml[$student->id
] = array(); // Collect all grades html formatted in this array
1231 $totals[$student->id
] = array(); // Collect all totals in this array
1234 $columns = array(); // Accumulate column names in this array.
1235 $columnhtml = array(); // Accumulate column html in this array.
1238 /// Collect modules data
1239 get_all_mods($course->id
, $mods, $modnames, $modnamesplural, $modnamesused);
1241 /// Search through all the modules, pulling out grade data
1242 $sections = get_all_sections($course->id
); // Sort everything the same as the course
1243 for ($i=0; $i<=$course->numsections
; $i++
) {
1244 if (isset($sections[$i])) { // should always be true
1245 $section = $sections[$i];
1246 if ($section->sequence
) {
1247 $sectionmods = explode(",", $section->sequence
);
1248 foreach ($sectionmods as $sectionmod) {
1249 $mod = $mods[$sectionmod];
1250 $instance = get_record("$mod->modname", "id", "$mod->instance");
1251 $libfile = "$CFG->dirroot/mod/$mod->modname/lib.php";
1253 if (file_exists($libfile)) {
1254 require_once($libfile);
1255 $gradefunction = $mod->modname
."_grades";
1256 if (function_exists($gradefunction)) { // Skip modules without grade function
1257 if ($modgrades = $gradefunction($mod->instance
)) {
1258 if (!empty($modgrades->maxgrade
)) {
1259 if ($mod->visible
) {
1260 $maxgrade = "$strmax: $modgrades->maxgrade";
1262 $maxgrade = "$strmax: $modgrades->maxgrade";
1268 $columns[] = "$mod->modfullname: ".format_string($instance->name
,true)." - $maxgrade";
1270 if (!empty($students)) {
1271 foreach ($students as $student) {
1272 if (!empty($modgrades->grades
[$student->id
])) {
1273 $grades[$student->id
][] = $currentstudentgrade = $modgrades->grades
[$student->id
];
1275 $grades[$student->id
][] = $currentstudentgrade = "";
1276 $gradeshtml[$student->id
][] = "";
1278 if (!empty($modgrades->maxgrade
)) {
1279 $totals[$student->id
] = (float)($totals[$student->id
]) +
(float)($currentstudentgrade);
1281 $totals[$student->id
] = (float)($totals[$student->id
]) +
0;
1291 } // a new Moodle nesting record? ;-)
1293 /// OK, we have all the data, now present it to the user
1294 /// OK, we have all the data, now present it to the user
1295 if ($download == "ods" and confirm_sesskey()) {
1296 require_once("../lib/odslib.class.php");
1298 /// Calculate file name
1299 $downloadfilename = clean_filename("$course->shortname $strgrades.ods");
1300 /// Creating a workbook
1301 $workbook = new MoodleODSWorkbook("-");
1302 /// Sending HTTP headers
1303 $workbook->send($downloadfilename);
1304 /// Adding the worksheet
1305 $myxls =& $workbook->add_worksheet($strgrades);
1307 /// Print names of all the fields
1308 $myxls->write_string(0,0,get_string("firstname"));
1309 $myxls->write_string(0,1,get_string("lastname"));
1310 $myxls->write_string(0,2,get_string("idnumber"));
1311 $myxls->write_string(0,3,get_string("institution"));
1312 $myxls->write_string(0,4,get_string("department"));
1313 $myxls->write_string(0,5,get_string("email"));
1315 foreach ($columns as $column) {
1316 $myxls->write_string(0,$pos++
,strip_tags($column));
1318 $myxls->write_string(0,$pos,get_string("total"));
1320 /// Print all the lines of data.
1322 if (!empty($grades)) {
1323 foreach ($grades as $studentid => $studentgrades) {
1325 $student = $students[$studentid];
1326 if (empty($totals[$student->id
])) {
1327 $totals[$student->id
] = '';
1330 $myxls->write_string($i,0,$student->firstname
);
1331 $myxls->write_string($i,1,$student->lastname
);
1332 $myxls->write_string($i,2,$student->idnumber
);
1333 $myxls->write_string($i,3,$student->institution
);
1334 $myxls->write_string($i,4,$student->department
);
1335 $myxls->write_string($i,5,$student->email
);
1337 foreach ($studentgrades as $grade) {
1338 if (is_numeric($grade)) {
1339 $myxls->write_number($i,$j++
,strip_tags($grade));
1342 $myxls->write_string($i,$j++
,strip_tags($grade));
1345 $myxls->write_number($i,$j,$totals[$student->id
]);
1349 /// Close the workbook
1354 } else if ($download == "xls" and confirm_sesskey()) {
1355 require_once("../lib/excellib.class.php");
1357 /// Calculate file name
1358 $downloadfilename = clean_filename("$course->shortname $strgrades.xls");
1359 /// Creating a workbook
1360 $workbook = new MoodleExcelWorkbook("-");
1361 /// Sending HTTP headers
1362 $workbook->send($downloadfilename);
1363 /// Adding the worksheet
1364 $myxls =& $workbook->add_worksheet($strgrades);
1366 /// Print names of all the fields
1367 $myxls->write_string(0,0,get_string("firstname"));
1368 $myxls->write_string(0,1,get_string("lastname"));
1369 $myxls->write_string(0,2,get_string("idnumber"));
1370 $myxls->write_string(0,3,get_string("institution"));
1371 $myxls->write_string(0,4,get_string("department"));
1372 $myxls->write_string(0,5,get_string("email"));
1374 foreach ($columns as $column) {
1375 $myxls->write_string(0,$pos++
,strip_tags($column));
1377 $myxls->write_string(0,$pos,get_string("total"));
1379 /// Print all the lines of data.
1381 if (!empty($grades)) {
1382 foreach ($grades as $studentid => $studentgrades) {
1384 $student = $students[$studentid];
1385 if (empty($totals[$student->id
])) {
1386 $totals[$student->id
] = '';
1389 $myxls->write_string($i,0,$student->firstname
);
1390 $myxls->write_string($i,1,$student->lastname
);
1391 $myxls->write_string($i,2,$student->idnumber
);
1392 $myxls->write_string($i,3,$student->institution
);
1393 $myxls->write_string($i,4,$student->department
);
1394 $myxls->write_string($i,5,$student->email
);
1396 foreach ($studentgrades as $grade) {
1397 if (is_numeric($grade)) {
1398 $myxls->write_number($i,$j++
,strip_tags($grade));
1401 $myxls->write_string($i,$j++
,strip_tags($grade));
1404 $myxls->write_number($i,$j,$totals[$student->id
]);
1408 /// Close the workbook
1413 } else if ($download == "txt" and confirm_sesskey()) {
1415 /// Print header to force download
1417 header("Content-Type: application/download\n");
1418 $downloadfilename = clean_filename("$course->shortname $strgrades");
1419 header("Content-Disposition: attachment; filename=\"$downloadfilename.txt\"");
1421 /// Print names of all the fields
1423 echo get_string("firstname")."\t".
1424 get_string("lastname")."\t".
1425 get_string("idnumber")."\t".
1426 get_string("institution")."\t".
1427 get_string("department")."\t".
1428 get_string("email");
1429 foreach ($columns as $column) {
1430 $column = strip_tags($column);
1433 echo "\t".get_string("total")."\n";
1435 /// Print all the lines of data.
1436 foreach ($grades as $studentid => $studentgrades) {
1437 $student = $students[$studentid];
1438 if (empty($totals[$student->id
])) {
1439 $totals[$student->id
] = '';
1441 echo "$student->firstname\t$student->lastname\t$student->idnumber\t$student->institution\t$student->department\t$student->email";
1442 foreach ($studentgrades as $grade) {
1443 $grade = strip_tags($grade);
1446 echo "\t".$totals[$student->id
];
1452 }else if ($download == '' and confirm_sesskey()) {
1453 error("No file type specified");
1458 function grade_get_stats($category='all') {
1459 list($grades_by_student, $all_categories) = grade_get_formatted_grades();
1461 if ($grades_by_student != 0 && $all_categories != 0) {
1465 //populate the sum of student points, # items and totalpoints for each category
1466 foreach($grades_by_student as $student=>$categories) {
1467 foreach($categories as $cur_category=>$assignments) {
1468 if($category != 'student_data') {
1469 if (isset($assignments['stats'])) {
1470 if (isset($stats[$cur_category]['sum'])) {
1471 $stats[$cur_category]['sum'] = $stats[$cur_category]['sum'] +
$assignments['stats']['points'];
1474 $stats[$cur_category]['sum'] = $assignments['stats']['points'];
1476 $stats[$cur_category]['items'] = $assignments['stats']['grade_items'];
1477 $stats[$cur_category]['totalpoints'] = $assignments['stats']['totalpoints'];
1478 $stats[$cur_category]['weight'] = $all_categories[$cur_category]['stats']['weight'];
1483 // populate the overall sum,items and totalpoints
1484 foreach($stats as $cur_category=>$info) {
1485 if($cur_category != 'all' && $cur_category != 'student_data') {
1487 if ($stats[$cur_category]['totalpoints'] == get_string('excluded', 'grades')) {
1488 $stats[$cur_category]['totalpoints'] = 1;
1489 $stats['all']['sum'] = $stats['all']['sum'] +
$stats[$cur_category]['sum'];
1490 $stats['all']['items'] = $stats['all']['items'] +
$stats[$cur_category]['items'];
1491 $stats['all']['totalpoints'] = $stats['all']['totalpoints'] +
$stats[$cur_category]['totalpoints'];
1492 $stats['all']['weighted_sum'] = $stats['all']['weighted_sum'] +
($stats[$cur_category]['sum']/($stats[$cur_category]['totalpoints']))*$stats[$cur_category]['weight'];
1495 else if (isset($stats['all'])) {
1496 $stats['all']['sum'] = $stats['all']['sum'] +
$stats[$cur_category]['sum'];
1497 $stats['all']['items'] = $stats['all']['items'] +
$stats[$cur_category]['items'];
1498 $stats['all']['totalpoints'] = $stats['all']['totalpoints'] +
$stats[$cur_category]['totalpoints'];
1499 $stats['all']['weighted_sum'] = $stats['all']['weighted_sum'] +
($stats[$cur_category]['sum']/($stats[$cur_category]['totalpoints']))*$stats[$cur_category]['weight'];
1502 $stats['all']['sum'] = $stats[$cur_category]['sum'];
1503 $stats['all']['items'] = $stats[$cur_category]['items'];
1504 $stats['all']['totalpoints'] = $stats[$cur_category]['totalpoints'];
1505 $stats['all']['weighted_sum'] = ($stats[$cur_category]['sum']/($stats[$cur_category]['totalpoints']))*$stats[$cur_category]['weight'];
1510 $stats['all']['students'] = count($grades_by_student);
1511 $stats['all']['average'] = $stats['all']['sum'] / $stats['all']['students'];
1512 $stats['all']['average_weighted'] = $stats['all']['weighted_sum']/$stats['all']['students'];
1514 // calculate the average squared deviation and populate a list of all scores while we're at it
1515 $stats['all']['avgsqddev'] = 0;
1516 $stats['all']['avgsqddev_weighted'] = 0;
1517 foreach($grades_by_student as $student=>$categories) {
1518 foreach($categories as $cur_category=>$assignments) {
1519 if ($cur_category != 'student_data') {
1520 $stats['all']['avgsqddev'] = $stats['all']['avgsqddev'] +
pow(($grades_by_student[$student]['student_data']['points']-$stats['all']['average']),2);
1521 $stats['all']['avgsqddev_weighted'] = $stats['all']['avgsqddev_weighted'] +
pow(($grades_by_student[$student]['student_data']['weighted']-$stats['all']['average_weighted']),2);
1524 if (isset($stats['all']['all_scores'])) {
1525 $stats['all']['all_scores'] .= ','.$grades_by_student[$student]['student_data']['points'];
1526 $stats['all']['all_scores_weighted'] .= ','.$grades_by_student[$student]['student_data']['weighted'];
1529 $stats['all']['all_scores'] = $grades_by_student[$student]['student_data']['points'];
1530 $stats['all']['all_scores_weighted'] = $grades_by_student[$student]['student_data']['weighted'];
1533 $stats['all']['avgsqddev']=$stats['all']['avgsqddev']/$stats['all']['students'];
1534 $stats['all']['avgsqddev_weighted']=$stats['all']['avgsqddev_weighted']/$stats['all']['students'];
1535 $stats['all']['stddev'] = sqrt($stats['all']['avgsqddev']);
1536 $stats['all']['stddev_weighted'] = sqrt($stats['all']['avgsqddev_weighted']);
1537 $stats['all']['mode'] = grade_mode($stats['all']['all_scores']);
1538 $stats['all']['mode_weighted'] = grade_mode($stats['all']['all_scores_weighted']);
1540 // make sure the mode is not set to every score
1541 if(count($stats['all']['mode']) == count($grades_by_student)) {
1542 $stats['all']['mode'] = get_string('nomode','grade');
1544 if(count($stats['all']['mode_weighted']) == count($grades_by_student)) {
1545 $stats['all']['mode_weighted'] = get_string('nomode','grade');
1551 // get the stats for category
1552 //populate the sum of student points, # items and totalpoints for each category
1553 foreach($grades_by_student as $student=>$categories) {
1554 if(isset($grades_by_student[$student][$category]['stats'])) {
1555 if (isset($stats[$category]['sum'])) {
1556 $stats[$category]['sum'] = $stats[$category]['sum'] +
$grades_by_student[$student][$category]['stats']['points'];
1559 $stats[$category]['sum'] = $grades_by_student[$student][$category]['stats']['points'];
1561 $stats[$category]['items'] = $grades_by_student[$student][$category]['stats']['grade_items'];
1562 $stats[$category]['totalpoints'] = $grades_by_student[$student][$category]['stats']['totalpoints'];
1565 $stats[$category]['students'] = count($grades_by_student);
1566 $stats[$category]['average'] = $stats[$category]['sum']/$stats[$category]['students'];
1568 // calculate the average squared deviation and populate a list of all scores too
1569 $stats[$category]['avgsqddev'] = 0;
1570 foreach($grades_by_student as $student=>$categories) {
1571 foreach($categories as $cur_category=>$assignment) {
1572 if ($cur_category != 'student_data') {
1573 if ($grades_by_student[$student][$category]['stats']['points'] == '-' ||
$grades_by_student[$student][$category]['stats']['points'] == get_string('grades','excluded')) {
1574 // count grade as a zero
1575 $stats[$category]['avgsqddev'] = $stats[$category]['avgsqddev'] +
pow(($stats[$category]['average']),2);
1578 $stats[$category]['avgsqddev'] = $stats[$category]['avgsqddev'] +
pow(($grades_by_student[$student][$category]['stats']['points']-$stats[$category]['average']),2);
1583 if (isset($stats[$category]['all_scores'])) {
1584 $stats[$category]['all_scores'] .= ','.$grades_by_student[$student][$category]['stats']['points'];
1587 $stats[$category]['all_scores'] = $grades_by_student[$student][$category]['stats']['points'];
1590 $stats[$category]['avgsqddev'] = $stats[$category]['avgsqddev']/$stats[$category]['students'];
1591 $stats[$category]['stddev'] = sqrt($stats[$category]['avgsqddev']);
1592 $stats[$category]['mode'] = grade_mode($stats[$category]['all_scores']);
1596 // do a little cleanup
1597 $stats[$category]['stddev'] = sprintf("%0.2f", $stats[$category]['stddev']);
1598 $stats[$category]['average'] = sprintf("%0.2f", $stats[$category]['average']);
1599 $stats[$category]['max'] = max(explode(',',$stats[$category]['all_scores']));
1600 $stats[$category]['min'] = min(explode(',',$stats[$category]['all_scores']));
1601 $stats[$category]['median'] = explode(',',$stats[$category]['all_scores']);
1603 if (isset($stats[$category]['stddev_weighted'])) {
1604 $stats[$category]['stddev_weighted'] = sprintf("%0.2f", $stats[$category]['stddev_weighted']);
1606 if (isset($stats[$category]['average_weighted'])) {
1607 $stats[$category]['average_weighted'] = sprintf("%0.2f", $stats[$category]['average_weighted']);
1609 if (isset($stats[$category]['max_weighted'])) {
1610 $stats[$category]['max_weighted'] = max(explode(',',$stats[$category]['all_scores_weighted']));
1612 if (isset($stats[$category]['min_weighted'])) {
1613 $stats[$category]['min_weighted'] = min(explode(',',$stats[$category]['all_scores_weighted']));
1616 if (isset($stats[$category]['all_scores_weighted'])) {
1617 $stats[$category]['median_weighted'] = explode(',',$stats[$category]['all_scores_weighted']);
1624 sort($stats[$category]['median']);
1626 if (count($stats[$category]['median'])/2 == floor(count($stats[$category]['median'])/2) ) {
1627 // even number of scores
1628 $temp = $stats[$category]['median'][count($stats[$category]['median'])/2-1] +
$stats[$category]['median'][count($stats[$category]['median'])/2];
1632 // odd number of scores
1633 $temp = $stats[$category]['median'][floor(count($stats[$category]['median'])/2)];
1635 unset($stats[$category]['median']);
1636 $stats[$category]['median'] = $temp;
1638 if (isset($stats[$category]['median_weighted'])) {
1639 if (count($stats[$category]['median_weighted'])/2 == floor(count($stats[$category]['median_weighted'])/2)) {
1640 // even number of scores
1641 $temp = $stats[$category]['median_weighted'][count($stats[$category]['median_weighted'])/2-1] +
$stats[$category]['median_weighted'][count($stats[$category]['median_weighted'])/2+
1];
1645 // odd number of scores
1646 $temp = $stats[$category]['median_weighted'][floor(count($stats[$category]['median_weighted'])/2)];
1648 unset($stats[$category]['median_weighted']);
1649 $stats[$category]['median_weighted'] = $temp;
1655 // returns a comma seperated list of the most common values in $items, $items is expected to be a comma sperated list of numbers
1656 function grade_mode($items) {
1657 $all_scores = explode(',',$items);
1658 foreach($all_scores as $value) {
1659 if (isset($frequency[$value])) {
1660 $frequency[$value]++
;
1663 $frequency[$value] = 1;
1666 $max = max($frequency);
1667 foreach($frequency as $key=>$value) {
1668 if ($value == $max) {
1669 if (isset($retval)) {
1670 $retval .= ', '.$key;
1681 function grade_stats() {
1685 global $preferences;
1687 if (!isset($category)) {
1688 $category = clean_param($_REQUEST['category'], PARAM_CLEAN
);
1691 $stats = grade_get_stats($category);
1695 echo '<table align="center"><tr><th colspan="3" scope="col">'.$category.' '.get_string('stats','grades').'</th></tr>';
1696 if ($preferences->show_weighted
== 1 && $preferences->use_weighted_for_letter
== 1 && $category== 'all') {
1697 echo '<tr><th scope="col"> </th><th scope="col">'.get_string('points','grades').'<th scope="col">'.get_string('weight','grades').'</th></tr>';
1700 echo '<tr><td align="right">'.get_string('max','grades').':</td><td align="right">'.$stats[$category]['max'].'</td>';
1701 if ($preferences->show_weighted
== 1 && $preferences->use_weighted_for_letter
== 1 && $category== 'all') {
1702 echo '<td align="right">'.$stats[$category]['max_weighted'].'</td>';
1706 echo '<tr><td align="right">'.get_string('min','grades').':</td><td align="right">'.$stats[$category]['min'].'</td>';
1707 if ($preferences->show_weighted
== 1 && $preferences->use_weighted_for_letter
== 1 && $category== 'all') {
1708 echo '<td align="right">'.$stats[$category]['min_weighted'].'</td>';
1712 echo '<tr><td align="right">'.get_string('average','grades').':</td><td align="right">'.$stats[$category]['average'].'</td>';
1713 if ($preferences->show_weighted
== 1 && $preferences->use_weighted_for_letter
== 1 && $category== 'all') {
1714 echo '<td align="right">'.$stats[$category]['average_weighted'].'</td>';
1718 echo '<tr><td align="right">'.get_string('median','grades').':</td><td align="right">'.$stats[$category]['median'].'</td>';
1719 if ($preferences->show_weighted
== 1 && $preferences->use_weighted_for_letter
== 1 && $category== 'all') {
1720 echo '<td align="right">'.$stats[$category]['median_weighted'].'</td>';
1724 echo '<tr><td align="right">'.get_string('mode','grades').':</td><td align="right">'.$stats[$category]['mode'].'</td>';
1725 if ($preferences->show_weighted
== 1 && $preferences->use_weighted_for_letter
== 1 && $category== 'all') {
1726 echo '<td align="right">'.$stats[$category]['mode_weighted'].'</td>';
1730 echo '<tr><td align="right">'.get_string('standarddeviation','grades').':</td><td align="right">'.$stats[$category]['stddev'].'</td>';
1731 if ($preferences->show_weighted
== 1 && $preferences->use_weighted_for_letter
== 1 && $category== 'all') {
1732 echo '<td align="right">'.$stats[$category]['stddev_weighted'].'</td>';
1739 function grade_view_category_grades($view_by_student) {
1743 global $preferences;
1746 $context = get_context_instance(CONTEXT_COURSE
, $course->id
);
1748 // if can't see course grades, print single grade view
1749 if (!has_capability('moodle/course:viewcoursegrades', $context)) {
1750 return print_student_grade($USER, $course);
1753 if ($preferences->use_advanced
== 0) {
1754 $cview = UNCATEGORISED
;
1757 $cview=clean_param($_REQUEST['cview'], PARAM_CLEAN
);
1761 list($grades_by_student, $all_categories) = grade_get_formatted_grades();
1763 if ($grades_by_student != 0 && $all_categories != 0) {
1764 // output a form for the user to download the grades.
1765 grade_download_form();
1767 if ($view_by_student != -1) {
1768 // unset all grades except for this student
1769 foreach ($grades_by_student as $student=>$junk) {
1770 if($student != $view_by_student) {
1771 unset($grades_by_student[$student]);
1776 $grade_columns = $preferences->show_weighted +
$preferences->show_points +
$preferences->show_percent
;
1782 if (has_capability('moodle/course:viewcoursegrades', $context)) {
1783 $student_heading_link = get_string('student','grades');
1784 //only set sorting links if more than one student displayed.
1785 if ($view_by_student == -1) {
1786 $student_heading_link .='<br /><a href="?id='.$course->id
.'&group='.$group.'&action=vcats&cview='.$cview.'&sort=lastname">'.get_string('sortbylastname','grades').'</a>';
1787 $student_heading_link .= '<br /><a href="?id='.$course->id
.'&group='.$group.'&action=vcats&cview='.$cview.'&sort=firstname">'.get_string('sortbyfirstname','grades').'</a>';
1790 $student_heading_link .= '<br /><a href="?id='.$course->id
.'&group='.$group.'&action=vcats&cview='.$cview.'">'.get_string('showallstudents','grades').'</a>';
1793 echo '<table align="center" class="grades">';
1794 if (has_capability('moodle/course:viewcoursegrades', $context)) {
1795 $header = '<tr class="header"><th rowspan="2" scope="col">'.$student_heading_link.'</th>';
1798 $header = '<tr class="header">';
1800 $header1 = '<tr class="header">';
1802 // to keep track of what we've output
1807 // this next section is to display the items in the course order
1808 foreach($grades_by_student as $student => $categories) {
1809 if (isset($item_order)) {
1810 // we already have the sort order let's jump out
1813 $item_order = array();
1814 foreach($categories as $category => $items) {
1815 if ($category == $cview) {
1816 foreach ($items as $assignment=>$points) {
1817 if ($assignment != 'stats') {
1818 $temp = $points['sort_order'];
1819 $item_order[$temp] = $assignment;
1825 /// Make sure $item_order is initialised (bug 3424)
1826 if (empty($item_order)) $item_order = array();
1830 foreach($grades_by_student as $student => $categories) {
1832 if ($preferences->reprint_headers
!= 0 && $reprint >= $preferences->reprint_headers
) {
1833 echo $header.$header1.'</tr>';
1837 // alternate row classes
1838 $row = ($oddrow) ?
'<tr class="r0">' : '<tr class="r1">';
1841 // reset the col classes
1845 // set the links to student information based on multiview or individual... if individual go to student info... if many go to individual grades view.
1846 if (has_capability('moodle/course:viewcoursegrades', $context)) {
1847 if ($view_by_student != -1) {
1848 $student_link = '<a href="'.$CFG->wwwroot
.'/user/view.php?id='.$student.'&course='.$course->id
.'">';
1851 $student_link = '<a href="?id='.$course->id
.'&group='.$group.'&action=vcats&user='.$student.'&cview='.$cview.'">';
1853 $student_link .= $grades_by_student[$student]['student_data']['lastname'].', '.$grades_by_student[$student]['student_data']['firstname'].'</a>';
1854 $row .= '<th class="fullname" scope="row">'.$student_link.'</th>';
1857 foreach($categories as $category => $items) {
1858 if ($category == $cview) {
1859 // make sure that the grades come out in the same order
1860 foreach($item_order as $order=>$assignment) {
1862 $class = $all_categories[$category][$assignment]['modname'];
1864 if ($assignment != 'stats') {
1868 $link_id = grade_get_module_link($course->id
, $all_categories[$category][$assignment]['cminstance'], $all_categories[$category][$assignment]['modid']);
1870 $link = $CFG->wwwroot
.'/mod/'.$all_categories[$category][$assignment]['modname'].'/view.php?id='.$link_id->id
;
1871 $all_categories[$category][$assignment]['link'] = $link;
1872 if ($all_categories[$category][$assignment]['hidden'] == 0) {
1873 $header .= '<th class="'.$class.'" colspan="'.$grade_columns.'" scope="col"><a href="'.$link.'">'.format_string($assignment,true).'</a>';
1876 $header .= '<th class="'.$class.'" colspan="'.$grade_columns.'" scope="col"><a class="dimmed" href="'.$link.'">'.format_string($assignment,true).'</a>';
1878 if ($all_categories[$category][$assignment]['extra_credit'] == 1) {
1879 $header .= '<span class="extracredit">('.get_string('extracredit','grades').')</span>';
1882 if ($preferences->show_points
) {
1883 $header1 .= '<th class="'.$class.'" scope="col">'. $all_categories[$category][$assignment]['maxgrade'];
1884 if ($all_categories[$category][$assignment]['grade_against'] != $all_categories[$category][$assignment]['maxgrade']) {
1885 $header1 .= '('. $all_categories[$category][$assignment]['grade_against'].')';
1887 $header1 .= '</th>';
1890 if($preferences->show_percent
) {
1891 if ($all_categories[$category][$assignment]['grade_against'] != $all_categories[$category][$assignment]['maxgrade']) {
1892 $header1 .= '<th class="'.$class.'" scope="col">'.get_string('scaledpct','grades').'</th>';
1895 $header1 .= '<th class="'.$class.'" scope="col">'.get_string('rawpct','grades').'</th>';
1898 if ($preferences->show_weighted
) {
1899 if ($all_categories[$category]['stats']['totalpoints'] != 0) {
1900 $cur_weighted_max = sprintf("%0.2f", $all_categories[$category][$assignment]['grade_against']/$all_categories[$category]['stats']['totalpoints']*$all_categories[$category]['stats']['weight']);
1903 $cur_weighted_max = 0;
1905 $header1 .= '<th scope="col">'.$cur_weighted_max.get_string('pctoftotalgrade','grades').'</th>';
1910 if ($preferences->show_points
) {
1911 $class .= ($oddcol) ?
' c0 points' : ' c1 points';
1913 $row .= '<td class="'.$class.'"><a href="'.$all_categories[$category][$assignment]['link'].'">' . $items[$assignment]['grade'] . '</a></td>';
1916 if ($preferences->show_percent
) {
1917 $class .= ($oddcol) ?
' c0 percent' : ' c1 percent';
1919 $row .= '<td class="'.$class.'">'. $items[$assignment]['percent'].'%</td>';
1922 if ($preferences->show_weighted
) {
1923 $class .= ($oddcol) ?
' c0 weighted' : ' c1 weighted';
1925 $row .= '<td class="'.$class.'">'.$items[$assignment]['weighted'].'%</td>';
1935 if (has_capability('moodle/course:viewcoursegrades', $context) && $view_by_student == -1) {
1936 $total_sort_link = '<a href="?id='.$course->id
.'&group='.$group.'&action=vcats&cview='.$cview.'&sort=highgrade_category"><img src="'.$CFG->wwwroot
.'/pix/t/down.gif" alt="'.get_string('highgradedescending','grades').'" /></a>';
1937 $total_sort_link .= '<a href="?id='.$course->id
.'&group='.$group.'&action=vcats&cview='.$cview.'&sort=highgrade_category_asc"><img src="'.$CFG->wwwroot
.'/pix/t/up.gif" alt="'.get_string('highgradeascending','grades').'" /></a>';
1940 $total_sort_link = '';
1943 $stats_link = '<a href="javascript:void(0)" onclick="window.open(\'?id='.$course->id
.'&action=stats&group='.$group.'&category='.$cview.'\',\''.get_string('statslink','grades').'\',\'height=200,width=300,scrollbars=no\')">'.get_string('statslink','grades').'</a>';
1944 if ($all_categories[$cview]['stats']['drop'] != 0) {
1945 $header .= '<th class="'.$class.'" colspan="'.$grade_columns.'" scope="col">'.get_string('total','grades').' (Lowest '. $all_categories[$cview]['stats']['drop']. ' Dropped)'.$total_sort_link.' '.$stats_link.'</th>';
1948 $header .= '<th class="'.$class.'" colspan="'.$grade_columns.'" scope="col">'.get_string('total','grades').' '.$total_sort_link.' '.$stats_link.'</th>';
1951 if ($preferences->show_points
) {
1952 $header1 .= '<th class="'.$class.'" scope="col">'.$all_categories[$cview]['stats']['totalpoints'];
1953 if ($all_categories[$cview]['stats']['bonus_points'] != 0) {
1954 $header1 .='(+'.$all_categories[$cview]['stats']['bonus_points'].')';
1958 if ($preferences->show_percent
) {
1959 $header1 .= '<th class="'.$class.'" scope="col">'.get_string('percent','grades').'</th>';
1963 if ($preferences->show_weighted
) {
1964 $header1 .= '<th class="'.$class.'" scope="col">'.$all_categories[$cview]['stats']['weight'].get_string('pctoftotalgrade','grades').'</th>';
1967 if (has_capability('moodle/course:viewcoursegrades', $context)) {
1968 $header .= '<th rowspan="2" scope="col">'.$student_heading_link.'</th></tr>';
1974 //adjust colcount to reflect the actual number of columns output
1975 $colcount++
; // total column
1976 $colcount = $colcount*$grade_columns +
2;
1977 echo '<tr class="title"><th colspan="'.$colcount.'" scope="col">';
1978 if ($preferences->use_advanced
!= 0) {
1979 echo $cview.' '.get_string('grades','grades');
1982 echo get_string('grades','grades');
1985 if (has_capability('moodle/course:viewcoursegrades', $context)) {
1986 helpbutton('teacher', get_string('gradehelp','grades'), 'grade');
1989 helpbutton('student', get_string('gradehelp','grades'), 'grade');
1993 echo $header1.'</tr>';
1997 // total points for category
1998 if ($preferences->show_points
) {
1999 $class .= ($oddcol) ?
' c0 points' : ' c1 points';
2001 $row .= '<td class="'.$class.'">'.$grades_by_student[$student][$cview]['stats']['points'].'</td>';
2004 // total percent for category
2005 if ($preferences->show_percent
) {
2006 $class .= ($oddcol) ?
' c0 percent' : ' c1 percent';
2008 $row .= '<td class="'.$class.'">'.$grades_by_student[$student][$cview]['stats']['percent'].'%</td>';
2012 // total weighted for category
2013 if ($preferences->show_weighted
) {
2014 $class .= ($oddcol) ?
' c0 weighted' : ' c1 weighted';
2016 $row .= '<td class="'.$class.'">'.$grades_by_student[$student][$cview]['stats']['weighted'].'%</td>';
2019 if (has_capability('moodle/course:viewcoursegrades', $context)) {
2020 $row .= '<td class="fullname">'.$student_link.'</td>';
2028 else { // no grades returned
2029 error(get_string('nogradesreturned','grades'), $CFG->wwwroot
.'/course/view.php?id='.$course->id
);
2033 error(get_string('nocategoryview','grades'), $CFG->wwwroot
.'/course/view.php?id='.$course->id
);
2037 function grade_view_all_grades($view_by_student) { // if mode=='grade' then we are in user view
2038 // displays all grades for the course
2042 global $group; // yu: fix for 5814
2043 global $preferences;
2045 if (!$context = get_context_instance(CONTEXT_COURSE
, $course->id
)) {
2049 // if can't see course grades, print single grade view
2050 if (!has_capability('moodle/course:viewcoursegrades', $context)) {
2051 return print_student_grade($USER, $course);
2054 list($grades_by_student, $all_categories) = grade_get_formatted_grades();
2056 if ($grades_by_student != 0 && $all_categories != 0) {
2058 // output a form for the user to download the grades.
2059 grade_download_form();
2061 if ($view_by_student != -1) {
2062 // unset all grades except for this student
2063 foreach ($grades_by_student as $student=>$junk) {
2064 if($student != $view_by_student) {
2065 unset($grades_by_student[$student]);
2070 $grade_columns = $preferences->show_weighted +
$preferences->show_points +
$preferences->show_percent
;
2073 $total_course_points = 0;
2077 echo '<table align="center" class="grades">';
2078 if (has_capability('moodle/course:viewcoursegrades', $context)) {
2079 $student_heading_link = get_string('student','grades');
2080 if ($view_by_student == -1) {
2081 $student_heading_link .='<a href="?id='.$course->id
.'&action=grades&sort=lastname&group='.$group.'"><br /><font size="-2">'.get_string('sortbylastname','grades').'</font></a>';
2082 $student_heading_link .= '<a href="?id='.$course->id
.'&action=grades&sort=firstname&group='.$group.'"><br /><font size="-2">'.get_string('sortbyfirstname','grades').'</font></a>';
2085 $student_heading_link .= '<br /><a href="?id='.$course->id
.'&&action=grades"><font size="-2">'.get_string('showallstudents','grades').'</font></a>';
2087 $header = '<tr><th rowspan="2" scope="col">'.$student_heading_link.'</th>';
2098 foreach($grades_by_student as $student => $categories) {
2102 $total_bonus_points = 0;
2103 if ($preferences->reprint_headers
!= 0 && $reprint >= $preferences->reprint_headers
) {
2104 echo $header.$header1;
2108 // alternate row classes
2109 $row = ($oddrow) ?
'<tr class="r0">' : '<tr class="r1">';
2112 // set the links to student information based on multiview or individual... if individual go to student info... if many go to individual grades view.
2113 if (has_capability('moodle/course:viewcoursegrades', $context)) {
2114 if ($view_by_student != -1) {
2115 $studentviewlink = '<a href="'.$CFG->wwwroot
.'/user/view.php?id='.$student.'&course='.$course->id
.'">'.$grades_by_student[$student]['student_data']['lastname'].', '.$grades_by_student[$student]['student_data']['firstname'].'</a>';
2118 $studentviewlink = '<a href="?id='.$course->id
.'&action=view_student_grades&user='.$student.'">'.$grades_by_student[$student]['student_data']['lastname'].', '.$grades_by_student[$student]['student_data']['firstname'].'</a>';
2120 $row .= '<th scope="row">'. $studentviewlink .'</th>';
2124 foreach($categories as $category => $items) {
2125 if ($category != 'student_data') {
2129 if ($category == UNCATEGORISED
) {
2130 $categoryname = get_string(UNCATEGORISED
, 'grades');
2132 $categoryname = $category;
2134 // only print the category headers if something is displayed for them
2135 if ($preferences->show_weighted ||
$preferences->show_percent ||
$preferences->show_points
) {
2136 $stats_link = '<a href="javascript:void(0)" onclick="window.open(\'?id='.$course->id
.'&action=stats&category='.$category.'\',\''.get_string('statslink','grades').'\',\'height=200,width=300,scrollbars=no\')"><font size="-2">'.get_string('statslink','grades').'</font></a>';
2137 $header .= '<th colspan="'.$grade_columns.'" scope="col"><a href="?id='.$course->id
.'&action=vcats&cview='.$category;
2138 if ($view_by_student != -1) {
2139 $header .= '&user='.$view_by_student;
2141 $header .='">'. $categoryname .' '.$stats_link.'</a>';
2143 if ($preferences->display_weighted
!= 0) {
2144 $header .= '('. $all_categories[$category]['stats']['weight'] . '%)';
2147 if ($preferences->show_points
) {
2148 $header1 .= '<th scope="col">'.get_string('points','grades').'('.$all_categories[$category]['stats']['totalpoints'].')';
2149 if ($all_categories[$category]['stats']['bonus_points'] != 0) {
2150 $header1 .='(+'.$all_categories[$category]['stats']['bonus_points'].')';
2154 if ($preferences->show_percent
) {
2155 $header1 .= '<th scope="col">'.get_string('percent','grades').'</th>';
2157 if ($preferences->show_weighted
) {
2158 $header1 .= '<th scope="col">'.get_string('weightedpctcontribution','grades').'</th>';
2160 $maxpercent = $all_categories["$category"]['stats']['weight'] +
$maxpercent;
2161 //$total_course_points = $all_categories[$category]['stats']['totalpoints']+ $total_course_points;
2162 //$total_course_points = $all_categories[$category]['stats']['totalpoints']+ $total_course_points;
2165 if ($preferences->show_points
) {
2166 $row .= '<td align="right">' . $items['stats']['points'] . '</td>';
2168 if ($preferences->show_percent
) {
2169 $row .= '<td align="right">'. $items['stats']['percent'].'%</td>';
2172 if ($preferences->show_weighted
) {
2173 $row .= '<td align="right">'. $items['stats']['weighted'] . '%</td>';
2175 $total_bonus_points = $all_categories[$category]['stats']['bonus_points'];
2179 if ($preferences->show_letters
) {
2180 $total_columns = $grade_columns +
1;
2183 $total_columns = $grade_columns;
2186 if (has_capability('moodle/course:viewcoursegrades', $context) && $view_by_student == -1) {
2187 $grade_sort_link = '<a href="?id='.$course->id
.'&action=grades&sort=highgrade&group='.$group.'"><img src="'.$CFG->wwwroot
.'/pix/t/down.gif" alt="'.get_string('highgradedescending','grades').'" /></a>';
2188 $grade_sort_link .= '<a href="?id='.$course->id
.'&action=grades&sort=highgrade_asc&group='.$group.'"><img src="'.$CFG->wwwroot
.'/pix/t/up.gif" alt="'.get_string('highgradeascending','grades').'" /></a>';
2189 $points_sort_link = '<a href="?id='.$course->id
.'&action=grades&sort=points&group='.$group.'"><img src="'.$CFG->wwwroot
.'/pix/t/down.gif" alt="'.get_string('pointsdescending','grades').'" /></a>';
2190 $points_sort_link .= '<a href="?id='.$course->id
.'&action=grades&sort=points_asc&group='.$group.'"><img src="'.$CFG->wwwroot
.'/pix/t/up.gif" alt="'.get_string('pointsascending','grades').'" /></a>';
2191 $weighted_sort_link = '<a href="?id='.$course->id
.'&action=grades&sort=weighted&group='.$group.'"><img src="'.$CFG->wwwroot
.'/pix/t/down.gif" alt="'.get_string('weighteddescending','grades').'" /></a>';
2192 $weighted_sort_link .= '<a href="?id='.$course->id
.'&action=grades&sort=weighted_asc&group='.$group.'"><img src="'.$CFG->wwwroot
.'/pix/t/up.gif" alt="'.get_string('weightedascending','grades').'" /></a>';
2193 $percent_sort_link = '<a href="?id='.$course->id
.'&action=grades&sort=percent&group='.$group.'"><img src="'.$CFG->wwwroot
.'/pix/t/down.gif" alt="'.get_string('percentdescending','grades').'" /></a>';
2194 $percent_sort_link .= '<a href="?id='.$course->id
.'&action=grades&sort=percent_asc&group='.$group.'"><img src="'.$CFG->wwwroot
.'/pix/t/up.gif" alt="'.get_string('percentascending','grades').'" /></a>';
2196 $stats_link = '<a href="javascript:void(0)" onclick="window.open(\'?id='.$course->id
.'&action=stats&category=all\',\''.get_string('statslink','grades').'\',\'height=200,width=300,scrollbars=no\')"><font size="-2">'.get_string('statslink','grades').'</font></a>';
2197 $header .= '<th colspan="'.$total_columns.'" scope="col">'.get_string('total','grades').' '.$stats_link.'</th>';
2198 if (has_capability('moodle/course:viewcoursegrades', $context) && $view_by_student == -1) {
2199 if ($preferences->show_points
) {
2200 $header1 .= '<th scope="col">'.get_string('points','grades').'('.$all_categories['stats']['totalpoints'].')';
2201 if ($category != 'student_data' && $all_categories[$category]['stats']['bonus_points'] != 0) {
2203 $header1 .='(+'.$total_bonus_points.')';
2205 $header1 .= '<br />'.$points_sort_link.' '.'</th>';
2207 if ($preferences->show_percent
) {
2208 $header1 .= '<th scope="col">'.get_string('percentshort','grades').'<br />'.$percent_sort_link.' '.'</th>';
2210 if ($preferences->show_weighted
) {
2211 $header1 .= '<th scope="col">'.get_string('weightedpct','grades').'('.$all_categories['stats']['weight'].')'.'<br />'.$weighted_sort_link.' '.'</th>';
2213 if ($preferences->show_letters
) {
2214 $header1 .= '<th scope="col">'.get_string('lettergrade','grades').'<br />'.$grade_sort_link.' '.'</th>';
2216 $header1 .= '</tr>';
2219 if ($preferences->show_points
) {
2220 $header1 .= '<th scope="col">'.get_string('points','grades').'('.$all_categories['stats']['totalpoints'].')';
2221 if ($category != 'student_data' && $all_categories[$category]['stats']['bonus_points'] != 0) {
2222 $header1 .='(+'.$total_bonus_points.')';
2224 $header1 .= '</th>';
2226 if ($preferences->show_percent
) {
2227 $header1 .= '<th scope="col">'.get_string('percentshort','grades').'</th>';
2229 if ($preferences->show_weighted
) {
2230 $header1 .= '<th scope="col">'.get_string('weightedpct','grades').'('.$all_categories['stats']['weight'].')</th>';
2232 if ($preferences->show_letters
) {
2233 $header1 .= '<th scope="col">'.get_string('lettergrade','grades').'</th>';
2235 $header1 .= '</tr>';
2237 if (has_capability('moodle/course:viewcoursegrades', $context)) {
2238 $header .= '<th rowspan="2" scope="col">'.$student_heading_link.'</th></tr>';
2240 // adjust colcount to reflect actual number of columns output
2241 $colcount = $colcount * $grade_columns +
$total_columns +
2;
2243 echo '<tr><th colspan="'.$colcount.'" scope="col"><font size="+1">'.get_string('allgrades','grades').'</font>';
2244 if (has_capability('moodle/course:viewcoursegrades', $context)) {
2245 helpbutton('teacher', get_string('gradehelp','grades'), 'grade');
2248 helpbutton('student', get_string('gradehelp','grades'), 'grade');
2257 if ($preferences->show_points
) {
2258 $row .= '<td align="right">'.$grades_by_student[$student]['student_data']['points'].'</td>';
2260 if ($preferences->show_percent
) {
2261 $row .= '<td align="right">'.$grades_by_student[$student]['student_data']['percent'].'%</td>';
2263 if ($preferences->show_weighted
) {
2264 $row .= '<td align=right>'.$grades_by_student[$student]['student_data']['weighted'].'%</td>';
2266 if ($preferences->show_letters
) {
2267 if ($preferences->use_weighted_for_letter
== 1) {
2268 $grade = $grades_by_student[$student]['student_data']['weighted'];
2271 $grade = $grades_by_student[$student]['student_data']['percent'];
2273 $letter_grade = grade_get_grade_letter($course->id
, $grade);
2274 if ($letter_grade) {
2275 $row .= '<td align="right">'.$letter_grade->letter
.'</td>';
2278 // there wasn't an appropriate entry to use in the gradebook.
2279 if (grade_letters_set($course->id
)) {
2280 $row .= '<td align="right">'.get_string('nolettergrade','grades').' '.$grade.'</td>';
2283 $row .= '<td align="right">'.get_string('nogradeletters','grades').'</td>';
2287 if (has_capability('moodle/course:viewcoursegrades', $context)) {
2288 $row .= '<td>'. $studentviewlink .'</td></tr>';
2299 else { // no grades returned
2300 error(get_string('nogradesreturned','grades'));
2305 function grade_set_grade_weights() {
2306 // set the grade weights as submitted from the form generated by display_grade_weights
2311 if (!empty($USER->id
)) {
2312 if (!confirm_sesskey()) {
2313 error(get_string('confirmsesskeybad', 'error'));
2317 // get list of all categories
2318 $categories = get_records('grade_category', 'courseid', $course->id
);
2320 foreach ($categories as $category) {
2321 $form_catname = preg_replace('/[.| ]/', '_', $category->name
);
2323 $submitted_category = optional_param($form_catname);
2324 if (is_numeric($submitted_category)) {
2325 // see if there is a weight if so see if it needs to be updated
2326 $weight = grade_get_category_weight($course->id
, $category->name
);
2328 if ($weight->weight
!= $submitted_category)
2330 set_field('grade_category', 'weight', $submitted_category, 'id', $weight->id
);
2333 $cur_drop = optional_param("drop_x_lowest$form_catname");
2334 $cur_bonus_points = optional_param("bonus_points$form_catname");
2335 $cur_hidden = optional_param("hidden$form_catname");
2340 $cur_hidden = false;
2343 if ($weight->drop_x_lowest
!= $cur_drop) {
2344 set_field('grade_category', 'drop_x_lowest', $cur_drop, 'id', $weight->cat_id
);
2346 if ($weight->bonus_points
!= $cur_bonus_points) {
2347 set_field('grade_category', 'bonus_points', $cur_bonus_points, 'id', $weight->cat_id
);
2350 set_field('grade_category', 'hidden', 1, 'id', $weight->cat_id
);
2353 set_field('grade_category', 'hidden', 0, 'id', $weight->cat_id
);
2357 // insert the new record... we shouldn't reach this point anymore
2358 //$new_weight->course = $course->id;
2359 //$new_weight->category = $category->id;
2360 //$new_weight->weight = $submitted_category;
2361 //insert_record('grade_weight', $new_weight);
2365 echo '<center><font color="red">'.get_string('nonumericweight','grades').
2366 format_string($category->name
) .': "'.$submitted_category.'"</font></center><br />';
2372 function grade_display_grade_weights() {
2373 // get all categories with weights
2374 // then set and display that entry.
2379 $categories = get_records('grade_category', 'courseid', $course->id
);
2381 echo '<form id="grade_weights" action="./index.php" method="post">';
2382 echo '<table border="0" cellspacing="2" cellpadding="5" align="center" class="generalbox">';
2383 echo '<tr><th colspan="5" class="header" scope="col">'.get_string('setweights','grades');
2384 helpbutton('weight', get_string('gradeweighthelp','grades'), 'grade');
2386 echo '<tr><td align="center" class="generaltableheader">'.get_string('category','grades').'</td>';
2387 echo '<td align="center" class="generaltableheader">'.get_string('weight','grades').'</td>';
2388 echo '<td align="center" class="generaltableheader">'.get_string('dropxlowest','grades').'</td>';
2389 echo '<td align="center" class="generaltableheader">'.get_string('bonuspoints','grades').'</td>';
2390 echo '<td align="center" class="generaltableheader">'.get_string('hidecategory','grades').'</td>';
2392 echo '<input type="hidden" name="id" value="'.$course->id
.'" />';
2393 echo '<input type="hidden" name="action" value="set_grade_weights" />';
2394 echo '<input type="hidden" name="sesskey" value="'.$USER->sesskey
.'" />';
2398 foreach($categories as $category) {
2399 $val = $category->weight
;
2402 // make names form safe
2403 $form_catname = str_replace(' ', '_', $category->name
);
2404 if ($category->name
== UNCATEGORISED
) {
2405 $category->name
= get_string(UNCATEGORISED
, 'grades');
2407 echo '<tr><td align="center" class="generalboxcontent">'. format_string($category->name
) .'</td>';
2408 echo '<td align="center" class="generalboxcontent"><input type="text" size="5" name="'.$form_catname.'" value="'.$val.'" /></td>';
2409 echo '<td align="center" class="generalboxcontent"><input type="text" size="5" name="drop_x_lowest'.$form_catname.'" value="'.$category->drop_x_lowest
.'" /></td>';
2410 echo '<td align="center" class="generalboxcontent"><input type="text" size="5" name="bonus_points'.$form_catname.'" value="'.$category->bonus_points
.'" /></td>';
2411 echo '<td align="center" class="generalboxcontent"><input type="checkbox" name="hidden'.$form_catname.'" ';
2412 if ($category->hidden
== 1) {
2413 echo ' checked="checked"';
2415 echo ' /></td></tr>';
2417 echo '<tr><td colspan="5" align="center" class="generalboxcontent">';
2418 echo '<input type="submit" value="'.get_string('savechanges','grades').'" />';
2421 echo '<tr><td colspan="5" align="center" class="generalboxcontent"><font color="red">'.get_string('totalweightnot100','grades').'</font></td></tr>';
2424 echo '<tr><td colspan="5" align="center" class="generalboxcontent"><font color="green">'.get_string('totalweight100','grades').'</font></td></tr>';
2428 /// maybe this should just do the default population of the categories instead?
2429 echo '<font color="red">'.get_string('setcategorieserror','grades').'</font>';
2433 echo '<center>'.get_string('dropxlowestwarning','grades').'</center><br />';
2436 function grade_set_categories() {
2442 /// Collect modules data
2443 get_all_mods($course->id
, $mods, $modnames, $modnamesplural, $modnamesused);
2445 echo '<table border="0" cellspacing="2" cellpadding="5" align="center" class="generalbox">';
2446 echo '<tr><th colspan="5" class="header" scope="col">'.get_string('setcategories','grades');
2447 helpbutton('category', get_string('gradecategoryhelp','grades'), 'grade');
2449 echo '<tr><td align="center" class="generaltableheader">'.get_string('gradeitem','grades').'</td>';
2450 echo '<td align="center" class="generaltableheader">'.get_string('category','grades').'</td>';
2451 echo '<td align="center" class="generaltableheader">'.get_string('maxgrade','grades').'</td>';
2452 echo '<td align="center" class="generaltableheader">'.get_string('curveto','grades').'</td>';
2453 echo '<td align="center" class="generaltableheader">'.get_string('extracredit','grades').'</td></tr>';
2454 echo '<form id="set_categories" method="post" action="./index.php" >';
2455 echo '<input type="hidden" name="action" value="assign_categories" />';
2456 echo '<input type="hidden" name="id" value="'.$course->id
.'" />';
2457 echo '<input type="hidden" name="sesskey" value="'.$USER->sesskey
.'" />';
2461 /// Search through all the modules, pulling out grade data
2462 $sections = get_all_sections($course->id
); // Sort everything the same as the course
2463 for ($i=0; $i<=$course->numsections
; $i++
) {
2464 if (isset($sections[$i])) { // should always be true
2465 $section = $sections[$i];
2466 if ($section->sequence
) {
2467 $sectionmods = explode(",", $section->sequence
);
2468 foreach ($sectionmods as $sectionmod) {
2469 if (empty($mods[$sectionmod])) {
2472 $mod = $mods[$sectionmod];
2473 $instance = get_record("$mod->modname", "id", "$mod->instance");
2474 $libfile = "$CFG->dirroot/mod/$mod->modname/lib.php";
2475 if (file_exists($libfile)) {
2476 require_once($libfile);
2477 $gradefunction = $mod->modname
."_grades";
2478 if (function_exists($gradefunction)) { // Skip modules without grade function
2479 if ($modgrades = $gradefunction($mod->instance
)) {
2481 if ($modgrades->maxgrade
!= '')
2482 // this block traps out broken modules that don't return a maxgrade according to the moodle API
2485 //modgrades contains student information with associated grade
2486 //echo "<b>modname: $mod->modname id: $mod->id course: $mod->course</b><br />";
2487 echo '<input type="hidden" name="modname'.$itemcount.'" value="'.$mod->modname
.'" />';
2488 echo '<input type="hidden" name="mod'.$itemcount.'" value="'.$mod->instance
.'" />';
2489 echo '<input type="hidden" name="course'.$itemcount.'" value="'.$mod->course
.'" />';
2490 echo '<tr><td align="center" class="generalboxcontent">';
2491 // get instance name from db.
2492 $instance = get_record($mod->modname
, 'id', $mod->instance
);
2493 echo format_string($instance->name
)."</td>";
2494 // see if the item is already in the category table and if it is call category select with the id so it is selected
2495 echo '<td align="center" class="generalboxcontent"><select name="category'.$itemcount.'">';
2496 $item_cat_id = get_record('grade_item', 'modid', $mod->module
, 'courseid', $course->id
, 'cminstance', $mod->instance
);
2497 //print_object($item_cat_id);
2498 if (isset($item_cat_id)) {
2499 grade_category_select($item_cat_id->category
);
2502 grade_category_select(-1);
2504 echo '</select></td><td align="center" class="generalboxcontent">'.$modgrades->maxgrade
.'<input type="hidden" name="maxgrade'.$itemcount.'" value="'.$modgrades->maxgrade
.'" /></td>';
2506 if (isset($item_cat_id)) {
2507 // the value held in scale_grade is a scaling percent. The next line just formats it so it is easier for the user (they just enter the point value they want to be 100%)
2508 if ($item_cat_id->scale_grade
== '' ||
$item_cat_id->scale_grade
== 0)
2509 $scale_to = $modgrades->maxgrade
;
2511 $scale_to = round($modgrades->maxgrade
/$item_cat_id->scale_grade
);
2512 echo '<td align="center" class="generalboxcontent"><input type="text" size="5" name="scale_grade'.$itemcount.'" value="'.$scale_to.'" /></td>';
2515 echo '<td align="center" class="generalboxcontent"><input type="text" size="5" name="scale_grade'.$itemcount.'" value="'.$modgrades->maxgrade
.'" /></td>';
2518 echo '<td align="center" class="generalboxcontent"><input type="checkbox" name="extra_credit'.$itemcount.'" ';
2519 if ($item_cat_id->extra_credit
== 1) {
2520 echo ' checked="checked"';
2522 echo ' /></td></tr>';
2531 echo '<input type="hidden" name="totalitems" value="'.$itemcount.'" />';
2532 echo '<tr><td colspan="5" align="center" class="generalboxcontent"><input type="submit" value="'.get_string('savechanges','grades').'" /></td></tr>';
2534 echo '<tr><td colspan="5" align="center" class="generalboxcontent">';
2535 grade_add_category_form();
2536 echo '</td></tr><tr><td colspan="5" align="center" class="generalboxcontent">';
2537 grade_delete_category_form();
2538 echo '</td></tr></table>';
2539 echo '<center>'.get_string('extracreditwarning','grades').'</center>';
2542 function grade_delete_category() {
2547 if (!empty($USER->id
)) {
2548 if (!confirm_sesskey()) {
2549 error(get_string('confirmsesskeybad', 'error'));
2553 $cat_id = optional_param('category_id');
2554 if ($cat_id != 'blank') {
2555 // delete the record
2556 delete_records('grade_category', 'id', $cat_id, 'courseid', $course->id
);
2557 // set grade_item category field=0 where it was the deleted category (set uncategorized will clean this up)
2558 set_field('grade_item', 'category', 0, 'category', $cat_id);
2562 function grade_assign_categories() {
2566 $num_categories = optional_param('totalitems');
2568 if (!empty($USER->id
)) {
2569 if (!confirm_sesskey()) {
2570 error(get_string('confirmsesskeybad', 'error'));
2574 for ($i = 1; $i <= $num_categories; $i++
) {
2576 // these next sets of lines are a bit obtuse, but it lets there be a dynamic number of grade items
2577 // in the grade category form (maybe there's a better way?)
2578 $cur_cat_id = '$_REQUEST[\'category'.$i.'\'];';
2579 eval( "\$cur_cat_id = $cur_cat_id;" );
2580 $cur_modname = '$_REQUEST[\'modname'.$i.'\'];';
2581 eval( "\$cur_modname = $cur_modname;" );
2582 $cur_mod = '$_REQUEST[\'mod'.$i.'\'];';
2583 eval( "\$cur_mod = $cur_mod;" );
2584 $cur_maxgrade = '$_REQUEST[\'maxgrade'.$i.'\'];';
2585 eval( "\$cur_maxgrade = $cur_maxgrade;" );
2586 $cur_scale_grade = '$_REQUEST[\'scale_grade'.$i.'\'];';
2587 eval( "\$cur_scale_grade = $cur_scale_grade;" );
2588 $cur_extra_credit = '$_REQUEST[\'extra_credit'.$i.'\'];';
2589 $temp = 'extra_credit'.$i;
2590 $junk = get_record('modules','name',$cur_modname);
2591 $cur_modid = $junk->id
;
2592 if (isset($_REQUEST[$temp])) {
2593 eval( "\$cur_extra_credit = $cur_extra_credit;" );
2596 $cur_extra_credit = false;
2598 if ($cur_extra_credit) {
2599 $cur_extra_credit = 1;
2601 $cur_extra_credit = 0;
2603 if ($cur_scale_grade == 0 ||
$cur_scale_grade == '') {
2604 $cur_scale_grade = 1.0;
2607 $db_cat = get_record('grade_item', 'modid', $cur_modid, 'cminstance', $cur_mod, 'courseid', $course->id
);
2609 if ($db_cat->category
!= $cur_cat_id) {
2610 // item doesn't match in the db so update it to point to the new category
2611 set_field('grade_item', 'category', $cur_cat_id, 'id', $db_cat->id
);
2614 if ($db_cat->scale_grade
!= $cur_maxgrade/$cur_scale_grade) {
2615 // scale_grade doesn't match
2616 set_field('grade_item', 'scale_grade', ($cur_maxgrade/$cur_scale_grade), 'id', $db_cat->id
);
2619 set_field('grade_item', 'extra_credit', $cur_extra_credit, 'id', $db_cat->id
);
2623 $item->courseid
= $course->id
;
2624 $item->category
= $cur_cat_id;
2625 $item->modid
= $cur_modid;
2626 $item->cminstance
= $cur_mod;
2627 $item->scale_grade
= $cur_scale_grade;
2628 $item->extra_credit
= $cur_extra_credit;
2629 insert_record('grade_item', $item);
2634 function grade_add_category_form() {
2635 /// outputs a form to add a category
2636 /// just a simple text box with submit
2639 echo '<form id="new_category">';
2640 echo get_string('addcategory','grades').':<input type="text" name="name" size="20" />';
2641 echo '<input type="hidden" name="id" value="'.$course->id
.'" />';
2642 echo '<input type="hidden" name="action" value="insert_category" />';
2643 echo '<input type="hidden" name="sesskey" value="'.$USER->sesskey
.'" />';
2644 echo '<input type="submit" value="'.get_string('addcategory','grades').'" />';
2648 function grade_delete_category_form() {
2649 // outputs a form to delete a category
2652 echo '<form id="delete_category">';
2653 echo get_string('deletecategory','grades').': <select name="category_id">';
2654 grade_category_select();
2655 echo '</select><input type="hidden" name="id" value="'.$course->id
.'" />';
2656 echo '<input type="hidden" name="sesskey" value="'.$USER->sesskey
.'" />';
2657 echo '<input type="hidden" name="action" value="delete_category" />';
2658 echo '<input type="submit" value="'.get_string('deletecategory','grades').'" /></form>';
2661 function grade_insert_category() {
2666 $category->name
=optional_param('name');
2667 $category->courseid
=$course->id
;
2669 if (!empty($USER->id
)) {
2670 if (!confirm_sesskey()) {
2671 error(get_string('confirmsesskeybad', 'error'));
2675 // make sure the record isn't already there and insert if okay
2676 if (record_exists('grade_category', 'name', $category->name
, 'courseid', $category->courseid
)) {
2677 // category already exists
2679 elseif ($category->name
!= ''){
2680 if (!insert_record('grade_category', $category) ) {
2681 echo '<font color="red">'.get_string('addcategoryerror','grades').'</font>';
2686 function grade_category_select($id_selected = 0) {
2687 /// prints out a select box containing categories.
2692 echo '<option value="blank">'.get_string('choosecategory','grades').'</option>';
2694 $categories = get_records('grade_category', 'courseid', $course->id
, 'name');
2696 if (!isset($categories)) {
2697 error(get_string("nocategories"));
2700 foreach($categories as $category) {
2701 if ($category->name
== UNCATEGORISED
) {
2702 $category->name
= get_string('uncategorised', 'grades');
2704 if ($category->id
== $id_selected) {
2705 echo '<option value="'.$category->id
.'" selected="selected">'. format_string($category->name
) .'</option>';
2708 echo '<option value="'.$category->id
.'">'. format_string($category->name
) .'</option>';
2714 function grade_display_grade_preferences($course, $preferences) {
2718 if ($preferences->use_advanced
== 0) {
2720 $buttonlabel = get_string('useadvanced', 'grades');
2723 $buttonlabel = get_String('hideadvanced', 'grades');
2726 $buttonoptions = array('action' => 'set_grade_preferences',
2727 'id' => $course->id
,
2728 'sesskey' => sesskey(),
2729 'use_advanced' => $useadvanced);
2732 print_heading_with_help(get_string('setpreferences','grades'), 'preferences', 'grade');
2735 print_single_button('index.php', $buttonoptions, $buttonlabel, 'post');
2736 echo '<br /></center>';
2738 echo '<form id="set_grade_preferences" method="post" action="./index.php">';
2739 echo '<input type="hidden" name="action" value="set_grade_preferences" />';
2740 echo '<input type="hidden" name="id" value="'.$course->id
.'" />';
2741 echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
2742 echo '<table border="0" cellspacing="2" cellpadding="5" align="center" class="gradeprefs generalbox">';
2744 $optionsyesno = NULL;
2745 $optionsyesno[0] = get_string('no');
2746 $optionsyesno[1] = get_string('yes');
2749 if ($preferences->use_advanced
) {
2751 $options[0] = get_string('no');
2752 $options[1] = get_string('toonly', 'moodle', $course->teachers
);
2753 $options[2] = get_string('toeveryone', 'moodle');
2755 // display grade weights
2756 echo '<tr><td class="c0">'.get_string('displayweighted','grades').':</td>';
2757 echo '<td class="c1">';
2758 choose_from_menu($options, 'display_weighted', $preferences->display_weighted
, '');
2762 echo '<tr><td class="c0">'.get_string('displaypoints','grades').':</td>';
2763 echo '<td class="c1">';
2764 choose_from_menu($options, 'display_points', $preferences->display_points
, '');
2768 echo '<tr><td class="c0">'.get_string('displaypercent','grades').':</td>';
2769 echo '<td class="c1">';
2770 choose_from_menu($options, 'display_percent', $preferences->display_percent
, '');
2773 // display letter grade
2774 echo '<tr><td class="c0">'.get_string('displaylettergrade','grades').':</td>';
2775 echo '<td class="c1">';
2776 choose_from_menu($options, 'display_letters', $preferences->display_letters
, '');
2779 // letter grade uses weighted percent
2781 $options[0] = get_string('usepercent','grades');
2782 $options[1] = get_string('useweighted','grades');
2784 echo '<tr><td class="c0">'.get_string('lettergrade','grades').':</td>';
2785 echo '<td class="c1">';
2786 choose_from_menu($options, 'use_weighted_for_letter', $preferences->use_weighted_for_letter
, '');
2790 $headerlist[0] = get_string('none');
2791 for ($i=1; $i<=100; $i++
) {
2792 $headerlist[$i] = $i;
2795 // reprint headers every n lines default n=0
2796 echo '<tr><td class="c0">'.get_string('reprintheaders','grades').':</td>';
2797 echo '<td class="c1">';
2798 choose_from_menu($headerlist, 'reprint_headers', $preferences->reprint_headers
, '');
2801 // show hidden grade items to teacher
2802 echo '<tr><td class="c0">'.get_string('showhiddenitems','grades').'</td>';
2803 echo '<td class="c1">';
2804 choose_from_menu($optionsyesno, 'show_hidden', $preferences->show_hidden
, '');
2807 echo '<tr><td colspan="3" align="center"><input type="submit" value="'.get_string('savepreferences','grades').'" /></td></tr></table></form>';
2812 function grade_display_letter_grades() {
2817 $db_letters = get_records('grade_letter', 'courseid', $course->id
, 'grade_high DESC');
2820 $using_defaults = false;
2821 foreach ($db_letters as $letter) {
2822 $letters[$letter->id
]->letter
= $letter->letter
;
2823 $letters[$letter->id
]->grade_low
= $letter->grade_low
;
2824 $letters[$letter->id
]->grade_high
= $letter->grade_high
;
2825 $letters[$letter->id
]->courseid
= $course->id
;
2829 $using_defaults = true;
2831 $letters[0]->letter
='A';
2832 $letters[0]->grade_low
=93.00;
2833 $letters[0]->grade_high
=100.00;
2834 $letters[0]->courseid
= $course->id
;
2836 $letters[1]->letter
='A-';
2837 $letters[1]->grade_low
=90.00;
2838 $letters[1]->grade_high
=92.99;
2839 $letters[1]->courseid
= $course->id
;
2841 $letters[2]->letter
='B+';
2842 $letters[2]->grade_low
=87.00;
2843 $letters[2]->grade_high
=89.99;
2844 $letters[2]->courseid
= $course->id
;
2846 $letters[3]->letter
='B';
2847 $letters[3]->grade_low
=83.00;
2848 $letters[3]->grade_high
=86.99;
2849 $letters[3]->courseid
= $course->id
;
2851 $letters[4]->letter
='B-';
2852 $letters[4]->grade_low
=80.00;
2853 $letters[4]->grade_high
=82.99;
2854 $letters[4]->courseid
= $course->id
;
2856 $letters[5]->letter
='C+';
2857 $letters[5]->grade_low
=77.00;
2858 $letters[5]->grade_high
=79.99;
2859 $letters[5]->courseid
= $course->id
;
2861 $letters[6]->letter
='C';
2862 $letters[6]->grade_low
=73.00;
2863 $letters[6]->grade_high
=76.99;
2864 $letters[6]->courseid
= $course->id
;
2866 $letters[7]->letter
='C-';
2867 $letters[7]->grade_low
=70.00;
2868 $letters[7]->grade_high
=72.99;
2869 $letters[7]->courseid
= $course->id
;
2871 $letters[8]->letter
='D+';
2872 $letters[8]->grade_low
=67.00;
2873 $letters[8]->grade_high
=69.99;
2874 $letters[8]->courseid
= $course->id
;
2876 $letters[9]->letter
='D';
2877 $letters[9]->grade_low
=60.00;
2878 $letters[9]->grade_high
=66.99;
2879 $letters[9]->courseid
= $course->id
;
2881 $letters[10]->letter
='F';
2882 $letters[10]->grade_low
=0.00;
2883 $letters[10]->grade_high
=59.99;
2884 $letters[10]->courseid
= $course->id
;
2887 echo '<form id="grade_letter"><input type="hidden" name="id" value="'.$course->id
.'" />';
2888 echo '<table border="0" cellspacing="2" cellpadding="5" align="center" class="generalbox"><tr>';
2889 echo '<th colspan="3" class="header" scope="col">'.get_string('setgradeletters','grades');
2890 helpbutton('letter', get_string('gradeletterhelp','grades'), 'grade');
2892 echo '<tr><td align="center" class="generaltableheader">'.get_string('gradeletter','grades').'</td>';
2893 echo '<td align="center" class="generaltableheader">'.get_string('lowgradeletter','grades').'</td>';
2894 echo '<td align="center" class="generaltableheader">'.get_string('highgradeletter','grades').'</td></tr>';
2895 echo '<input type="hidden" name="action" value="set_letter_grades" />';
2896 echo '<input type="hidden" name="sesskey" value="'.$USER->sesskey
.'" />';
2898 foreach ($letters as $id=>$items) {
2899 if ($id !='' && !$using_defaults) {
2900 // send the record id so if the user deletes the values we can delete the row.
2901 echo '<input type="hidden" name="id'.$i.'" value="'.$id.'" />';
2903 echo '<tr><td align="center" class="generalboxcontent"><input size="8" type="text" name="letter'.$i.'" value="'.$items->letter
.'" /></td>'."\n";
2904 echo '<td align="center" class="generalboxcontent"><input size="8" type="text" name="grade_low'.$i.'" value="'.$items->grade_low
.'" /></td>'."\n";
2905 echo '<td align="center" class="generalboxcontent"><input size="8" type="text" name="grade_high'.$i.'" value="'.$items->grade_high
.'" /></td></tr>'."\n";
2908 echo '<tr><td align="center" class="generalboxcontent"><input size="8" type="text" name="letter'.$i.'" value="" /></td><td align="center" class="generalboxcontent"><input size="8" type="text" name="grade_low'.$i.'" value="" /></td><td align="center" class="generalboxcontent"><input type="text" size="8" name="grade_high'.$i.'" value="" /></td></tr>';
2909 echo '<tr><td colspan="3" align="center" class="generalboxcontent"><input type="submit" value="'.get_string('savechanges','grades').'" /></td></tr>';
2910 echo '<input type="hidden" name="totalitems" value="'.$i.'" />';
2911 echo '<tr><td colspan="3" align="center" class="generalboxcontent">'.get_string('gradeletternote','grades').'</td></tr></table>';
2915 function grade_set_letter_grades() {
2920 if (!empty($USER->id
)) {
2921 if (!confirm_sesskey()) {
2922 error(get_string('confirmsesskeybad', 'error'));
2926 $totalitems= clean_param($_REQUEST['totalitems'], PARAM_CLEAN
);
2928 for($i=0; $i<=$totalitems; $i++
) {
2929 if (isset($_REQUEST["id$i"])) {
2930 // item submitted was already in database
2931 $letterid = $_REQUEST["id$i"];
2932 $updateletters[$letterid]->letter
= clean_param($_REQUEST["letter$i"], PARAM_CLEAN
);
2933 // grade_low && grade_high don't need cleaning as they are possibly floats (no appropriate clean method) so we check is_numeric
2934 $updateletters[$letterid]->grade_low
= $_REQUEST["grade_low$i"];
2935 $updateletters[$letterid]->grade_high
= $_REQUEST["grade_high$i"];
2936 $updateletters[$letterid]->id
= $letterid;
2940 $newletter->letter
= clean_param($_REQUEST["letter$i"], PARAM_CLEAN
);
2941 $newletter->grade_low
= $_REQUEST["grade_low$i"];
2942 $newletter->grade_high
= $_REQUEST["grade_high$i"];
2943 $newletter->courseid
= $course->id
;
2944 if (is_numeric($newletter->grade_high
) && is_numeric($newletter->grade_low
)) {
2945 insert_record('grade_letter', $newletter);
2948 if ($i < $totalitems) {
2949 if ($newletter->grade_high
!= '' or $newletter->grade_low
!= '') {
2950 echo '<center>'.get_string('lettergradenonnumber','grades').' '.$newletter->letter
.' item number: '.$i.'<br /></center>';
2957 if (isset($updateletters)) {
2958 foreach($updateletters as $id=>$items) {
2959 // see if any of the values are blank... if so delete them
2960 if ($items->letter
== '' ||
$items->grade_low
== '' ||
$items->grade_high
== '') {
2961 delete_records('grade_letter', 'id', $id);
2964 if (is_numeric($items->grade_high
) && is_numeric($items->grade_low
)) {
2965 update_record('grade_letter', $items);
2968 echo '<center><font color="red">'.get_string('errorgradevaluenonnumeric','grades').$letter.'</font></center>';
2975 function grade_download_form($type='both') {
2976 global $course,$USER, $action, $cview;
2977 if ($type != 'both' and $type != 'ods' and $type != 'excel' and $type != 'text') {
2981 if (has_capability('moodle/course:viewcoursegrades', get_context_instance(CONTEXT_COURSE
, $course->id
))) {
2982 echo '<table align="center"><tr>';
2983 $options['id'] = $course->id
;
2984 $options['sesskey'] = $USER->sesskey
;
2986 if ($type == 'both' ||
$type == 'ods') {
2987 $options['action'] = 'ods';
2988 echo '<td align="center">';
2989 print_single_button("index.php", $options, get_string("downloadods"));
2992 if ($type == 'both' ||
$type == 'excel') {
2993 $options['action'] = 'excel';
2994 echo '<td align="center">';
2995 print_single_button("index.php", $options, get_string("downloadexcel"));
2998 if ($type == 'both' ||
$type == 'text') {
2999 $options['action'] = 'text';
3000 echo '<td align="center">';
3001 print_single_button("index.php", $options, get_string("downloadtext"));
3006 $url = 'index.php?id='.$course->id
;
3007 if (!empty($action)) {
3008 $url .= '&action='.$action;
3009 if ($action == 'vcats') {
3010 $url .= '&cview='.$cview;
3013 setup_and_print_groups($course, $course->groupmode
, $url);
3016 echo '</tr></table>';
3025 * Simply prints all grade of one student from all modules from a given course
3026 * used in the grade book for student view, and grade button under user profile
3027 * @param int $userid;
3028 * @param int $courseid;
3030 function print_student_grade($user, $course) {
3034 if (!empty($user)) {
3035 $grades[$user->id
] = array(); // Collect all grades in this array
3036 $gradeshtml[$user->id
] = array(); // Collect all grades html formatted in this array
3037 $totals[$user->id
] = array(); // Collect all totals in this array
3040 $strmax = get_string("maximumshort");
3041 /// Collect modules data
3042 get_all_mods($course->id
, $mods, $modnames, $modnamesplural, $modnamesused);
3044 /// Search through all the modules, pulling out grade data
3045 $sections = get_all_sections($course->id
); // Sort everything the same as the course
3049 // flag for detecting whether to print table header or not
3052 for ($i=0; $i<=$course->numsections
; $i++
) {
3053 if (isset($sections[$i])) { // should always be true
3054 $section = $sections[$i];
3055 if ($section->sequence
) {
3056 $sectionmods = explode(",", $section->sequence
);
3057 foreach ($sectionmods as $sectionmod) {
3059 $mod = $mods[$sectionmod];
3060 if (empty($mod->modname
)) {
3061 continue; // Just in case, see MDL-7150
3063 $instance = get_record($mod->modname
, 'id', $mod->instance
);
3064 $libfile = "$CFG->dirroot/mod/$mod->modname/lib.php";
3066 if (file_exists($libfile)) {
3067 require_once($libfile);
3068 $gradefunction = $mod->modname
.'_grades';
3069 if (function_exists($gradefunction)) { // Skip modules without grade function
3070 if ($modgrades = $gradefunction($mod->instance
)) {
3071 if (!empty($modgrades->maxgrade
)) {
3072 if ($mod->visible
) {
3073 $maxgrade = $modgrades->maxgrade
;
3075 $maxgrade = $modgrades->maxgrade
;
3083 echo ('<table align="center" class="grades"><tr><th scope="col">'.get_string('activity').'</th><th scope="col">'.get_string('yourgrade','grades').'</th><th scope="col">'.get_string('maxgrade','grades').'</th></tr>');
3087 $link_id = grade_get_module_link($course->id
, $mod->instance
, $mod->module
);
3088 $link = $CFG->wwwroot
.'/mod/'.$mod->modname
.'/view.php?id='.$link_id->id
;
3091 if (!empty($modgrades->grades
[$user->id
])) {
3092 $currentgrade = $modgrades->grades
[$user->id
];
3093 echo "<td><a href='$link'>$mod->modfullname: ".format_string($instance->name
,true)."</a></td><td>$currentgrade</td><td>$maxgrade</td>";
3095 echo "<td><a href='$link'>$mod->modfullname: ".format_string($instance->name
,true)."</a></td><td>".get_string('nograde')."</td><td>$maxgrade</td>";
3105 } // a new Moodle nesting record? ;-)
3112 function grade_get_course_students($courseid) {
3114 // The list of roles to display is stored in CFG->gradebookroles
3115 if (!$context = get_context_instance(CONTEXT_COURSE
, $courseid)) {
3119 $configvar = get_config('', 'gradebookroles');
3120 if (empty($configvar)) {
3121 notify ('no roles defined in admin->appearance->graderoles');
3122 return false; // no roles to displayreturn false;
3125 if ($rolestoget = explode(',', $configvar)) {
3126 foreach ($rolestoget as $crole) {
3127 if ($tempstudents = get_role_users($crole, $context, true)) {
3128 foreach ($tempstudents as $tempuserid=>$tempstudent) {
3129 $students[$tempuserid] = $tempstudent;
3134 notify ('no roles defined in admin->appearance->graderoles');
3135 return false; // no roles to displayreturn false;
3137 return isset($students)?
$students:'';