Removed some commented out code from studentview additions.
[moodle-linuxchix.git] / grade / lib.php
blobc43787211cafe78f6ead5dbb6c3654c18c01312e
1 <?php // $Id$
3 require_once('../config.php');
4 require_once($CFG->dirroot.'/course/lib.php');
6 define('UNCATEGORISED', 'uncategorised');
8 $GRADEPREFS = array('use_advanced', // Only add new preferences to the end of this array!
9 'use_weighted_for_letter', // as the order counts and will affect backward compatibility
10 'display_weighted',
11 'display_points',
12 'display_percent',
13 'display_letters',
14 'reprint_headers',
15 'show_hidden',
19 $GRADEPREFSDEFAULTS = array('use_advanced' => 0,
20 'use_weighted_for_letter' => 0,
21 'display_weighted' => 0,
22 'display_points' => 2,
23 'display_percent' => 1,
24 'display_letters' => 0,
25 'reprint_headers' => 0,
26 'show_hidden' => 1
30 //******************************************************************
31 // SQL FUNCTIONS
32 //******************************************************************
34 function grade_get_category_weight($course, $category) {
35 global $CFG;
36 $sql = "SELECT id, weight, drop_x_lowest, bonus_points, hidden, c.id AS cat_id
37 FROM {$CFG->prefix}grade_category c
38 WHERE c.courseid=$course
39 AND c.name='$category'";
40 $temp = get_record_sql($sql);
41 return $temp;
44 function grade_get_grade_items($course) {
45 global $CFG;
46 $sql = "SELECT i.id, c.name as cname, i.modid, mm.name as modname, i.cminstance, c.hidden, cm.visible, i.sort_order
47 FROM {$CFG->prefix}grade_item i,
48 {$CFG->prefix}grade_category c,
49 {$CFG->prefix}course_modules cm,
50 {$CFG->prefix}modules mm
51 WHERE c.id=i.category
52 AND i.courseid=c.courseid
53 AND c.courseid=$course
54 AND cm.course=c.courseid
55 AND cm.module=mm.id
56 AND i.modid=mm.id
57 AND cm.instance=i.cminstance";
58 $temp = get_records_sql($sql);
59 return $temp;
62 function grade_get_module_link($course, $cminstance, $modid) {
63 global $CFG;
64 $sql = "SELECT cm.id, 1 FROM {$CFG->prefix}course_modules cm, {$CFG->prefix}modules mm, {$CFG->prefix}grade_item i
65 WHERE i.modid='".$modid."'
66 AND i.modid=mm.id
67 AND cm.instance = i.cminstance
68 AND i.cminstance=".$cminstance."
69 AND i.courseid=cm.course AND cm.module=mm.id AND i.courseid=$course";
70 $temp = get_record_sql($sql);
71 return $temp;
74 function grade_get_grade_letter($course, $grade) {
75 global $CFG;
76 $sql = "SELECT id, letter FROM {$CFG->prefix}grade_letter WHERE courseid=$course AND grade_high >= $grade AND grade_low <= $grade";
77 $temp = get_record_sql($sql);
78 return $temp;
81 function grade_get_exceptions($course) {
82 global $CFG;
83 $sql = "SELECT e.id, e.userid, gi.cminstance, gi.modid, c.name as catname, mm.name as modname
84 FROM {$CFG->prefix}grade_exceptions e,
85 {$CFG->prefix}grade_item gi,
86 {$CFG->prefix}grade_category c,
87 {$CFG->prefix}course_modules cm,
88 {$CFG->prefix}modules mm
89 WHERE e.courseid=$course
90 AND gi.id = e.grade_itemid
91 AND c.id = gi.category
92 AND cm.course=c.courseid
93 AND cm.module=mm.id
94 AND gi.modid=mm.id";
96 $temp = get_records_sql($sql);
97 return $temp;
100 function grade_letters_set($course) {
101 global $CFG;
102 $sql = "SELECT * FROM {$CFG->prefix}grade_letter WHERE courseid=$course";
103 $letters_set = get_records_sql($sql);
104 if ($letters_set) {
105 return true;
107 else {
108 return false;
112 function grade_get_users_by_group($course, $group) {
113 global $CFG;
114 $sql = "SELECT userid FROM {$CFG->prefix}groups_members WHERE courseid=$course AND groupid = $group";
115 $members = get_records_sql($sql);
116 if ($members) {
117 foreach($members as $member) {
118 $group->$userid = true;
120 return $group;
122 else {
123 return NULL;
127 //******************************************************************
128 // END SQL FUNCTIONS
129 //******************************************************************
131 function grade_get_formatted_grades() {
132 global $CFG;
133 global $course;
134 global $preferences;
135 $i = 1;
136 $grades = grade_get_grades();
137 if (isset($grades)) {
138 // iterate through all students
139 foreach($grades as $cur_category=>$grade_category) {
140 // $cur_category holds the value of the current category name
141 // $grade_category holds an array of all the mod types that are in this category
142 if (isset($grade_category)) {
143 foreach($grade_category as $cur_mod=>$mod_category) {
144 // $cur_mod is the id of the current moodle module type
145 // $mod_category holds the grades for $cur_mod (current mod type)
146 $module_info = get_record('modules', 'id', $cur_mod);
147 $cur_modname = $module_info->name;
148 if (isset($mod_category)) {
149 foreach($mod_category as $cur_cminstance=>$students_grade) {
150 // $cur_cminstance is the course module instance for the cur_mod
151 $instance = get_record($cur_modname, 'id',$cur_cminstance, 'course',$course->id);
152 // it's necessary to check if the name is blank because some mods don't clean up the grades when the instance is deleted
153 // this is a bug. as it is plausible that some item could get created and have old data from a previous mod laying around
154 if ($instance->name != '') {
155 // 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
156 if (isset($all_categories["$cur_category"]["$instance->name"])) {
157 $instance->name= $instance->name.' *'.$i.'*';
160 if (isset($students_grade->grades) && $students_grade->grades != '') {
161 foreach($students_grade->grades as $student=>$grade) {
162 // add an entry for any student that has a grade
163 $grades_by_student["$student"]["$cur_category"]["$instance->name"]['grade'] = $grade;
164 $grades_by_student["$student"]["$cur_category"]["$instance->name"]['sort_order'] = $students_grade->sort_order;
166 if (!isset($grades_by_student["$student"]["$cur_category"]['stats'])) {
167 $grades_by_student["$student"]["$cur_category"]['stats'] = array();
170 if (!isset($grades_by_student["$student"]["$cur_category"]['stats']['points'])) {
171 $grades_by_student["$student"]["$cur_category"]['stats']['points'] = $grade;
173 else {
174 $grades_by_student["$student"]["$cur_category"]['stats']['points'] = $grades_by_student["$student"]["$cur_category"]['stats']['points'] + $grade;
177 // This next block just creates a comma seperated list of all grades for the category
178 if (isset($grades_by_student["$student"]["$cur_category"]['stats']['allgrades'])) {
179 $grades_by_student["$student"]["$cur_category"]['stats']['allgrades'] .= ','.$grade;
181 else {
182 $grades_by_student["$student"]["$cur_category"]['stats']['allgrades'] = $grade;
186 // set up a list of all categories and assignments (adjusting things for extra credit where necessary)
187 $all_categories["$cur_category"]["$instance->name"]['hidden'] = $students_grade->hidden;
188 $all_categories["$cur_category"]["$instance->name"]['sort_order'] = $students_grade->sort_order;
190 $all_categories["$cur_category"]["$instance->name"]['extra_credit'] = $students_grade->extra_credit;
192 if ($all_categories["$cur_category"]["$instance->name"]['extra_credit'] != 1) {
193 $all_categories["$cur_category"]["$instance->name"]['maxgrade'] = $students_grade->maxgrade;
195 else {
196 $all_categories["$cur_category"]["$instance->name"]['maxgrade'] = 0;
198 $all_categories["$cur_category"]["$instance->name"]['scale_grade'] = $students_grade->scale_grade;
199 if ($students_grade->scale_grade != 0) {
200 $all_categories["$cur_category"]["$instance->name"]['scaled_max'] = round($all_categories["$cur_category"]["$instance->name"]['maxgrade']/$students_grade->scale_grade);
202 else {
203 // avoids divide by zero... scale_grade shouldn't be set to 0 anyway
204 $all_categories["$cur_category"]["$instance->name"]['scaled_max'] = $all_categories["$cur_category"]["$instance->name"]['maxgrade'];
205 $all_categories["$cur_category"]["$instance->name"]['scale_grade'] = 1.0;
207 if (! isset($all_categories["$cur_category"]['stats']) ) {
208 $all_categories["$cur_category"]['stats'] = array();
210 $all_categories["$cur_category"]["$instance->name"]['grade_against'] = $all_categories["$cur_category"]["$instance->name"]['scaled_max'];
211 if (!isset($all_categories["$cur_category"]['stats']['weight'])) {
212 $weight = grade_get_category_weight($course->id, $cur_category);
213 $all_categories["$cur_category"]['stats']['weight'] = $weight->weight;
216 $all_categories["$cur_category"]["$instance->name"]['cminstance'] = $cur_cminstance;
217 $all_categories["$cur_category"]["$instance->name"]['modid'] = $cur_mod;
218 $modname = get_record('modules','id',$cur_mod);
219 $all_categories["$cur_category"]["$instance->name"]['modname'] = $modname->name;
221 // get bonus points and drop the x lowest
222 $drop = get_record('grade_category', 'courseid', $course->id, 'name', $cur_category);
223 $all_categories["$cur_category"]['stats']['drop'] = $drop->drop_x_lowest;
224 $all_categories["$cur_category"]['stats']['bonus_points'] = $drop->bonus_points;
232 // set the students name under student_data (this has the added bonus of creating an entry for students who do not have any grades)
233 $students = get_course_students($course->id);
234 if (isset($students) && $students) {
235 foreach ($students as $userid => $student) {
236 $grades_by_student["$userid"]['student_data']['firstname'] = $student->firstname;
237 $grades_by_student["$userid"]['student_data']['lastname'] = $student->lastname;
238 $grades_by_student["$userid"]['student_data']['email'] = $student->email;
239 if (isset($student->location)) {
240 $grades_by_student["$userid"]['student_data']['location'] = $student->location;
242 $grades_by_student["$userid"]['student_data']['department'] = $student->department;
243 $grades_by_student["$userid"]['student_data']['idnumber'] = $student->idnumber;
247 // unset any item that has a "" for a name at this point this inludes instructors who have grades or any student formerly enrolled.
248 if (isset($grades_by_student)) {
249 foreach ($grades_by_student as $student => $assignments) {
250 if (!isset($grades_by_student["$student"]['student_data']['firstname']) && !isset($grades_by_student["$student"]['student_data']['lastname'])) {
251 unset($grades_by_student["$student"]);
257 // set the totalpoints for each category taking into account drop_x_lowest
258 // also set the number of grade items for the category to make calculating grades for students who have not taken anything easier
259 foreach($all_categories as $category => $assignments) {
260 $dropcount = 0;
261 $all_categories["$category"]['stats']['totalpoints'] = 0;
262 $all_categories["$category"]['stats']['grade_items'] = 0;
263 if (isset($assignments)) {
264 foreach($assignments as $assignment=>$grade) {
265 if ($assignment != 'stats') {
266 if ($dropcount < $all_categories["$category"]['stats']['drop']) {
267 // skip a grade in the total
268 $dropcount++;
270 else {
271 // make sure the current assignment is not extra credit and then add it to the totalpoints
272 if ($all_categories["$category"][$assignment]['extra_credit'] != 1) {
273 $all_categories["$category"]['stats']['totalpoints'] = $all_categories["$category"]['stats']['totalpoints'] + $assignments["$assignment"]['grade_against'];
274 $all_categories["$category"]['stats']['grade_items'] = $all_categories["$category"]['stats']['grade_items'] + 1;
282 if (isset($_REQUEST['group'])) {
283 $group = clean_param($_REQUEST['group'], PARAM_INT);
285 // if the user has selected a group to view by get the group members
286 if (isset($group) && $group != 0) {
287 $groupmembers = get_group_users($group);
290 // this next block catches any students who do not have a grade for any item in a particular category
291 foreach($all_categories as $category => $main_category) {
292 // make sure each student has an entry for each category
293 if (isset($grades_by_student)) {
294 foreach($grades_by_student as $student=>$categories) {
295 if ( (isset($groupmembers) && isset($groupmembers[$student])) || !isset($groupmembers)) {
296 $grades_by_student["$student"]["$category"]['stats']['totalpoints'] = $main_category['stats']['totalpoints'];
297 $grades_by_student["$student"]["$category"]['stats']['weight'] = $main_category['stats']['weight'];
298 $grades_by_student["$student"]["$category"]['stats']['grade_items'] = $main_category['stats']['grade_items'];
299 if (!isset($grades_by_student["$student"]["$category"]['stats']['points'])) {
300 $grades_by_student["$student"]["$category"]['stats']['points'] = '-';
302 else {
303 // points are set... see if the current category is using drop the x lowest and do so
304 if ($main_category['stats']['drop'] != 0) {
305 $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']);
306 if ($grades_by_student["$student"]["$category"]['stats']['points'] != '-') {
307 $cat_points = 0;
308 $count_grades = explode(',',$grades_by_student["$student"]["$category"]['stats']['allgrades']);
309 foreach($count_grades as $grade) {
310 $cat_points = $cat_points + $grade;
312 $grades_by_student["$student"]["$category"]['stats']['points'] = $cat_points;
317 // add any bonus points for the category
318 if ($all_categories["$category"]['stats']['bonus_points'] != 0) {
319 $grades_by_student["$student"]["$category"]['stats']['points'] = $grades_by_student["$student"]["$category"]['stats']['points'] + $all_categories["$category"]['stats']['bonus_points'];
322 foreach($main_category as $assignment => $items) {
323 if ($assignment != 'stats') {
324 if(!isset($grades_by_student["$student"]["$category"]["$assignment"]['maxgrade'])) {
325 $grades_by_student["$student"]["$category"]["$assignment"]['maxgrade'] = $all_categories["$category"]["$assignment"]['grade_against'];
327 if(!isset($grades_by_student["$student"]["$category"]["$assignment"]['grade'])) {
328 $grades_by_student["$student"]["$category"]["$assignment"]['grade'] = '-';
329 $grades_by_student["$student"]["$category"]["$assignment"]['sort_order'] = $all_categories["$category"]["$assignment"]['sort_order'];
333 } // end groupmember if
334 else {
335 // unset grade since they are not in the selected group.
336 unset($grades_by_student["$student"]);
342 // set the total coursepoints
343 $all_categories['stats']['weight'] = 0;
344 $all_categories['stats']['totalpoints'] = 0;
345 foreach($all_categories as $category => $info) {
346 if ($category != 'stats') {
347 $all_categories['stats']['weight'] = $all_categories['stats']['weight'] + $all_categories["$category"]['stats']['weight'];
348 $all_categories['stats']['totalpoints'] = $all_categories['stats']['totalpoints'] + $all_categories["$category"]['stats']['totalpoints'];
352 // set each individuals total points by category so we can then exclude some grades if set to use exceptions
353 if (isset($grades_by_student)) {
354 foreach($grades_by_student as $student => $categories) {
355 foreach($all_categories as $category => $assignments) {
356 if ($category != 'stats') {
357 $grades_by_student["$student"]["$category"]['stats']['totalpoints'] = $all_categories["$category"]['stats']['totalpoints'];
360 $grades_by_student["$student"]['student_data']['totalpoints'] = $all_categories['stats']['totalpoints'];
364 // take into account any excluded grade_items
365 $strexcluded = get_string('excluded', 'grades');
366 $exceptions = grade_get_exceptions($course->id);
367 if (isset($exceptions) && $exceptions) {
368 foreach($exceptions as $exception) {
369 if (isset($grades_by_student["$exception->userid"])) {
370 if ($grades_by_student["$exception->userid"]["$exception->catname"]) {
371 $assgn = get_record($exception->modname, 'id', $exception->cminstance, 'course', $course->id);
372 $grades_by_student["$exception->userid"]['student_data']['totalpoints'] = $grades_by_student["$exception->userid"]['student_data']['totalpoints'] - $all_categories["$exception->catname"]["$assgn->name"]['maxgrade'];
373 $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'];
374 $grades_by_student["$exception->userid"]["$exception->catname"]['stats']['grade_items'] = $grades_by_student["$exception->userid"]["$exception->catname"]['stats']['grade_items'] - 1;
375 if ($grades_by_student["$exception->userid"]["$exception->catname"]['stats']['grade_items'] < 0) {
376 $grades_by_student["$exception->userid"]["$exception->catname"]['stats']['grade_items'] = 0;
378 $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'];
379 $grades_by_student["$exception->userid"]["$exception->catname"]["$assgn->name"]['maxgrade'] = $strexcluded;
380 $grades_by_student["$exception->userid"]["$exception->catname"]["$assgn->name"]['grade'] = $strexcluded;
381 // see if they are excluded entirely from a category
382 if ($grades_by_student["$exception->userid"]["$exception->catname"]['stats']['totalpoints'] == 0) {
383 $grades_by_student["$exception->userid"]["$exception->catname"]['stats']['totalpoints'] = $strexcluded;
384 $grades_by_student["$exception->userid"]["$exception->catname"]['stats']['percent'] = $strexcluded;
385 $grades_by_student["$exception->userid"]["$exception->catname"]['stats']['points'] = $strexcluded;
386 $grades_by_student["$exception->userid"]["$exception->catname"]['stats']['weight'] = $strexcluded;
387 $grades_by_student["$exception->userid"]["$exception->catname"]['stats']['weighted'] = $strexcluded;
391 else {
392 // 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
397 if (isset($grades_by_student)) {
398 foreach($grades_by_student as $student => $categories) {
399 $grades_by_student["$student"]['student_data']['points'] = '-';
400 $grades_by_student["$student"]['student_data']['totalpoints'] = 0;
401 $grades_by_student["$student"]['student_data']['weight'] = 0;
402 $grades_by_student["$student"]['student_data']['weighted'] = 0;
403 foreach($categories as $category => $assignments) {
404 if ($category != 'student_data') {
405 // set the student's total points earned
406 if ($grades_by_student["$student"]["$category"]['stats']['points'] != $strexcluded) {
407 if ($grades_by_student["$student"]["$category"]['stats']['points'] != '-') {
408 $grades_by_student["$student"]['student_data']['points'] = $grades_by_student["$student"]['student_data']['points'] + $grades_by_student["$student"]["$category"]['stats']['points'];
410 $grades_by_student["$student"]['student_data']['totalpoints'] = $grades_by_student["$student"]['student_data']['totalpoints'] + $grades_by_student["$student"]["$category"]['stats']['totalpoints'];
413 // set percents and weights for each assignment
414 foreach($assignments as $assignment => $info) {
415 if ($assignment != 'stats') {
416 if ($grades_by_student["$student"]["$category"]["$assignment"]['grade'] != $strexcluded) {
417 if ($grades_by_student["$student"]["$category"]["$assignment"]['maxgrade'] != 0) {
418 $grades_by_student["$student"]["$category"]["$assignment"]['percent'] = round($grades_by_student["$student"]["$category"]["$assignment"]['grade']/$grades_by_student["$student"]["$category"]["$assignment"]['maxgrade']*100,2);
420 else {
421 $grades_by_student["$student"]["$category"]["$assignment"]['percent'] = 0;
423 if ($grades_by_student["$student"]["$category"]['stats']['totalpoints'] != 0) {
424 $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);
426 else {
427 $grades_by_student["$student"]["$category"]["$assignment"]['weight'] = 0.00;
429 if ($grades_by_student["$student"]["$category"]["$assignment"]['weight'] != 0) {
430 $grades_by_student["$student"]["$category"]["$assignment"]['weighted'] = round($grades_by_student["$student"]["$category"]["$assignment"]['percent']*$grades_by_student["$student"]["$category"]["$assignment"]['weight']/100,2);
432 else {
433 // should only be here if this is extra credit
434 $grades_by_student["$student"]["$category"]["$assignment"]['weighted'] = 0.00;
437 else {
438 $grades_by_student["$student"]["$category"]["$assignment"]['percent'] = $strexcluded;
439 $grades_by_student["$student"]["$category"]["$assignment"]['weight'] = $strexcluded;
440 $grades_by_student["$student"]["$category"]["$assignment"]['weighted'] = $strexcluded;
444 // set the percent and weight per category
445 if ($grades_by_student["$student"]["$category"]['stats']['totalpoints'] != 0 ) {
446 $grades_by_student["$student"]["$category"]['stats']['percent'] = round($grades_by_student["$student"]["$category"]['stats']['points']/$grades_by_student["$student"]["$category"]['stats']['totalpoints']*100,2);
447 $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);
449 else {
450 if ($grades_by_student["$student"]["$category"]['stats']['totalpoints'] != $strexcluded) {
451 $grades_by_student["$student"]["$category"]['stats']['percent'] = 0.00;
452 $grades_by_student["$student"]["$category"]['stats']['weighted'] = 0.00;
456 // set students overall weight (this is what percent they will be graded against)
457 if ($grades_by_student["$student"]["$category"]['stats']['weight'] != $strexcluded) {
458 $grades_by_student["$student"]['student_data']['weight'] = $grades_by_student["$student"]['student_data']['weight'] + $grades_by_student["$student"]["$category"]['stats']['weight'];
461 // 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
462 // be excluded from a whole category.
463 if ($all_categories["$category"]['stats']['totalpoints'] != 0) {
464 $grades_by_student["$student"]['student_data']['weighted'] = $grades_by_student["$student"]['student_data']['weighted'] + $grades_by_student["$student"]["$category"]['stats']['weighted'];
471 // set the percent and weight overall
472 if ($grades_by_student["$student"]['student_data']['totalpoints'] != 0 && $grades_by_student["$student"]['student_data']['totalpoints'] != $strexcluded) {
473 $grades_by_student["$student"]['student_data']['percent'] = round($grades_by_student["$student"]['student_data']['points']/$grades_by_student["$student"]['student_data']['totalpoints']*100,2);
474 if ($grades_by_student["$student"]['student_data']['weight'] != 0) {
475 $grades_by_student["$student"]['student_data']['weighted'] = round($grades_by_student["$student"]['student_data']['weighted']/$grades_by_student["$student"]['student_data']['weight']*100,2);
477 else {
478 $grades_by_student["$student"]['student_data']['weighted'] = 0.00;
481 else if ($grades_by_student["$student"]['student_data']['totalpoints'] == 0) {
482 $grades_by_student["$student"]['student_data']['percent'] = 0.00;
488 if (isset($grades_by_student)) {
489 $sort = optional_param('sort','default');
491 switch ($sort) {
492 case 'highgrade_category':
493 uasort($grades_by_student, 'grade_sort_by_highgrade_category');
494 break;
495 case 'highgrade_category_asc':
496 uasort($grades_by_student, 'grade_sort_by_highgrade_category_asc');
497 break;
498 case 'highgrade':
500 if ($preferences->use_weighted_for_letter == 1) {
501 uasort($grades_by_student, 'grade_sort_by_weighted');
503 else {
504 uasort($grades_by_student, 'grade_sort_by_percent');
506 break;
508 case 'points':
509 uasort($grades_by_student, 'grade_sort_by_points');
510 break;
511 case 'points_asc':
512 uasort($grades_by_student, 'grade_sort_by_points_asc');
513 break;
514 case 'weighted':
515 uasort($grades_by_student, 'grade_sort_by_weighted');
516 break;
517 case 'weighted_asc':
518 uasort($grades_by_student, 'grade_sort_by_weighted_asc');
519 break;
520 case 'percent':
521 uasort($grades_by_student, 'grade_sort_by_percent');
522 break;
523 case 'percent_asc':
524 uasort($grades_by_student, 'grade_sort_by_percent_asc');
525 break;
526 case 'highgrade_asc':
528 if ($preferences->use_weighted_for_letter == 1) {
529 uasort($grades_by_student, 'grade_sort_by_weighted_asc');
531 else {
532 uasort($grades_by_student, 'grade_sort_by_percent_asc');
534 break;
536 case 'firstname':
537 uasort($grades_by_student, 'grade_sort_by_firstname');
538 break;
539 default:
540 uasort($grades_by_student, 'grade_sort_by_lastname');
543 else {
544 $grades_by_student = 0;
546 //print_object($grades_by_student);
547 //print_object($all_categories);
548 $retval = array($grades_by_student, $all_categories);
550 else {
551 $retval = array(0,0);
552 // echo "<center><font color=red>Could not find any graded items for this course.</font></center>";
554 return $retval;
557 function grade_drop_lowest($grades, $drop, $total) {
558 // drops the lowest $drop numbers from the comma seperated $grades making sure that if $grades has
559 // fewer items than $total that we don't drop too many
560 $grade_array = explode(',',$grades);
562 $actually_drop = (count($grade_array) - $total);
563 if ($actually_drop > 0) {
564 rsort($grade_array);
566 for($i=0; $i < (count($grade_array) - $actually_drop); $i++) {
567 $ret_grades["$i"] = $grade_array["$i"];
569 if ($ret_grades) {
570 $grades = implode(',',$ret_grades);
572 else {
573 // set grades to 0... they decided to drop too many
574 $grades = 0;
577 return $grades;
580 function grade_get_grades() {
581 global $CFG;
582 global $course;
583 $mods = grade_get_grade_items($course->id);
584 $preferences = grade_get_preferences($course->id);
586 if ($mods) {
587 foreach ($mods as $mod) {
588 // hidden is a gradebook setting for an assignment and visible is a course_module setting
589 if (($mod->hidden != 1 && $mod->visible==1) or (isteacher($course->id) && $preferences->show_hidden==1)) {
590 $libfile = "$CFG->dirroot/mod/$mod->modname/lib.php";
591 if (file_exists($libfile)) {
592 require_once($libfile);
593 $gradefunction = $mod->modname."_grades";
594 if ($grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"] = $gradefunction($mod->cminstance)) {
595 // added grades for particular mod
596 // now get the grade_item modifiers ie. scale_grade and extra credit
597 $scale_grade = get_record('grade_item', 'courseid', $course->id, 'cminstance', $mod->cminstance, 'modid', $mod->modid);
599 if (isset($scale_grade)) {
600 $grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"]->scale_grade = $scale_grade->scale_grade;
601 $grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"]->extra_credit = $scale_grade->extra_credit;
603 else {
604 $grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"]->scale_grade = 1.00;
605 $grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"]->extra_credit = 0;
608 if ($mod->hidden != 1 && $mod->visible==1) {
609 $grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"]->hidden = 0;
611 else {
612 $grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"]->hidden = 1;
615 $grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"]->sort_order = $scale_grade->sort_order;
617 // 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
618 // 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.
619 // this happens when grading is set to a non-numeric for a forum ie. uses "seperate and connected ways of knowing"
620 if ($grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"]->maxgrade == '')
622 $grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"]->maxgrade = 100;
623 //unset($grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"]);
626 else {
627 // delete this item from the grade_item table since it was deleted through the mod interface
628 delete_records('grade_item', 'modid', $mods->modid, 'courseid', $course->id);
629 delete_records('grade_exceptions', 'grade_itemid', $mod->id, 'courseid', $course->id);
632 else {
633 //echo "<center><font color=red>Could not find lib file for $mod->modid</font></center>";
638 else {
639 // Do something here for no grades
640 //echo "<center><font color=red>No grades returned. It appears that there are no items with grades for this course.</font></center>";
642 if (isset($grades)) {
643 return $grades;
645 else {
646 return NULL;
650 function grade_set_uncategorized() {
651 // this function checks to see if any mods have not been assigned a category and sets them to uncategorized.
652 global $CFG;
653 global $course;
654 $uncat = UNCATEGORISED;
656 $uncat_id = get_record('grade_category', 'courseid', $course->id, 'name', $uncat);
658 if (!$uncat_id) {
659 // insert the uncategorized category
660 $temp->name=$uncat;
661 $temp->courseid=$course->id;
662 $temp->drop_x_lowest = 0;
663 $temp->bonus_points = 0;
664 $temp->hidden = 0;
665 $temp->weight = 100.00;
667 insert_record('grade_category', $temp);
668 $uncat_id = get_record('grade_category', 'courseid', $course->id, 'name', $uncat);
669 if (!$uncat_id) {
670 error(get_string('errornocategorizedid','grades'));
671 exit(0);
676 /// Collect modules data
677 get_all_mods($course->id, $mods, $modnames, $modnamesplural, $modnamesused);
678 $itemcount = 0;
680 // this will let us establish the order for gradebook item display
681 $sort = 0;
683 /// Search through all the modules, pulling out grade data
684 $sections = get_all_sections($course->id); // Sort everything the same as the course
685 for ($i=0; $i<=$course->numsections; $i++) {
686 if (isset($sections["$i"])) { // should always be true
687 $section = $sections["$i"];
688 if ($section->sequence) {
689 $sectionmods = explode(",", $section->sequence);
690 foreach ($sectionmods as $sectionmod) {
691 if (isset($mods["$sectionmod"])) {
692 $mod = $mods["$sectionmod"];
693 $instance = get_record("$mod->modname", "id", "$mod->instance");
694 $libfile = "$CFG->dirroot/mod/$mod->modname/lib.php";
695 if (file_exists($libfile)) {
696 require_once($libfile);
697 $gradefunction = $mod->modname."_grades";
698 if (function_exists($gradefunction)) { // Skip modules without grade function
699 if ($modgrades = $gradefunction($mod->instance)) {
700 $itemcount++;
701 //modgrades contains student information with associated grade
702 //echo "<b>modname: $mod->modname id: $mod->id course: $mod->course</b><br>";
703 // get instance name from db.
704 $instance = get_record($mod->modname, 'id', $mod->instance);
705 // see if the item is already in the category table and if it is call category select with the id so it is selected
706 get_record('modules', 'name', $mod->modname);
707 $item = get_record('grade_item', 'courseid', $course->id, 'modid', $mod->module, 'cminstance', $mod->instance);
708 if (!$item) {
709 // set the item to uncategorized in grade_item
710 $item->courseid = $course->id;
711 $item->category = $uncat_id->id;
712 $item->modid = $mod->module;
713 $item->cminstance = $mod->instance;
714 $item->id = insert_record('grade_item', $item);
716 else if ($item->category == 0) {
717 // this catches any errors where they may have some wierd category set
718 set_field('grade_item', 'category', $uncat_id->id, 'id', $item->id);
720 set_field('grade_item', 'sort_order', $sort, 'id', $item->id);
721 $sort++;
732 // sorting functions for grades
733 function grade_sort_by_lastname($x,$y)
735 //$grades_by_student["$student->userid"]['student_data']['firstname'] = $student->firstname;
736 //$grades_by_student["$student->userid"]['student_data']['lastname'] = $student->lastname;
737 if (strnatcasecmp($x['student_data']['lastname'],$y['student_data']['lastname']) == 0) {
738 return strnatcasecmp($x['student_data']['firstname'],$y['student_data']['firstname']);
740 else {
741 return strnatcasecmp($x['student_data']['lastname'],$y['student_data']['lastname']);
745 function grade_sort_by_firstname($x,$y)
747 //$grades_by_student["$student->userid"]['student_data']['firstname'] = $student->firstname;
748 //$grades_by_student["$student->userid"]['student_data']['lastname'] = $student->lastname;
749 if (strnatcasecmp($x['student_data']['firstname'],$y['student_data']['firstname']) == 0) {
750 return strnatcasecmp($x['student_data']['lastname'],$y['student_data']['lastname']);
752 else {
753 return strnatcasecmp($x['student_data']['firstname'],$y['student_data']['firstname']);
757 function grade_sort_by_points($x,$y) {
758 if ($x['student_data']['points'] == $y['student_data']['points']) {
759 return grade_sort_by_lastname($x,$y);
761 else {
762 if ($x['student_data']['points'] > $y['student_data']['points'])
763 return -1;
764 else
765 return 1;
769 function grade_sort_by_points_asc($x,$y) {
770 if ($x['student_data']['points'] == $y['student_data']['points']) {
771 return grade_sort_by_lastname($x,$y);
773 else {
774 if ($x['student_data']['points'] < $y['student_data']['points'])
775 return -1;
776 else
777 return 1;
781 function grade_sort_by_weighted($x,$y) {
782 if ($x['student_data']['weighted'] == $y['student_data']['weighted']) {
783 return grade_sort_by_lastname($x,$y);
785 else {
786 if ($x['student_data']['weighted'] > $y['student_data']['weighted'])
787 return -1;
788 else
789 return 1;
793 function grade_sort_by_percent($x,$y) {
794 if ($x['student_data']['percent'] == $y['student_data']['percent']) {
795 return grade_sort_by_lastname($x,$y);
797 else {
798 if ($x['student_data']['percent'] > $y['student_data']['percent'])
799 return -1;
800 else
801 return 1;
805 function grade_sort_by_percent_asc($x,$y) {
806 if ($x['student_data']['percent'] == $y['student_data']['percent']) {
807 return grade_sort_by_lastname($x,$y);
809 else {
810 if ($x['student_data']['percent'] < $y['student_data']['percent'])
811 return -1;
812 else
813 return 1;
817 function grade_sort_by_weighted_asc($x,$y) {
818 if ($x['student_data']['weighted'] == $y['student_data']['weighted']) {
819 return grade_sort_by_lastname($x,$y);
821 else {
822 if ($x['student_data']['weighted'] < $y['student_data']['weighted'])
823 return -1;
824 else
825 return 1;
829 function grade_sort_by_highgrade_category($x,$y) {
830 global $cview;
832 if(!$cview) {
833 $cview = optional_param('cview');
836 if ($x["$cview"]['stats']['points'] == $y["$cview"]['stats']['points']) {
837 return grade_sort_by_lastname($x,$y);
839 else {
840 return ($y["$cview"]['stats']['points'] - $x["$cview"]['stats']['points']);
844 function grade_sort_by_highgrade_category_asc($x,$y) {
845 global $cview;
847 if(!$cview)
848 $cview = optional_param('cview');
850 if ($x["$cview"]['stats']['points'] == $y["$cview"]['stats']['points']) {
851 return grade_sort_by_lastname($x,$y);
853 else {
854 return ($x["$cview"]['stats']['points'] - $y["$cview"]['stats']['points']);
859 function grade_set_preference($courseid, $name, $value) {
860 global $GRADEPREFS;
862 if (false !== ($key = array_search($name, $GRADEPREFS))) {
863 if ($record = get_record('grade_preferences', 'courseid', $courseid, 'preference', $key)) {
864 $record->value = $value;
865 update_record('grade_preferences', $record);
866 } else { // Make a new one
867 $record->preference = $key;
868 $record->courseid = $courseid;
869 $record->value = $value;
870 insert_record('grade_preferences', $record);
875 function grade_get_preference($courseid, $name) {
876 global $GRADEPREFS, $GRADEPREFSDEFAULTS;
878 if (false !== ($key = array_search($name, $GRADEPREFS))) {
879 if (!($record = get_record('grade_preferences', 'courseid', $courseid, 'preference', $key))) {
880 // Make a new one
881 $record->preference = $key;
882 $record->courseid = $courseid;
883 $record->value = $GRADEPREFSDEFAULTS[$name];
884 insert_record('grade_preferences', $record);
886 return $record->value;
888 return NULL;
891 function grade_get_preferences($courseid) {
892 global $CFG;
893 global $GRADEPREFS, $GRADEPREFSDEFAULTS;
895 $preferences = NULL;
897 // Get the preferences for the course.
898 if ($rawprefs = get_records('grade_preferences', 'courseid', $courseid)) {
899 foreach ($rawprefs as $pref) {
900 if (isset($GRADEPREFS[$pref->preference])) { // Valid pref
901 $name = $GRADEPREFS[$pref->preference];
902 $preferences->$name = $pref->value;
907 // Check for any missing ones and create them from defaults
908 // We don't save them in the database so we save space
909 foreach ($GRADEPREFS as $number => $name) {
910 if (!isset($preferences->$name)) {
911 $preferences->$name = $GRADEPREFSDEFAULTS[$name];
915 // Construct some other ones about which fields are shown
917 $isteacher = isteacher($courseid);
919 $preferences->show_weighted = (($preferences->display_weighted > 0 && $isteacher) ||
920 ($preferences->display_weighted > 1 && !$isteacher));
922 $preferences->show_points = (($preferences->display_points > 0 && $isteacher) ||
923 ($preferences->display_points > 1 && !$isteacher));
925 $preferences->show_percent = (($preferences->display_percent > 0 && $isteacher) ||
926 ($preferences->display_percent > 1 && !$isteacher));
928 $preferences->show_letters = (($preferences->display_letters > 0 && $isteacher) ||
929 ($preferences->display_letters > 1 && !$isteacher));
931 return $preferences;
935 function grade_set_preferences($course, $newprefs) {
937 if (!isset($newprefs->use_advanced) or ($newprefs->use_advanced == 1)) {
938 foreach ($newprefs as $name => $value) { /// Just save them all
939 grade_set_preference($course->id, $name, $value);
941 return true;
944 /// We don't need advanced features, and we need to unset all extra features
945 /// So they don't affect grades (This approach should be revisited because it resets everything!!)
947 grade_set_preference($course->id, 'use_advanced', 0);
948 grade_set_preference($course->id, 'use_weighted_for_letter', 0);
949 grade_set_preference($course->id, 'display_weighted', 0);
950 grade_set_preference($course->id, 'display_points', 2);
951 grade_set_preference($course->id, 'display_percent', 0);
952 grade_set_preference($course->id, 'display_letters', 0);
954 /// Lose all exceptions
955 delete_records('grade_exceptions', 'courseid', $course->id);
957 if (!$uncat = get_record('grade_category', 'courseid', $course->id, 'name', UNCATEGORISED)) {
958 /// Make a category for uncategorised stuff
959 $uncat->name=UNCATEGORISED;
960 $uncat->courseid=$course->id;
961 if (!$uncat->id = insert_record('grade_category', $uncat)) {
962 error(get_string('errornocategorizedid','grades'));
966 set_field('grade_item', 'category', $uncat->id, 'courseid', $course->id);
967 set_field('grade_item', 'scale_grade', 1.00, 'courseid', $course->id);
968 set_field('grade_item', 'extra_credit', 0, 'courseid', $course->id);
970 set_field('grade_category', 'weight', 100.0, 'courseid', $course->id, 'id', $uncat->id);
971 set_field('grade_category', 'bonus_points', '0', 'courseid', $course->id);
975 function grade_preferences_menu($action, $course, $group=0) {
977 if (!isteacher($course->id)) {
978 return;
981 // remap some actions to simplify later code
982 switch ($action) {
983 case 'prefs':
984 case 'set_grade_preferences':
985 $curraction = 'prefs';
986 break;
987 case 'cats':
988 case 'vcats':
989 case 'insert_category':
990 case 'assign_categories':
991 case 'delete_category':
992 $curraction = 'cats';
993 break;
994 case 'set_grade_weights':
995 case 'weights':
996 $curraction = 'weights';
997 break;
998 case 'letters':
999 case 'set_letter_grades':
1000 $curraction = 'letters';
1001 break;
1002 case 'view_student_grades':
1003 case 'view_student_category_grades':
1004 case 'grades':
1005 $curraction = 'grades';
1006 break;
1007 case 'excepts':
1008 $curraction = 'excepts';
1009 break;
1011 default:
1012 $curraction = 'grades';
1015 $tabs = $row = array();
1016 $row[] = new tabobject('grades', 'index.php?id='.$course->id,
1017 get_string('viewgrades', 'grades'));
1018 $row[] = new tabobject('prefs', 'index.php?id='.$course->id.'&amp;action=prefs',
1019 get_string('setpreferences', 'grades'));
1020 // only show the extra options if advanced is turned on, they don't do anything otherwise
1021 if (grade_get_preference($course->id, 'use_advanced') == 1) {
1022 $row[] = new tabobject('cats', 'index.php?id='.$course->id.'&amp;action=cats',
1023 get_string('setcategories', 'grades'));
1024 $row[] = new tabobject('weights', 'index.php?id='.$course->id.'&amp;action=weights',
1025 get_string('setweights', 'grades'));
1026 $row[] = new tabobject('letters', 'index.php?id='.$course->id.'&amp;action=letters',
1027 get_string('setgradeletters', 'grades'));
1028 $row[] = new tabobject('excepts', 'exceptions.php?id='.$course->id.'&amp;action=excepts',
1029 get_string('gradeexceptions', 'grades'));
1031 $tabs[] = $row;
1033 print_tabs($tabs, $curraction);
1037 function grade_nav($course, $action='grades') {
1038 global $CFG;
1039 global $USER;
1040 global $cview;
1042 $strgrades = get_string('grades', 'grades');
1043 $gradenav = "<a href=\"$CFG->wwwroot/course/view.php?id=$course->id\">$course->shortname</a>";
1045 if (isteacher($course->id)) {
1046 switch ($action) {
1047 case 'prefs':
1048 case 'set_grade_preferences':
1049 $strcurpage = get_string('setpreferences','grades');
1050 break;
1051 case 'cats':
1052 case 'delete_category':
1053 case 'cats':
1054 case 'insert_category':
1055 case 'assign_categories':
1056 $strcurpage = get_string('setcategories','grades');
1057 break;
1058 case 'weights':
1059 case 'set_grade_weights':
1060 $strcurpage = get_string('setweights','grades');
1061 break;
1062 case 'set_letter_grades':
1063 case 'letters':
1064 $strcurpage = get_string('setgradeletters','grades');
1065 break;
1066 case 'excepts':
1067 $strcurpage = get_string('gradeexceptions', 'grades');
1068 break;
1069 default:
1070 unset($strcurpage);
1071 break;
1074 if ($action=='grades') {
1075 $gradenav .= " -> $strgrades";
1076 } else {
1077 $gradenav .= " -> <a href=\"index.php?id=$course->id&amp;action=grades\">$strgrades</a>";
1080 // if we are on a grades sub-page provide a link back (including grade preferences and grade items
1082 if (isset($strcurpage)) {
1083 $gradenav .= " -> $strcurpage";
1084 } else if($action =='vcats') {
1085 // show sub category
1086 if (isset($cview)) {
1087 $gradenav .= " -> $cview";
1091 } else {
1092 $gradenav .= " -> $strgrades";
1095 return $gradenav;
1098 function grade_download($download, $id) {
1099 global $CFG;
1101 require_variable($id); // course id
1102 optional_variable($download, ""); // to download data
1104 require_login();
1106 if (! $course = get_record("course", "id", $id)) {
1107 error("Course ID was incorrect");
1110 if (!isteacher($course->id)) {
1111 error("Only teachers can use this page!");
1114 $strgrades = get_string("grades");
1115 $strgrade = get_string("grade");
1116 $strmax = get_string("maximumshort");
1117 $stractivityreport = get_string("activityreport");
1119 /// Check to see if groups are being used in this course
1120 if ($groupmode = groupmode($course)) { // Groups are being used
1121 if (isset($_GET['group'])) {
1122 $changegroup = $_GET['group']; /// 0 or higher
1123 } else {
1124 $changegroup = -1; /// This means no group change was specified
1127 $currentgroup = get_and_set_current_group($course, $groupmode, $changegroup);
1128 } else {
1129 $currentgroup = false;
1132 if ($currentgroup) {
1133 $students = get_group_students($currentgroup, "u.lastname ASC");
1134 } else {
1135 $students = get_course_students($course->id, "u.lastname ASC");
1138 foreach ($students as $student) {
1139 $grades[$student->id] = array(); // Collect all grades in this array
1140 $gradeshtml[$student->id] = array(); // Collect all grades html formatted in this array
1141 $totals[$student->id] = array(); // Collect all totals in this array
1143 $columns = array(); // Accumulate column names in this array.
1144 $columnhtml = array(); // Accumulate column html in this array.
1147 /// Collect modules data
1148 get_all_mods($course->id, $mods, $modnames, $modnamesplural, $modnamesused);
1150 /// Search through all the modules, pulling out grade data
1151 $sections = get_all_sections($course->id); // Sort everything the same as the course
1152 for ($i=0; $i<=$course->numsections; $i++) {
1153 if (isset($sections[$i])) { // should always be true
1154 $section = $sections[$i];
1155 if ($section->sequence) {
1156 $sectionmods = explode(",", $section->sequence);
1157 foreach ($sectionmods as $sectionmod) {
1158 $mod = $mods[$sectionmod];
1159 $instance = get_record("$mod->modname", "id", "$mod->instance");
1160 $libfile = "$CFG->dirroot/mod/$mod->modname/lib.php";
1162 if (file_exists($libfile)) {
1163 require_once($libfile);
1164 $gradefunction = $mod->modname."_grades";
1165 if (function_exists($gradefunction)) { // Skip modules without grade function
1166 if ($modgrades = $gradefunction($mod->instance)) {
1167 if (!empty($modgrades->maxgrade)) {
1168 if ($mod->visible) {
1169 $maxgrade = "$strmax: $modgrades->maxgrade";
1170 } else {
1171 $maxgrade = "$strmax: $modgrades->maxgrade";
1173 } else {
1174 $maxgrade = "";
1177 $columns[] = "$mod->modfullname: ".format_string($instance->name,true)." - $maxgrade";
1179 foreach ($students as $student) {
1180 if (!empty($modgrades->grades[$student->id])) {
1181 $grades[$student->id][] = $currentstudentgrade = $modgrades->grades[$student->id];
1182 } else {
1183 $grades[$student->id][] = $currentstudentgrade = "";
1184 $gradeshtml[$student->id][] = "";
1186 if (!empty($modgrades->maxgrade)) {
1187 $totals[$student->id] = (float)($totals[$student->id]) + (float)($currentstudentgrade);
1188 } else {
1189 $totals[$student->id] = (float)($totals[$student->id]) + 0;
1198 } // a new Moodle nesting record? ;-)
1200 /// OK, we have all the data, now present it to the user
1201 if ($download == "xls" and confirm_sesskey()) {
1202 require_once("../lib/excel/Worksheet.php");
1203 require_once("../lib/excel/Workbook.php");
1205 // HTTP headers
1206 header("Content-type: application/vnd.ms-excel");
1207 $downloadfilename = clean_filename("$course->shortname $strgrades");
1208 header("Content-Disposition: attachment; filename=\"$downloadfilename.xls\"");
1209 header("Expires: 0");
1210 header("Cache-Control: must-revalidate,post-check=0,pre-check=0");
1211 header("Pragma: public");
1213 /// Creating a workbook
1214 $workbook = new Workbook("-");
1215 $myxls =& $workbook->add_worksheet($strgrades);
1217 /// Print names of all the fields
1219 $myxls->write_string(0,0,get_string("firstname"));
1220 $myxls->write_string(0,1,get_string("lastname"));
1221 $myxls->write_string(0,2,get_string("idnumber"));
1222 $myxls->write_string(0,3,get_string("institution"));
1223 $myxls->write_string(0,4,get_string("department"));
1224 $myxls->write_string(0,5,get_string("email"));
1225 $pos=6;
1226 foreach ($columns as $column) {
1227 $myxls->write_string(0,$pos++,strip_tags($column));
1229 $myxls->write_string(0,$pos,get_string("total"));
1232 /// Print all the lines of data.
1234 $i = 0;
1235 foreach ($grades as $studentid => $studentgrades) {
1236 $i++;
1237 $student = $students[$studentid];
1238 if (empty($totals[$student->id])) {
1239 $totals[$student->id] = '';
1242 $myxls->write_string($i,0,$student->firstname);
1243 $myxls->write_string($i,1,$student->lastname);
1244 $myxls->write_string($i,2,$student->idnumber);
1245 $myxls->write_string($i,3,$student->institution);
1246 $myxls->write_string($i,4,$student->department);
1247 $myxls->write_string($i,5,$student->email);
1248 $j=6;
1249 foreach ($studentgrades as $grade) {
1250 if (is_numeric($grades)) {
1251 $myxls->write_number($i,$j++,strip_tags($grade));
1253 else {
1254 $myxls->write_string($i,$j++,strip_tags($grade));
1257 $myxls->write_number($i,$j,$totals[$student->id]);
1260 $workbook->close();
1262 exit;
1264 } else if ($download == "txt" and confirm_sesskey()) {
1266 /// Print header to force download
1268 header("Content-Type: application/download\n");
1269 $downloadfilename = clean_filename("$course->shortname $strgrades");
1270 header("Content-Disposition: attachment; filename=\"$downloadfilename.txt\"");
1272 /// Print names of all the fields
1274 echo get_string("firstname")."\t".
1275 get_string("lastname")."\t".
1276 get_string("idnumber")."\t".
1277 get_string("institution")."\t".
1278 get_string("department")."\t".
1279 get_string("email");
1280 foreach ($columns as $column) {
1281 $column = strip_tags($column);
1282 echo "\t$column";
1284 echo "\t".get_string("total")."\n";
1286 /// Print all the lines of data.
1287 foreach ($grades as $studentid => $studentgrades) {
1288 $student = $students[$studentid];
1289 if (empty($totals[$student->id])) {
1290 $totals[$student->id] = '';
1292 echo "$student->firstname\t$student->lastname\t$student->idnumber\t$student->institution\t$student->department\t$student->email";
1293 foreach ($studentgrades as $grade) {
1294 $grade = strip_tags($grade);
1295 echo "\t$grade";
1297 echo "\t".$totals[$student->id];
1298 echo "\n";
1301 exit;
1306 function grade_get_stats($category='all') {
1307 list($grades_by_student, $all_categories) = grade_get_formatted_grades();
1309 if ($grades_by_student != 0 && $all_categories != 0) {
1310 switch($category) {
1311 case 'all':
1313 //populate the sum of student points, # items and totalpoints for each category
1314 foreach($grades_by_student as $student=>$categories) {
1315 foreach($categories as $cur_category=>$assignments) {
1316 if($category != 'student_data') {
1317 if (isset($assignments['stats'])) {
1318 if (isset($stats[$cur_category]['sum'])) {
1319 $stats[$cur_category]['sum'] = $stats[$cur_category]['sum'] + $assignments['stats']['points'];
1321 else {
1322 $stats[$cur_category]['sum'] = $assignments['stats']['points'];
1324 $stats[$cur_category]['items'] = $assignments['stats']['grade_items'];
1325 $stats[$cur_category]['totalpoints'] = $assignments['stats']['totalpoints'];
1326 $stats[$cur_category]['weight'] = $all_categories[$cur_category]['stats']['weight'];
1331 // populate the overall sum,items and totalpoints
1332 foreach($stats as $cur_category=>$info) {
1333 if($cur_category != 'all' && $cur_category != 'student_data') {
1334 if (isset($stats['all'])) {
1335 $stats['all']['sum'] = $stats['all']['sum'] + $stats[$cur_category]['sum'];
1336 $stats['all']['items'] = $stats['all']['items'] + $stats[$cur_category]['items'];
1337 $stats['all']['totalpoints'] = $stats['all']['totalpoints'] + $stats[$cur_category]['totalpoints'];
1338 $stats['all']['weighted_sum'] = $stats['all']['weighted_sum'] + ($stats[$cur_category]['sum']/($stats[$cur_category]['totalpoints']))*$stats[$cur_category]['weight'];
1340 else {
1341 $stats['all']['sum'] = $stats[$cur_category]['sum'];
1342 $stats['all']['items'] = $stats[$cur_category]['items'];
1343 $stats['all']['totalpoints'] = $stats[$cur_category]['totalpoints'];
1344 $stats['all']['weighted_sum'] = ($stats[$cur_category]['sum']/($stats[$cur_category]['totalpoints']))*$stats[$cur_category]['weight'];
1348 $stats['all']['students'] = count($grades_by_student);
1349 $stats['all']['average'] = $stats['all']['sum'] / $stats['all']['students'];
1350 $stats['all']['average_weighted'] = $stats['all']['weighted_sum']/$stats['all']['students'];
1352 // calculate the average squared deviation and populate a list of all scores while we're at it
1353 $stats['all']['avgsqddev'] = 0;
1354 $stats['all']['avgsqddev_weighted'] = 0;
1355 foreach($grades_by_student as $student=>$categories) {
1356 foreach($categories as $cur_category=>$assignments) {
1357 if ($cur_category != 'student_data') {
1358 $stats['all']['avgsqddev'] = $stats['all']['avgsqddev'] + pow(($grades_by_student[$student]['student_data']['points']-$stats['all']['average']),2);
1359 $stats['all']['avgsqddev_weighted'] = $stats['all']['avgsqddev_weighted'] + pow(($grades_by_student[$student]['student_data']['weighted']-$stats['all']['average_weighted']),2);
1362 if (isset($stats['all']['all_scores'])) {
1363 $stats['all']['all_scores'] .= ','.$grades_by_student[$student]['student_data']['points'];
1364 $stats['all']['all_scores_weighted'] .= ','.$grades_by_student[$student]['student_data']['weighted'];
1366 else {
1367 $stats['all']['all_scores'] = $grades_by_student[$student]['student_data']['points'];
1368 $stats['all']['all_scores_weighted'] = $grades_by_student[$student]['student_data']['weighted'];
1371 $stats['all']['avgsqddev']=$stats['all']['avgsqddev']/$stats['all']['students'];
1372 $stats['all']['avgsqddev_weighted']=$stats['all']['avgsqddev_weighted']/$stats['all']['students'];
1373 $stats['all']['stddev'] = sqrt($stats['all']['avgsqddev']);
1374 $stats['all']['stddev_weighted'] = sqrt($stats['all']['avgsqddev_weighted']);
1375 $stats['all']['mode'] = grade_mode($stats['all']['all_scores']);
1376 $stats['all']['mode_weighted'] = grade_mode($stats['all']['all_scores_weighted']);
1378 // make sure the mode is not set to every score
1379 if(count($stats['all']['mode']) == count($grades_by_student)) {
1380 $stats['all']['mode'] = get_string('nomode','grade');
1382 if(count($stats['all']['mode_weighted']) == count($grades_by_student)) {
1383 $stats['all']['mode_weighted'] = get_string('nomode','grade');
1385 break;
1387 default:
1389 // get the stats for category
1390 //populate the sum of student points, # items and totalpoints for each category
1391 foreach($grades_by_student as $student=>$categories) {
1392 if(isset($grades_by_student[$student][$category]['stats'])) {
1393 if (isset($stats[$category]['sum'])) {
1394 $stats[$category]['sum'] = $stats[$category]['sum'] + $grades_by_student[$student][$category]['stats']['points'];
1396 else {
1397 $stats[$category]['sum'] = $grades_by_student[$student][$category]['stats']['points'];
1399 $stats[$category]['items'] = $grades_by_student[$student][$category]['stats']['grade_items'];
1400 $stats[$category]['totalpoints'] = $grades_by_student[$student][$category]['stats']['totalpoints'];
1403 $stats[$category]['students'] = count($grades_by_student);
1404 $stats[$category]['average'] = $stats[$category]['sum']/$stats[$category]['students'];
1406 // calculate the average squared deviation and populate a list of all scores too
1407 $stats[$category]['avgsqddev'] = 0;
1408 foreach($grades_by_student as $student=>$categories) {
1409 foreach($categories as $cur_category=>$assignment) {
1410 if ($cur_category != 'student_data') {
1411 if ($grades_by_student[$student][$category]['stats']['points'] == '-' || $grades_by_student[$student][$category]['stats']['points'] == get_string('grades','excluded')) {
1412 // count grade as a zero
1413 $stats[$category]['avgsqddev'] = $stats[$category]['avgsqddev'] + pow(($stats[$category]['average']),2);
1415 else {
1416 $stats[$category]['avgsqddev'] = $stats[$category]['avgsqddev'] + pow(($grades_by_student[$student][$category]['stats']['points']-$stats[$category]['average']),2);
1421 if (isset($stats[$category]['all_scores'])) {
1422 $stats[$category]['all_scores'] .= ','.$grades_by_student[$student][$category]['stats']['points'];
1424 else {
1425 $stats[$category]['all_scores'] = $grades_by_student[$student][$category]['stats']['points'];
1428 $stats[$category]['avgsqddev'] = $stats[$category]['avgsqddev']/$stats[$category]['students'];
1429 $stats[$category]['stddev'] = sqrt($stats[$category]['avgsqddev']);
1430 $stats[$category]['mode'] = grade_mode($stats[$category]['all_scores']);
1431 break;
1433 } // end switch
1434 // do a little cleanup
1435 $stats[$category]['stddev'] = sprintf("%0.2f", $stats[$category]['stddev']);
1436 $stats[$category]['average'] = sprintf("%0.2f", $stats[$category]['average']);
1437 $stats[$category]['max'] = max(explode(',',$stats[$category]['all_scores']));
1438 $stats[$category]['min'] = min(explode(',',$stats[$category]['all_scores']));
1439 $stats[$category]['median'] = explode(',',$stats[$category]['all_scores']);
1441 if (isset($stats[$category]['stddev_weighted'])) {
1442 $stats[$category]['stddev_weighted'] = sprintf("%0.2f", $stats[$category]['stddev_weighted']);
1444 if (isset($stats[$category]['average_weighted'])) {
1445 $stats[$category]['average_weighted'] = sprintf("%0.2f", $stats[$category]['average_weighted']);
1447 if (isset($stats[$category]['max_weighted'])) {
1448 $stats[$category]['max_weighted'] = max(explode(',',$stats[$category]['all_scores_weighted']));
1450 if (isset($stats[$category]['min_weighted'])) {
1451 $stats[$category]['min_weighted'] = min(explode(',',$stats[$category]['all_scores_weighted']));
1454 if (isset($stats[$category]['all_scores_weighted'])) {
1455 $stats[$category]['median_weighted'] = explode(',',$stats[$category]['all_scores_weighted']);
1457 else {
1462 sort($stats[$category]['median']);
1464 if (count($stats[$category]['median'])/2 == floor(count($stats[$category]['median'])/2) ) {
1465 // even number of scores
1466 $temp = $stats[$category]['median'][count($stats[$category]['median'])/2-1] + $stats[$category]['median'][count($stats[$category]['median'])/2];
1467 $temp = $temp/2;
1469 else {
1470 // odd number of scores
1471 $temp = $stats[$category]['median'][floor(count($stats[$category]['median'])/2)];
1473 unset($stats[$category]['median']);
1474 $stats[$category]['median'] = $temp;
1476 if (isset($stats[$category]['median_weighted'])) {
1477 if (count($stats[$category]['median_weighted'])/2 == floor(count($stats[$category]['median_weighted'])/2)) {
1478 // even number of scores
1479 $temp = $stats[$category]['median_weighted'][count($stats[$category]['median_weighted'])/2-1] + $stats[$category]['median_weighted'][count($stats[$category]['median_weighted'])/2+1];
1480 $temp = $temp/2;
1482 else {
1483 // odd number of scores
1484 $temp = $stats[$category]['median_weighted'][floor(count($stats[$category]['median_weighted'])/2)];
1486 unset($stats[$category]['median_weighted']);
1487 $stats[$category]['median_weighted'] = $temp;
1490 return $stats;
1493 // returns a comma seperated list of the most common values in $items, $items is expected to be a comma sperated list of numbers
1494 function grade_mode($items) {
1495 $all_scores = explode(',',$items);
1496 foreach($all_scores as $value) {
1497 if (isset($frequency[$value])) {
1498 $frequency[$value]++;
1500 else {
1501 $frequency[$value] = 1;
1504 $max = max($frequency);
1505 foreach($frequency as $key=>$value) {
1506 if ($value == $max) {
1507 if (isset($retval)) {
1508 $retval .= ', '.$key;
1510 else {
1511 $retval = $key;
1515 return $retval;
1519 function grade_stats() {
1520 global $CFG;
1521 global $course;
1522 global $USER;
1523 global $preferences;
1525 if (!isset($category)) {
1526 $category = clean_param($_REQUEST['category'], PARAM_CLEAN);
1529 $stats = grade_get_stats($category);
1531 // output our data
1532 print_header();
1533 echo '<table align="center"><tr><th colspan="3">'.$category.' '.get_string('stats','grades').'</th></tr>';
1534 if ($preferences->show_weighted == 1 && $preferences->use_weighted_for_letter == 1 && $category== 'all') {
1535 echo '<tr><th>&nbsp;</th><th>'.get_string('points','grades').'<th>'.get_string('weight','grades').'</th></tr>';
1538 echo '<tr><td align="right">'.get_string('max','grades').':</td><td align="right">'.$stats[$category]['max'].'</td>';
1539 if ($preferences->show_weighted == 1 && $preferences->use_weighted_for_letter == 1 && $category== 'all') {
1540 echo '<td align="right">'.$stats[$category]['max_weighted'].'</td>';
1542 echo '</tr>';
1544 echo '<tr><td align="right">'.get_string('min','grades').':</td><td align="right">'.$stats[$category]['min'].'</td>';
1545 if ($preferences->show_weighted == 1 && $preferences->use_weighted_for_letter == 1 && $category== 'all') {
1546 echo '<td align="right">'.$stats[$category]['min_weighted'].'</td>';
1548 echo '</tr>';
1550 echo '<tr><td align="right">'.get_string('average','grades').':</td><td align="right">'.$stats[$category]['average'].'</td>';
1551 if ($preferences->show_weighted == 1 && $preferences->use_weighted_for_letter == 1 && $category== 'all') {
1552 echo '<td align="right">'.$stats[$category]['average_weighted'].'</td>';
1554 echo '</tr>';
1556 echo '<tr><td align="right">'.get_string('median','grades').':</td><td align="right">'.$stats[$category]['median'].'</td>';
1557 if ($preferences->show_weighted == 1 && $preferences->use_weighted_for_letter == 1 && $category== 'all') {
1558 echo '<td align="right">'.$stats[$category]['median_weighted'].'</td>';
1560 echo '</tr>';
1562 echo '<tr><td align="right">'.get_string('mode','grades').':</td><td align="right">'.$stats[$category]['mode'].'</td>';
1563 if ($preferences->show_weighted == 1 && $preferences->use_weighted_for_letter == 1 && $category== 'all') {
1564 echo '<td align="right">'.$stats[$category]['mode_weighted'].'</td>';
1566 echo '</tr>';
1568 echo '<tr><td align="right">'.get_string('standarddeviation','grades').':</td><td align="right">'.$stats[$category]['stddev'].'</td>';
1569 if ($preferences->show_weighted == 1 && $preferences->use_weighted_for_letter == 1 && $category== 'all') {
1570 echo '<td align="right">'.$stats[$category]['stddev_weighted'].'</td>';
1572 echo '</tr>';
1573 echo '</table>';
1574 //print_footer();
1577 function grade_view_category_grades($view_by_student) {
1578 global $CFG;
1579 global $course;
1580 global $USER;
1581 global $preferences;
1582 global $group;
1583 if (!isteacher($course->id)) {
1584 $view_by_student = $USER->id;
1587 if ($preferences->use_advanced == 0) {
1588 $cview = UNCATEGORISED;
1590 else {
1591 $cview=clean_param($_REQUEST['cview'], PARAM_CLEAN);
1594 if ($cview) {
1595 list($grades_by_student, $all_categories) = grade_get_formatted_grades();
1597 if ($grades_by_student != 0 && $all_categories != 0) {
1598 // output a form for the user to download the grades.
1599 grade_download_form();
1601 if ($view_by_student != -1) {
1602 // unset all grades except for this student
1603 foreach ($grades_by_student as $student=>$junk) {
1604 if($student != $view_by_student) {
1605 unset($grades_by_student[$student]);
1610 $grade_columns = $preferences->show_weighted + $preferences->show_points + $preferences->show_percent;
1612 $first = 0;
1613 //$maxpoints = 0;
1614 $maxpercent = 0;
1615 $reprint = 0;
1616 if (isteacher($course->id)) {
1617 $student_heading_link = get_string('student','grades');
1618 //only set sorting links if more than one student displayed.
1619 if ($view_by_student == -1) {
1620 $student_heading_link .='<br /><a href="?id='.$course->id.'&amp;group='.$group.'&amp;action=vcats&amp;cview='.$cview.'&amp;sort=lastname">'.get_string('sortbylastname','grades').'</a>';
1621 $student_heading_link .= '<br /><a href="?id='.$course->id.'&amp;group='.$group.'&amp;action=vcats&amp;cview='.$cview.'&amp;sort=firstname">'.get_string('sortbyfirstname','grades').'</a>';
1623 else {
1624 $student_heading_link .= '<br /><a href="?id='.$course->id.'&amp;group='.$group.'&amp;action=vcats&amp;cview='.$cview.'">'.get_string('showallstudents','grades').'</a>';
1627 echo '<table align="center" class="grades">';
1628 if (isteacher($course->id)) {
1629 $header = '<tr class="header"><th rowspan="2">'.$student_heading_link.'</th>';
1631 else {
1632 $header = '<tr class="header">';
1634 $header1 = '<tr class="header">';
1636 // to keep track of what we've output
1637 $colcount = 0;
1638 $oddrow = true;
1639 $reprint = 0;
1641 // this next section is to display the items in the course order
1642 foreach($grades_by_student as $student => $categories) {
1643 if (isset($item_order)) {
1644 // we already have the sort order let's jump out
1645 break;
1647 $item_order = array();
1648 foreach($categories as $category => $items) {
1649 if ($category == $cview) {
1650 foreach ($items as $assignment=>$points) {
1651 if ($assignment != 'stats') {
1652 $temp = $points['sort_order'];
1653 $item_order[$temp] = $assignment;
1659 /// Make sure $item_order is initialised (bug 3424)
1660 if (empty($item_order)) $item_order = array();
1662 ksort($item_order);
1664 foreach($grades_by_student as $student => $categories) {
1666 if ($preferences->reprint_headers != 0 && $reprint >= $preferences->reprint_headers) {
1667 echo $header.$header1.'</tr>';
1668 $reprint=0;
1671 // alternate row classes
1672 $row = ($oddrow) ? '<tr class="r0">' : '<tr class="r1">';
1673 $oddrow = !$oddrow;
1675 // reset the col classes
1676 $oddcol = true;
1679 // set the links to student information based on multiview or individual... if individual go to student info... if many go to individual grades view.
1680 if (isteacher($course->id)) {
1681 if ($view_by_student != -1) {
1682 $student_link = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$student.'&amp;course='.$course->id.'">';
1684 else {
1685 $student_link = '<a href="?id='.$course->id.'&amp;group='.$group.'&amp;action=vcats&amp;user='.$student.'&amp;cview='.$cview.'">';
1687 $student_link .= $grades_by_student[$student]['student_data']['lastname'].', '.$grades_by_student[$student]['student_data']['firstname'].'</a>';
1688 $row .= '<td class="fullname">'.$student_link.'</td>';
1691 foreach($categories as $category => $items) {
1692 if ($category == $cview) {
1693 // make sure that the grades come out in the same order
1694 foreach($item_order as $order=>$assignment) {
1696 $class = $all_categories[$category][$assignment]['modname'];
1698 if ($assignment != 'stats') {
1700 if ($first == 0) {
1701 $colcount++;
1702 $link_id = grade_get_module_link($course->id, $all_categories[$category][$assignment]['cminstance'], $all_categories[$category][$assignment]['modid']);
1704 $link = $CFG->wwwroot.'/mod/'.$all_categories[$category][$assignment]['modname'].'/view.php?id='.$link_id->id;
1705 $all_categories[$category][$assignment]['link'] = $link;
1706 if ($all_categories[$category][$assignment]['hidden'] == 0) {
1707 $header .= '<th class="'.$class.'" colspan="'.$grade_columns.'"><a href="'.$link.'">'.format_string($assignment,true).'</a>';
1709 else {
1710 $header .= '<th class="'.$class.'" colspan="'.$grade_columns.'"><a class="dimmed" href="'.$link.'">'.format_string($assignment,true).'</a>';
1712 if ($all_categories[$category][$assignment]['extra_credit'] == 1) {
1713 $header .= '<span class="extracredit">('.get_string('extracredit','grades').')</span>';
1715 $header .='</th>';
1716 if ($preferences->show_points) {
1717 $header1 .= '<th class="'.$class.'">'. $all_categories[$category][$assignment]['maxgrade'];
1718 if ($all_categories[$category][$assignment]['grade_against'] != $all_categories[$category][$assignment]['maxgrade']) {
1719 $header1 .= '('. $all_categories[$category][$assignment]['grade_against'].')';
1721 $header1 .= '</th>';
1724 if($preferences->show_percent) {
1725 if ($all_categories[$category][$assignment]['grade_against'] != $all_categories[$category][$assignment]['maxgrade']) {
1726 $header1 .= '<th class="'.$class.'">'.get_string('scaledpct','grades').'</th>';
1728 else {
1729 $header1 .= '<th class="'.$class.'">'.get_string('rawpct','grades').'</th>';
1732 if ($preferences->show_weighted) {
1733 if ($all_categories[$category]['stats']['totalpoints'] != 0) {
1734 $cur_weighted_max = sprintf("%0.2f", $all_categories[$category][$assignment]['grade_against']/$all_categories[$category]['stats']['totalpoints']*$all_categories[$category]['stats']['weight']);
1736 else {
1737 $cur_weighted_max = 0;
1739 $header1 .= '<th>'.$cur_weighted_max.get_string('pctoftotalgrade','grades').'</th>';
1743 // display points
1744 if ($preferences->show_points) {
1745 $class .= ($oddcol) ? ' c0 points' : ' c1 points';
1746 $oddcol = !$oddcol;
1747 $row .= '<td class="'.$class.'"><a href="'.$all_categories[$category][$assignment]['link'].'">' . $items[$assignment]['grade'] . '</a></td>';
1750 if ($preferences->show_percent) {
1751 $class .= ($oddcol) ? ' c0 percent' : ' c1 percent';
1752 $oddcol = !$oddcol;
1753 $row .= '<td class="'.$class.'">'. $items[$assignment]['percent'].'%</td>';
1756 if ($preferences->show_weighted) {
1757 $class .= ($oddcol) ? ' c0 weighted' : ' c1 weighted';
1758 $oddcol = !$oddcol;
1759 $row .= '<td class="'.$class.'">'.$items[$assignment]['weighted'].'%</td>';
1763 } else {
1764 $class = '';
1768 if ($first == 0) {
1769 if (isteacher($course->id) && $view_by_student == -1) {
1770 $total_sort_link = '<a href="?id='.$course->id.'&amp;group='.$group.'&amp;action=vcats&amp;cview='.$cview.'&amp;sort=highgrade_category"><img src="'.$CFG->wwwroot.'/pix/t/down.gif" alt="'.get_string('highgradedescending','grades').'" /></a>';
1771 $total_sort_link .= '<a href="?id='.$course->id.'&amp;group='.$group.'&amp;action=vcats&amp;cview='.$cview.'&amp;sort=highgrade_category_asc"><img src="'.$CFG->wwwroot.'/pix/t/up.gif" alt="'.get_string('highgradeascending','grades').'" /></a>';
1773 else {
1774 $total_sort_link = '';
1777 $stats_link = '<a href="javascript:void(0)"onclick="window.open(\'?id='.$course->id.'&amp;action=stats&amp;group='.$group.'&amp;category='.$cview.'\',\''.get_string('statslink','grades').'\',\'height=200,width=300,scrollbars=no\')">'.get_string('statslink','grades').'</a>';
1778 if ($all_categories[$cview]['stats']['drop'] != 0) {
1779 $header .= '<th class="'.$class.'" colspan="'.$grade_columns.'">'.get_string('total','grades').'&nbsp; (Lowest '. $all_categories[$cview]['stats']['drop']. ' Dropped)'.$total_sort_link.' '.$stats_link.'</th>';
1781 else {
1782 $header .= '<th class="'.$class.'" colspan="'.$grade_columns.'">'.get_string('total','grades').'&nbsp;'.$total_sort_link.' '.$stats_link.'</th>';
1785 if ($preferences->show_points) {
1786 $header1 .= '<th class="'.$class.'">'.$all_categories[$cview]['stats']['totalpoints'];
1787 if ($all_categories[$cview]['stats']['bonus_points'] != 0) {
1788 $header1 .='(+'.$all_categories[$cview]['stats']['bonus_points'].')';
1790 $header1 .='</th>';
1792 if ($preferences->show_percent) {
1793 $header1 .= '<th class="'.$class.'">'.get_string('percent','grades').'</th>';
1797 if ($preferences->show_weighted) {
1798 $header1 .= '<th class="'.$class.'">'.$all_categories[$cview]['stats']['weight'].get_string('pctoftotalgrade','grades').'</th>';
1801 if (isteacher($course->id) ) {
1802 $header .= '<th rowspan="2">'.$student_heading_link.'</th></tr>';
1804 else {
1805 $header .= '</tr>';
1808 //adjust colcount to reflect the actual number of columns output
1809 $colcount++; // total column
1810 $colcount = $colcount*$grade_columns + 2;
1811 echo '<tr class="title"><th colspan="'.$colcount.'">';
1812 if ($preferences->use_advanced != 0) {
1813 echo $cview.' '.get_string('grades','grades');
1815 else {
1816 echo get_string('grades','grades');
1819 if (isteacher($course->id)) {
1820 helpbutton('teacher', get_string('gradehelp','grades'), 'grade');
1822 else {
1823 helpbutton('student', get_string('gradehelp','grades'), 'grade');
1825 echo '</th></tr>';
1826 echo $header;
1827 echo $header1.'</tr>';
1828 $first = 1;
1831 // total points for category
1832 if ($preferences->show_points) {
1833 $class .= ($oddcol) ? ' c0 points' : ' c1 points';
1834 $oddcol = !$oddcol;
1835 $row .= '<td class="'.$class.'">'.$grades_by_student[$student][$cview]['stats']['points'].'</td>';
1838 // total percent for category
1839 if ($preferences->show_percent) {
1840 $class .= ($oddcol) ? ' c0 percent' : ' c1 percent';
1841 $oddcol = !$oddcol;
1842 $row .= '<td class="'.$class.'">'.$grades_by_student[$student][$cview]['stats']['percent'].'%</td>';
1846 // total weighted for category
1847 if ($preferences->show_weighted) {
1848 $class .= ($oddcol) ? ' c0 weighted' : ' c1 weighted';
1849 $oddcol = !$oddcol;
1850 $row .= '<td class="'.$class.'">'.$grades_by_student[$student][$cview]['stats']['weighted'].'%</td>';
1853 if (isteacher($course->id) ) {
1854 $row .= '<td class="fullname">'.$student_link.'</td>';
1856 $row .= '</tr>';
1857 echo $row;
1858 $reprint++;
1860 echo '</table>';
1862 else { // no grades returned
1863 error(get_string('nogradesreturned','grades'), $CFG->wwwroot.'/course/view.php?id='.$course->id);
1866 else {
1867 error(get_string('nocategoryview','grades'), $CFG->wwwroot.'/course/view.php?id='.$course->id);
1871 function grade_view_all_grades($view_by_student) {
1872 // displays all grades for the course
1873 global $CFG;
1874 global $course;
1875 global $preferences;
1876 global $USER;
1878 if (!isteacher($course->id)) {
1879 $view_by_student = $USER->id;
1882 list($grades_by_student, $all_categories) = grade_get_formatted_grades();
1884 if ($grades_by_student != 0 && $all_categories != 0) {
1885 // output a form for the user to download the grades.
1886 grade_download_form();
1888 if ($view_by_student != -1) {
1889 // unset all grades except for this student
1890 foreach ($grades_by_student as $student=>$junk) {
1891 if($student != $view_by_student) {
1892 unset($grades_by_student[$student]);
1896 $grade_columns = $preferences->show_weighted + $preferences->show_points + $preferences->show_percent;
1898 $first = 0;
1899 $total_course_points = 0;
1900 $maxpercent = 0;
1901 $reprint=0;
1903 echo '<table align="center" class="grades">';
1904 if (isteacher($course->id) ) {
1905 $student_heading_link = get_string('student','grades');
1906 if ($view_by_student == -1) {
1907 $student_heading_link .='<a href="?id='.$course->id.'&amp;action=grades&amp;sort=lastname"><br /><font size="-2">'.get_string('sortbylastname','grades').'</font></a>';
1908 $student_heading_link .= '<a href="?id='.$course->id.'&amp;action=grades&amp;sort=firstname"><br /><font size="-2">'.get_string('sortbyfirstname','grades').'</font></a>';
1910 else {
1911 $student_heading_link .= '<br /><a href="?id='.$course->id.'&amp;&amp;action=grades"><font size="-2">'.get_string('showallstudents','grades').'</font></a>';
1913 $header = '<tr><th rowspan="2">'.$student_heading_link.'</th>';
1915 else {
1916 $header = '</tr>';
1918 $header1 = '<tr">';
1920 $rowcount = 0;
1921 $oddrow = true;
1922 $colcount = 0;
1923 foreach($grades_by_student as $student => $categories) {
1924 $totalpoints = 0;
1925 $totalgrade = 0;
1926 $total_bonus_points = 0;
1927 if ($preferences->reprint_headers != 0 && $reprint >= $preferences->reprint_headers) {
1928 echo $header.$header1;
1929 $reprint=0;
1932 // alternate row classes
1933 $row = ($oddrow) ? '<tr class="r0">' : '<tr class="r1">';
1934 $oddrow = !$oddrow;
1936 // set the links to student information based on multiview or individual... if individual go to student info... if many go to individual grades view.
1937 if (isteacher($course->id)) {
1938 if ($view_by_student != -1) {
1939 $studentviewlink = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$student.'&amp;course='.$course->id.'">'.$grades_by_student[$student]['student_data']['lastname'].', '.$grades_by_student[$student]['student_data']['firstname'].'</a>';
1941 else {
1942 $studentviewlink = '<a href="?id='.$course->id.'&amp;action=view_student_grades&amp;user='.$student.'">'.$grades_by_student[$student]['student_data']['lastname'].', '.$grades_by_student[$student]['student_data']['firstname'].'</a>';
1944 $row .= '<td>'. $studentviewlink .'</td>';
1946 ksort($categories);
1947 foreach($categories as $category => $items) {
1948 if ($category != 'student_data') {
1949 if ($first == 0) {
1950 $colcount++;
1951 if ($category == UNCATEGORISED) {
1952 $categoryname = get_string(UNCATEGORISED, 'grades');
1953 } else {
1954 $categoryname = $category;
1956 // only print the category headers if something is displayed for them
1957 if ($preferences->show_weighted || $preferences->show_percent || $preferences->show_points) {
1958 $stats_link = '<a href="javascript:void(0)"onclick="window.open(\'?id='.$course->id.'&amp;action=stats&amp;category='.$category.'\',\''.get_string('statslink','grades').'\',\'height=200,width=300,scrollbars=no\')"><font size=-2>'.get_string('statslink','grades').'</font></a>';
1959 $header .= '<th colspan="'.$grade_columns.'"><a href="?id='.$course->id.'&amp;action=vcats&amp;cview='.$category;
1960 if ($view_by_student != -1) {
1961 $header .= '&amp;user='.$view_by_student;
1963 $header .='">'. $categoryname .' '.$stats_link.'</a>';
1965 if ($preferences->display_weighted != 0) {
1966 $header .= '('. $all_categories[$category]['stats']['weight'] . '%)';
1968 $header .= '</th>';
1969 if ($preferences->show_points) {
1970 $header1 .= '<th>'.get_string('points','grades').'('.$all_categories[$category]['stats']['totalpoints'].')';
1971 if ($all_categories[$category]['stats']['bonus_points'] != 0) {
1972 $header1 .='(+'.$all_categories[$category]['stats']['bonus_points'].')';
1974 $header1 .='</th>';
1976 if ($preferences->show_percent) {
1977 $header1 .= '<th>'.get_string('percent','grades').'</th>';
1979 if ($preferences->show_weighted) {
1980 $header1 .= '<th>'.get_string('weightedpctcontribution','grades').'</th>';
1982 $maxpercent = $all_categories["$category"]['stats']['weight'] + $maxpercent;
1983 //$total_course_points = $all_categories[$category]['stats']['totalpoints']+ $total_course_points;
1984 //$total_course_points = $all_categories[$category]['stats']['totalpoints']+ $total_course_points;
1988 if ($preferences->show_points) {
1989 $row .= '<td align="right">' . $items['stats']['points'] . '</td>';
1991 if ($preferences->show_percent) {
1992 $row .= '<td align="right">'. $items['stats']['percent'].'%</td>';
1995 if ($preferences->show_weighted) {
1996 $row .= '<td align="right">'. $items['stats']['weighted'] . '%</td>';
1998 $total_bonus_points = $all_categories[$category]['stats']['bonus_points'];
2001 if ($first == 0) {
2002 if ($preferences->show_letters) {
2003 $total_columns = $grade_columns + 1;
2005 else {
2006 $total_columns = $grade_columns;
2009 if (isteacher($course->id) && $view_by_student == -1) {
2010 $grade_sort_link = '<a href="?id='.$course->id.'&amp;action=grades&amp;sort=highgrade"><img src="'.$CFG->wwwroot.'/pix/t/down.gif" alt="'.get_string('highgradedescending','grades').'" /></a>';
2011 $grade_sort_link .= '<a href="?id='.$course->id.'&amp;action=grades&amp;sort=highgrade_asc"><img src="'.$CFG->wwwroot.'/pix/t/up.gif" alt="'.get_string('highgradeascending','grades').'" /></a>';
2012 $points_sort_link = '<a href="?id='.$course->id.'&amp;action=grades&amp;sort=points"><img src="'.$CFG->wwwroot.'/pix/t/down.gif" alt="'.get_string('pointsdescending','grades').'" /></a>';
2013 $points_sort_link .= '<a href="?id='.$course->id.'&amp;action=grades&amp;sort=points_asc"><img src="'.$CFG->wwwroot.'/pix/t/up.gif" alt="'.get_string('pointsascending','grades').'" /></a>';
2014 $weighted_sort_link = '<a href="?id='.$course->id.'&amp;action=grades&amp;sort=weighted"><img src="'.$CFG->wwwroot.'/pix/t/down.gif" alt="'.get_string('weighteddescending','grades').'" /></a>';
2015 $weighted_sort_link .= '<a href="?id='.$course->id.'&amp;action=grades&amp;sort=weighted_asc"><img src="'.$CFG->wwwroot.'/pix/t/up.gif" alt="'.get_string('weightedascending','grades').'" /></a>';
2016 $percent_sort_link = '<a href="?id='.$course->id.'&amp;action=grades&amp;sort=percent"><img src="'.$CFG->wwwroot.'/pix/t/down.gif" alt="'.get_string('percentdescending','grades').'" /></a>';
2017 $percent_sort_link .= '<a href="?id='.$course->id.'&amp;action=grades&amp;sort=percent_asc"><img src="'.$CFG->wwwroot.'/pix/t/up.gif" alt="'.get_string('percentascending','grades').'" /></a>';
2019 $stats_link = '<a href="javascript:void(0)"onclick="window.open(\'?id='.$course->id.'&amp;action=stats&amp;category=all\',\''.get_string('statslink','grades').'\',\'height=200,width=300,scrollbars=no\')"><font size=-2>'.get_string('statslink','grades').'</font></a>';
2020 $header .= '<th colspan="'.$total_columns.'">'.get_string('total','grades').'&nbsp;'.$stats_link.'</th>';
2021 if (isteacher($course->id) && $view_by_student == -1) {
2022 if ($preferences->show_points) {
2023 $header1 .= '<th>'.get_string('points','grades').'('.$all_categories['stats']['totalpoints'].')';
2024 if ($category != 'student_data' && $all_categories[$category]['stats']['bonus_points'] != 0) {
2026 $header1 .='(+'.$total_bonus_points.')';
2028 $header1 .= '<br />'.$points_sort_link.' '.'</th>';
2030 if ($preferences->show_percent) {
2031 $header1 .= '<th>'.get_string('percentshort','grades').'<br />'.$percent_sort_link.' '.'</th>';
2033 if ($preferences->show_weighted) {
2034 $header1 .= '<th>'.get_string('weightedpct','grades').'('.$all_categories['stats']['weight'].')'.'<br />'.$weighted_sort_link.' '.'</th>';
2036 if ($preferences->show_letters) {
2037 $header1 .= '<th>'.get_string('lettergrade','grades').'<br />'.$grade_sort_link.' '.'</th>';
2039 $header1 .= '</tr>';
2041 else {
2042 if ($preferences->show_points) {
2043 $header1 .= '<th>'.get_string('points','grades').'('.$all_categories['stats']['totalpoints'].')';
2044 if ($category != 'student_data' && $all_categories[$category]['stats']['bonus_points'] != 0) {
2045 $header1 .='(+'.$total_bonus_points.')';
2047 $header1 .= '</th>';
2049 if ($preferences->show_percent) {
2050 $header1 .= '<th>'.get_string('percentshort','grades').'</th>';
2052 if ($preferences->show_weighted) {
2053 $header1 .= '<th>'.get_string('weightedpct','grades').'('.$all_categories['stats']['weight'].')</th>';
2055 if ($preferences->show_letters) {
2056 $header1 .= '<th>'.get_string('lettergrade','grades').'</th>';
2058 $header1 .= '</tr>';
2060 if (isteacher($course->id)) {
2061 $header .= '<th rowspan="2">'.$student_heading_link.'</th></tr>';
2063 // adjust colcount to reflect actual number of columns output
2064 $colcount = $colcount * $grade_columns + $total_columns + 2;
2066 echo '<tr><th colspan="'.$colcount.'"><font size="+1">'.get_string('allgrades','grades').'</font>';
2067 if (isteacher($course->id)) {
2068 helpbutton('teacher', get_string('gradehelp','grades'), 'grade');
2070 else {
2071 helpbutton('student', get_string('gradehelp','grades'), 'grade');
2073 echo '</th></tr>';
2076 echo $header;
2077 echo $header1;
2078 $first = 1;
2080 if ($preferences->show_points) {
2081 $row .= '<td align="right">'.$grades_by_student[$student]['student_data']['points'].'</td>';
2083 if ($preferences->show_percent) {
2084 $row .= '<td align="right">'.$grades_by_student[$student]['student_data']['percent'].'%</td>';
2086 if ($preferences->show_weighted) {
2087 $row .= '<td align=right>'.$grades_by_student[$student]['student_data']['weighted'].'%</td>';
2089 if ($preferences->show_letters) {
2090 if ($preferences->use_weighted_for_letter == 1) {
2091 $grade = $grades_by_student[$student]['student_data']['weighted'];
2093 else {
2094 $grade = $grades_by_student[$student]['student_data']['percent'];
2096 $letter_grade = grade_get_grade_letter($course->id, $grade);
2097 if ($letter_grade) {
2098 $row .= '<td align="right">'.$letter_grade->letter.'</td>';
2100 else {
2101 // there wasn't an appropriate entry to use in the gradebook.
2102 if (grade_letters_set($course->id)) {
2103 $row .= '<td align="right">'.get_string('nolettergrade','grades').' '.$grade.'</td>';
2105 else {
2106 $row .= '<td align="right">'.get_string('nogradeletters','grades').'</td>';
2110 if (isteacher($course->id) ) {
2111 $row .= '<td>'. $studentviewlink .'</td></tr>';
2113 else {
2114 $row .= '</tr>';
2116 echo $row;
2117 $reprint++;
2119 echo '</table>';
2121 else { // no grades returned
2122 error(get_string('nogradesreturned','grades'));
2127 function grade_set_grade_weights() {
2128 // set the grade weights as submitted from the form generated by display_grade_weights
2129 global $CFG;
2130 global $course;
2131 global $USER;
2133 if (!empty($USER->id)) {
2134 if (!confirm_sesskey()) {
2135 error(get_string('confirmsesskeybad', 'error'));
2139 // get list of all categories
2140 $categories = get_records('grade_category', 'courseid', $course->id);
2141 if ($categories) {
2142 foreach ($categories as $category) {
2143 $form_catname = str_replace(' ', '_', $category->name);
2145 $submitted_category = optional_param($form_catname);
2146 if (is_numeric($submitted_category)) {
2147 // see if there is a weight if so see if it needs to be updated
2148 $weight = grade_get_category_weight($course->id, $category->name);
2149 if ($weight) {
2150 if ($weight->weight != $submitted_category)
2152 set_field('grade_category', 'weight', $submitted_category, 'id', $weight->id);
2155 $cur_drop = optional_param("drop_x_lowest$form_catname");
2156 $cur_bonus_points = optional_param("bonus_points$form_catname");
2157 $cur_hidden = optional_param("hidden$form_catname");
2158 if ($cur_hidden) {
2159 $cur_hidden = true;
2161 else {
2162 $cur_hidden = false;
2165 if ($weight->drop_x_lowest != $cur_drop) {
2166 set_field('grade_category', 'drop_x_lowest', $cur_drop, 'id', $weight->cat_id);
2168 if ($weight->bonus_points != $cur_bonus_points) {
2169 set_field('grade_category', 'bonus_points', $cur_bonus_points, 'id', $weight->cat_id);
2171 if ($cur_hidden) {
2172 set_field('grade_category', 'hidden', 1, 'id', $weight->cat_id);
2174 else {
2175 set_field('grade_category', 'hidden', 0, 'id', $weight->cat_id);
2178 else {
2179 // insert the new record... we shouldn't reach this point anymore
2180 //$new_weight->course = $course->id;
2181 //$new_weight->category = $category->id;
2182 //$new_weight->weight = $submitted_category;
2183 //insert_record('grade_weight', $new_weight);
2186 else {
2187 echo '<center><font color="red">'.get_string('nonumericweight','grades').$category->name.': "'.$submitted_category.'"</font></center><br />';
2193 function grade_display_grade_weights() {
2194 // get all categories with weights
2195 // then set and display that entry.
2196 global $CFG;
2197 global $course;
2198 global $USER;
2200 $categories = get_records('grade_category', 'courseid', $course->id);
2201 if ($categories) {
2202 echo '<table border="0" cellspacing="2" cellpadding="5" align="center" class="generalbox"><tr><th colspan="5" class="header">'.get_string('setweights','grades');
2203 helpbutton('weight', get_string('gradeweighthelp','grades'), 'grade');
2204 echo '</th></tr>';
2205 echo '<tr><td align="center" class="generaltableheader">'.get_string('category','grades').'</td><td align="center" class="generaltableheader">'.get_string('weight','grades').'</td><td align="center" class="generaltableheader">'.get_string('dropxlowest','grades').'</td><td align="center" class="generaltableheader">'.get_string('bonuspoints','grades').'</td><td align="center" class="generaltableheader">'.get_string('hidecategory','grades').'</td></tr>';
2206 echo '<form name="grade_weights" action="./index.php" method="post">';
2207 echo '<input type="hidden" name="id" value="'.$course->id.'" />';
2208 echo '<input type="hidden" name="action" value="set_grade_weights" />';
2209 echo '<input type="hidden" name="sesskey" value="'.$USER->sesskey.'" />';
2211 $sum = 0;
2213 foreach($categories as $category) {
2214 $val = $category->weight;
2215 $sum = $sum + $val;
2217 // make names form safe
2218 $form_catname = str_replace(' ', '_', $category->name);
2219 if ($category->name == UNCATEGORISED) {
2220 $category->name = get_string(UNCATEGORISED, 'grades');
2222 echo '<tr><td align="center" class="generalboxcontent">'.$category->name.'</td>';
2223 echo '<td align="center" class="generalboxcontent"><input type="text" size="5" name="'.$form_catname.'" value="'.$val.'" /></td>';
2224 echo '<td align="center" class="generalboxcontent"><input type="text" size="5" name="drop_x_lowest'.$form_catname.'" value="'.$category->drop_x_lowest.'" /></td>';
2225 echo '<td align="center" class="generalboxcontent"><input type="text" size="5" name="bonus_points'.$form_catname.'" value="'.$category->bonus_points.'" /></td>';
2226 echo '<td align="center" class="generalboxcontent"><input type="checkbox" name="hidden'.$form_catname.'" ';
2227 if ($category->hidden == 1) {
2228 echo ' checked="checked"';
2230 echo ' /></td>';
2232 echo '<tr><td colspan="5" align="center" class="generalboxcontent"><input type="submit" value="'.get_string('savechanges','grades').'" /></td></tr></form>';
2233 if ($sum != 100) {
2234 echo '<tr><td colspan="5" align="center" class="generalboxcontent"><font color="red">'.get_string('totalweightnot100','grades').'</font></td></tr>';
2236 else {
2237 echo '<tr><td colspan="5" align="center" class="generalboxcontent"><font color="green">'.get_string('totalweight100','grades').'</font></td></tr>';
2240 else {
2241 /// maybe this should just do the default population of the categories instead?
2242 echo '<font color="red">'.get_string('setcategorieserror','grades').'</font>';
2244 echo '</table>';
2245 echo '<center>'.get_string('dropxlowestwarning','grades').'</center><br />';
2248 function grade_set_categories() {
2249 global $CFG;
2250 global $course;
2251 global $USER;
2254 /// Collect modules data
2255 get_all_mods($course->id, $mods, $modnames, $modnamesplural, $modnamesused);
2257 echo '<table border="0" cellspacing="2" cellpadding="5" align="center" class="generalbox"><tr><th colspan="5" class="header">'.get_string('setcategories','grades');
2258 helpbutton('category', get_string('gradecategoryhelp','grades'), 'grade');
2259 echo '<tr><td align="center" class="generaltableheader">'.get_string('gradeitem','grades').'</td><td align="center" class="generaltableheader">'.get_string('category','grades').'</td><td align="center" class="generaltableheader">'.get_string('maxgrade','grades').'</td><td align="center" class="generaltableheader">'.get_string('curveto','grades').'</td><td align="center" class="generaltableheader">'.get_string('extracredit','grades').'</td></tr>';
2260 echo '<form name="set_categories" method="post" action="./index.php" >';
2261 echo '<input type="hidden" name="action" value="assign_categories" />';
2262 echo '<input type="hidden" name="id" value="'.$course->id.'" />';
2263 echo '<input type="hidden" name="sesskey" value="'.$USER->sesskey.'" />';
2265 $itemcount = 0;
2267 /// Search through all the modules, pulling out grade data
2268 $sections = get_all_sections($course->id); // Sort everything the same as the course
2269 for ($i=0; $i<=$course->numsections; $i++) {
2270 if (isset($sections[$i])) { // should always be true
2271 $section = $sections[$i];
2272 if ($section->sequence) {
2273 $sectionmods = explode(",", $section->sequence);
2274 foreach ($sectionmods as $sectionmod) {
2275 if (empty($mods[$sectionmod])) {
2276 continue;
2278 $mod = $mods[$sectionmod];
2279 $instance = get_record("$mod->modname", "id", "$mod->instance");
2280 $libfile = "$CFG->dirroot/mod/$mod->modname/lib.php";
2281 if (file_exists($libfile)) {
2282 require_once($libfile);
2283 $gradefunction = $mod->modname."_grades";
2284 if (function_exists($gradefunction)) { // Skip modules without grade function
2285 if ($modgrades = $gradefunction($mod->instance)) {
2287 if ($modgrades->maxgrade != '')
2288 // this block traps out broken modules that don't return a maxgrade according to the moodle API
2290 $itemcount++;
2291 //modgrades contains student information with associated grade
2292 //echo "<b>modname: $mod->modname id: $mod->id course: $mod->course</b><br />";
2293 echo '<input type="hidden" name="modname'.$itemcount.'" value="'.$mod->modname.'" />';
2294 echo '<input type="hidden" name="mod'.$itemcount.'" value="'.$mod->instance.'" />';
2295 echo '<input type="hidden" name="course'.$itemcount.'" value="'.$mod->course.'" />';
2296 echo '<tr><td align="center" class="generalboxcontent">';
2297 // get instance name from db.
2298 $instance = get_record($mod->modname, 'id', $mod->instance);
2299 echo format_string($instance->name)."</td>";
2300 // see if the item is already in the category table and if it is call category select with the id so it is selected
2301 echo '<td align="center" class="generalboxcontent"><select name="category'.$itemcount.'">';
2302 $item_cat_id = get_record('grade_item', 'modid', $mod->module, 'courseid', $course->id, 'cminstance', $mod->instance);
2303 //print_object($item_cat_id);
2304 if (isset($item_cat_id)) {
2305 grade_category_select($item_cat_id->category);
2307 else {
2308 grade_category_select(-1);
2310 echo '</select></td><td align="center" class="generalboxcontent">'.$modgrades->maxgrade.'<input type="hidden" name="maxgrade'.$itemcount.'" value="'.$modgrades->maxgrade.'" /></td>';
2312 if (isset($item_cat_id)) {
2313 // 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%)
2314 if ($item_cat_id->scale_grade == '' || $item_cat_id->scale_grade == 0)
2315 $scale_to = $modgrades->maxgrade;
2316 else
2317 $scale_to = round($modgrades->maxgrade/$item_cat_id->scale_grade);
2318 echo '<td align="center" class="generalboxcontent"><input type="text" size="5" name="scale_grade'.$itemcount.'" value="'.$scale_to.'" /></td>';
2320 else {
2321 echo '<td align="center" class="generalboxcontent"><input type="text" size="5" name="scale_grade'.$itemcount.'" value="'.$modgrades->maxgrade.'" /></td>';
2324 echo '<td align="center" class="generalboxcontent"><input type="checkbox" name="extra_credit'.$itemcount.'" ';
2325 if ($item_cat_id->extra_credit == 1) {
2326 echo ' checked="checked"';
2328 echo ' /></td></tr>';
2337 echo '<input type="hidden" name="totalitems" value="'.$itemcount.'" />';
2338 echo '<tr><td colspan="5" align="center" class="generalboxcontent"><input type="submit" value="'.get_string('savechanges','grades').'" /></td></tr>';
2339 echo '</form>';
2340 echo '<tr><td colspan="5" align="center" class="generalboxcontent">';
2341 grade_add_category_form();
2342 echo '</td></tr><tr><td colspan="5" align="center" class="generalboxcontent">';
2343 grade_delete_category_form();
2344 echo '</td></tr></table>';
2345 echo '<center>'.get_string('extracreditwarning','grades').'<center>';
2348 function grade_delete_category() {
2349 global $CFG;
2350 global $course;
2351 global $USER;
2353 if (!empty($USER->id)) {
2354 if (!confirm_sesskey()) {
2355 error(get_string('confirmsesskeybad', 'error'));
2359 $cat_id = optional_param('category_id');
2360 if ($cat_id != 'blank') {
2361 // delete the record
2362 delete_records('grade_category', 'id', $cat_id, 'courseid', $course->id);
2363 // set grade_item category field=0 where it was the deleted category (set uncategorized will clean this up)
2364 set_field('grade_item', 'category', 0, 'category', $cat_id);
2368 function grade_assign_categories() {
2369 global $CFG;
2370 global $course;
2371 global $USER;
2372 $num_categories = optional_param('totalitems');
2374 if (!empty($USER->id)) {
2375 if (!confirm_sesskey()) {
2376 error(get_string('confirmsesskeybad', 'error'));
2380 for ($i = 1; $i <= $num_categories; $i++) {
2382 // these next sets of lines are a bit obtuse, but it lets there be a dynamic number of grade items
2383 // in the grade category form (maybe there's a better way?)
2384 $cur_cat_id = '$_REQUEST[\'category'.$i.'\'];';
2385 eval( "\$cur_cat_id = $cur_cat_id;" );
2386 $cur_modname = '$_REQUEST[\'modname'.$i.'\'];';
2387 eval( "\$cur_modname = $cur_modname;" );
2388 $cur_mod = '$_REQUEST[\'mod'.$i.'\'];';
2389 eval( "\$cur_mod = $cur_mod;" );
2390 $cur_maxgrade = '$_REQUEST[\'maxgrade'.$i.'\'];';
2391 eval( "\$cur_maxgrade = $cur_maxgrade;" );
2392 $cur_scale_grade = '$_REQUEST[\'scale_grade'.$i.'\'];';
2393 eval( "\$cur_scale_grade = $cur_scale_grade;" );
2394 $cur_extra_credit = '$_REQUEST[\'extra_credit'.$i.'\'];';
2395 $temp = 'extra_credit'.$i;
2396 $junk = get_record('modules','name',$cur_modname);
2397 $cur_modid = $junk->id;
2398 if (isset($_REQUEST[$temp])) {
2399 eval( "\$cur_extra_credit = $cur_extra_credit;" );
2401 else {
2402 $cur_extra_credit = false;
2404 if ($cur_extra_credit) {
2405 $cur_extra_credit = 1;
2406 } else {
2407 $cur_extra_credit = 0;
2409 if ($cur_scale_grade == 0 || $cur_scale_grade == '') {
2410 $cur_scale_grade = 1.0;
2413 $db_cat = get_record('grade_item', 'modid', $cur_modid, 'cminstance', $cur_mod, 'courseid', $course->id);
2414 if ( $db_cat ) {
2415 if ($db_cat->category != $cur_cat_id) {
2416 // item doesn't match in the db so update it to point to the new category
2417 set_field('grade_item', 'category', $cur_cat_id, 'id', $db_cat->id);
2420 if ($db_cat->scale_grade != $cur_maxgrade/$cur_scale_grade) {
2421 // scale_grade doesn't match
2422 set_field('grade_item', 'scale_grade', ($cur_maxgrade/$cur_scale_grade), 'id', $db_cat->id);
2425 set_field('grade_item', 'extra_credit', $cur_extra_credit, 'id', $db_cat->id);
2427 else {
2428 // add a new record
2429 $item->courseid = $course->id;
2430 $item->category = $cur_cat_id;
2431 $item->modid = $cur_modid;
2432 $item->cminstance = $cur_mod;
2433 $item->scale_grade = $cur_scale_grade;
2434 $item->extra_credit = $cur_extra_credit;
2435 insert_record('grade_item', $item);
2440 function grade_add_category_form() {
2441 /// outputs a form to add a category
2442 /// just a simple text box with submit
2443 global $course;
2444 global $USER;
2445 echo '<form name="new_category">';
2446 echo get_string('addcategory','grades').':<input type="text" name="name" size="20" />';
2447 echo '<input type="hidden" name="id" value="'.$course->id.'" />';
2448 echo '<input type="hidden" name="action" value="insert_category" />';
2449 echo '<input type="hidden" name="sesskey" value="'.$USER->sesskey.'" />';
2450 echo '<input type="submit" value="'.get_string('addcategory','grades').'" />';
2451 echo '</form>';
2454 function grade_delete_category_form() {
2455 // outputs a form to delete a category
2456 global $course;
2457 global $USER;
2458 echo '<form name="delete_category">';
2459 echo get_string('deletecategory','grades').': <select name="category_id">';
2460 grade_category_select();
2461 echo '</select><input type="hidden" name="id" value="'.$course->id.'" />';
2462 echo '<input type="hidden" name="sesskey" value="'.$USER->sesskey.'" />';
2463 echo '<input type="hidden" name="action" value="delete_category" />';
2464 echo '<input type="submit" value="'.get_string('deletecategory','grades').'" /></form>';
2467 function grade_insert_category() {
2468 global $CFG;
2469 global $course;
2470 global $USER;
2472 $category->name=optional_param('name');
2473 $category->courseid=$course->id;
2475 if (!empty($USER->id)) {
2476 if (!confirm_sesskey()) {
2477 error(get_string('confirmsesskeybad', 'error'));
2481 // make sure the record isn't already there and insert if okay
2482 if (record_exists('grade_category', 'name', $category->name, 'courseid', $category->course)) {
2483 // category already exists
2485 elseif ($category->name != ''){
2486 if (!insert_record('grade_category', $category) ) {
2487 echo '<font color="red">'.get_string('addcategoryerror','grades').'</font>';
2492 function grade_category_select($id_selected) {
2493 /// prints out a select box containing categories.
2494 global $CFG;
2495 global $course;
2498 echo '<option value="blank">'.get_string('choosecategory','grades').'</option>';
2500 $categories = get_records('grade_category', 'courseid', $course->id, 'name');
2502 if (!isset($categories)) {
2503 error(get_string("nocategories"));
2505 else {
2506 foreach($categories as $category) {
2507 if ($category->name == UNCATEGORISED) {
2508 $category->name = get_string('uncategorised', 'grades');
2510 if ($category->id == $id_selected) {
2511 echo '<option value="'.$category->id.'" selected="selected">'.$category->name.'</option>';
2513 else {
2514 echo '<option value="'.$category->id.'">'.$category->name.'</option>';
2520 function grade_display_grade_preferences($course, $preferences) {
2521 global $CFG;
2522 global $USER;
2524 if ($preferences->use_advanced == 0) {
2525 $useadvanced = 1;
2526 $buttonlabel = get_string('useadvanced', 'grades');
2527 } else {
2528 $useadvanced = 0;
2529 $buttonlabel = get_String('hideadvanced', 'grades');
2532 $buttonoptions = array('action' => 'set_grade_preferences',
2533 'id' => $course->id,
2534 'sesskey' => sesskey(),
2535 'use_advanced' => $useadvanced);
2538 print_heading_with_help(get_string('setpreferences','grades'), 'preferences', 'grade');
2540 echo '<center>';
2541 print_single_button('index.php', $buttonoptions, $buttonlabel, 'post');
2542 echo '<br /></center>';
2544 echo '<form name="set_grade_preferences" method="post" action="./index.php">';
2545 echo '<input type="hidden" name="action" value="set_grade_preferences" />';
2546 echo '<input type="hidden" name="id" value="'.$course->id.'" />';
2547 echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
2548 echo '<table border="0" cellspacing="2" cellpadding="5" align="center" class="gradeprefs generalbox"';
2550 $optionsyesno = NULL;
2551 $optionsyesno[0] = get_string('no');
2552 $optionsyesno[1] = get_string('yes');
2555 if ($preferences->use_advanced) {
2556 $options = NULL;
2557 $options[0] = get_string('no');
2558 $options[1] = get_string('toonly', 'moodle', $course->teachers);
2559 $options[2] = get_string('toeveryone', 'moodle');
2561 // display grade weights
2562 echo '<tr><td class="c0">'.get_string('displayweighted','grades').':</td>';
2563 echo '<td class="c1">';
2564 choose_from_menu($options, 'display_weighted', $preferences->display_weighted, '');
2565 echo '</td></tr>';
2567 // display points
2568 echo '<tr><td class="c0">'.get_string('displaypoints','grades').':</td>';
2569 echo '<td class="c1">';
2570 choose_from_menu($options, 'display_points', $preferences->display_points, '');
2571 echo '</td></tr>';
2573 // display percent
2574 echo '<tr><td class="c0">'.get_string('displaypercent','grades').':</td>';
2575 echo '<td class="c1">';
2576 choose_from_menu($options, 'display_percent', $preferences->display_percent, '');
2577 echo '</td></tr>';
2579 // display letter grade
2580 echo '<tr><td class="c0">'.get_string('displaylettergrade','grades').':</td>';
2581 echo '<td class="c1">';
2582 choose_from_menu($options, 'display_letters', $preferences->display_letters, '');
2583 echo '</td></tr>';
2585 // letter grade uses weighted percent
2586 $options = NULL;
2587 $options[0] = get_string('usepercent','grades');
2588 $options[1] = get_string('useweighted','grades');
2590 echo '<tr><td class="c0">'.get_string('lettergrade','grades').':</td>';
2591 echo '<td class="c1">';
2592 choose_from_menu($options, 'use_weighted_for_letter', $preferences->use_weighted_for_letter, '');
2593 echo '</td></tr>';
2596 $headerlist[0] = get_string('none');
2597 for ($i=1; $i<=100; $i++) {
2598 $headerlist[$i] = $i;
2601 // reprint headers every n lines default n=0
2602 echo '<tr><td class="c0">'.get_string('reprintheaders','grades').':</td>';
2603 echo '<td class="c1">';
2604 choose_from_menu($headerlist, 'reprint_headers', $preferences->reprint_headers, '');
2605 echo '</td></tr>';
2607 // show hidden grade items to teacher
2608 echo '<tr><td class="c0">'.get_string('showhiddenitems','grades').'</td>';
2609 echo '<td class="c1">';
2610 choose_from_menu($optionsyesno, 'show_hidden', $preferences->show_hidden, '');
2611 echo '</td></tr>';
2613 echo '<tr><td colspan="3" align="center"><input type="submit" value="'.get_string('savepreferences','grades').'" /></td></tr></table></form>';
2618 function grade_display_letter_grades() {
2619 global $CFG;
2620 global $course;
2621 global $USER;
2623 $db_letters = get_records('grade_letter', 'courseid', $course->id, 'grade_high DESC');
2625 if ($db_letters) {
2626 $using_defaults = false;
2627 foreach ($db_letters as $letter) {
2628 $letters[$letter->id]->letter = $letter->letter;
2629 $letters[$letter->id]->grade_low = $letter->grade_low;
2630 $letters[$letter->id]->grade_high = $letter->grade_high;
2631 $letters[$letter->id]->courseid = $course->id;
2634 else {
2635 $using_defaults = true;
2636 // default A
2637 $letters[0]->letter='A';
2638 $letters[0]->grade_low=93.00;
2639 $letters[0]->grade_high=100.00;
2640 $letters[0]->courseid = $course->id;
2641 // default A-
2642 $letters[1]->letter='A-';
2643 $letters[1]->grade_low=90.00;
2644 $letters[1]->grade_high=92.99;
2645 $letters[1]->courseid = $course->id;
2646 // default B+
2647 $letters[2]->letter='B+';
2648 $letters[2]->grade_low=87.00;
2649 $letters[2]->grade_high=89.99;
2650 $letters[2]->courseid = $course->id;
2651 // default B
2652 $letters[3]->letter='B';
2653 $letters[3]->grade_low=83.00;
2654 $letters[3]->grade_high=86.99;
2655 $letters[3]->courseid = $course->id;
2656 // default B-
2657 $letters[4]->letter='B-';
2658 $letters[4]->grade_low=80.00;
2659 $letters[4]->grade_high=82.99;
2660 $letters[4]->courseid = $course->id;
2661 // default C+
2662 $letters[5]->letter='C+';
2663 $letters[5]->grade_low=77.00;
2664 $letters[5]->grade_high=79.99;
2665 $letters[5]->courseid = $course->id;
2666 // default C
2667 $letters[6]->letter='C';
2668 $letters[6]->grade_low=73.00;
2669 $letters[6]->grade_high=76.99;
2670 $letters[6]->courseid = $course->id;
2671 // default C-
2672 $letters[7]->letter='C-';
2673 $letters[7]->grade_low=70.00;
2674 $letters[7]->grade_high=72.99;
2675 $letters[7]->courseid = $course->id;
2676 // default D+
2677 $letters[8]->letter='D+';
2678 $letters[8]->grade_low=67.00;
2679 $letters[8]->grade_high=69.99;
2680 $letters[8]->courseid = $course->id;
2681 // default D
2682 $letters[9]->letter='D';
2683 $letters[9]->grade_low=60.00;
2684 $letters[9]->grade_high=66.99;
2685 $letters[9]->courseid = $course->id;
2686 // default F
2687 $letters[10]->letter='F';
2688 $letters[10]->grade_low=0.00;
2689 $letters[10]->grade_high=59.99;
2690 $letters[10]->courseid = $course->id;
2693 echo '<table border="0" cellspacing="2" cellpadding="5" align="center" class="generalbox"><tr><th colspan="3" class="header">'.get_string('setgradeletters','grades');
2694 helpbutton('letter', get_string('gradeletterhelp','grades'), 'grade');
2695 echo '</th></tr><tr><td align="center" class="generaltableheader">'.get_string('gradeletter','grades').'</td><td align="center" class="generaltableheader">'.get_string('lowgradeletter','grades').'</td><td align="center" class="generaltableheader">'.get_string('highgradeletter','grades').'</td></tr>';
2696 echo '<form name="grade_letter"><input type="hidden" name="id" value="'.$course->id.'" />';
2697 echo '<input type="hidden" name="action" value="set_letter_grades" />';
2698 echo '<input type="hidden" name="sesskey" value="'.$USER->sesskey.'" />';
2699 $i=0;
2700 foreach ($letters as $id=>$items) {
2701 if ($id !='' && !$using_defaults) {
2702 // send the record id so if the user deletes the values we can delete the row.
2703 echo '<input type="hidden" name="id'.$i.'" value="'.$id.'" />';
2705 echo '<tr><td align="center" class="generalboxcontent"><input size="8" type="text" name="letter'.$i.'" value="'.$items->letter.'" /></td>'."\n";
2706 echo '<td align="center" class="generalboxcontent"><input size="8" type="text" name="grade_low'.$i.'" value="'.$items->grade_low.'" /></td>'."\n";
2707 echo '<td align="center" class="generalboxcontent"><input size="8" type="text" name="grade_high'.$i.'" value="'.$items->grade_high.'" /></td></tr>'."\n";
2708 $i++;
2710 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>';
2711 echo '<tr><td colspan="3" align="center" class="generalboxcontent"><input type="submit" value="'.get_string('savechanges','grades').'" /></td></tr>';
2712 echo '<input type="hidden" name="totalitems" value="'.$i.'" />';
2713 echo '</form><tr><td colspan="3" align="center" class="generalboxcontent">'.get_string('gradeletternote','grades').'</table>';
2716 function grade_set_letter_grades() {
2717 global $CFG;
2718 global $course;
2719 global $USER;
2721 if (!empty($USER->id)) {
2722 if (!confirm_sesskey()) {
2723 error(get_string('confirmsesskeybad', 'error'));
2727 $totalitems= clean_param($_REQUEST['totalitems'], PARAM_CLEAN);
2729 for($i=0; $i<=$totalitems; $i++) {
2730 if (isset($_REQUEST["id$i"])) {
2731 // item submitted was already in database
2732 $letterid = $_REQUEST["id$i"];
2733 $updateletters[$letterid]->letter = clean_param($_REQUEST["letter$i"], PARAM_CLEAN);
2734 // grade_low && grade_high don't need cleaning as they are possibly floats (no appropriate clean method) so we check is_numeric
2735 $updateletters[$letterid]->grade_low = $_REQUEST["grade_low$i"];
2736 $updateletters[$letterid]->grade_high = $_REQUEST["grade_high$i"];
2737 $updateletters[$letterid]->id = $letterid;
2739 else {
2740 // its a new item
2741 $newletter->letter = clean_param($_REQUEST["letter$i"], PARAM_CLEAN);
2742 $newletter->grade_low = $_REQUEST["grade_low$i"];
2743 $newletter->grade_high = $_REQUEST["grade_high$i"];
2744 $newletter->courseid = $course->id;
2745 if (is_numeric($newletter->grade_high) && is_numeric($newletter->grade_low)) {
2746 insert_record('grade_letter', $newletter);
2748 else {
2749 if ($i < $totalitems) {
2750 if ($newletter->grade_high != '' or $newletter->grade_low != '') {
2751 echo '<center>'.get_string('lettergradenonnumber','grades').' '.$newletter->letter.' item number: '.$i.'<br /></center>';
2758 if (isset($updateletters)) {
2759 foreach($updateletters as $id=>$items) {
2760 // see if any of the values are blank... if so delete them
2761 if ($items->letter == '' || $items->grade_low == '' || $items->grade_high == '') {
2762 delete_records('grade_letter', 'id', $id);
2764 else {
2765 if (is_numeric($items->grade_high) && is_numeric($items->grade_low)) {
2766 update_record('grade_letter', $items);
2768 else {
2769 echo '<center><font color="red">'.get_string('errorgradevaluenonnumeric','grades').$letter.'</font></center>';
2776 function grade_download_form($type='both') {
2777 global $course,$USER, $action, $cview;
2778 if ($type != 'both' || $type != 'excel' || $type != 'text') {
2779 $type = 'both';
2782 if (isteacher($course->id)) {
2783 echo '<table align="center"><tr>';
2784 $options['id'] = $course->id;
2785 $options['sesskey'] = $USER->sesskey;
2787 if ($type = 'both' || $type == 'excel') {
2788 $options['action'] = 'excel';
2789 echo '<td align="center">';
2790 print_single_button("index.php", $options, get_string("downloadexcel"));
2791 echo '</td>';
2793 if ($type = 'both' || $type == 'text') {
2794 $options['action'] = 'text';
2795 echo '<td align="center">';
2796 print_single_button("index.php", $options, get_string("downloadtext"));
2797 echo '</td>';
2799 echo '<td>';
2801 $url = 'index.php?id='.$course->id;
2802 if (!empty($action)) {
2803 $url .= '&amp;action='.$action;
2804 if ($action == 'vcats') {
2805 $url .= '&amp;cview='.$cview;
2808 setup_and_print_groups($course, $course->groupmode, $url);
2809 echo '</td>';
2811 echo '</tr></table>';