MDL-10482 incorrect texarea height
[moodle.git] / grade / lib.php
CommitLineData
cbff94ba 1<?php // $Id$
2
1cd12527 3if (!defined('MOODLE_INTERNAL')) {
4 die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page
5}
6
cbff94ba 7require_once($CFG->dirroot.'/course/lib.php');
8
1d9498e4 9define('UNCATEGORISED', 'uncategorised');
281ffa4a 10
1cd12527 11global $GRADEPREFS, $GRADEPREFSDEFAULTS; // This variables are going to be global... :-/
12
281ffa4a 13$GRADEPREFS = array('use_advanced', // Only add new preferences to the end of this array!
14 'use_weighted_for_letter', // as the order counts and will affect backward compatibility
15 'display_weighted',
16 'display_points',
17 'display_percent',
b623ea5e 18 'display_letters',
281ffa4a 19 'reprint_headers',
20 'show_hidden',
21 );
22
23
24$GRADEPREFSDEFAULTS = array('use_advanced' => 0,
25 'use_weighted_for_letter' => 0,
26 'display_weighted' => 0,
b623ea5e 27 'display_points' => 2,
281ffa4a 28 'display_percent' => 1,
b623ea5e 29 'display_letters' => 0,
281ffa4a 30 'reprint_headers' => 0,
31 'show_hidden' => 1
32 );
cbff94ba 33
34
cbff94ba 35//******************************************************************
36// SQL FUNCTIONS
37//******************************************************************
38
39function grade_get_category_weight($course, $category) {
40 global $CFG;
03c40bb7 41 $sql = "SELECT id, weight, drop_x_lowest, bonus_points, hidden, c.id AS cat_id
cbff94ba 42 FROM {$CFG->prefix}grade_category c
43 WHERE c.courseid=$course
44 AND c.name='$category'";
45 $temp = get_record_sql($sql);
46 return $temp;
47}
48
49function grade_get_grade_items($course) {
50 global $CFG;
51 $sql = "SELECT i.id, c.name as cname, i.modid, mm.name as modname, i.cminstance, c.hidden, cm.visible, i.sort_order
52 FROM {$CFG->prefix}grade_item i,
53 {$CFG->prefix}grade_category c,
54 {$CFG->prefix}course_modules cm,
55 {$CFG->prefix}modules mm
56 WHERE c.id=i.category
57 AND i.courseid=c.courseid
58 AND c.courseid=$course
59 AND cm.course=c.courseid
60 AND cm.module=mm.id
61 AND i.modid=mm.id
62 AND cm.instance=i.cminstance";
63 $temp = get_records_sql($sql);
64 return $temp;
65}
66
67function grade_get_module_link($course, $cminstance, $modid) {
68 global $CFG;
4e83cfdf 69 $sql = "SELECT cm.id, 1 FROM {$CFG->prefix}course_modules cm, {$CFG->prefix}modules mm, {$CFG->prefix}grade_item i
cbff94ba 70 WHERE i.modid='".$modid."'
71 AND i.modid=mm.id
72 AND cm.instance = i.cminstance
73 AND i.cminstance=".$cminstance."
74 AND i.courseid=cm.course AND cm.module=mm.id AND i.courseid=$course";
75 $temp = get_record_sql($sql);
76 return $temp;
77}
78
79function grade_get_grade_letter($course, $grade) {
80 global $CFG;
81 $sql = "SELECT id, letter FROM {$CFG->prefix}grade_letter WHERE courseid=$course AND grade_high >= $grade AND grade_low <= $grade";
82 $temp = get_record_sql($sql);
83 return $temp;
84}
85
86function grade_get_exceptions($course) {
87 global $CFG;
88 $sql = "SELECT e.id, e.userid, gi.cminstance, gi.modid, c.name as catname, mm.name as modname
89 FROM {$CFG->prefix}grade_exceptions e,
90 {$CFG->prefix}grade_item gi,
91 {$CFG->prefix}grade_category c,
92 {$CFG->prefix}course_modules cm,
93 {$CFG->prefix}modules mm
94 WHERE e.courseid=$course
95 AND gi.id = e.grade_itemid
96 AND c.id = gi.category
97 AND cm.course=c.courseid
98 AND cm.module=mm.id
99 AND gi.modid=mm.id";
100
101 $temp = get_records_sql($sql);
102 return $temp;
103}
104
04678d8e 105function grade_get_exceptions_user($course, $userid) {
106 global $CFG;
107 $sql = "SELECT e.id, e.userid, gi.cminstance, gi.modid, c.name as catname, mm.name as modname
108 FROM {$CFG->prefix}grade_exceptions e,
109 {$CFG->prefix}grade_item gi,
110 {$CFG->prefix}grade_category c,
111 {$CFG->prefix}course_modules cm,
112 {$CFG->prefix}modules mm
113 WHERE e.courseid=$course
61240489 114 AND e.userid=$userid
04678d8e 115 AND gi.id = e.grade_itemid
116 AND c.id = gi.category
117 AND cm.course=c.courseid
118 AND cm.module=mm.id
119 AND gi.modid=mm.id";
120
121 $temp = get_records_sql($sql);
122 return $temp;
123}
cbff94ba 124function grade_letters_set($course) {
125 global $CFG;
126 $sql = "SELECT * FROM {$CFG->prefix}grade_letter WHERE courseid=$course";
127 $letters_set = get_records_sql($sql);
128 if ($letters_set) {
129 return true;
130 }
131 else {
132 return false;
133 }
134}
135
136function grade_get_users_by_group($course, $group) {
137 global $CFG;
138 $sql = "SELECT userid FROM {$CFG->prefix}groups_members WHERE courseid=$course AND groupid = $group";
139 $members = get_records_sql($sql);
140 if ($members) {
141 foreach($members as $member) {
7ceed560 142 // FIX ME: there is no $userid defined!!! - from where is this function used anyway??
cbff94ba 143 $group->$userid = true;
144 }
145 return $group;
146 }
147 else {
148 return NULL;
149 }
150}
151
152//******************************************************************
153// END SQL FUNCTIONS
154//******************************************************************
155
156function grade_get_formatted_grades() {
157 global $CFG;
60f9e36e 158 global $COURSE;
cbff94ba 159 global $preferences;
60f9e36e 160 $course = $COURSE;
91b678f3 161 $i = 2; // index to differentiate activities with the same name MDL-6876
cbff94ba 162 $grades = grade_get_grades();
163 if (isset($grades)) {
164 // iterate through all students
165 foreach($grades as $cur_category=>$grade_category) {
166 // $cur_category holds the value of the current category name
167 // $grade_category holds an array of all the mod types that are in this category
168 if (isset($grade_category)) {
169 foreach($grade_category as $cur_mod=>$mod_category) {
170 // $cur_mod is the id of the current moodle module type
171 // $mod_category holds the grades for $cur_mod (current mod type)
172 $module_info = get_record('modules', 'id', $cur_mod);
173 $cur_modname = $module_info->name;
174 if (isset($mod_category)) {
175 foreach($mod_category as $cur_cminstance=>$students_grade) {
176 // $cur_cminstance is the course module instance for the cur_mod
177 $instance = get_record($cur_modname, 'id',$cur_cminstance, 'course',$course->id);
178 // it's necessary to check if the name is blank because some mods don't clean up the grades when the instance is deleted
179 // this is a bug. as it is plausible that some item could get created and have old data from a previous mod laying around
180 if ($instance->name != '') {
181 // duplicate grade item name, the user should know better than to name to things by the same name, but to make sure grades don't disappear lets modify the name slightly
182 if (isset($all_categories["$cur_category"]["$instance->name"])) {
91b678f3 183 $instance->name= $instance->name.' #'.$i++;
cbff94ba 184 }
185
186 if (isset($students_grade->grades) && $students_grade->grades != '') {
187 foreach($students_grade->grades as $student=>$grade) {
188 // add an entry for any student that has a grade
189 $grades_by_student["$student"]["$cur_category"]["$instance->name"]['grade'] = $grade;
190 $grades_by_student["$student"]["$cur_category"]["$instance->name"]['sort_order'] = $students_grade->sort_order;
191
192 if (!isset($grades_by_student["$student"]["$cur_category"]['stats'])) {
193 $grades_by_student["$student"]["$cur_category"]['stats'] = array();
194 }
195
196 if (!isset($grades_by_student["$student"]["$cur_category"]['stats']['points'])) {
197 $grades_by_student["$student"]["$cur_category"]['stats']['points'] = $grade;
198 }
199 else {
200 $grades_by_student["$student"]["$cur_category"]['stats']['points'] = $grades_by_student["$student"]["$cur_category"]['stats']['points'] + $grade;
201 }
202
203 // This next block just creates a comma seperated list of all grades for the category
204 if (isset($grades_by_student["$student"]["$cur_category"]['stats']['allgrades'])) {
205 $grades_by_student["$student"]["$cur_category"]['stats']['allgrades'] .= ','.$grade;
206 }
207 else {
208 $grades_by_student["$student"]["$cur_category"]['stats']['allgrades'] = $grade;
209 }
210 }
211 }
04678d8e 212
61240489 213
04678d8e 214
cbff94ba 215 // set up a list of all categories and assignments (adjusting things for extra credit where necessary)
216 $all_categories["$cur_category"]["$instance->name"]['hidden'] = $students_grade->hidden;
217 $all_categories["$cur_category"]["$instance->name"]['sort_order'] = $students_grade->sort_order;
218
219 $all_categories["$cur_category"]["$instance->name"]['extra_credit'] = $students_grade->extra_credit;
220
221 if ($all_categories["$cur_category"]["$instance->name"]['extra_credit'] != 1) {
222 $all_categories["$cur_category"]["$instance->name"]['maxgrade'] = $students_grade->maxgrade;
223 }
224 else {
225 $all_categories["$cur_category"]["$instance->name"]['maxgrade'] = 0;
226 }
227 $all_categories["$cur_category"]["$instance->name"]['scale_grade'] = $students_grade->scale_grade;
228 if ($students_grade->scale_grade != 0) {
229 $all_categories["$cur_category"]["$instance->name"]['scaled_max'] = round($all_categories["$cur_category"]["$instance->name"]['maxgrade']/$students_grade->scale_grade);
230 }
231 else {
232 // avoids divide by zero... scale_grade shouldn't be set to 0 anyway
233 $all_categories["$cur_category"]["$instance->name"]['scaled_max'] = $all_categories["$cur_category"]["$instance->name"]['maxgrade'];
234 $all_categories["$cur_category"]["$instance->name"]['scale_grade'] = 1.0;
235 }
236 if (! isset($all_categories["$cur_category"]['stats']) ) {
237 $all_categories["$cur_category"]['stats'] = array();
238 }
239 $all_categories["$cur_category"]["$instance->name"]['grade_against'] = $all_categories["$cur_category"]["$instance->name"]['scaled_max'];
240 if (!isset($all_categories["$cur_category"]['stats']['weight'])) {
241 $weight = grade_get_category_weight($course->id, $cur_category);
242 $all_categories["$cur_category"]['stats']['weight'] = $weight->weight;
243 }
244
245 $all_categories["$cur_category"]["$instance->name"]['cminstance'] = $cur_cminstance;
246 $all_categories["$cur_category"]["$instance->name"]['modid'] = $cur_mod;
247 $modname = get_record('modules','id',$cur_mod);
248 $all_categories["$cur_category"]["$instance->name"]['modname'] = $modname->name;
249
250 // get bonus points and drop the x lowest
251 $drop = get_record('grade_category', 'courseid', $course->id, 'name', $cur_category);
252 $all_categories["$cur_category"]['stats']['drop'] = $drop->drop_x_lowest;
253 $all_categories["$cur_category"]['stats']['bonus_points'] = $drop->bonus_points;
254 }
255 }
256 }
257 }
258 }
259 }
5a412dbf 260 if (!$students = grade_get_course_students($course->id)) {
261 return false;
262 }
263
264
cbff94ba 265 if (isset($students) && $students) {
fc9b712e 266 foreach ($students as $userid => $student) {
cbff94ba 267 $grades_by_student["$userid"]['student_data']['firstname'] = $student->firstname;
268 $grades_by_student["$userid"]['student_data']['lastname'] = $student->lastname;
269 $grades_by_student["$userid"]['student_data']['email'] = $student->email;
270 if (isset($student->location)) {
271 $grades_by_student["$userid"]['student_data']['location'] = $student->location;
272 }
273 $grades_by_student["$userid"]['student_data']['department'] = $student->department;
274 $grades_by_student["$userid"]['student_data']['idnumber'] = $student->idnumber;
275 }
276 }
277
278 // unset any item that has a "" for a name at this point this inludes instructors who have grades or any student formerly enrolled.
279 if (isset($grades_by_student)) {
280 foreach ($grades_by_student as $student => $assignments) {
281 if (!isset($grades_by_student["$student"]['student_data']['firstname']) && !isset($grades_by_student["$student"]['student_data']['lastname'])) {
282 unset($grades_by_student["$student"]);
283 }
284 }
285 }
286
287
288 // set the totalpoints for each category taking into account drop_x_lowest
289 // also set the number of grade items for the category to make calculating grades for students who have not taken anything easier
290 foreach($all_categories as $category => $assignments) {
291 $dropcount = 0;
292 $all_categories["$category"]['stats']['totalpoints'] = 0;
293 $all_categories["$category"]['stats']['grade_items'] = 0;
294 if (isset($assignments)) {
295 foreach($assignments as $assignment=>$grade) {
296 if ($assignment != 'stats') {
297 if ($dropcount < $all_categories["$category"]['stats']['drop']) {
298 // skip a grade in the total
299 $dropcount++;
300 }
301 else {
302 // make sure the current assignment is not extra credit and then add it to the totalpoints
303 if ($all_categories["$category"][$assignment]['extra_credit'] != 1) {
304 $all_categories["$category"]['stats']['totalpoints'] = $all_categories["$category"]['stats']['totalpoints'] + $assignments["$assignment"]['grade_against'];
305 $all_categories["$category"]['stats']['grade_items'] = $all_categories["$category"]['stats']['grade_items'] + 1;
306 }
307 }
308 }
309 }
310 }
311 }
61240489 312
cbff94ba 313
cbff94ba 314 // if the user has selected a group to view by get the group members
68d0c80c 315 if ($currentgroup = get_current_group($course->id)) {
316 $groupmembers = get_group_users($currentgroup);
cbff94ba 317 }
318
319 // this next block catches any students who do not have a grade for any item in a particular category
320 foreach($all_categories as $category => $main_category) {
321 // make sure each student has an entry for each category
322 if (isset($grades_by_student)) {
323 foreach($grades_by_student as $student=>$categories) {
324 if ( (isset($groupmembers) && isset($groupmembers[$student])) || !isset($groupmembers)) {
61240489 325
cbff94ba 326 $grades_by_student["$student"]["$category"]['stats']['totalpoints'] = $main_category['stats']['totalpoints'];
327 $grades_by_student["$student"]["$category"]['stats']['weight'] = $main_category['stats']['weight'];
328 $grades_by_student["$student"]["$category"]['stats']['grade_items'] = $main_category['stats']['grade_items'];
04678d8e 329
330 foreach($main_category as $assignment => $items) {
331 if ($assignment != 'stats') {
332 if(!isset($grades_by_student["$student"]["$category"]["$assignment"]['grade'])) {
9ef80fa4 333 if (isset($grades_by_student["$student"]["$category"]['stats']['allgrades'])) {
334 $grades_by_student["$student"]["$category"]['stats']['allgrades'] .= ',0';
335 } else {
336 $grades_by_student["$student"]["$category"]['stats']['allgrades'] = '0';
337 }
04678d8e 338 }
339 }
340 }
61240489 341
cbff94ba 342 if (!isset($grades_by_student["$student"]["$category"]['stats']['points'])) {
04678d8e 343 $grades_by_student["$student"]["$category"]['stats']['points'] = '-';
61240489 344
cbff94ba 345 }
61240489 346
cbff94ba 347 else {
348 // points are set... see if the current category is using drop the x lowest and do so
04678d8e 349 // also drop exceptions first, so then this grades(s) won't be recoqnized as the x lowest
61240489 350 // Get exception scores and assign them in the array
cbff94ba 351 if ($main_category['stats']['drop'] != 0) {
04678d8e 352 $exceptions = grade_get_exceptions_user($course->id, $student);
353 if (isset($exceptions) && $exceptions) {
354 foreach($exceptions as $exception) {
355 if (isset($grades_by_student["$exception->userid"])) {
356 if ($grades_by_student["$exception->userid"]["$exception->catname"]) {
357 $assgn = get_record($exception->modname, 'id', $exception->cminstance, 'course', $course->id);
358 $grade = $grades_by_student["$exception->userid"]["$exception->catname"]["$assgn->name"]['grade'];
61240489 359 if (isset($grade)) {
360 if (!isset($grades_by_student["$exception->userid"]["$exception->catname"]['stats']['exceptions'])) {
04678d8e 361 $grades_by_student["$exception->userid"]["$exception->catname"]['stats']['exceptions'] = $grade;
362 }
363 elseif (isset($grades_by_student["$exception->userid"]["$exception->catname"]['stats']['exceptions'])) {
364 $grades_by_student["$exception->userid"]["$exception->catname"]['stats']['exceptions'] .= ','. $grade;
61240489 365 }
366 }
04678d8e 367 }
368 }
369 }
61240489 370 }
04678d8e 371 if (isset($grades_by_student["$student"]["$category"]['stats']['exceptions'])) {
372 $grades_by_student["$student"]["$category"]['stats']['allgrades'] = grade_drop_exceptions($grades_by_student["$student"]["$category"]['stats']['allgrades'], $grades_by_student["$student"]["$category"]['stats']['exceptions']);
373 }
61240489 374
cbff94ba 375 $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']);
376 if ($grades_by_student["$student"]["$category"]['stats']['points'] != '-') {
377 $cat_points = 0;
378 $count_grades = explode(',',$grades_by_student["$student"]["$category"]['stats']['allgrades']);
379 foreach($count_grades as $grade) {
380 $cat_points = $cat_points + $grade;
381 }
382 $grades_by_student["$student"]["$category"]['stats']['points'] = $cat_points;
383 }
384 }
385 }
04678d8e 386
cbff94ba 387 // add any bonus points for the category
388 if ($all_categories["$category"]['stats']['bonus_points'] != 0) {
389 $grades_by_student["$student"]["$category"]['stats']['points'] = $grades_by_student["$student"]["$category"]['stats']['points'] + $all_categories["$category"]['stats']['bonus_points'];
390 }
391
392 foreach($main_category as $assignment => $items) {
393 if ($assignment != 'stats') {
394 if(!isset($grades_by_student["$student"]["$category"]["$assignment"]['maxgrade'])) {
395 $grades_by_student["$student"]["$category"]["$assignment"]['maxgrade'] = $all_categories["$category"]["$assignment"]['grade_against'];
396 }
397 if(!isset($grades_by_student["$student"]["$category"]["$assignment"]['grade'])) {
398 $grades_by_student["$student"]["$category"]["$assignment"]['grade'] = '-';
399 $grades_by_student["$student"]["$category"]["$assignment"]['sort_order'] = $all_categories["$category"]["$assignment"]['sort_order'];
400 }
401 }
402 }
403 } // end groupmember if
404 else {
405 // unset grade since they are not in the selected group.
406 unset($grades_by_student["$student"]);
407 }
408 }
409 }
410 }
cbff94ba 411 // set the total coursepoints
412 $all_categories['stats']['weight'] = 0;
413 $all_categories['stats']['totalpoints'] = 0;
414 foreach($all_categories as $category => $info) {
415 if ($category != 'stats') {
416 $all_categories['stats']['weight'] = $all_categories['stats']['weight'] + $all_categories["$category"]['stats']['weight'];
417 $all_categories['stats']['totalpoints'] = $all_categories['stats']['totalpoints'] + $all_categories["$category"]['stats']['totalpoints'];
418 }
419 }
420
421 // set each individuals total points by category so we can then exclude some grades if set to use exceptions
422 if (isset($grades_by_student)) {
423 foreach($grades_by_student as $student => $categories) {
424 foreach($all_categories as $category => $assignments) {
425 if ($category != 'stats') {
426 $grades_by_student["$student"]["$category"]['stats']['totalpoints'] = $all_categories["$category"]['stats']['totalpoints'];
427 }
428 }
429 $grades_by_student["$student"]['student_data']['totalpoints'] = $all_categories['stats']['totalpoints'];
430 }
431 }
04678d8e 432
cbff94ba 433 // take into account any excluded grade_items
434 $strexcluded = get_string('excluded', 'grades');
435 $exceptions = grade_get_exceptions($course->id);
436 if (isset($exceptions) && $exceptions) {
437 foreach($exceptions as $exception) {
438 if (isset($grades_by_student["$exception->userid"])) {
439 if ($grades_by_student["$exception->userid"]["$exception->catname"]) {
440 $assgn = get_record($exception->modname, 'id', $exception->cminstance, 'course', $course->id);
441 $grades_by_student["$exception->userid"]['student_data']['totalpoints'] = $grades_by_student["$exception->userid"]['student_data']['totalpoints'] - $all_categories["$exception->catname"]["$assgn->name"]['maxgrade'];
61240489 442 //total point should not be smaller than grade against
443 if ($grades_by_student["$exception->userid"]["$exception->catname"]['stats']['totalpoints'] - $all_categories["$exception->catname"]["$assgn->name"]['grade_against'] != 0 ) {
04678d8e 444 $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'];
61240489 445 }
cbff94ba 446 $grades_by_student["$exception->userid"]["$exception->catname"]['stats']['grade_items'] = $grades_by_student["$exception->userid"]["$exception->catname"]['stats']['grade_items'] - 1;
447 if ($grades_by_student["$exception->userid"]["$exception->catname"]['stats']['grade_items'] < 0) {
448 $grades_by_student["$exception->userid"]["$exception->catname"]['stats']['grade_items'] = 0;
61240489 449 }
04678d8e 450 if ($all_categories["$exception->catname"]['stats']['drop'] == 0) {
451 $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'];
cbff94ba 452 }
cbff94ba 453 $grades_by_student["$exception->userid"]["$exception->catname"]["$assgn->name"]['maxgrade'] = $strexcluded;
454 $grades_by_student["$exception->userid"]["$exception->catname"]["$assgn->name"]['grade'] = $strexcluded;
455 // see if they are excluded entirely from a category
456 if ($grades_by_student["$exception->userid"]["$exception->catname"]['stats']['totalpoints'] == 0) {
457 $grades_by_student["$exception->userid"]["$exception->catname"]['stats']['totalpoints'] = $strexcluded;
458 $grades_by_student["$exception->userid"]["$exception->catname"]['stats']['percent'] = $strexcluded;
459 $grades_by_student["$exception->userid"]["$exception->catname"]['stats']['points'] = $strexcluded;
460 $grades_by_student["$exception->userid"]["$exception->catname"]['stats']['weight'] = $strexcluded;
461 $grades_by_student["$exception->userid"]["$exception->catname"]['stats']['weighted'] = $strexcluded;
462 }
463 }
464 }
465 else {
466 // 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
467 }
468 }
469 }
04678d8e 470
cbff94ba 471 if (isset($grades_by_student)) {
472 foreach($grades_by_student as $student => $categories) {
473 $grades_by_student["$student"]['student_data']['points'] = '-';
474 $grades_by_student["$student"]['student_data']['totalpoints'] = 0;
475 $grades_by_student["$student"]['student_data']['weight'] = 0;
476 $grades_by_student["$student"]['student_data']['weighted'] = 0;
477 foreach($categories as $category => $assignments) {
478 if ($category != 'student_data') {
479 // set the student's total points earned
480 if ($grades_by_student["$student"]["$category"]['stats']['points'] != $strexcluded) {
481 if ($grades_by_student["$student"]["$category"]['stats']['points'] != '-') {
482 $grades_by_student["$student"]['student_data']['points'] = $grades_by_student["$student"]['student_data']['points'] + $grades_by_student["$student"]["$category"]['stats']['points'];
483 }
04678d8e 484 $grades_by_student["$student"]['student_data']['totalpoints'] = $grades_by_student["$student"]['student_data']['totalpoints'] + $grades_by_student["$student"]["$category"]['stats']['totalpoints'];
cbff94ba 485 }
486
487 // set percents and weights for each assignment
488 foreach($assignments as $assignment => $info) {
489 if ($assignment != 'stats') {
490 if ($grades_by_student["$student"]["$category"]["$assignment"]['grade'] != $strexcluded) {
491 if ($grades_by_student["$student"]["$category"]["$assignment"]['maxgrade'] != 0) {
492 $grades_by_student["$student"]["$category"]["$assignment"]['percent'] = round($grades_by_student["$student"]["$category"]["$assignment"]['grade']/$grades_by_student["$student"]["$category"]["$assignment"]['maxgrade']*100,2);
493 }
494 else {
495 $grades_by_student["$student"]["$category"]["$assignment"]['percent'] = 0;
496 }
497 if ($grades_by_student["$student"]["$category"]['stats']['totalpoints'] != 0) {
498 $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);
499 }
500 else {
501 $grades_by_student["$student"]["$category"]["$assignment"]['weight'] = 0.00;
502 }
503 if ($grades_by_student["$student"]["$category"]["$assignment"]['weight'] != 0) {
504 $grades_by_student["$student"]["$category"]["$assignment"]['weighted'] = round($grades_by_student["$student"]["$category"]["$assignment"]['percent']*$grades_by_student["$student"]["$category"]["$assignment"]['weight']/100,2);
505 }
506 else {
507 // should only be here if this is extra credit
508 $grades_by_student["$student"]["$category"]["$assignment"]['weighted'] = 0.00;
509 }
510 }
511 else {
512 $grades_by_student["$student"]["$category"]["$assignment"]['percent'] = $strexcluded;
513 $grades_by_student["$student"]["$category"]["$assignment"]['weight'] = $strexcluded;
514 $grades_by_student["$student"]["$category"]["$assignment"]['weighted'] = $strexcluded;
515 }
516 }
517 }
518 // set the percent and weight per category
519 if ($grades_by_student["$student"]["$category"]['stats']['totalpoints'] != 0 ) {
520 $grades_by_student["$student"]["$category"]['stats']['percent'] = round($grades_by_student["$student"]["$category"]['stats']['points']/$grades_by_student["$student"]["$category"]['stats']['totalpoints']*100,2);
521 $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);
522 }
523 else {
524 if ($grades_by_student["$student"]["$category"]['stats']['totalpoints'] != $strexcluded) {
525 $grades_by_student["$student"]["$category"]['stats']['percent'] = 0.00;
526 $grades_by_student["$student"]["$category"]['stats']['weighted'] = 0.00;
527 }
528 }
61240489 529
cbff94ba 530 // set students overall weight (this is what percent they will be graded against)
531 if ($grades_by_student["$student"]["$category"]['stats']['weight'] != $strexcluded) {
532 $grades_by_student["$student"]['student_data']['weight'] = $grades_by_student["$student"]['student_data']['weight'] + $grades_by_student["$student"]["$category"]['stats']['weight'];
533 }
534
535 // 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
536 // be excluded from a whole category.
537 if ($all_categories["$category"]['stats']['totalpoints'] != 0) {
538 $grades_by_student["$student"]['student_data']['weighted'] = $grades_by_student["$student"]['student_data']['weighted'] + $grades_by_student["$student"]["$category"]['stats']['weighted'];
539 }
540 }
541
542
543 }
04678d8e 544
cbff94ba 545 // set the percent and weight overall
546 if ($grades_by_student["$student"]['student_data']['totalpoints'] != 0 && $grades_by_student["$student"]['student_data']['totalpoints'] != $strexcluded) {
547 $grades_by_student["$student"]['student_data']['percent'] = round($grades_by_student["$student"]['student_data']['points']/$grades_by_student["$student"]['student_data']['totalpoints']*100,2);
548 if ($grades_by_student["$student"]['student_data']['weight'] != 0) {
549 $grades_by_student["$student"]['student_data']['weighted'] = round($grades_by_student["$student"]['student_data']['weighted']/$grades_by_student["$student"]['student_data']['weight']*100,2);
550 }
551 else {
552 $grades_by_student["$student"]['student_data']['weighted'] = 0.00;
553 }
554 }
555 else if ($grades_by_student["$student"]['student_data']['totalpoints'] == 0) {
556 $grades_by_student["$student"]['student_data']['percent'] = 0.00;
557 }
558
559 }
560 }
561
562 if (isset($grades_by_student)) {
563 $sort = optional_param('sort','default');
564
565 switch ($sort) {
566 case 'highgrade_category':
567 uasort($grades_by_student, 'grade_sort_by_highgrade_category');
568 break;
569 case 'highgrade_category_asc':
570 uasort($grades_by_student, 'grade_sort_by_highgrade_category_asc');
571 break;
572 case 'highgrade':
573 {
574 if ($preferences->use_weighted_for_letter == 1) {
575 uasort($grades_by_student, 'grade_sort_by_weighted');
576 }
577 else {
578 uasort($grades_by_student, 'grade_sort_by_percent');
579 }
580 break;
581 }
582 case 'points':
583 uasort($grades_by_student, 'grade_sort_by_points');
584 break;
585 case 'points_asc':
586 uasort($grades_by_student, 'grade_sort_by_points_asc');
587 break;
588 case 'weighted':
589 uasort($grades_by_student, 'grade_sort_by_weighted');
590 break;
591 case 'weighted_asc':
592 uasort($grades_by_student, 'grade_sort_by_weighted_asc');
593 break;
594 case 'percent':
595 uasort($grades_by_student, 'grade_sort_by_percent');
596 break;
597 case 'percent_asc':
598 uasort($grades_by_student, 'grade_sort_by_percent_asc');
599 break;
600 case 'highgrade_asc':
601 {
602 if ($preferences->use_weighted_for_letter == 1) {
603 uasort($grades_by_student, 'grade_sort_by_weighted_asc');
604 }
605 else {
606 uasort($grades_by_student, 'grade_sort_by_percent_asc');
607 }
608 break;
609 }
610 case 'firstname':
611 uasort($grades_by_student, 'grade_sort_by_firstname');
612 break;
613 default:
614 uasort($grades_by_student, 'grade_sort_by_lastname');
615 }
616 }
617 else {
618 $grades_by_student = 0;
619 }
cbff94ba 620 $retval = array($grades_by_student, $all_categories);
621 }
622 else {
623 $retval = array(0,0);
281ffa4a 624 // echo "<center><font color=red>Could not find any graded items for this course.</font></center>";
cbff94ba 625 }
626 return $retval;
627}
628
04678d8e 629function grade_drop_exceptions($grades, $grades_exceptions) {
630 $grade_array = explode(',',$grades);
631 $grade_exception_array = explode(',',$grades_exceptions);
632 $ret_grades = Array();
633 foreach ($grade_array as $key => $val) {
634 $posb = array_search($val,$grade_exception_array);
635 if (is_integer($posb)) {
636 unset($grade_exception_array[$posb]);
637 } else {
638
639 $ret_grades[] = $val;
640 }
641 }
642 $grades = implode(',', $ret_grades);
643 return $grades;
644}
645
cbff94ba 646function grade_drop_lowest($grades, $drop, $total) {
647 // drops the lowest $drop numbers from the comma seperated $grades making sure that if $grades has
648 // fewer items than $total that we don't drop too many
649 $grade_array = explode(',',$grades);
04678d8e 650 if (count($grade_array) == 1) {
61240489 651 $grades = implode('', $grade_array);
04678d8e 652 }
653 else if ($drop > 0 AND (count($grade_array) > $drop)) {
cbff94ba 654 rsort($grade_array);
655
04678d8e 656 for($i=0; $i < (count($grade_array) - $drop); $i++) {
cbff94ba 657 $ret_grades["$i"] = $grade_array["$i"];
658 }
04678d8e 659 if (isset($ret_grades)) {
cbff94ba 660 $grades = implode(',',$ret_grades);
661 }
04678d8e 662 }
663 else {
664 $grades = 0;
cbff94ba 665 }
666 return $grades;
667}
668
dd91f415 669function grade_get_grades() {
cbff94ba 670 global $CFG;
671 global $course;
672 $mods = grade_get_grade_items($course->id);
281ffa4a 673 $preferences = grade_get_preferences($course->id);
cbff94ba 674
675 if ($mods) {
676 foreach ($mods as $mod) {
677 // hidden is a gradebook setting for an assignment and visible is a course_module setting
1c45e42e 678 if (($mod->hidden != 1 && $mod->visible==1) or (has_capability('moodle/course:viewhiddenactivities', get_context_instance(CONTEXT_MODULE, $mod->id)) && $preferences->show_hidden==1)) {
cbff94ba 679 $libfile = "$CFG->dirroot/mod/$mod->modname/lib.php";
680 if (file_exists($libfile)) {
681 require_once($libfile);
682 $gradefunction = $mod->modname."_grades";
683 if ($grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"] = $gradefunction($mod->cminstance)) {
684 // added grades for particular mod
685 // now get the grade_item modifiers ie. scale_grade and extra credit
686 $scale_grade = get_record('grade_item', 'courseid', $course->id, 'cminstance', $mod->cminstance, 'modid', $mod->modid);
687
688 if (isset($scale_grade)) {
689 $grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"]->scale_grade = $scale_grade->scale_grade;
690 $grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"]->extra_credit = $scale_grade->extra_credit;
691 }
692 else {
693 $grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"]->scale_grade = 1.00;
694 $grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"]->extra_credit = 0;
695 }
696
697 if ($mod->hidden != 1 && $mod->visible==1) {
698 $grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"]->hidden = 0;
699 }
700 else {
701 $grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"]->hidden = 1;
702 }
703
704 $grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"]->sort_order = $scale_grade->sort_order;
705
706 // 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
707 // 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.
708 // this happens when grading is set to a non-numeric for a forum ie. uses "seperate and connected ways of knowing"
709 if ($grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"]->maxgrade == '')
710 {
711 $grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"]->maxgrade = 100;
712 //unset($grades["$mod->cname"]["$mod->modid"]["$mod->cminstance"]);
713 }
714 }
715 else {
716 // delete this item from the grade_item table since it was deleted through the mod interface
717 delete_records('grade_item', 'modid', $mods->modid, 'courseid', $course->id);
0edcd419 718 delete_records('grade_exceptions', 'grade_itemid', $mod->id, 'courseid', $course->id);
cbff94ba 719 }
720 }
721 else {
281ffa4a 722 //echo "<center><font color=red>Could not find lib file for $mod->modid</font></center>";
cbff94ba 723 }
724 }
725 }
726 }
727 else {
728 // Do something here for no grades
281ffa4a 729 //echo "<center><font color=red>No grades returned. It appears that there are no items with grades for this course.</font></center>";
cbff94ba 730 }
731 if (isset($grades)) {
732 return $grades;
733 }
734 else {
735 return NULL;
736 }
737}
738
739function grade_set_uncategorized() {
740 // this function checks to see if any mods have not been assigned a category and sets them to uncategorized.
741 global $CFG;
742 global $course;
281ffa4a 743 $uncat = UNCATEGORISED;
cbff94ba 744
745 $uncat_id = get_record('grade_category', 'courseid', $course->id, 'name', $uncat);
746
747 if (!$uncat_id) {
748 // insert the uncategorized category
749 $temp->name=$uncat;
750 $temp->courseid=$course->id;
751 $temp->drop_x_lowest = 0;
752 $temp->bonus_points = 0;
753 $temp->hidden = 0;
754 $temp->weight = 100.00;
755
756 insert_record('grade_category', $temp);
757 $uncat_id = get_record('grade_category', 'courseid', $course->id, 'name', $uncat);
758 if (!$uncat_id) {
759 error(get_string('errornocategorizedid','grades'));
760 exit(0);
761 }
762 }
763
764
765 /// Collect modules data
766 get_all_mods($course->id, $mods, $modnames, $modnamesplural, $modnamesused);
767 $itemcount = 0;
768
769 // this will let us establish the order for gradebook item display
770 $sort = 0;
771
772 /// Search through all the modules, pulling out grade data
773 $sections = get_all_sections($course->id); // Sort everything the same as the course
774 for ($i=0; $i<=$course->numsections; $i++) {
775 if (isset($sections["$i"])) { // should always be true
776 $section = $sections["$i"];
777 if ($section->sequence) {
778 $sectionmods = explode(",", $section->sequence);
779 foreach ($sectionmods as $sectionmod) {
780 if (isset($mods["$sectionmod"])) {
781 $mod = $mods["$sectionmod"];
782 $instance = get_record("$mod->modname", "id", "$mod->instance");
783 $libfile = "$CFG->dirroot/mod/$mod->modname/lib.php";
784 if (file_exists($libfile)) {
785 require_once($libfile);
786 $gradefunction = $mod->modname."_grades";
787 if (function_exists($gradefunction)) { // Skip modules without grade function
788 if ($modgrades = $gradefunction($mod->instance)) {
789 $itemcount++;
790 //modgrades contains student information with associated grade
71502268 791 //echo "<b>modname: $mod->modname id: $mod->id course: $mod->course</b><br/>";
cbff94ba 792 // get instance name from db.
793 $instance = get_record($mod->modname, 'id', $mod->instance);
794 // see if the item is already in the category table and if it is call category select with the id so it is selected
795 get_record('modules', 'name', $mod->modname);
796 $item = get_record('grade_item', 'courseid', $course->id, 'modid', $mod->module, 'cminstance', $mod->instance);
797 if (!$item) {
798 // set the item to uncategorized in grade_item
799 $item->courseid = $course->id;
800 $item->category = $uncat_id->id;
801 $item->modid = $mod->module;
802 $item->cminstance = $mod->instance;
803 $item->id = insert_record('grade_item', $item);
804 }
805 else if ($item->category == 0) {
806 // this catches any errors where they may have some wierd category set
807 set_field('grade_item', 'category', $uncat_id->id, 'id', $item->id);
808 }
809 set_field('grade_item', 'sort_order', $sort, 'id', $item->id);
810 $sort++;
811 }
812 }
813 }
814 }
815 }
816 }
817 }
818 }
819}
820
821// sorting functions for grades
822function grade_sort_by_lastname($x,$y)
823{
824 //$grades_by_student["$student->userid"]['student_data']['firstname'] = $student->firstname;
825 //$grades_by_student["$student->userid"]['student_data']['lastname'] = $student->lastname;
826 if (strnatcasecmp($x['student_data']['lastname'],$y['student_data']['lastname']) == 0) {
827 return strnatcasecmp($x['student_data']['firstname'],$y['student_data']['firstname']);
828 }
829 else {
830 return strnatcasecmp($x['student_data']['lastname'],$y['student_data']['lastname']);
831 }
832}
833
834function grade_sort_by_firstname($x,$y)
835{
836 //$grades_by_student["$student->userid"]['student_data']['firstname'] = $student->firstname;
837 //$grades_by_student["$student->userid"]['student_data']['lastname'] = $student->lastname;
838 if (strnatcasecmp($x['student_data']['firstname'],$y['student_data']['firstname']) == 0) {
839 return strnatcasecmp($x['student_data']['lastname'],$y['student_data']['lastname']);
840 }
841 else {
842 return strnatcasecmp($x['student_data']['firstname'],$y['student_data']['firstname']);
843 }
844}
845
846function grade_sort_by_points($x,$y) {
847 if ($x['student_data']['points'] == $y['student_data']['points']) {
848 return grade_sort_by_lastname($x,$y);
849 }
850 else {
851 if ($x['student_data']['points'] > $y['student_data']['points'])
852 return -1;
853 else
854 return 1;
855 }
856}
857
858function grade_sort_by_points_asc($x,$y) {
859 if ($x['student_data']['points'] == $y['student_data']['points']) {
860 return grade_sort_by_lastname($x,$y);
861 }
862 else {
863 if ($x['student_data']['points'] < $y['student_data']['points'])
864 return -1;
865 else
866 return 1;
867 }
868}
869
870function grade_sort_by_weighted($x,$y) {
871 if ($x['student_data']['weighted'] == $y['student_data']['weighted']) {
872 return grade_sort_by_lastname($x,$y);
873 }
874 else {
875 if ($x['student_data']['weighted'] > $y['student_data']['weighted'])
876 return -1;
877 else
878 return 1;
879 }
880}
881
882function grade_sort_by_percent($x,$y) {
883 if ($x['student_data']['percent'] == $y['student_data']['percent']) {
884 return grade_sort_by_lastname($x,$y);
885 }
886 else {
887 if ($x['student_data']['percent'] > $y['student_data']['percent'])
888 return -1;
889 else
890 return 1;
891 }
892}
893
894function grade_sort_by_percent_asc($x,$y) {
895 if ($x['student_data']['percent'] == $y['student_data']['percent']) {
896 return grade_sort_by_lastname($x,$y);
897 }
898 else {
899 if ($x['student_data']['percent'] < $y['student_data']['percent'])
900 return -1;
901 else
902 return 1;
903 }
904}
905
906function grade_sort_by_weighted_asc($x,$y) {
907 if ($x['student_data']['weighted'] == $y['student_data']['weighted']) {
908 return grade_sort_by_lastname($x,$y);
909 }
910 else {
911 if ($x['student_data']['weighted'] < $y['student_data']['weighted'])
912 return -1;
913 else
914 return 1;
915 }
916}
917
918function grade_sort_by_highgrade_category($x,$y) {
919 global $cview;
920
921 if(!$cview) {
922 $cview = optional_param('cview');
923 }
924
925 if ($x["$cview"]['stats']['points'] == $y["$cview"]['stats']['points']) {
926 return grade_sort_by_lastname($x,$y);
927 }
928 else {
929 return ($y["$cview"]['stats']['points'] - $x["$cview"]['stats']['points']);
930 }
931}
932
933function grade_sort_by_highgrade_category_asc($x,$y) {
934 global $cview;
935
936 if(!$cview)
937 $cview = optional_param('cview');
938
939 if ($x["$cview"]['stats']['points'] == $y["$cview"]['stats']['points']) {
940 return grade_sort_by_lastname($x,$y);
941 }
942 else {
943 return ($x["$cview"]['stats']['points'] - $y["$cview"]['stats']['points']);
944 }
945}
946
947
281ffa4a 948function grade_set_preference($courseid, $name, $value) {
949 global $GRADEPREFS;
cbff94ba 950
281ffa4a 951 if (false !== ($key = array_search($name, $GRADEPREFS))) {
952 if ($record = get_record('grade_preferences', 'courseid', $courseid, 'preference', $key)) {
953 $record->value = $value;
954 update_record('grade_preferences', $record);
955 } else { // Make a new one
956 $record->preference = $key;
957 $record->courseid = $courseid;
958 $record->value = $value;
959 insert_record('grade_preferences', $record);
960 }
961 }
962}
963
964function grade_get_preference($courseid, $name) {
914493e9 965 global $GRADEPREFS, $GRADEPREFSDEFAULTS;
281ffa4a 966
967 if (false !== ($key = array_search($name, $GRADEPREFS))) {
914493e9 968 if (!($record = get_record('grade_preferences', 'courseid', $courseid, 'preference', $key))) {
969 // Make a new one
281ffa4a 970 $record->preference = $key;
971 $record->courseid = $courseid;
914493e9 972 $record->value = $GRADEPREFSDEFAULTS[$name];
281ffa4a 973 insert_record('grade_preferences', $record);
974 }
914493e9 975 return $record->value;
281ffa4a 976 }
977 return NULL;
978}
979
980function grade_get_preferences($courseid) {
cbff94ba 981 global $CFG;
281ffa4a 982 global $GRADEPREFS, $GRADEPREFSDEFAULTS;
983
984 $preferences = NULL;
985
cbff94ba 986 // Get the preferences for the course.
281ffa4a 987 if ($rawprefs = get_records('grade_preferences', 'courseid', $courseid)) {
988 foreach ($rawprefs as $pref) {
989 if (isset($GRADEPREFS[$pref->preference])) { // Valid pref
990 $name = $GRADEPREFS[$pref->preference];
991 $preferences->$name = $pref->value;
992 }
993 }
cbff94ba 994 }
281ffa4a 995
996 // Check for any missing ones and create them from defaults
997 // We don't save them in the database so we save space
998 foreach ($GRADEPREFS as $number => $name) {
999 if (!isset($preferences->$name)) {
1000 $preferences->$name = $GRADEPREFSDEFAULTS[$name];
1001 }
cbff94ba 1002 }
281ffa4a 1003
b623ea5e 1004 // Construct some other ones about which fields are shown
281ffa4a 1005
d02eeded 1006 $isteacher = has_capability('moodle/course:managegrades', get_context_instance(CONTEXT_COURSE, $courseid));
281ffa4a 1007
b623ea5e 1008 $preferences->show_weighted = (($preferences->display_weighted > 0 && $isteacher) ||
1009 ($preferences->display_weighted > 1 && !$isteacher));
cbff94ba 1010
b623ea5e 1011 $preferences->show_points = (($preferences->display_points > 0 && $isteacher) ||
1012 ($preferences->display_points > 1 && !$isteacher));
cbff94ba 1013
b623ea5e 1014 $preferences->show_percent = (($preferences->display_percent > 0 && $isteacher) ||
1015 ($preferences->display_percent > 1 && !$isteacher));
281ffa4a 1016
b623ea5e 1017 $preferences->show_letters = (($preferences->display_letters > 0 && $isteacher) ||
1018 ($preferences->display_letters > 1 && !$isteacher));
281ffa4a 1019
cbff94ba 1020 return $preferences;
1021}
1022
281ffa4a 1023
1024function grade_set_preferences($course, $newprefs) {
cbff94ba 1025
281ffa4a 1026 if (!isset($newprefs->use_advanced) or ($newprefs->use_advanced == 1)) {
1027 foreach ($newprefs as $name => $value) { /// Just save them all
1028 grade_set_preference($course->id, $name, $value);
cbff94ba 1029 }
281ffa4a 1030 return true;
1031 }
cbff94ba 1032
281ffa4a 1033/// We don't need advanced features, and we need to unset all extra features
1034/// So they don't affect grades (This approach should be revisited because it resets everything!!)
cbff94ba 1035
281ffa4a 1036 grade_set_preference($course->id, 'use_advanced', 0);
1037 grade_set_preference($course->id, 'use_weighted_for_letter', 0);
1038 grade_set_preference($course->id, 'display_weighted', 0);
b623ea5e 1039 grade_set_preference($course->id, 'display_points', 2);
281ffa4a 1040 grade_set_preference($course->id, 'display_percent', 0);
b623ea5e 1041 grade_set_preference($course->id, 'display_letters', 0);
cbff94ba 1042
281ffa4a 1043/// Lose all exceptions
1044 delete_records('grade_exceptions', 'courseid', $course->id);
1045
1046 if (!$uncat = get_record('grade_category', 'courseid', $course->id, 'name', UNCATEGORISED)) {
1047 /// Make a category for uncategorised stuff
1048 $uncat->name=UNCATEGORISED;
1049 $uncat->courseid=$course->id;
1050 if (!$uncat->id = insert_record('grade_category', $uncat)) {
1051 error(get_string('errornocategorizedid','grades'));
cbff94ba 1052 }
cbff94ba 1053 }
281ffa4a 1054
1055 set_field('grade_item', 'category', $uncat->id, 'courseid', $course->id);
1056 set_field('grade_item', 'scale_grade', 1.00, 'courseid', $course->id);
1057 set_field('grade_item', 'extra_credit', 0, 'courseid', $course->id);
1058
1059 set_field('grade_category', 'weight', 100.0, 'courseid', $course->id, 'id', $uncat->id);
1060 set_field('grade_category', 'bonus_points', '0', 'courseid', $course->id);
cbff94ba 1061}
1062
cbff94ba 1063
68d0c80c 1064function grade_preferences_menu($action, $course) {
281ffa4a 1065
e91f3c2d 1066 if (!has_capability('moodle/course:managegrades', get_context_instance(CONTEXT_COURSE, $course->id))) {
281ffa4a 1067 return;
1068 }
1069
1070 // remap some actions to simplify later code
1071 switch ($action) {
1072 case 'prefs':
1073 case 'set_grade_preferences':
1074 $curraction = 'prefs';
1075 break;
1076 case 'cats':
1077 case 'vcats':
b0ef72a6 1078 $curraction = '';
1079 break;
281ffa4a 1080 case 'insert_category':
1081 case 'assign_categories':
1082 case 'delete_category':
1083 $curraction = 'cats';
1084 break;
1085 case 'set_grade_weights':
1086 case 'weights':
1087 $curraction = 'weights';
1088 break;
1089 case 'letters':
1090 case 'set_letter_grades':
1091 $curraction = 'letters';
1092 break;
1093 case 'view_student_grades':
1094 case 'view_student_category_grades':
1095 case 'grades':
1096 $curraction = 'grades';
1097 break;
1098 case 'excepts':
1099 $curraction = 'excepts';
1100 break;
1101
1102 default:
1103 $curraction = 'grades';
1104 }
1105
1106 $tabs = $row = array();
1107 $row[] = new tabobject('grades', 'index.php?id='.$course->id,
1108 get_string('viewgrades', 'grades'));
1109 $row[] = new tabobject('prefs', 'index.php?id='.$course->id.'&amp;action=prefs',
1110 get_string('setpreferences', 'grades'));
6cd8c592 1111 // only show the extra options if advanced is turned on, they don't do anything otherwise
1112 if (grade_get_preference($course->id, 'use_advanced') == 1) {
1113 $row[] = new tabobject('cats', 'index.php?id='.$course->id.'&amp;action=cats',
1114 get_string('setcategories', 'grades'));
1115 $row[] = new tabobject('weights', 'index.php?id='.$course->id.'&amp;action=weights',
1116 get_string('setweights', 'grades'));
1117 $row[] = new tabobject('letters', 'index.php?id='.$course->id.'&amp;action=letters',
1118 get_string('setgradeletters', 'grades'));
1119 $row[] = new tabobject('excepts', 'exceptions.php?id='.$course->id.'&amp;action=excepts',
1120 get_string('gradeexceptions', 'grades'));
1121 }
281ffa4a 1122 $tabs[] = $row;
1123
1124 print_tabs($tabs, $curraction);
cbff94ba 1125}
1126
281ffa4a 1127
a983b6ec 1128function grade_nav($course, $action='grades') {
cbff94ba 1129 global $CFG;
1130 global $USER;
1131 global $cview;
1132
cbff94ba 1133 $strgrades = get_string('grades', 'grades');
a983b6ec 1134 $gradenav = "<a href=\"$CFG->wwwroot/course/view.php?id=$course->id\">$course->shortname</a>";
1135
d02eeded 1136 if (has_capability('moodle/course:managegrades', get_context_instance(CONTEXT_COURSE, $course->id))) {
cbff94ba 1137 switch ($action) {
1138 case 'prefs':
1139 case 'set_grade_preferences':
1140 $strcurpage = get_string('setpreferences','grades');
1141 break;
1142 case 'cats':
1143 case 'delete_category':
1144 case 'cats':
1145 case 'insert_category':
1146 case 'assign_categories':
1147 $strcurpage = get_string('setcategories','grades');
1148 break;
1149 case 'weights':
1150 case 'set_grade_weights':
1151 $strcurpage = get_string('setweights','grades');
1152 break;
1153 case 'set_letter_grades':
1154 case 'letters':
1155 $strcurpage = get_string('setgradeletters','grades');
1156 break;
1157 case 'excepts':
1158 $strcurpage = get_string('gradeexceptions', 'grades');
1159 break;
f5f4967e 1160 case 'exporttxt':
1161 case 'exportxml':
1162 case 'exportods':
1163 case 'exportxls':
1164 case 'importcsv':
1165 case 'importxml':
f115f8c8 1166 $strcurpage = get_string($action, 'grades');
f5f4967e 1167 break;
cbff94ba 1168 default:
1169 unset($strcurpage);
1170 break;
1171 }
cbff94ba 1172
cbff94ba 1173 if ($action=='grades') {
a983b6ec 1174 $gradenav .= " -> $strgrades";
1175 } else {
1176 $gradenav .= " -> <a href=\"index.php?id=$course->id&amp;action=grades\">$strgrades</a>";
cbff94ba 1177 }
1178
cbff94ba 1179 // if we are on a grades sub-page provide a link back (including grade preferences and grade items
cbff94ba 1180
1181 if (isset($strcurpage)) {
a983b6ec 1182 $gradenav .= " -> $strcurpage";
1183 } else if($action =='vcats') {
cbff94ba 1184 // show sub category
1185 if (isset($cview)) {
a983b6ec 1186 $gradenav .= " -> $cview";
cbff94ba 1187 }
1188 }
a983b6ec 1189
1190 } else {
1191 $gradenav .= " -> $strgrades";
cbff94ba 1192 }
1193
a983b6ec 1194 return $gradenav;
cbff94ba 1195}
1196
6cd8c592 1197function grade_download($download, $id) {
cbff94ba 1198 global $CFG;
cbff94ba 1199
6cd8c592 1200 require_login();
1201
1202 if (! $course = get_record("course", "id", $id)) {
1203 error("Course ID was incorrect");
1204 }
1205
1c45e42e 1206 require_capability('moodle/course:viewcoursegrades', get_context_instance(CONTEXT_COURSE, $id));
6cd8c592 1207
cbff94ba 1208 $strgrades = get_string("grades");
6cd8c592 1209 $strgrade = get_string("grade");
1210 $strmax = get_string("maximumshort");
1211 $stractivityreport = get_string("activityreport");
1212
1213/// Check to see if groups are being used in this course
68d0c80c 1214 $currentgroup = get_current_group($course->id);
6cd8c592 1215
1216 if ($currentgroup) {
1217 $students = get_group_students($currentgroup, "u.lastname ASC");
1218 } else {
5a412dbf 1219 $students = grade_get_course_students($course->id);
6cd8c592 1220 }
1221
865e9a82 1222 if (!empty($students)) {
1223 foreach ($students as $student) {
1224 $grades[$student->id] = array(); // Collect all grades in this array
1225 $gradeshtml[$student->id] = array(); // Collect all grades html formatted in this array
1226 $totals[$student->id] = array(); // Collect all totals in this array
1227 }
6cd8c592 1228 }
1229 $columns = array(); // Accumulate column names in this array.
1230 $columnhtml = array(); // Accumulate column html in this array.
1231
1232
1233/// Collect modules data
1234 get_all_mods($course->id, $mods, $modnames, $modnamesplural, $modnamesused);
1235
1236/// Search through all the modules, pulling out grade data
1237 $sections = get_all_sections($course->id); // Sort everything the same as the course
1238 for ($i=0; $i<=$course->numsections; $i++) {
1239 if (isset($sections[$i])) { // should always be true
1240 $section = $sections[$i];
1241 if ($section->sequence) {
1242 $sectionmods = explode(",", $section->sequence);
1243 foreach ($sectionmods as $sectionmod) {
1244 $mod = $mods[$sectionmod];
1245 $instance = get_record("$mod->modname", "id", "$mod->instance");
1246 $libfile = "$CFG->dirroot/mod/$mod->modname/lib.php";
1247
1248 if (file_exists($libfile)) {
1249 require_once($libfile);
1250 $gradefunction = $mod->modname."_grades";
1251 if (function_exists($gradefunction)) { // Skip modules without grade function
1252 if ($modgrades = $gradefunction($mod->instance)) {
1253 if (!empty($modgrades->maxgrade)) {
1254 if ($mod->visible) {
1255 $maxgrade = "$strmax: $modgrades->maxgrade";
1256 } else {
1257 $maxgrade = "$strmax: $modgrades->maxgrade";
1258 }
1259 } else {
1260 $maxgrade = "";
1261 }
1262
0e60c772 1263 $columns[] = "$mod->modfullname: ".format_string($instance->name,true)." - $maxgrade";
865e9a82 1264
1265 if (!empty($students)) {
1266 foreach ($students as $student) {
1267 if (!empty($modgrades->grades[$student->id])) {
1268 $grades[$student->id][] = $currentstudentgrade = $modgrades->grades[$student->id];
1269 } else {
1270 $grades[$student->id][] = $currentstudentgrade = "";
1271 $gradeshtml[$student->id][] = "";
1272 }
1273 if (!empty($modgrades->maxgrade)) {
1274 $totals[$student->id] = (float)($totals[$student->id]) + (float)($currentstudentgrade);
1275 } else {
1276 $totals[$student->id] = (float)($totals[$student->id]) + 0;
1277 }
6cd8c592 1278 }
1279 }
1280 }
1281 }
1282 }
1283 }
1284 }
1285 }
1286 } // a new Moodle nesting record? ;-)
1287
1288/// OK, we have all the data, now present it to the user
9c61ba4d 1289/// OK, we have all the data, now present it to the user
1290 if ($download == "ods" and confirm_sesskey()) {
1291 require_once("../lib/odslib.class.php");
1292
1293 /// Calculate file name
1294 $downloadfilename = clean_filename("$course->shortname $strgrades.ods");
1295 /// Creating a workbook
1296 $workbook = new MoodleODSWorkbook("-");
1297 /// Sending HTTP headers
1298 $workbook->send($downloadfilename);
1299 /// Adding the worksheet
1300 $myxls =& $workbook->add_worksheet($strgrades);
1301
1302 /// Print names of all the fields
1303 $myxls->write_string(0,0,get_string("firstname"));
1304 $myxls->write_string(0,1,get_string("lastname"));
1305 $myxls->write_string(0,2,get_string("idnumber"));
1306 $myxls->write_string(0,3,get_string("institution"));
1307 $myxls->write_string(0,4,get_string("department"));
1308 $myxls->write_string(0,5,get_string("email"));
1309 $pos=6;
1310 foreach ($columns as $column) {
1311 $myxls->write_string(0,$pos++,strip_tags($column));
1312 }
1313 $myxls->write_string(0,$pos,get_string("total"));
1314
1315 /// Print all the lines of data.
1316 $i = 0;
1317 if (!empty($grades)) {
1318 foreach ($grades as $studentid => $studentgrades) {
1319 $i++;
1320 $student = $students[$studentid];
1321 if (empty($totals[$student->id])) {
1322 $totals[$student->id] = '';
1323 }
1324
1325 $myxls->write_string($i,0,$student->firstname);
1326 $myxls->write_string($i,1,$student->lastname);
1327 $myxls->write_string($i,2,$student->idnumber);
1328 $myxls->write_string($i,3,$student->institution);
1329 $myxls->write_string($i,4,$student->department);
1330 $myxls->write_string($i,5,$student->email);
1331 $j=6;
1332 foreach ($studentgrades as $grade) {
1333 if (is_numeric($grade)) {
1334 $myxls->write_number($i,$j++,strip_tags($grade));
1335 }
1336 else {
1337 $myxls->write_string($i,$j++,strip_tags($grade));
1338 }
1339 }
1340 $myxls->write_number($i,$j,$totals[$student->id]);
1341 }
1342 }
1343
1344 /// Close the workbook
1345 $workbook->close();
1346
1347 exit;
1348
1349 } else if ($download == "xls" and confirm_sesskey()) {
865e9a82 1350 require_once("../lib/excellib.class.php");
1351
1352 /// Calculate file name
1353 $downloadfilename = clean_filename("$course->shortname $strgrades.xls");
1354 /// Creating a workbook
1355 $workbook = new MoodleExcelWorkbook("-");
1356 /// Sending HTTP headers
1357 $workbook->send($downloadfilename);
1358 /// Adding the worksheet
cbff94ba 1359 $myxls =& $workbook->add_worksheet($strgrades);
6cd8c592 1360
865e9a82 1361 /// Print names of all the fields
6cd8c592 1362 $myxls->write_string(0,0,get_string("firstname"));
1363 $myxls->write_string(0,1,get_string("lastname"));
1364 $myxls->write_string(0,2,get_string("idnumber"));
1365 $myxls->write_string(0,3,get_string("institution"));
1366 $myxls->write_string(0,4,get_string("department"));
1367 $myxls->write_string(0,5,get_string("email"));
1368 $pos=6;
1369 foreach ($columns as $column) {
1370 $myxls->write_string(0,$pos++,strip_tags($column));
1371 }
1372 $myxls->write_string(0,$pos,get_string("total"));
1373
865e9a82 1374 /// Print all the lines of data.
6cd8c592 1375 $i = 0;
865e9a82 1376 if (!empty($grades)) {
1377 foreach ($grades as $studentid => $studentgrades) {
1378 $i++;
1379 $student = $students[$studentid];
1380 if (empty($totals[$student->id])) {
1381 $totals[$student->id] = '';
cbff94ba 1382 }
865e9a82 1383
1384 $myxls->write_string($i,0,$student->firstname);
1385 $myxls->write_string($i,1,$student->lastname);
1386 $myxls->write_string($i,2,$student->idnumber);
1387 $myxls->write_string($i,3,$student->institution);
1388 $myxls->write_string($i,4,$student->department);
1389 $myxls->write_string($i,5,$student->email);
1390 $j=6;
1391 foreach ($studentgrades as $grade) {
74350013 1392 if (is_numeric($grade)) {
865e9a82 1393 $myxls->write_number($i,$j++,strip_tags($grade));
1394 }
1395 else {
1396 $myxls->write_string($i,$j++,strip_tags($grade));
1397 }
cbff94ba 1398 }
865e9a82 1399 $myxls->write_number($i,$j,$totals[$student->id]);
cbff94ba 1400 }
1401 }
865e9a82 1402
1403 /// Close the workbook
cbff94ba 1404 $workbook->close();
6cd8c592 1405
cbff94ba 1406 exit;
cbff94ba 1407
6cd8c592 1408 } else if ($download == "txt" and confirm_sesskey()) {
cbff94ba 1409
6cd8c592 1410/// Print header to force download
1411
1412 header("Content-Type: application/download\n");
cbff94ba 1413 $downloadfilename = clean_filename("$course->shortname $strgrades");
1414 header("Content-Disposition: attachment; filename=\"$downloadfilename.txt\"");
6cd8c592 1415
1416/// Print names of all the fields
1417
1418 echo get_string("firstname")."\t".
1419 get_string("lastname")."\t".
1420 get_string("idnumber")."\t".
1421 get_string("institution")."\t".
1422 get_string("department")."\t".
1423 get_string("email");
1424 foreach ($columns as $column) {
1425 $column = strip_tags($column);
1426 echo "\t$column";
1427 }
1428 echo "\t".get_string("total")."\n";
1429
1430/// Print all the lines of data.
1431 foreach ($grades as $studentid => $studentgrades) {
1432 $student = $students[$studentid];
1433 if (empty($totals[$student->id])) {
1434 $totals[$student->id] = '';
cbff94ba 1435 }
6cd8c592 1436 echo "$student->firstname\t$student->lastname\t$student->idnumber\t$student->institution\t$student->department\t$student->email";
1437 foreach ($studentgrades as $grade) {
1438 $grade = strip_tags($grade);
1439 echo "\t$grade";
cbff94ba 1440 }
6cd8c592 1441 echo "\t".$totals[$student->id];
1442 echo "\n";
cbff94ba 1443 }
6cd8c592 1444
cbff94ba 1445 exit;
6cd8c592 1446
a844e88f 1447 }else if ($download == '' and confirm_sesskey()) {
1448 error("No file type specified");
1449 exit;
cbff94ba 1450 }
1451}
1452
1453function grade_get_stats($category='all') {
1454 list($grades_by_student, $all_categories) = grade_get_formatted_grades();
1455
1456 if ($grades_by_student != 0 && $all_categories != 0) {
1457 switch($category) {
1458 case 'all':
1459 {
1460 //populate the sum of student points, # items and totalpoints for each category
1461 foreach($grades_by_student as $student=>$categories) {
1462 foreach($categories as $cur_category=>$assignments) {
1463 if($category != 'student_data') {
1464 if (isset($assignments['stats'])) {
1465 if (isset($stats[$cur_category]['sum'])) {
1466 $stats[$cur_category]['sum'] = $stats[$cur_category]['sum'] + $assignments['stats']['points'];
1467 }
1468 else {
1469 $stats[$cur_category]['sum'] = $assignments['stats']['points'];
1470 }
1471 $stats[$cur_category]['items'] = $assignments['stats']['grade_items'];
1472 $stats[$cur_category]['totalpoints'] = $assignments['stats']['totalpoints'];
1473 $stats[$cur_category]['weight'] = $all_categories[$cur_category]['stats']['weight'];
1474 }
1475 }
1476 }
1477 }
1478 // populate the overall sum,items and totalpoints
1479 foreach($stats as $cur_category=>$info) {
1480 if($cur_category != 'all' && $cur_category != 'student_data') {
a844e88f 1481
1482 if ($stats[$cur_category]['totalpoints'] == get_string('excluded', 'grades')) {
1483 $stats[$cur_category]['totalpoints'] = 1;
1484 $stats['all']['sum'] = $stats['all']['sum'] + $stats[$cur_category]['sum'];
1485 $stats['all']['items'] = $stats['all']['items'] + $stats[$cur_category]['items'];
1486 $stats['all']['totalpoints'] = $stats['all']['totalpoints'] + $stats[$cur_category]['totalpoints'];
1487 $stats['all']['weighted_sum'] = $stats['all']['weighted_sum'] + ($stats[$cur_category]['sum']/($stats[$cur_category]['totalpoints']))*$stats[$cur_category]['weight'];
1488 }
1489
1490 else if (isset($stats['all'])) {
cbff94ba 1491 $stats['all']['sum'] = $stats['all']['sum'] + $stats[$cur_category]['sum'];
1492 $stats['all']['items'] = $stats['all']['items'] + $stats[$cur_category]['items'];
1493 $stats['all']['totalpoints'] = $stats['all']['totalpoints'] + $stats[$cur_category]['totalpoints'];
1494 $stats['all']['weighted_sum'] = $stats['all']['weighted_sum'] + ($stats[$cur_category]['sum']/($stats[$cur_category]['totalpoints']))*$stats[$cur_category]['weight'];
1495 }
1496 else {
1497 $stats['all']['sum'] = $stats[$cur_category]['sum'];
1498 $stats['all']['items'] = $stats[$cur_category]['items'];
1499 $stats['all']['totalpoints'] = $stats[$cur_category]['totalpoints'];
1500 $stats['all']['weighted_sum'] = ($stats[$cur_category]['sum']/($stats[$cur_category]['totalpoints']))*$stats[$cur_category]['weight'];
a844e88f 1501
cbff94ba 1502 }
1503 }
1504 }
1505 $stats['all']['students'] = count($grades_by_student);
1506 $stats['all']['average'] = $stats['all']['sum'] / $stats['all']['students'];
1507 $stats['all']['average_weighted'] = $stats['all']['weighted_sum']/$stats['all']['students'];
1508
1509 // calculate the average squared deviation and populate a list of all scores while we're at it
1510 $stats['all']['avgsqddev'] = 0;
1511 $stats['all']['avgsqddev_weighted'] = 0;
1512 foreach($grades_by_student as $student=>$categories) {
1513 foreach($categories as $cur_category=>$assignments) {
1514 if ($cur_category != 'student_data') {
1515 $stats['all']['avgsqddev'] = $stats['all']['avgsqddev'] + pow(($grades_by_student[$student]['student_data']['points']-$stats['all']['average']),2);
1516 $stats['all']['avgsqddev_weighted'] = $stats['all']['avgsqddev_weighted'] + pow(($grades_by_student[$student]['student_data']['weighted']-$stats['all']['average_weighted']),2);
1517 }
1518 }
1519 if (isset($stats['all']['all_scores'])) {
1520 $stats['all']['all_scores'] .= ','.$grades_by_student[$student]['student_data']['points'];
1521 $stats['all']['all_scores_weighted'] .= ','.$grades_by_student[$student]['student_data']['weighted'];
1522 }
1523 else {
1524 $stats['all']['all_scores'] = $grades_by_student[$student]['student_data']['points'];
1525 $stats['all']['all_scores_weighted'] = $grades_by_student[$student]['student_data']['weighted'];
1526 }
1527 }
1528 $stats['all']['avgsqddev']=$stats['all']['avgsqddev']/$stats['all']['students'];
1529 $stats['all']['avgsqddev_weighted']=$stats['all']['avgsqddev_weighted']/$stats['all']['students'];
1530 $stats['all']['stddev'] = sqrt($stats['all']['avgsqddev']);
1531 $stats['all']['stddev_weighted'] = sqrt($stats['all']['avgsqddev_weighted']);
1532 $stats['all']['mode'] = grade_mode($stats['all']['all_scores']);
1533 $stats['all']['mode_weighted'] = grade_mode($stats['all']['all_scores_weighted']);
1534
1535 // make sure the mode is not set to every score
1536 if(count($stats['all']['mode']) == count($grades_by_student)) {
1537 $stats['all']['mode'] = get_string('nomode','grade');
1538 }
1539 if(count($stats['all']['mode_weighted']) == count($grades_by_student)) {
1540 $stats['all']['mode_weighted'] = get_string('nomode','grade');
1541 }
1542 break;
1543 }
1544 default:
1545 {
1546 // get the stats for category
1547 //populate the sum of student points, # items and totalpoints for each category
1548 foreach($grades_by_student as $student=>$categories) {
1549 if(isset($grades_by_student[$student][$category]['stats'])) {
1550 if (isset($stats[$category]['sum'])) {
1551 $stats[$category]['sum'] = $stats[$category]['sum'] + $grades_by_student[$student][$category]['stats']['points'];
1552 }
1553 else {
1554 $stats[$category]['sum'] = $grades_by_student[$student][$category]['stats']['points'];
1555 }
1556 $stats[$category]['items'] = $grades_by_student[$student][$category]['stats']['grade_items'];
1557 $stats[$category]['totalpoints'] = $grades_by_student[$student][$category]['stats']['totalpoints'];
1558 }
1559 }
1560 $stats[$category]['students'] = count($grades_by_student);
1561 $stats[$category]['average'] = $stats[$category]['sum']/$stats[$category]['students'];
1562
1563 // calculate the average squared deviation and populate a list of all scores too
1564 $stats[$category]['avgsqddev'] = 0;
1565 foreach($grades_by_student as $student=>$categories) {
1566 foreach($categories as $cur_category=>$assignment) {
1567 if ($cur_category != 'student_data') {
1568 if ($grades_by_student[$student][$category]['stats']['points'] == '-' || $grades_by_student[$student][$category]['stats']['points'] == get_string('grades','excluded')) {
1569 // count grade as a zero
1570 $stats[$category]['avgsqddev'] = $stats[$category]['avgsqddev'] + pow(($stats[$category]['average']),2);
1571 }
1572 else {
1573 $stats[$category]['avgsqddev'] = $stats[$category]['avgsqddev'] + pow(($grades_by_student[$student][$category]['stats']['points']-$stats[$category]['average']),2);
1574 }
1575 }
1576 }
1577
1578 if (isset($stats[$category]['all_scores'])) {
1579 $stats[$category]['all_scores'] .= ','.$grades_by_student[$student][$category]['stats']['points'];
1580 }
1581 else {
1582 $stats[$category]['all_scores'] = $grades_by_student[$student][$category]['stats']['points'];
1583 }
1584 }
1585 $stats[$category]['avgsqddev'] = $stats[$category]['avgsqddev']/$stats[$category]['students'];
1586 $stats[$category]['stddev'] = sqrt($stats[$category]['avgsqddev']);
1587 $stats[$category]['mode'] = grade_mode($stats[$category]['all_scores']);
1588 break;
1589 }
1590 } // end switch
1591 // do a little cleanup
1592 $stats[$category]['stddev'] = sprintf("%0.2f", $stats[$category]['stddev']);
1593 $stats[$category]['average'] = sprintf("%0.2f", $stats[$category]['average']);
1594 $stats[$category]['max'] = max(explode(',',$stats[$category]['all_scores']));
1595 $stats[$category]['min'] = min(explode(',',$stats[$category]['all_scores']));
1596 $stats[$category]['median'] = explode(',',$stats[$category]['all_scores']);
1597
1598 if (isset($stats[$category]['stddev_weighted'])) {
1599 $stats[$category]['stddev_weighted'] = sprintf("%0.2f", $stats[$category]['stddev_weighted']);
1600 }
1601 if (isset($stats[$category]['average_weighted'])) {
1602 $stats[$category]['average_weighted'] = sprintf("%0.2f", $stats[$category]['average_weighted']);
1603 }
1604 if (isset($stats[$category]['max_weighted'])) {
1605 $stats[$category]['max_weighted'] = max(explode(',',$stats[$category]['all_scores_weighted']));
1606 }
1607 if (isset($stats[$category]['min_weighted'])) {
1608 $stats[$category]['min_weighted'] = min(explode(',',$stats[$category]['all_scores_weighted']));
1609 }
1610
1611 if (isset($stats[$category]['all_scores_weighted'])) {
1612 $stats[$category]['median_weighted'] = explode(',',$stats[$category]['all_scores_weighted']);
1613 }
1614 else {
1615
1616 }
1617
1618
1619 sort($stats[$category]['median']);
1620
1621 if (count($stats[$category]['median'])/2 == floor(count($stats[$category]['median'])/2) ) {
1622 // even number of scores
1623 $temp = $stats[$category]['median'][count($stats[$category]['median'])/2-1] + $stats[$category]['median'][count($stats[$category]['median'])/2];
1624 $temp = $temp/2;
1625 }
1626 else {
1627 // odd number of scores
1628 $temp = $stats[$category]['median'][floor(count($stats[$category]['median'])/2)];
1629 }
1630 unset($stats[$category]['median']);
1631 $stats[$category]['median'] = $temp;
1632
1633 if (isset($stats[$category]['median_weighted'])) {
1634 if (count($stats[$category]['median_weighted'])/2 == floor(count($stats[$category]['median_weighted'])/2)) {
1635 // even number of scores
1636 $temp = $stats[$category]['median_weighted'][count($stats[$category]['median_weighted'])/2-1] + $stats[$category]['median_weighted'][count($stats[$category]['median_weighted'])/2+1];
1637 $temp = $temp/2;
1638 }
1639 else {
1640 // odd number of scores
1641 $temp = $stats[$category]['median_weighted'][floor(count($stats[$category]['median_weighted'])/2)];
1642 }
1643 unset($stats[$category]['median_weighted']);
1644 $stats[$category]['median_weighted'] = $temp;
1645 }
1646 }
1647 return $stats;
1648}
1649
1650// returns a comma seperated list of the most common values in $items, $items is expected to be a comma sperated list of numbers
1651function grade_mode($items) {
1652 $all_scores = explode(',',$items);
1653 foreach($all_scores as $value) {
1654 if (isset($frequency[$value])) {
1655 $frequency[$value]++;
1656 }
1657 else {
1658 $frequency[$value] = 1;
1659 }
1660 }
1661 $max = max($frequency);
1662 foreach($frequency as $key=>$value) {
1663 if ($value == $max) {
1664 if (isset($retval)) {
1665 $retval .= ', '.$key;
1666 }
1667 else {
1668 $retval = $key;
1669 }
1670 }
1671 }
1672 return $retval;
1673}
1674
1675
1676function grade_stats() {
1677 global $CFG;
1678 global $course;
1679 global $USER;
1680 global $preferences;
1681
1682 if (!isset($category)) {
1683 $category = clean_param($_REQUEST['category'], PARAM_CLEAN);
1684 }
1685
1686 $stats = grade_get_stats($category);
1687
1688 // output our data
1689 print_header();
fc9b712e 1690 echo '<table align="center"><tr><th colspan="3" scope="col">'.$category.' '.get_string('stats','grades').'</th></tr>';
cbff94ba 1691 if ($preferences->show_weighted == 1 && $preferences->use_weighted_for_letter == 1 && $category== 'all') {
fc9b712e 1692 echo '<tr><th scope="col">&nbsp;</th><th scope="col">'.get_string('points','grades').'<th scope="col">'.get_string('weight','grades').'</th></tr>';
cbff94ba 1693 }
1694
281ffa4a 1695 echo '<tr><td align="right">'.get_string('max','grades').':</td><td align="right">'.$stats[$category]['max'].'</td>';
cbff94ba 1696 if ($preferences->show_weighted == 1 && $preferences->use_weighted_for_letter == 1 && $category== 'all') {
281ffa4a 1697 echo '<td align="right">'.$stats[$category]['max_weighted'].'</td>';
cbff94ba 1698 }
281ffa4a 1699 echo '</tr>';
cbff94ba 1700
281ffa4a 1701 echo '<tr><td align="right">'.get_string('min','grades').':</td><td align="right">'.$stats[$category]['min'].'</td>';
cbff94ba 1702 if ($preferences->show_weighted == 1 && $preferences->use_weighted_for_letter == 1 && $category== 'all') {
281ffa4a 1703 echo '<td align="right">'.$stats[$category]['min_weighted'].'</td>';
cbff94ba 1704 }
281ffa4a 1705 echo '</tr>';
cbff94ba 1706
281ffa4a 1707 echo '<tr><td align="right">'.get_string('average','grades').':</td><td align="right">'.$stats[$category]['average'].'</td>';
cbff94ba 1708 if ($preferences->show_weighted == 1 && $preferences->use_weighted_for_letter == 1 && $category== 'all') {
281ffa4a 1709 echo '<td align="right">'.$stats[$category]['average_weighted'].'</td>';
cbff94ba 1710 }
281ffa4a 1711 echo '</tr>';
cbff94ba 1712
281ffa4a 1713 echo '<tr><td align="right">'.get_string('median','grades').':</td><td align="right">'.$stats[$category]['median'].'</td>';
cbff94ba 1714 if ($preferences->show_weighted == 1 && $preferences->use_weighted_for_letter == 1 && $category== 'all') {
281ffa4a 1715 echo '<td align="right">'.$stats[$category]['median_weighted'].'</td>';
cbff94ba 1716 }
281ffa4a 1717 echo '</tr>';
cbff94ba 1718
281ffa4a 1719 echo '<tr><td align="right">'.get_string('mode','grades').':</td><td align="right">'.$stats[$category]['mode'].'</td>';
cbff94ba 1720 if ($preferences->show_weighted == 1 && $preferences->use_weighted_for_letter == 1 && $category== 'all') {
281ffa4a 1721 echo '<td align="right">'.$stats[$category]['mode_weighted'].'</td>';
cbff94ba 1722 }
281ffa4a 1723 echo '</tr>';
cbff94ba 1724
281ffa4a 1725 echo '<tr><td align="right">'.get_string('standarddeviation','grades').':</td><td align="right">'.$stats[$category]['stddev'].'</td>';
cbff94ba 1726 if ($preferences->show_weighted == 1 && $preferences->use_weighted_for_letter == 1 && $category== 'all') {
281ffa4a 1727 echo '<td align="right">'.$stats[$category]['stddev_weighted'].'</td>';
cbff94ba 1728 }
281ffa4a 1729 echo '</tr>';
1730 echo '</table>';
60078fff 1731 print_footer();
cbff94ba 1732}
1733
1734function grade_view_category_grades($view_by_student) {
1735 global $CFG;
1736 global $course;
1737 global $USER;
1738 global $preferences;
fc9b712e 1739
1c45e42e 1740 $context = get_context_instance(CONTEXT_COURSE, $course->id);
1741
59fd781a 1742 // if can't see course grades, print single grade view
1c45e42e 1743 if (!has_capability('moodle/course:viewcoursegrades', $context)) {
68d0c80c 1744 $view_by_student = $USER->id;
cbff94ba 1745 }
1746
1747 if ($preferences->use_advanced == 0) {
281ffa4a 1748 $cview = UNCATEGORISED;
cbff94ba 1749 }
1750 else {
1751 $cview=clean_param($_REQUEST['cview'], PARAM_CLEAN);
1752 }
1753
1754 if ($cview) {
1755 list($grades_by_student, $all_categories) = grade_get_formatted_grades();
1756
1757 if ($grades_by_student != 0 && $all_categories != 0) {
1758 // output a form for the user to download the grades.
1759 grade_download_form();
1760
1761 if ($view_by_student != -1) {
1762 // unset all grades except for this student
1763 foreach ($grades_by_student as $student=>$junk) {
1764 if($student != $view_by_student) {
1765 unset($grades_by_student[$student]);
1766 }
1767 }
1768 }
1769
b623ea5e 1770 $grade_columns = $preferences->show_weighted + $preferences->show_points + $preferences->show_percent;
cbff94ba 1771
1772 $first = 0;
1773 //$maxpoints = 0;
1774 $maxpercent = 0;
1775 $reprint = 0;
1c45e42e 1776 if (has_capability('moodle/course:viewcoursegrades', $context)) {
cbff94ba 1777 $student_heading_link = get_string('student','grades');
1778 //only set sorting links if more than one student displayed.
1779 if ($view_by_student == -1) {
68d0c80c 1780 $student_heading_link .='<br /><a href="?id='.$course->id.'&amp;action=vcats&amp;cview='.$cview.'&amp;sort=lastname">'.get_string('sortbylastname','grades').'</a>';
1781 $student_heading_link .= '<br /><a href="?id='.$course->id.'&amp;action=vcats&amp;cview='.$cview.'&amp;sort=firstname">'.get_string('sortbyfirstname','grades').'</a>';
cbff94ba 1782 }
1783 else {
68d0c80c 1784 $student_heading_link .= '<br /><a href="?id='.$course->id.'&amp;action=vcats&amp;cview='.$cview.'">'.get_string('showallstudents','grades').'</a>';
cbff94ba 1785 }
1786 }
4e83cfdf 1787 echo '<table align="center" class="grades">';
1c45e42e 1788 if (has_capability('moodle/course:viewcoursegrades', $context)) {
fc9b712e 1789 $header = '<tr class="header"><th rowspan="2" scope="col">'.$student_heading_link.'</th>';
cbff94ba 1790 }
1791 else {
2cbf6b5a 1792 $header = '<tr class="header">';
cbff94ba 1793 }
2cbf6b5a 1794 $header1 = '<tr class="header">';
cbff94ba 1795
1796 // to keep track of what we've output
1797 $colcount = 0;
2cbf6b5a 1798 $oddrow = true;
cbff94ba 1799 $reprint = 0;
1800
1801 // this next section is to display the items in the course order
1802 foreach($grades_by_student as $student => $categories) {
1803 if (isset($item_order)) {
1804 // we already have the sort order let's jump out
1805 break;
1806 }
1807 $item_order = array();
1808 foreach($categories as $category => $items) {
1809 if ($category == $cview) {
1810 foreach ($items as $assignment=>$points) {
1811 if ($assignment != 'stats') {
1812 $temp = $points['sort_order'];
1813 $item_order[$temp] = $assignment;
1814 }
1815 }
1816 }
1817 }
1818 }
5fadde83 1819 /// Make sure $item_order is initialised (bug 3424)
1820 if (empty($item_order)) $item_order = array();
1821
cbff94ba 1822 ksort($item_order);
1823
1824 foreach($grades_by_student as $student => $categories) {
1825
1826 if ($preferences->reprint_headers != 0 && $reprint >= $preferences->reprint_headers) {
2cbf6b5a 1827 echo $header.$header1.'</tr>';
cbff94ba 1828 $reprint=0;
1829 }
1830
2cbf6b5a 1831 // alternate row classes
1832 $row = ($oddrow) ? '<tr class="r0">' : '<tr class="r1">';
1833 $oddrow = !$oddrow;
1834
1835 // reset the col classes
1836 $oddcol = true;
1837
1838
cbff94ba 1839 // set the links to student information based on multiview or individual... if individual go to student info... if many go to individual grades view.
1c45e42e 1840 if (has_capability('moodle/course:viewcoursegrades', $context)) {
cbff94ba 1841 if ($view_by_student != -1) {
1842 $student_link = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$student.'&amp;course='.$course->id.'">';
1843 }
1844 else {
68d0c80c 1845 $student_link = '<a href="?id='.$course->id.'&amp;action=vcats&amp;user='.$student.'&amp;cview='.$cview.'">';
cbff94ba 1846 }
1847 $student_link .= $grades_by_student[$student]['student_data']['lastname'].', '.$grades_by_student[$student]['student_data']['firstname'].'</a>';
fc9b712e 1848 $row .= '<th class="fullname" scope="row">'.$student_link.'</th>';
cbff94ba 1849 }
1850
1851 foreach($categories as $category => $items) {
1852 if ($category == $cview) {
1853 // make sure that the grades come out in the same order
2cbf6b5a 1854 foreach($item_order as $order=>$assignment) {
1855
1856 $class = $all_categories[$category][$assignment]['modname'];
1857
cbff94ba 1858 if ($assignment != 'stats') {
2cbf6b5a 1859
cbff94ba 1860 if ($first == 0) {
1861 $colcount++;
1862 $link_id = grade_get_module_link($course->id, $all_categories[$category][$assignment]['cminstance'], $all_categories[$category][$assignment]['modid']);
1863
1864 $link = $CFG->wwwroot.'/mod/'.$all_categories[$category][$assignment]['modname'].'/view.php?id='.$link_id->id;
0edcd419 1865 $all_categories[$category][$assignment]['link'] = $link;
cbff94ba 1866 if ($all_categories[$category][$assignment]['hidden'] == 0) {
fc9b712e 1867 $header .= '<th class="'.$class.'" colspan="'.$grade_columns.'" scope="col"><a href="'.$link.'">'.format_string($assignment,true).'</a>';
cbff94ba 1868 }
1869 else {
fc9b712e 1870 $header .= '<th class="'.$class.'" colspan="'.$grade_columns.'" scope="col"><a class="dimmed" href="'.$link.'">'.format_string($assignment,true).'</a>';
cbff94ba 1871 }
1872 if ($all_categories[$category][$assignment]['extra_credit'] == 1) {
2cbf6b5a 1873 $header .= '<span class="extracredit">('.get_string('extracredit','grades').')</span>';
cbff94ba 1874 }
1875 $header .='</th>';
1876 if ($preferences->show_points) {
fc9b712e 1877 $header1 .= '<th class="'.$class.'" scope="col">'. $all_categories[$category][$assignment]['maxgrade'];
cbff94ba 1878 if ($all_categories[$category][$assignment]['grade_against'] != $all_categories[$category][$assignment]['maxgrade']) {
b623ea5e 1879 $header1 .= '('. $all_categories[$category][$assignment]['grade_against'].')';
cbff94ba 1880 }
b623ea5e 1881 $header1 .= '</th>';
cbff94ba 1882 }
1883
1884 if($preferences->show_percent) {
1885 if ($all_categories[$category][$assignment]['grade_against'] != $all_categories[$category][$assignment]['maxgrade']) {
fc9b712e 1886 $header1 .= '<th class="'.$class.'" scope="col">'.get_string('scaledpct','grades').'</th>';
cbff94ba 1887 }
1888 else {
fc9b712e 1889 $header1 .= '<th class="'.$class.'" scope="col">'.get_string('rawpct','grades').'</th>';
cbff94ba 1890 }
1891 }
1892 if ($preferences->show_weighted) {
1893 if ($all_categories[$category]['stats']['totalpoints'] != 0) {
1894 $cur_weighted_max = sprintf("%0.2f", $all_categories[$category][$assignment]['grade_against']/$all_categories[$category]['stats']['totalpoints']*$all_categories[$category]['stats']['weight']);
1895 }
1896 else {
1897 $cur_weighted_max = 0;
1898 }
fc9b712e 1899 $header1 .= '<th scope="col">'.$cur_weighted_max.get_string('pctoftotalgrade','grades').'</th>';
cbff94ba 1900 }
1901 }
1902
1903 // display points
1904 if ($preferences->show_points) {
2cbf6b5a 1905 $class .= ($oddcol) ? ' c0 points' : ' c1 points';
1906 $oddcol = !$oddcol;
1907 $row .= '<td class="'.$class.'"><a href="'.$all_categories[$category][$assignment]['link'].'">' . $items[$assignment]['grade'] . '</a></td>';
cbff94ba 1908 }
1909
1910 if ($preferences->show_percent) {
2cbf6b5a 1911 $class .= ($oddcol) ? ' c0 percent' : ' c1 percent';
1912 $oddcol = !$oddcol;
1913 $row .= '<td class="'.$class.'">'. $items[$assignment]['percent'].'%</td>';
cbff94ba 1914 }
1915
1916 if ($preferences->show_weighted) {
2cbf6b5a 1917 $class .= ($oddcol) ? ' c0 weighted' : ' c1 weighted';
1918 $oddcol = !$oddcol;
1919 $row .= '<td class="'.$class.'">'.$items[$assignment]['weighted'].'%</td>';
cbff94ba 1920 }
1921 }
1922 }
2cbf6b5a 1923 } else {
1924 $class = '';
cbff94ba 1925 }
1926 }
1927
1928 if ($first == 0) {
1c45e42e 1929 if (has_capability('moodle/course:viewcoursegrades', $context) && $view_by_student == -1) {
68d0c80c 1930 $total_sort_link = '<a href="?id='.$course->id.'&amp;action=vcats&amp;cview='.$cview.'&amp;sort=highgrade_category"><img src="'.$CFG->wwwroot.'/pix/t/down.gif" alt="'.get_string('highgradedescending','grades').'" /></a>';
1931 $total_sort_link .= '<a href="?id='.$course->id.'&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>';
cbff94ba 1932 }
1933 else {
1934 $total_sort_link = '';
1935 }
1936
68d0c80c 1937 $stats_link = '<a href="javascript:void(0)" onclick="window.open(\'?id='.$course->id.'&amp;action=stats&amp;category='.$cview.'\',\''.get_string('statslink','grades').'\',\'height=200,width=300,scrollbars=no\')">'.get_string('statslink','grades').'</a>';
cbff94ba 1938 if ($all_categories[$cview]['stats']['drop'] != 0) {
fc9b712e 1939 $header .= '<th class="'.$class.'" colspan="'.$grade_columns.'" scope="col">'.get_string('total','grades').'&nbsp; (Lowest '. $all_categories[$cview]['stats']['drop']. ' Dropped)'.$total_sort_link.' '.$stats_link.'</th>';
cbff94ba 1940 }
1941 else {
fc9b712e 1942 $header .= '<th class="'.$class.'" colspan="'.$grade_columns.'" scope="col">'.get_string('total','grades').'&nbsp;'.$total_sort_link.' '.$stats_link.'</th>';
cbff94ba 1943 }
1944
1945 if ($preferences->show_points) {
fc9b712e 1946 $header1 .= '<th class="'.$class.'" scope="col">'.$all_categories[$cview]['stats']['totalpoints'];
cbff94ba 1947 if ($all_categories[$cview]['stats']['bonus_points'] != 0) {
1948 $header1 .='(+'.$all_categories[$cview]['stats']['bonus_points'].')';
1949 }
1950 $header1 .='</th>';
1951 }
1952 if ($preferences->show_percent) {
fc9b712e 1953 $header1 .= '<th class="'.$class.'" scope="col">'.get_string('percent','grades').'</th>';
cbff94ba 1954 }
1955
1956
1957 if ($preferences->show_weighted) {
fc9b712e 1958 $header1 .= '<th class="'.$class.'" scope="col">'.$all_categories[$cview]['stats']['weight'].get_string('pctoftotalgrade','grades').'</th>';
cbff94ba 1959 }
1960
1c45e42e 1961 if (has_capability('moodle/course:viewcoursegrades', $context)) {
fc9b712e 1962 $header .= '<th rowspan="2" scope="col">'.$student_heading_link.'</th></tr>';
cbff94ba 1963 }
1964 else {
1965 $header .= '</tr>';
1966 }
1967
1968 //adjust colcount to reflect the actual number of columns output
1969 $colcount++; // total column
1970 $colcount = $colcount*$grade_columns + 2;
fc9b712e 1971 echo '<tr class="title"><th colspan="'.$colcount.'" scope="col">';
cbff94ba 1972 if ($preferences->use_advanced != 0) {
281ffa4a 1973 echo $cview.' '.get_string('grades','grades');
cbff94ba 1974 }
1975 else {
281ffa4a 1976 echo get_string('grades','grades');
cbff94ba 1977 }
1978
1c45e42e 1979 if (has_capability('moodle/course:viewcoursegrades', $context)) {
67f42581 1980 helpbutton('teacher', get_string('gradehelp','grades'), 'grade');
cbff94ba 1981 }
1982 else {
67f42581 1983 helpbutton('student', get_string('gradehelp','grades'), 'grade');
cbff94ba 1984 }
281ffa4a 1985 echo '</th></tr>';
1986 echo $header;
2cbf6b5a 1987 echo $header1.'</tr>';
cbff94ba 1988 $first = 1;
1989 }
1990
1991 // total points for category
1992 if ($preferences->show_points) {
2cbf6b5a 1993 $class .= ($oddcol) ? ' c0 points' : ' c1 points';
1994 $oddcol = !$oddcol;
1995 $row .= '<td class="'.$class.'">'.$grades_by_student[$student][$cview]['stats']['points'].'</td>';
cbff94ba 1996 }
1997
1998 // total percent for category
1999 if ($preferences->show_percent) {
2cbf6b5a 2000 $class .= ($oddcol) ? ' c0 percent' : ' c1 percent';
2001 $oddcol = !$oddcol;
2002 $row .= '<td class="'.$class.'">'.$grades_by_student[$student][$cview]['stats']['percent'].'%</td>';
cbff94ba 2003 }
2004
2005
2006 // total weighted for category
2007 if ($preferences->show_weighted) {
2cbf6b5a 2008 $class .= ($oddcol) ? ' c0 weighted' : ' c1 weighted';
2009 $oddcol = !$oddcol;
2010 $row .= '<td class="'.$class.'">'.$grades_by_student[$student][$cview]['stats']['weighted'].'%</td>';
cbff94ba 2011 }
2012
1c45e42e 2013 if (has_capability('moodle/course:viewcoursegrades', $context)) {
2cbf6b5a 2014 $row .= '<td class="fullname">'.$student_link.'</td>';
cbff94ba 2015 }
2016 $row .= '</tr>';
281ffa4a 2017 echo $row;
cbff94ba 2018 $reprint++;
2019 }
281ffa4a 2020 echo '</table>';
cbff94ba 2021 }
2022 else { // no grades returned
1eca6133 2023 error(get_string('nogradesreturned','grades'), $CFG->wwwroot.'/course/view.php?id='.$course->id);
cbff94ba 2024 }
2025 }
2026 else {
1eca6133 2027 error(get_string('nocategoryview','grades'), $CFG->wwwroot.'/course/view.php?id='.$course->id);
cbff94ba 2028 }
2029}
2030
dd91f415 2031function grade_view_all_grades($view_by_student) { // if mode=='grade' then we are in user view
cbff94ba 2032// displays all grades for the course
2033 global $CFG;
2034 global $course;
cbff94ba 2035 global $USER;
dd91f415 2036 global $preferences;
cbff94ba 2037
5a412dbf 2038 if (!$context = get_context_instance(CONTEXT_COURSE, $course->id)) {
2039 return false;
2040 }
2041
59fd781a 2042 // if can't see course grades, print single grade view
1c45e42e 2043 if (!has_capability('moodle/course:viewcoursegrades', $context)) {
68d0c80c 2044 $view_by_student = $USER->id;
cbff94ba 2045 }
2046
2047 list($grades_by_student, $all_categories) = grade_get_formatted_grades();
5a412dbf 2048
cbff94ba 2049 if ($grades_by_student != 0 && $all_categories != 0) {
7e2d7c92 2050
dd91f415 2051 // output a form for the user to download the grades.
2052 grade_download_form();
cbff94ba 2053
2054 if ($view_by_student != -1) {
2055 // unset all grades except for this student
2056 foreach ($grades_by_student as $student=>$junk) {
2057 if($student != $view_by_student) {
2058 unset($grades_by_student[$student]);
2059 }
2060 }
2061 }
7e2d7c92 2062
b623ea5e 2063 $grade_columns = $preferences->show_weighted + $preferences->show_points + $preferences->show_percent;
cbff94ba 2064
2065 $first = 0;
2066 $total_course_points = 0;
2067 $maxpercent = 0;
2068 $reprint=0;
7e2d7c92 2069
4e83cfdf 2070 echo '<table align="center" class="grades">';
1c45e42e 2071 if (has_capability('moodle/course:viewcoursegrades', $context)) {
cbff94ba 2072 $student_heading_link = get_string('student','grades');
2073 if ($view_by_student == -1) {
68d0c80c 2074 $student_heading_link .='<a href="?id='.$course->id.'&amp;action=grades&amp;sort=lastname"><br /><font size="-2">'.get_string('sortbylastname','grades').'</font></a>';
2075 $student_heading_link .= '<a href="?id='.$course->id.'&amp;action=grades&amp;sort=firstname"><br /><font size="-2">'.get_string('sortbyfirstname','grades').'</font></a>';
cbff94ba 2076 }
2077 else {
b623ea5e 2078 $student_heading_link .= '<br /><a href="?id='.$course->id.'&amp;&amp;action=grades"><font size="-2">'.get_string('showallstudents','grades').'</font></a>';
cbff94ba 2079 }
fc9b712e 2080 $header = '<tr><th rowspan="2" scope="col">'.$student_heading_link.'</th>';
cbff94ba 2081 }
2082 else {
2083 $header = '</tr>';
2084 }
90e7e987 2085 $header1 = '<tr>';
cbff94ba 2086
2087 $rowcount = 0;
4e83cfdf 2088 $oddrow = true;
cbff94ba 2089 $colcount = 0;
7e2d7c92 2090
cbff94ba 2091 foreach($grades_by_student as $student => $categories) {
7e2d7c92 2092
cbff94ba 2093 $totalpoints = 0;
2094 $totalgrade = 0;
2095 $total_bonus_points = 0;
2096 if ($preferences->reprint_headers != 0 && $reprint >= $preferences->reprint_headers) {
281ffa4a 2097 echo $header.$header1;
cbff94ba 2098 $reprint=0;
2099 }
4e83cfdf 2100
2101 // alternate row classes
2102 $row = ($oddrow) ? '<tr class="r0">' : '<tr class="r1">';
2103 $oddrow = !$oddrow;
2104
cbff94ba 2105 // set the links to student information based on multiview or individual... if individual go to student info... if many go to individual grades view.
1c45e42e 2106 if (has_capability('moodle/course:viewcoursegrades', $context)) {
cbff94ba 2107 if ($view_by_student != -1) {
b623ea5e 2108 $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>';
cbff94ba 2109 }
2110 else {
b623ea5e 2111 $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>';
cbff94ba 2112 }
fc9b712e 2113 $row .= '<th scope="row">'. $studentviewlink .'</th>';
cbff94ba 2114 }
2115 ksort($categories);
7e2d7c92 2116
cbff94ba 2117 foreach($categories as $category => $items) {
2118 if ($category != 'student_data') {
7e2d7c92 2119
cbff94ba 2120 if ($first == 0) {
2121 $colcount++;
a0a83fca 2122 if ($category == UNCATEGORISED) {
2123 $categoryname = get_string(UNCATEGORISED, 'grades');
2124 } else {
2125 $categoryname = $category;
2126 }
cbff94ba 2127 // only print the category headers if something is displayed for them
2128 if ($preferences->show_weighted || $preferences->show_percent || $preferences->show_points) {
54926e78 2129 $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>';
fc9b712e 2130 $header .= '<th colspan="'.$grade_columns.'" scope="col"><a href="?id='.$course->id.'&amp;action=vcats&amp;cview='.$category;
cbff94ba 2131 if ($view_by_student != -1) {
5305e2eb 2132 $header .= '&amp;user='.$view_by_student;
cbff94ba 2133 }
a0a83fca 2134 $header .='">'. $categoryname .' '.$stats_link.'</a>';
cbff94ba 2135 }
2136 if ($preferences->display_weighted != 0) {
2137 $header .= '('. $all_categories[$category]['stats']['weight'] . '%)';
2138 }
2139 $header .= '</th>';
2140 if ($preferences->show_points) {
fc9b712e 2141 $header1 .= '<th scope="col">'.get_string('points','grades').'('.$all_categories[$category]['stats']['totalpoints'].')';
cbff94ba 2142 if ($all_categories[$category]['stats']['bonus_points'] != 0) {
2143 $header1 .='(+'.$all_categories[$category]['stats']['bonus_points'].')';
2144 }
2145 $header1 .='</th>';
2146 }
2147 if ($preferences->show_percent) {
fc9b712e 2148 $header1 .= '<th scope="col">'.get_string('percent','grades').'</th>';
cbff94ba 2149 }
2150 if ($preferences->show_weighted) {
fc9b712e 2151 $header1 .= '<th scope="col">'.get_string('weightedpctcontribution','grades').'</th>';
cbff94ba 2152 }
2153 $maxpercent = $all_categories["$category"]['stats']['weight'] + $maxpercent;
2154 //$total_course_points = $all_categories[$category]['stats']['totalpoints']+ $total_course_points;
2155 //$total_course_points = $all_categories[$category]['stats']['totalpoints']+ $total_course_points;
2156 }
2157
cbff94ba 2158 if ($preferences->show_points) {
2159 $row .= '<td align="right">' . $items['stats']['points'] . '</td>';
2160 }
2161 if ($preferences->show_percent) {
2162 $row .= '<td align="right">'. $items['stats']['percent'].'%</td>';
2163 }
2164
2165 if ($preferences->show_weighted) {
2166 $row .= '<td align="right">'. $items['stats']['weighted'] . '%</td>';
2167 }
2168 $total_bonus_points = $all_categories[$category]['stats']['bonus_points'];
2169 }
2170 }
2171 if ($first == 0) {
b623ea5e 2172 if ($preferences->show_letters) {
cbff94ba 2173 $total_columns = $grade_columns + 1;
2174 }
2175 else {
2176 $total_columns = $grade_columns;
2177 }
2178
1c45e42e 2179 if (has_capability('moodle/course:viewcoursegrades', $context) && $view_by_student == -1) {
68d0c80c 2180 $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>';
2181 $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>';
2182 $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>';
2183 $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>';
2184 $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>';
2185 $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>';
2186 $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>';
2187 $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>';
b623ea5e 2188 }
54926e78 2189 $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>';
fc9b712e 2190 $header .= '<th colspan="'.$total_columns.'" scope="col">'.get_string('total','grades').'&nbsp;'.$stats_link.'</th>';
1c45e42e 2191 if (has_capability('moodle/course:viewcoursegrades', $context) && $view_by_student == -1) {
cbff94ba 2192 if ($preferences->show_points) {
fc9b712e 2193 $header1 .= '<th scope="col">'.get_string('points','grades').'('.$all_categories['stats']['totalpoints'].')';
cbff94ba 2194 if ($category != 'student_data' && $all_categories[$category]['stats']['bonus_points'] != 0) {
2195
2196 $header1 .='(+'.$total_bonus_points.')';
2197 }
2198 $header1 .= '<br />'.$points_sort_link.' '.'</th>';
2199 }
2200 if ($preferences->show_percent) {
fc9b712e 2201 $header1 .= '<th scope="col">'.get_string('percentshort','grades').'<br />'.$percent_sort_link.' '.'</th>';
cbff94ba 2202 }
2203 if ($preferences->show_weighted) {
fc9b712e 2204 $header1 .= '<th scope="col">'.get_string('weightedpct','grades').'('.$all_categories['stats']['weight'].')'.'<br />'.$weighted_sort_link.' '.'</th>';
cbff94ba 2205 }
b623ea5e 2206 if ($preferences->show_letters) {
fc9b712e 2207 $header1 .= '<th scope="col">'.get_string('lettergrade','grades').'<br />'.$grade_sort_link.' '.'</th>';
cbff94ba 2208 }
2209 $header1 .= '</tr>';
2210 }
2211 else {
2212 if ($preferences->show_points) {
fc9b712e 2213 $header1 .= '<th scope="col">'.get_string('points','grades').'('.$all_categories['stats']['totalpoints'].')';
cbff94ba 2214 if ($category != 'student_data' && $all_categories[$category]['stats']['bonus_points'] != 0) {
2215 $header1 .='(+'.$total_bonus_points.')';
2216 }
2217 $header1 .= '</th>';
2218 }
2219 if ($preferences->show_percent) {
fc9b712e 2220 $header1 .= '<th scope="col">'.get_string('percentshort','grades').'</th>';
cbff94ba 2221 }
2222 if ($preferences->show_weighted) {
fc9b712e 2223 $header1 .= '<th scope="col">'.get_string('weightedpct','grades').'('.$all_categories['stats']['weight'].')</th>';
cbff94ba 2224 }
b623ea5e 2225 if ($preferences->show_letters) {
fc9b712e 2226 $header1 .= '<th scope="col">'.get_string('lettergrade','grades').'</th>';
cbff94ba 2227 }
2228 $header1 .= '</tr>';
2229 }
1c45e42e 2230 if (has_capability('moodle/course:viewcoursegrades', $context)) {
fc9b712e 2231 $header .= '<th rowspan="2" scope="col">'.$student_heading_link.'</th></tr>';
cbff94ba 2232 }
2233 // adjust colcount to reflect actual number of columns output
2234 $colcount = $colcount * $grade_columns + $total_columns + 2;
7e2d7c92 2235
fc9b712e 2236 echo '<tr><th colspan="'.$colcount.'" scope="col"><font size="+1">'.get_string('allgrades','grades').'</font>';
1c45e42e 2237 if (has_capability('moodle/course:viewcoursegrades', $context)) {
67f42581 2238 helpbutton('teacher', get_string('gradehelp','grades'), 'grade');
cbff94ba 2239 }
2240 else {
67f42581 2241 helpbutton('student', get_string('gradehelp','grades'), 'grade');
cbff94ba 2242 }
281ffa4a 2243 echo '</th></tr>';
cbff94ba 2244
2245
281ffa4a 2246 echo $header;
2247 echo $header1;
cbff94ba 2248 $first = 1;
2249 }
2250 if ($preferences->show_points) {
2251 $row .= '<td align="right">'.$grades_by_student[$student]['student_data']['points'].'</td>';
2252 }
2253 if ($preferences->show_percent) {
2254 $row .= '<td align="right">'.$grades_by_student[$student]['student_data']['percent'].'%</td>';
2255 }
2256 if ($preferences->show_weighted) {
2257 $row .= '<td align=right>'.$grades_by_student[$student]['student_data']['weighted'].'%</td>';
2258 }
b623ea5e 2259 if ($preferences->show_letters) {
cbff94ba 2260 if ($preferences->use_weighted_for_letter == 1) {
2261 $grade = $grades_by_student[$student]['student_data']['weighted'];
2262 }
2263 else {
2264 $grade = $grades_by_student[$student]['student_data']['percent'];
2265 }
2266 $letter_grade = grade_get_grade_letter($course->id, $grade);
2267 if ($letter_grade) {
2268 $row .= '<td align="right">'.$letter_grade->letter.'</td>';
2269 }
2270 else {
2271 // there wasn't an appropriate entry to use in the gradebook.
2272 if (grade_letters_set($course->id)) {
2273 $row .= '<td align="right">'.get_string('nolettergrade','grades').' '.$grade.'</td>';
2274 }
2275 else {
2276 $row .= '<td align="right">'.get_string('nogradeletters','grades').'</td>';
2277 }
2278 }
2279 }
1c45e42e 2280 if (has_capability('moodle/course:viewcoursegrades', $context)) {
cbff94ba 2281 $row .= '<td>'. $studentviewlink .'</td></tr>';
2282 }
2283 else {
2284 $row .= '</tr>';
2285 }
7e2d7c92 2286
2287 echo $row;
cbff94ba 2288 $reprint++;
2289 }
281ffa4a 2290 echo '</table>';
cbff94ba 2291 }
2292 else { // no grades returned
2293 error(get_string('nogradesreturned','grades'));
2294 }
2295}
2296
cbff94ba 2297
2298function grade_set_grade_weights() {
2299// set the grade weights as submitted from the form generated by display_grade_weights
2300 global $CFG;
2301 global $course;
2302 global $USER;
2303
2304 if (!empty($USER->id)) {
2305 if (!confirm_sesskey()) {
2306 error(get_string('confirmsesskeybad', 'error'));
2307 }
2308 }
2309
2310 // get list of all categories
2311 $categories = get_records('grade_category', 'courseid', $course->id);
2312 if ($categories) {
2313 foreach ($categories as $category) {
550c8b9c 2314 $form_catname = preg_replace('/[.| ]/', '_', $category->name);
cbff94ba 2315
2316 $submitted_category = optional_param($form_catname);
2317 if (is_numeric($submitted_category)) {
2318 // see if there is a weight if so see if it needs to be updated
2319 $weight = grade_get_category_weight($course->id, $category->name);
2320 if ($weight) {
2321 if ($weight->weight != $submitted_category)
2322 {
2323 set_field('grade_category', 'weight', $submitted_category, 'id', $weight->id);
2324 }
2325
2326 $cur_drop = optional_param("drop_x_lowest$form_catname");
2327 $cur_bonus_points = optional_param("bonus_points$form_catname");
2328 $cur_hidden = optional_param("hidden$form_catname");
2329 if ($cur_hidden) {
2330 $cur_hidden = true;
2331 }
2332 else {
2333 $cur_hidden = false;
2334 }
2335
2336 if ($weight->drop_x_lowest != $cur_drop) {
2337 set_field('grade_category', 'drop_x_lowest', $cur_drop, 'id', $weight->cat_id);
2338 }
2339 if ($weight->bonus_points != $cur_bonus_points) {
2340 set_field('grade_category', 'bonus_points', $cur_bonus_points, 'id', $weight->cat_id);
2341 }
2342 if ($cur_hidden) {
2343 set_field('grade_category', 'hidden', 1, 'id', $weight->cat_id);
2344 }
2345 else {
2346 set_field('grade_category', 'hidden', 0, 'id', $weight->cat_id);
2347 }
2348 }
2349 else {
2350 // insert the new record... we shouldn't reach this point anymore
2351 //$new_weight->course = $course->id;
2352 //$new_weight->category = $category->id;
2353 //$new_weight->weight = $submitted_category;
2354 //insert_record('grade_weight', $new_weight);
2355 }
2356 }
2357 else {
6ba65fa0 2358 echo '<center><font color="red">'.get_string('nonumericweight','grades').
2359 format_string($category->name) .': "'.$submitted_category.'"</font></center><br />';
cbff94ba 2360 }
2361 }
2362 }
2363}
2364
2365function grade_display_grade_weights() {
2366// get all categories with weights
2367// then set and display that entry.
2368 global $CFG;
2369 global $course;
2370 global $USER;
2371
2372 $categories = get_records('grade_category', 'courseid', $course->id);
2373 if ($categories) {
b7dc2256 2374 echo '<form id="grade_weights" action="./index.php" method="post">';
0ca5abd6 2375 echo '<table border="0" cellspacing="2" cellpadding="5" align="center" class="generalbox">';
2376 echo '<tr><th colspan="5" class="header" scope="col">'.get_string('setweights','grades');
67f42581 2377 helpbutton('weight', get_string('gradeweighthelp','grades'), 'grade');
281ffa4a 2378 echo '</th></tr>';
0ca5abd6 2379 echo '<tr><td align="center" class="generaltableheader">'.get_string('category','grades').'</td>';
2380 echo '<td align="center" class="generaltableheader">'.get_string('weight','grades').'</td>';
2381 echo '<td align="center" class="generaltableheader">'.get_string('dropxlowest','grades').'</td>';
2382 echo '<td align="center" class="generaltableheader">'.get_string('bonuspoints','grades').'</td>';
2383 echo '<td align="center" class="generaltableheader">'.get_string('hidecategory','grades').'</td>';
2384 echo '</tr>';
281ffa4a 2385 echo '<input type="hidden" name="id" value="'.$course->id.'" />';
2386 echo '<input type="hidden" name="action" value="set_grade_weights" />';
2387 echo '<input type="hidden" name="sesskey" value="'.$USER->sesskey.'" />';
0ca5abd6 2388
cbff94ba 2389 $sum = 0;
2390
2391 foreach($categories as $category) {
2392 $val = $category->weight;
2393 $sum = $sum + $val;
2394
2395 // make names form safe
2396 $form_catname = str_replace(' ', '_', $category->name);
1d9498e4 2397 if ($category->name == UNCATEGORISED) {
2398 $category->name = get_string(UNCATEGORISED, 'grades');
2399 }
6ba65fa0 2400 echo '<tr><td align="center" class="generalboxcontent">'. format_string($category->name) .'</td>';
e1540e50 2401 echo '<td align="center" class="generalboxcontent"><input type="text" size="5" name="'.$form_catname.'" value="'.$val.'" /></td>';
2402 echo '<td align="center" class="generalboxcontent"><input type="text" size="5" name="drop_x_lowest'.$form_catname.'" value="'.$category->drop_x_lowest.'" /></td>';
2403 echo '<td align="center" class="generalboxcontent"><input type="text" size="5" name="bonus_points'.$form_catname.'" value="'.$category->bonus_points.'" /></td>';
2404 echo '<td align="center" class="generalboxcontent"><input type="checkbox" name="hidden'.$form_catname.'" ';
cbff94ba 2405 if ($category->hidden == 1) {
281ffa4a 2406 echo ' checked="checked"';
cbff94ba 2407 }
0ca5abd6 2408 echo ' /></td></tr>';
cbff94ba 2409 }
0ca5abd6 2410 echo '<tr><td colspan="5" align="center" class="generalboxcontent">';
2411 echo '<input type="submit" value="'.get_string('savechanges','grades').'" />';
2412 echo '</td></tr>';
cbff94ba 2413 if ($sum != 100) {
e1540e50 2414 echo '<tr><td colspan="5" align="center" class="generalboxcontent"><font color="red">'.get_string('totalweightnot100','grades').'</font></td></tr>';
cbff94ba 2415 }
2416 else {
e1540e50 2417 echo '<tr><td colspan="5" align="center" class="generalboxcontent"><font color="green">'.get_string('totalweight100','grades').'</font></td></tr>';
cbff94ba 2418 }
2419 }
2420 else {
2421 /// maybe this should just do the default population of the categories instead?
281ffa4a 2422 echo '<font color="red">'.get_string('setcategorieserror','grades').'</font>';
cbff94ba 2423 }
281ffa4a 2424 echo '</table>';
0ca5abd6 2425 echo '</form>';
281ffa4a 2426 echo '<center>'.get_string('dropxlowestwarning','grades').'</center><br />';
cbff94ba 2427}
2428
2429function grade_set_categories() {
2430 global $CFG;
2431 global $course;
2432 global $USER;
2433
2434
2435 /// Collect modules data
2436 get_all_mods($course->id, $mods, $modnames, $modnamesplural, $modnamesused);
2437
5609f9e6 2438 echo '<table border="0" cellspacing="2" cellpadding="5" align="center" class="generalbox">';
2439 echo '<tr><th colspan="5" class="header" scope="col">'.get_string('setcategories','grades');
67f42581 2440 helpbutton('category', get_string('gradecategoryhelp','grades'), 'grade');
39f5a2bd 2441 echo '</th></tr>';
5609f9e6 2442 echo '<tr><td align="center" class="generaltableheader">'.get_string('gradeitem','grades').'</td>';
2443 echo '<td align="center" class="generaltableheader">'.get_string('category','grades').'</td>';
2444 echo '<td align="center" class="generaltableheader">'.get_string('maxgrade','grades').'</td>';
2445 echo '<td align="center" class="generaltableheader">'.get_string('curveto','grades').'</td>';
2446 echo '<td align="center" class="generaltableheader">'.get_string('extracredit','grades').'</td></tr>';
b7dc2256 2447 echo '<form id="set_categories" method="post" action="./index.php" >';
281ffa4a 2448 echo '<input type="hidden" name="action" value="assign_categories" />';
2449 echo '<input type="hidden" name="id" value="'.$course->id.'" />';
2450 echo '<input type="hidden" name="sesskey" value="'.$USER->sesskey.'" />';
cbff94ba 2451
2452 $itemcount = 0;
2453
2454 /// Search through all the modules, pulling out grade data
2455 $sections = get_all_sections($course->id); // Sort everything the same as the course
2456 for ($i=0; $i<=$course->numsections; $i++) {
2457 if (isset($sections[$i])) { // should always be true
2458 $section = $sections[$i];
2459 if ($section->sequence) {
2460 $sectionmods = explode(",", $section->sequence);
2461 foreach ($sectionmods as $sectionmod) {
dd4fd4f9 2462 if (empty($mods[$sectionmod])) {
2463 continue;
2464 }
cbff94ba 2465 $mod = $mods[$sectionmod];
2466 $instance = get_record("$mod->modname", "id", "$mod->instance");
2467 $libfile = "$CFG->dirroot/mod/$mod->modname/lib.php";
2468 if (file_exists($libfile)) {
2469 require_once($libfile);
2470 $gradefunction = $mod->modname."_grades";
2471 if (function_exists($gradefunction)) { // Skip modules without grade function
2472 if ($modgrades = $gradefunction($mod->instance)) {
2473
2474 if ($modgrades->maxgrade != '')
2475 // this block traps out broken modules that don't return a maxgrade according to the moodle API
2476 {
2477 $itemcount++;
2478 //modgrades contains student information with associated grade
281ffa4a 2479 //echo "<b>modname: $mod->modname id: $mod->id course: $mod->course</b><br />";
2480 echo '<input type="hidden" name="modname'.$itemcount.'" value="'.$mod->modname.'" />';
2481 echo '<input type="hidden" name="mod'.$itemcount.'" value="'.$mod->instance.'" />';
2482 echo '<input type="hidden" name="course'.$itemcount.'" value="'.$mod->course.'" />';
e1540e50 2483 echo '<tr><td align="center" class="generalboxcontent">';
cbff94ba 2484 // get instance name from db.
2485 $instance = get_record($mod->modname, 'id', $mod->instance);
0e60c772 2486 echo format_string($instance->name)."</td>";
cbff94ba 2487 // see if the item is already in the category table and if it is call category select with the id so it is selected
e1540e50 2488 echo '<td align="center" class="generalboxcontent"><select name="category'.$itemcount.'">';
cbff94ba 2489 $item_cat_id = get_record('grade_item', 'modid', $mod->module, 'courseid', $course->id, 'cminstance', $mod->instance);
2490 //print_object($item_cat_id);
2491 if (isset($item_cat_id)) {
2492 grade_category_select($item_cat_id->category);
2493 }
2494 else {
2495 grade_category_select(-1);
2496 }
e1540e50 2497 echo '</select></td><td align="center" class="generalboxcontent">'.$modgrades->maxgrade.'<input type="hidden" name="maxgrade'.$itemcount.'" value="'.$modgrades->maxgrade.'" /></td>';
cbff94ba 2498
2499 if (isset($item_cat_id)) {
2500 // 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%)
2501 if ($item_cat_id->scale_grade == '' || $item_cat_id->scale_grade == 0)
2502 $scale_to = $modgrades->maxgrade;
2503 else
2504 $scale_to = round($modgrades->maxgrade/$item_cat_id->scale_grade);
e1540e50 2505 echo '<td align="center" class="generalboxcontent"><input type="text" size="5" name="scale_grade'.$itemcount.'" value="'.$scale_to.'" /></td>';
cbff94ba 2506 }
2507 else {
e1540e50 2508 echo '<td align="center" class="generalboxcontent"><input type="text" size="5" name="scale_grade'.$itemcount.'" value="'.$modgrades->maxgrade.'" /></td>';
cbff94ba 2509 }
2510
e1540e50 2511 echo '<td align="center" class="generalboxcontent"><input type="checkbox" name="extra_credit'.$itemcount.'" ';
cbff94ba 2512 if ($item_cat_id->extra_credit == 1) {
281ffa4a 2513 echo ' checked="checked"';
cbff94ba 2514 }
281ffa4a 2515 echo ' /></td></tr>';
cbff94ba 2516 }
2517 }
2518 }
2519 }
2520 }
2521 }
2522 }
2523 }
281ffa4a 2524 echo '<input type="hidden" name="totalitems" value="'.$itemcount.'" />';
e1540e50 2525 echo '<tr><td colspan="5" align="center" class="generalboxcontent"><input type="submit" value="'.get_string('savechanges','grades').'" /></td></tr>';
281ffa4a 2526 echo '</form>';
e1540e50 2527 echo '<tr><td colspan="5" align="center" class="generalboxcontent">';
cbff94ba 2528 grade_add_category_form();
e1540e50 2529 echo '</td></tr><tr><td colspan="5" align="center" class="generalboxcontent">';
cbff94ba 2530 grade_delete_category_form();
e1540e50 2531 echo '</td></tr></table>';
39f5a2bd 2532 echo '<center>'.get_string('extracreditwarning','grades').'</center>';
cbff94ba 2533}
2534
2535function grade_delete_category() {
2536 global $CFG;
2537 global $course;
2538 global $USER;
2539
2540 if (!empty($USER->id)) {
2541 if (!confirm_sesskey()) {
2542 error(get_string('confirmsesskeybad', 'error'));
2543 }
2544 }
2545
2546 $cat_id = optional_param('category_id');
2547 if ($cat_id != 'blank') {
2548 // delete the record
2549 delete_records('grade_category', 'id', $cat_id, 'courseid', $course->id);
2550 // set grade_item category field=0 where it was the deleted category (set uncategorized will clean this up)
2551 set_field('grade_item', 'category', 0, 'category', $cat_id);
2552 }
2553}
2554
2555function grade_assign_categories() {
2556 global $CFG;
2557 global $course;
2558 global $USER;
2559 $num_categories = optional_param('totalitems');
2560
2561 if (!empty($USER->id)) {
2562 if (!confirm_sesskey()) {
2563 error(get_string('confirmsesskeybad', 'error'));
2564 }
2565 }
2566
2567 for ($i = 1; $i <= $num_categories; $i++) {
2568
2569 // these next sets of lines are a bit obtuse, but it lets there be a dynamic number of grade items
2570 // in the grade category form (maybe there's a better way?)
2571 $cur_cat_id = '$_REQUEST[\'category'.$i.'\'];';
2572 eval( "\$cur_cat_id = $cur_cat_id;" );
2573 $cur_modname = '$_REQUEST[\'modname'.$i.'\'];';
2574 eval( "\$cur_modname = $cur_modname;" );
2575 $cur_mod = '$_REQUEST[\'mod'.$i.'\'];';
2576 eval( "\$cur_mod = $cur_mod;" );
2577 $cur_maxgrade = '$_REQUEST[\'maxgrade'.$i.'\'];';
2578 eval( "\$cur_maxgrade = $cur_maxgrade;" );
2579 $cur_scale_grade = '$_REQUEST[\'scale_grade'.$i.'\'];';
2580 eval( "\$cur_scale_grade = $cur_scale_grade;" );
2581 $cur_extra_credit = '$_REQUEST[\'extra_credit'.$i.'\'];';
2582 $temp = 'extra_credit'.$i;
2583 $junk = get_record('modules','name',$cur_modname);
2584 $cur_modid = $junk->id;
2585 if (isset($_REQUEST[$temp])) {
2586 eval( "\$cur_extra_credit = $cur_extra_credit;" );
2587 }
2588 else {
2589 $cur_extra_credit = false;
2590 }
97033c86 2591 if ($cur_extra_credit) {
61240489 2592 $cur_extra_credit = 1;
97033c86 2593 } else {
2594 $cur_extra_credit = 0;
2595 }
cbff94ba 2596 if ($cur_scale_grade == 0 || $cur_scale_grade == '') {
2597 $cur_scale_grade = 1.0;
2598 }
2599
2600 $db_cat = get_record('grade_item', 'modid', $cur_modid, 'cminstance', $cur_mod, 'courseid', $course->id);
2601 if ( $db_cat ) {
2602 if ($db_cat->category != $cur_cat_id) {
2603 // item doesn't match in the db so update it to point to the new category
2604 set_field('grade_item', 'category', $cur_cat_id, 'id', $db_cat->id);
2605 }
2606
2607 if ($db_cat->scale_grade != $cur_maxgrade/$cur_scale_grade) {
2608 // scale_grade doesn't match
2609 set_field('grade_item', 'scale_grade', ($cur_maxgrade/$cur_scale_grade), 'id', $db_cat->id);
2610 }
97033c86 2611
2612 set_field('grade_item', 'extra_credit', $cur_extra_credit, 'id', $db_cat->id);
cbff94ba 2613 }
2614 else {
2615 // add a new record
2616 $item->courseid = $course->id;
2617 $item->category = $cur_cat_id;
2618 $item->modid = $cur_modid;
2619 $item->cminstance = $cur_mod;
2620 $item->scale_grade = $cur_scale_grade;
2621 $item->extra_credit = $cur_extra_credit;
2622 insert_record('grade_item', $item);
2623 }
2624 }
2625}
2626
2627function grade_add_category_form() {
2628 /// outputs a form to add a category
2629 /// just a simple text box with submit
2630 global $course;
2631 global $USER;
b7dc2256 2632 echo '<form id="new_category">';
281ffa4a 2633 echo get_string('addcategory','grades').':<input type="text" name="name" size="20" />';
2634 echo '<input type="hidden" name="id" value="'.$course->id.'" />';
2635 echo '<input type="hidden" name="action" value="insert_category" />';
2636 echo '<input type="hidden" name="sesskey" value="'.$USER->sesskey.'" />';
2637 echo '<input type="submit" value="'.get_string('addcategory','grades').'" />';
2638 echo '</form>';
cbff94ba 2639}
2640
2641function grade_delete_category_form() {
2642 // outputs a form to delete a category
2643 global $course;
2644 global $USER;
b7dc2256 2645 echo '<form id="delete_category">';
281ffa4a 2646 echo get_string('deletecategory','grades').': <select name="category_id">';
cbff94ba 2647 grade_category_select();
281ffa4a 2648 echo '</select><input type="hidden" name="id" value="'.$course->id.'" />';
2649 echo '<input type="hidden" name="sesskey" value="'.$USER->sesskey.'" />';
2650 echo '<input type="hidden" name="action" value="delete_category" />';
2651 echo '<input type="submit" value="'.get_string('deletecategory','grades').'" /></form>';
cbff94ba 2652}
2653
2654function grade_insert_category() {
2655 global $CFG;
2656 global $course;
2657 global $USER;
2658
2659 $category->name=optional_param('name');
2660 $category->courseid=$course->id;
2661
2662 if (!empty($USER->id)) {
2663 if (!confirm_sesskey()) {
2664 error(get_string('confirmsesskeybad', 'error'));
2665 }
2666 }
2667
2668 // make sure the record isn't already there and insert if okay
d662b0a0 2669 if (record_exists('grade_category', 'name', $category->name, 'courseid', $category->courseid)) {
cbff94ba 2670 // category already exists
2671 }
2672 elseif ($category->name != ''){
2673 if (!insert_record('grade_category', $category) ) {
281ffa4a 2674 echo '<font color="red">'.get_string('addcategoryerror','grades').'</font>';
cbff94ba 2675 }
2676 }
2677}
2678
c74ae30c 2679function grade_category_select($id_selected = 0) {
cbff94ba 2680 /// prints out a select box containing categories.
2681 global $CFG;
2682 global $course;
2683
2684
281ffa4a 2685 echo '<option value="blank">'.get_string('choosecategory','grades').'</option>';
cbff94ba 2686
2687 $categories = get_records('grade_category', 'courseid', $course->id, 'name');
2688
2689 if (!isset($categories)) {
2690 error(get_string("nocategories"));
2691 }
2692 else {
2693 foreach($categories as $category) {
281ffa4a 2694 if ($category->name == UNCATEGORISED) {
2695 $category->name = get_string('uncategorised', 'grades');
2696 }
cbff94ba 2697 if ($category->id == $id_selected) {
6ba65fa0 2698 echo '<option value="'.$category->id.'" selected="selected">'. format_string($category->name) .'</option>';
cbff94ba 2699 }
2700 else {
6ba65fa0 2701 echo '<option value="'.$category->id.'">'. format_string($category->name) .'</option>';
cbff94ba 2702 }
2703 }
2704 }
2705}
2706
b623ea5e 2707function grade_display_grade_preferences($course, $preferences) {
cbff94ba 2708 global $CFG;
cbff94ba 2709 global $USER;
2710
e478f7b7 2711 if ($preferences->use_advanced == 0) {
2712 $useadvanced = 1;
2713 $buttonlabel = get_string('useadvanced', 'grades');
2714 } else {
2715 $useadvanced = 0;
2716 $buttonlabel = get_String('hideadvanced', 'grades');
2717 }
2718
2719 $buttonoptions = array('action' => 'set_grade_preferences',
2720 'id' => $course->id,
2721 'sesskey' => sesskey(),
2722 'use_advanced' => $useadvanced);
2723
2724
67f42581 2725 print_heading_with_help(get_string('setpreferences','grades'), 'preferences', 'grade');
e478f7b7 2726
2727 echo '<center>';
2728 print_single_button('index.php', $buttonoptions, $buttonlabel, 'post');
2729 echo '<br /></center>';
b623ea5e 2730
b7dc2256 2731 echo '<form id="set_grade_preferences" method="post" action="./index.php">';
281ffa4a 2732 echo '<input type="hidden" name="action" value="set_grade_preferences" />';
e478f7b7 2733 echo '<input type="hidden" name="id" value="'.$course->id.'" />';
b623ea5e 2734 echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
9d95a8dd 2735 echo '<table border="0" cellspacing="2" cellpadding="5" align="center" class="gradeprefs generalbox">';
cbff94ba 2736
b623ea5e 2737 $optionsyesno = NULL;
2738 $optionsyesno[0] = get_string('no');
2739 $optionsyesno[1] = get_string('yes');
e478f7b7 2740
cbff94ba 2741
b623ea5e 2742 if ($preferences->use_advanced) {
2743 $options = NULL;
2744 $options[0] = get_string('no');
2745 $options[1] = get_string('toonly', 'moodle', $course->teachers);
2746 $options[2] = get_string('toeveryone', 'moodle');
2747
cbff94ba 2748 // display grade weights
b623ea5e 2749 echo '<tr><td class="c0">'.get_string('displayweighted','grades').':</td>';
2750 echo '<td class="c1">';
2751 choose_from_menu($options, 'display_weighted', $preferences->display_weighted, '');
2752 echo '</td></tr>';
cbff94ba 2753
2754 // display points
b623ea5e 2755 echo '<tr><td class="c0">'.get_string('displaypoints','grades').':</td>';
2756 echo '<td class="c1">';
2757 choose_from_menu($options, 'display_points', $preferences->display_points, '');
2758 echo '</td></tr>';
2759
cbff94ba 2760 // display percent
b623ea5e 2761 echo '<tr><td class="c0">'.get_string('displaypercent','grades').':</td>';
2762 echo '<td class="c1">';
2763 choose_from_menu($options, 'display_percent', $preferences->display_percent, '');
2764 echo '</td></tr>';
cbff94ba 2765
2766 // display letter grade
b623ea5e 2767 echo '<tr><td class="c0">'.get_string('displaylettergrade','grades').':</td>';
2768 echo '<td class="c1">';
2769 choose_from_menu($options, 'display_letters', $preferences->display_letters, '');
2770 echo '</td></tr>';
2771
cbff94ba 2772 // letter grade uses weighted percent
b623ea5e 2773 $options = NULL;
2774 $options[0] = get_string('usepercent','grades');
2775 $options[1] = get_string('useweighted','grades');
2776
2777 echo '<tr><td class="c0">'.get_string('lettergrade','grades').':</td>';
2778 echo '<td class="c1">';
2779 choose_from_menu($options, 'use_weighted_for_letter', $preferences->use_weighted_for_letter, '');
2780 echo '</td></tr>';
281ffa4a 2781 }
2782
2783 $headerlist[0] = get_string('none');
2784 for ($i=1; $i<=100; $i++) {
2785 $headerlist[$i] = $i;
cbff94ba 2786 }
2787
2788 // reprint headers every n lines default n=0
b623ea5e 2789 echo '<tr><td class="c0">'.get_string('reprintheaders','grades').':</td>';
2790 echo '<td class="c1">';
281ffa4a 2791 choose_from_menu($headerlist, 'reprint_headers', $preferences->reprint_headers, '');
2792 echo '</td></tr>';
cbff94ba 2793
2794 // show hidden grade items to teacher
b623ea5e 2795 echo '<tr><td class="c0">'.get_string('showhiddenitems','grades').'</td>';
2796 echo '<td class="c1">';
2797 choose_from_menu($optionsyesno, 'show_hidden', $preferences->show_hidden, '');
281ffa4a 2798 echo '</td></tr>';
cbff94ba 2799
e478f7b7 2800 echo '<tr><td colspan="3" align="center"><input type="submit" value="'.get_string('savepreferences','grades').'" /></td></tr></table></form>';
cbff94ba 2801}
2802
cbff94ba 2803
2804
2805function grade_display_letter_grades() {
2806 global $CFG;
2807 global $course;
2808 global $USER;
2809
2810 $db_letters = get_records('grade_letter', 'courseid', $course->id, 'grade_high DESC');
2811
2812 if ($db_letters) {
2813 $using_defaults = false;
2814 foreach ($db_letters as $letter) {
2815 $letters[$letter->id]->letter = $letter->letter;
2816 $letters[$letter->id]->grade_low = $letter->grade_low;
2817 $letters[$letter->id]->grade_high = $letter->grade_high;
2818 $letters[$letter->id]->courseid = $course->id;
2819 }
2820 }
2821 else {
2822 $using_defaults = true;
2823 // default A
2824 $letters[0]->letter='A';
2825 $letters[0]->grade_low=93.00;
2826 $letters[0]->grade_high=100.00;
2827 $letters[0]->courseid = $course->id;
2828 // default A-
2829 $letters[1]->letter='A-';
2830 $letters[1]->grade_low=90.00;
2831 $letters[1]->grade_high=92.99;
2832 $letters[1]->courseid = $course->id;
2833 // default B+
2834 $letters[2]->letter='B+';
2835 $letters[2]->grade_low=87.00;
2836 $letters[2]->grade_high=89.99;
2837 $letters[2]->courseid = $course->id;
2838 // default B
2839 $letters[3]->letter='B';
2840 $letters[3]->grade_low=83.00;
2841 $letters[3]->grade_high=86.99;
2842 $letters[3]->courseid = $course->id;
2843 // default B-
2844 $letters[4]->letter='B-';
2845 $letters[4]->grade_low=80.00;
2846 $letters[4]->grade_high=82.99;
2847 $letters[4]->courseid = $course->id;
2848 // default C+
2849 $letters[5]->letter='C+';
2850 $letters[5]->grade_low=77.00;
2851 $letters[5]->grade_high=79.99;
2852 $letters[5]->courseid = $course->id;
2853 // default C
2854 $letters[6]->letter='C';
2855 $letters[6]->grade_low=73.00;
2856 $letters[6]->grade_high=76.99;
2857 $letters[6]->courseid = $course->id;
2858 // default C-
2859 $letters[7]->letter='C-';
2860 $letters[7]->grade_low=70.00;
2861 $letters[7]->grade_high=72.99;
2862 $letters[7]->courseid = $course->id;
2863 // default D+
2864 $letters[8]->letter='D+';
2865 $letters[8]->grade_low=67.00;
2866 $letters[8]->grade_high=69.99;
2867 $letters[8]->courseid = $course->id;
2868 // default D
2869 $letters[9]->letter='D';
2870 $letters[9]->grade_low=60.00;
2871 $letters[9]->grade_high=66.99;
2872 $letters[9]->courseid = $course->id;
2873 // default F
2874 $letters[10]->letter='F';
2875 $letters[10]->grade_low=0.00;
2876 $letters[10]->grade_high=59.99;
2877 $letters[10]->courseid = $course->id;
2878 }
5609f9e6 2879
b7dc2256 2880 echo '<form id="grade_letter"><input type="hidden" name="id" value="'.$course->id.'" />';
5609f9e6 2881 echo '<table border="0" cellspacing="2" cellpadding="5" align="center" class="generalbox"><tr>';
2882 echo '<th colspan="3" class="header" scope="col">'.get_string('setgradeletters','grades');
2883 helpbutton('letter', get_string('gradeletterhelp','grades'), 'grade');
2884 echo '</th></tr>';
2885 echo '<tr><td align="center" class="generaltableheader">'.get_string('gradeletter','grades').'</td>';
2886 echo '<td align="center" class="generaltableheader">'.get_string('lowgradeletter','grades').'</td>';
2887 echo '<td align="center" class="generaltableheader">'.get_string('highgradeletter','grades').'</td></tr>';
281ffa4a 2888 echo '<input type="hidden" name="action" value="set_letter_grades" />';
2889 echo '<input type="hidden" name="sesskey" value="'.$USER->sesskey.'" />';
cbff94ba 2890 $i=0;
2891 foreach ($letters as $id=>$items) {
2892 if ($id !='' && !$using_defaults) {
2893 // send the record id so if the user deletes the values we can delete the row.
281ffa4a 2894 echo '<input type="hidden" name="id'.$i.'" value="'.$id.'" />';
cbff94ba 2895 }
e1540e50 2896 echo '<tr><td align="center" class="generalboxcontent"><input size="8" type="text" name="letter'.$i.'" value="'.$items->letter.'" /></td>'."\n";
2897 echo '<td align="center" class="generalboxcontent"><input size="8" type="text" name="grade_low'.$i.'" value="'.$items->grade_low.'" /></td>'."\n";
2898 echo '<td align="center" class="generalboxcontent"><input size="8" type="text" name="grade_high'.$i.'" value="'.$items->grade_high.'" /></td></tr>'."\n";
cbff94ba 2899 $i++;
2900 }
e1540e50 2901 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>';
2902 echo '<tr><td colspan="3" align="center" class="generalboxcontent"><input type="submit" value="'.get_string('savechanges','grades').'" /></td></tr>';
281ffa4a 2903 echo '<input type="hidden" name="totalitems" value="'.$i.'" />';
5609f9e6 2904 echo '<tr><td colspan="3" align="center" class="generalboxcontent">'.get_string('gradeletternote','grades').'</td></tr></table>';
2905 echo '</form>';
cbff94ba 2906}
2907
2908function grade_set_letter_grades() {
2909 global $CFG;
2910 global $course;
2911 global $USER;
2912
2913 if (!empty($USER->id)) {
2914 if (!confirm_sesskey()) {
2915 error(get_string('confirmsesskeybad', 'error'));
2916 }
2917 }
2918
2919 $totalitems= clean_param($_REQUEST['totalitems'], PARAM_CLEAN);
2920
2921 for($i=0; $i<=$totalitems; $i++) {
2922 if (isset($_REQUEST["id$i"])) {
2923 // item submitted was already in database
2924 $letterid = $_REQUEST["id$i"];
2925 $updateletters[$letterid]->letter = clean_param($_REQUEST["letter$i"], PARAM_CLEAN);
4e83cfdf 2926 // grade_low && grade_high don't need cleaning as they are possibly floats (no appropriate clean method) so we check is_numeric
2927 $updateletters[$letterid]->grade_low = $_REQUEST["grade_low$i"];
2928 $updateletters[$letterid]->grade_high = $_REQUEST["grade_high$i"];
cbff94ba 2929 $updateletters[$letterid]->id = $letterid;
2930 }
2931 else {
2932 // its a new item
2933 $newletter->letter = clean_param($_REQUEST["letter$i"], PARAM_CLEAN);
4e83cfdf 2934 $newletter->grade_low = $_REQUEST["grade_low$i"];
2935 $newletter->grade_high = $_REQUEST["grade_high$i"];
cbff94ba 2936 $newletter->courseid = $course->id;
2937 if (is_numeric($newletter->grade_high) && is_numeric($newletter->grade_low)) {
2938 insert_record('grade_letter', $newletter);
2939 }
2940 else {
2941 if ($i < $totalitems) {
2942 if ($newletter->grade_high != '' or $newletter->grade_low != '') {
281ffa4a 2943 echo '<center>'.get_string('lettergradenonnumber','grades').' '.$newletter->letter.' item number: '.$i.'<br /></center>';
cbff94ba 2944 }
2945 }
2946 }
2947 }
2948 }
2949
2950 if (isset($updateletters)) {
2951 foreach($updateletters as $id=>$items) {
2952 // see if any of the values are blank... if so delete them
2953 if ($items->letter == '' || $items->grade_low == '' || $items->grade_high == '') {
2954 delete_records('grade_letter', 'id', $id);
2955 }
2956 else {
2957 if (is_numeric($items->grade_high) && is_numeric($items->grade_low)) {
2958 update_record('grade_letter', $items);
2959 }
2960 else {
281ffa4a 2961 echo '<center><font color="red">'.get_string('errorgradevaluenonnumeric','grades').$letter.'</font></center>';
cbff94ba 2962 }
2963 }
2964 }
2965 }
2966}
2967
cbff94ba 2968function grade_download_form($type='both') {
ee50df92 2969 global $course,$USER, $action, $cview;
9c61ba4d 2970 if ($type != 'both' and $type != 'ods' and $type != 'excel' and $type != 'text') {
cbff94ba 2971 $type = 'both';
2972 }
2973
1c45e42e 2974 if (has_capability('moodle/course:viewcoursegrades', get_context_instance(CONTEXT_COURSE, $course->id))) {
281ffa4a 2975 echo '<table align="center"><tr>';
cbff94ba 2976 $options['id'] = $course->id;
6cd8c592 2977 $options['sesskey'] = $USER->sesskey;
cbff94ba 2978
9c61ba4d 2979 if ($type == 'both' || $type == 'ods') {
2980 $options['action'] = 'ods';
2981 echo '<td align="center">';
2982 print_single_button("index.php", $options, get_string("downloadods"));
2983 echo '</td>';
2984 }
8332de16 2985 if ($type == 'both' || $type == 'excel') {
cbff94ba 2986 $options['action'] = 'excel';
281ffa4a 2987 echo '<td align="center">';
cbff94ba 2988 print_single_button("index.php", $options, get_string("downloadexcel"));
281ffa4a 2989 echo '</td>';
cbff94ba 2990 }
8332de16 2991 if ($type == 'both' || $type == 'text') {
cbff94ba 2992 $options['action'] = 'text';
281ffa4a 2993 echo '<td align="center">';
cbff94ba 2994 print_single_button("index.php", $options, get_string("downloadtext"));
281ffa4a 2995 echo '</td>';
cbff94ba 2996 }
b623ea5e 2997 echo '<td>';
d662b0a0 2998
ee50df92 2999 $url = 'index.php?id='.$course->id;
3000 if (!empty($action)) {
3001 $url .= '&amp;action='.$action;
3002 if ($action == 'vcats') {
3003 $url .= '&amp;cview='.$cview;
3004 }
3005 }
b623ea5e 3006 echo '</td>';
3007
281ffa4a 3008 echo '</tr></table>';
cbff94ba 3009 }
3010}
3011
0a8a95c9 3012
3013
3014
3015
3016/**
3017 * Simply prints all grade of one student from all modules from a given course
59fd781a 3018 * used in the grade book for student view, and grade button under user profile
0a8a95c9 3019 * @param int $userid;
3020 * @param int $courseid;
3021 */
3022function print_student_grade($user, $course) {
3023
3024 global $CFG;
3025
3026 if (!empty($user)) {
3027 $grades[$user->id] = array(); // Collect all grades in this array
3028 $gradeshtml[$user->id] = array(); // Collect all grades html formatted in this array
3029 $totals[$user->id] = array(); // Collect all totals in this array
3030 }
3031
3032 $strmax = get_string("maximumshort");
3033 /// Collect modules data
3034 get_all_mods($course->id, $mods, $modnames, $modnamesplural, $modnamesused);
3035
3036/// Search through all the modules, pulling out grade data
3037 $sections = get_all_sections($course->id); // Sort everything the same as the course
59fd781a 3038
3039 // prints table
102b6e33 3040
3041 // flag for detecting whether to print table header or not
3042 $nograde = 0;
59fd781a 3043
0a8a95c9 3044 for ($i=0; $i<=$course->numsections; $i++) {
3045 if (isset($sections[$i])) { // should always be true
3046 $section = $sections[$i];
3047 if ($section->sequence) {
3048 $sectionmods = explode(",", $section->sequence);
3049 foreach ($sectionmods as $sectionmod) {
59fd781a 3050
0a8a95c9 3051 $mod = $mods[$sectionmod];
f9c471df 3052 if (empty($mod->modname)) {
3053 continue; // Just in case, see MDL-7150
3054 }
3055 $instance = get_record($mod->modname, 'id', $mod->instance);
0a8a95c9 3056 $libfile = "$CFG->dirroot/mod/$mod->modname/lib.php";
3057
3058 if (file_exists($libfile)) {
3059 require_once($libfile);
f9c471df 3060 $gradefunction = $mod->modname.'_grades';
0a8a95c9 3061 if (function_exists($gradefunction)) { // Skip modules without grade function
3062 if ($modgrades = $gradefunction($mod->instance)) {
3063 if (!empty($modgrades->maxgrade)) {
3064 if ($mod->visible) {
f9c471df 3065 $maxgrade = $modgrades->maxgrade;
0a8a95c9 3066 } else {
f9c471df 3067 $maxgrade = $modgrades->maxgrade;
0a8a95c9 3068 }
3069 } else {
f9c471df 3070 $maxgrade = '';
0a8a95c9 3071 }
3072
3073 if ($maxgrade) {
102b6e33 3074 if (!$nograde) {
3075 echo ('<table align="center" class="grades"><tr><th scope="col">'.get_string('activity').'</th><th scope="col">'.get_string('yourgrade','grades').'</th><th scope="col">'.get_string('maxgrade','grades').'</th></tr>');
3076 }
3077 $nograde++;
59fd781a 3078
3079 $link_id = grade_get_module_link($course->id, $mod->instance, $mod->module);
3080 $link = $CFG->wwwroot.'/mod/'.$mod->modname.'/view.php?id='.$link_id->id;
3081
3082 echo '<tr>';
0a8a95c9 3083 if (!empty($modgrades->grades[$user->id])) {
3084 $currentgrade = $modgrades->grades[$user->id];
102b6e33 3085 echo "<td><a href='$link'>$mod->modfullname: ".format_string($instance->name,true)."</a></td><td>$currentgrade</td><td>$maxgrade</td>";
3086 } else {
b034bdff 3087 echo "<td><a href='$link'>$mod->modfullname: ".format_string($instance->name,true)."</a></td><td>".get_string('nograde')."</td><td>$maxgrade</td>";
0a8a95c9 3088 }
59fd781a 3089 echo '</tr>';
0a8a95c9 3090 }
3091 }
3092 }
3093 }
3094 }
3095 }
3096 }
59fd781a 3097 } // a new Moodle nesting record? ;-)
102b6e33 3098
3099 if ($nograde) {
3100 echo '</table>';
3101 }
0a8a95c9 3102}
5a412dbf 3103
3104function grade_get_course_students($courseid) {
3105 global $CFG;
0909d44e 3106 // The list of roles to display is stored in CFG->gradebookroles
5a412dbf 3107 if (!$context = get_context_instance(CONTEXT_COURSE, $courseid)) {
3108 return false;
3109 }
3110
0909d44e 3111 $configvar = get_config('', 'gradebookroles');
1fd471a1 3112 if (empty($configvar)) {
5a412dbf 3113 notify ('no roles defined in admin->appearance->graderoles');
3114 return false; // no roles to displayreturn false;
3115 }
3116
1fd471a1 3117 if ($rolestoget = explode(',', $configvar)) {
5a412dbf 3118 foreach ($rolestoget as $crole) {
3119 if ($tempstudents = get_role_users($crole, $context, true)) {
3120 foreach ($tempstudents as $tempuserid=>$tempstudent) {
3121 $students[$tempuserid] = $tempstudent;
3122 }
3123 }
3124 }
3125 } else {
3126 notify ('no roles defined in admin->appearance->graderoles');
3127 return false; // no roles to displayreturn false;
3128 }
7f7d5063 3129 return isset($students)?$students:'';
5a412dbf 3130}
cbff94ba 3131?>